source: mainline/uspace/lib/drv/generic/remote_nic.c@ acdb5bac

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since acdb5bac was acdb5bac, checked in by Jiri Svoboda <jiri@…>, 12 years ago

Replace usage of bzero() with C standard memset().

  • Property mode set to 100644
File size: 31.9 KB
RevLine 
[609243f4]1/*
2 * Copyright (c) 2011 Radim Vansa
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libdrv
30 * @{
31 */
32/**
33 * @file
34 * @brief Driver-side RPC skeletons for DDF NIC interface
35 */
36
37#include <assert.h>
38#include <async.h>
39#include <errno.h>
40#include <ipc/services.h>
41#include <sys/time.h>
42#include "ops/nic.h"
43
[6d8455d]44static void remote_nic_send_frame(ddf_fun_t *dev, void *iface,
[609243f4]45 ipc_callid_t callid, ipc_call_t *call)
46{
47 nic_iface_t *nic_iface = (nic_iface_t *) iface;
[6d8455d]48 assert(nic_iface->send_frame);
[609243f4]49
[6d8455d]50 void *data;
51 size_t size;
52 int rc;
[609243f4]53
[6d8455d]54 rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
55 if (rc != EOK) {
56 async_answer_0(callid, EINVAL);
57 return;
58 }
59
60 rc = nic_iface->send_frame(dev, data, size);
[609243f4]61 async_answer_0(callid, rc);
[6d8455d]62 free(data);
[609243f4]63}
64
[8d7ec69d]65static void remote_nic_callback_create(ddf_fun_t *dev, void *iface,
[609243f4]66 ipc_callid_t callid, ipc_call_t *call)
67{
68 nic_iface_t *nic_iface = (nic_iface_t *) iface;
[8d7ec69d]69 assert(nic_iface->callback_create);
[609243f4]70
[9cd8165]71 int rc = nic_iface->callback_create(dev);
[609243f4]72 async_answer_0(callid, rc);
73}
74
75static void remote_nic_get_state(ddf_fun_t *dev, void *iface,
76 ipc_callid_t callid, ipc_call_t *call)
77{
78 nic_iface_t *nic_iface = (nic_iface_t *) iface;
79 assert(nic_iface->get_state);
80
81 nic_device_state_t state = NIC_STATE_MAX;
82
83 int rc = nic_iface->get_state(dev, &state);
84 async_answer_1(callid, rc, state);
85}
86
87static void remote_nic_set_state(ddf_fun_t *dev, void *iface,
88 ipc_callid_t callid, ipc_call_t *call)
89{
90 nic_iface_t *nic_iface = (nic_iface_t *) iface;
91 assert(nic_iface->set_state);
92
93 nic_device_state_t state = (nic_device_state_t) IPC_GET_ARG2(*call);
94
95 int rc = nic_iface->set_state(dev, state);
96 async_answer_0(callid, rc);
97}
98
99static void remote_nic_get_address(ddf_fun_t *dev, void *iface,
100 ipc_callid_t callid, ipc_call_t *call)
101{
102 nic_iface_t *nic_iface = (nic_iface_t *) iface;
103 assert(nic_iface->get_address);
104
105 nic_address_t address;
[acdb5bac]106 memset(&address, 0, sizeof(nic_address_t));
[609243f4]107
108 int rc = nic_iface->get_address(dev, &address);
109 if (rc == EOK) {
110 size_t max_len;
111 ipc_callid_t data_callid;
112
113 /* All errors will be translated into EPARTY anyway */
114 if (!async_data_read_receive(&data_callid, &max_len)) {
115 async_answer_0(data_callid, EINVAL);
116 async_answer_0(callid, EINVAL);
117 return;
118 }
119
120 if (max_len != sizeof(nic_address_t)) {
121 async_answer_0(data_callid, ELIMIT);
122 async_answer_0(callid, ELIMIT);
123 return;
124 }
125
126 async_data_read_finalize(data_callid, &address,
127 sizeof(nic_address_t));
128 }
129
130 async_answer_0(callid, rc);
131}
132
133static void remote_nic_set_address(ddf_fun_t *dev, void *iface,
134 ipc_callid_t callid, ipc_call_t *call)
135{
136 nic_iface_t *nic_iface = (nic_iface_t *) iface;
137
138 size_t length;
139 ipc_callid_t data_callid;
140 if (!async_data_write_receive(&data_callid, &length)) {
141 async_answer_0(data_callid, EINVAL);
142 async_answer_0(callid, EINVAL);
143 return;
144 }
145
146 if (length > sizeof(nic_address_t)) {
147 async_answer_0(data_callid, ELIMIT);
148 async_answer_0(callid, ELIMIT);
149 return;
150 }
151
152 nic_address_t address;
153 if (async_data_write_finalize(data_callid, &address, length) != EOK) {
154 async_answer_0(callid, EINVAL);
155 return;
156 }
157
158 if (nic_iface->set_address != NULL) {
159 int rc = nic_iface->set_address(dev, &address);
160 async_answer_0(callid, rc);
161 } else
162 async_answer_0(callid, ENOTSUP);
163}
164
165static void remote_nic_get_stats(ddf_fun_t *dev, void *iface,
166 ipc_callid_t callid, ipc_call_t *call)
167{
168 nic_iface_t *nic_iface = (nic_iface_t *) iface;
169 if (nic_iface->get_stats == NULL) {
170 async_answer_0(callid, ENOTSUP);
171 return;
172 }
173
174 nic_device_stats_t stats;
[acdb5bac]175 memset(&stats, 0, sizeof(nic_device_stats_t));
[609243f4]176
177 int rc = nic_iface->get_stats(dev, &stats);
178 if (rc == EOK) {
179 ipc_callid_t data_callid;
180 size_t max_len;
181 if (!async_data_read_receive(&data_callid, &max_len)) {
182 async_answer_0(data_callid, EINVAL);
183 async_answer_0(callid, EINVAL);
184 return;
185 }
186
187 if (max_len < sizeof(nic_device_stats_t)) {
188 async_answer_0(data_callid, ELIMIT);
189 async_answer_0(callid, ELIMIT);
190 return;
191 }
192
193 async_data_read_finalize(data_callid, &stats,
194 sizeof(nic_device_stats_t));
195 }
196
197 async_answer_0(callid, rc);
198}
199
200static void remote_nic_get_device_info(ddf_fun_t *dev, void *iface,
201 ipc_callid_t callid, ipc_call_t *call)
202{
203 nic_iface_t *nic_iface = (nic_iface_t *) iface;
204 if (nic_iface->get_device_info == NULL) {
205 async_answer_0(callid, ENOTSUP);
206 return;
207 }
208
209 nic_device_info_t info;
[acdb5bac]210 memset(&info, 0, sizeof(nic_device_info_t));
[609243f4]211
212 int rc = nic_iface->get_device_info(dev, &info);
213 if (rc == EOK) {
214 ipc_callid_t data_callid;
215 size_t max_len;
216 if (!async_data_read_receive(&data_callid, &max_len)) {
217 async_answer_0(data_callid, EINVAL);
218 async_answer_0(callid, EINVAL);
219 return;
220 }
221
222 if (max_len < sizeof (nic_device_info_t)) {
223 async_answer_0(data_callid, ELIMIT);
224 async_answer_0(callid, ELIMIT);
225 return;
226 }
227
228 async_data_read_finalize(data_callid, &info,
229 sizeof(nic_device_info_t));
230 }
231
232 async_answer_0(callid, rc);
233}
234
235static void remote_nic_get_cable_state(ddf_fun_t *dev, void *iface,
236 ipc_callid_t callid, ipc_call_t *call)
237{
238 nic_iface_t *nic_iface = (nic_iface_t *) iface;
239 if (nic_iface->get_cable_state == NULL) {
240 async_answer_0(callid, ENOTSUP);
241 return;
242 }
243
244 nic_cable_state_t cs = NIC_CS_UNKNOWN;
245
246 int rc = nic_iface->get_cable_state(dev, &cs);
247 async_answer_1(callid, rc, (sysarg_t) cs);
248}
249
250static void remote_nic_get_operation_mode(ddf_fun_t *dev, void *iface,
251 ipc_callid_t callid, ipc_call_t *call)
252{
253 nic_iface_t *nic_iface = (nic_iface_t *) iface;
254 if (nic_iface->get_operation_mode == NULL) {
255 async_answer_0(callid, ENOTSUP);
256 return;
257 }
258
259 int speed = 0;
260 nic_channel_mode_t duplex = NIC_CM_UNKNOWN;
261 nic_role_t role = NIC_ROLE_UNKNOWN;
262
263 int rc = nic_iface->get_operation_mode(dev, &speed, &duplex, &role);
264 async_answer_3(callid, rc, (sysarg_t) speed, (sysarg_t) duplex,
265 (sysarg_t) role);
266}
267
268static void remote_nic_set_operation_mode(ddf_fun_t *dev, void *iface,
269 ipc_callid_t callid, ipc_call_t *call)
270{
271 nic_iface_t *nic_iface = (nic_iface_t *) iface;
272 if (nic_iface->set_operation_mode == NULL) {
273 async_answer_0(callid, ENOTSUP);
274 return;
275 }
276
277 int speed = (int) IPC_GET_ARG2(*call);
278 nic_channel_mode_t duplex = (nic_channel_mode_t) IPC_GET_ARG3(*call);
279 nic_role_t role = (nic_role_t) IPC_GET_ARG4(*call);
280
281 int rc = nic_iface->set_operation_mode(dev, speed, duplex, role);
282 async_answer_0(callid, rc);
283}
284
285static void remote_nic_autoneg_enable(ddf_fun_t *dev, void *iface,
286 ipc_callid_t callid, ipc_call_t *call)
287{
288 nic_iface_t *nic_iface = (nic_iface_t *) iface;
289 if (nic_iface->autoneg_enable == NULL) {
290 async_answer_0(callid, ENOTSUP);
291 return;
292 }
293
294 uint32_t advertisement = (uint32_t) IPC_GET_ARG2(*call);
295
296 int rc = nic_iface->autoneg_enable(dev, advertisement);
297 async_answer_0(callid, rc);
298}
299
300static void remote_nic_autoneg_disable(ddf_fun_t *dev, void *iface,
301 ipc_callid_t callid, ipc_call_t *call)
302{
303 nic_iface_t *nic_iface = (nic_iface_t *) iface;
304 if (nic_iface->autoneg_disable == NULL) {
305 async_answer_0(callid, ENOTSUP);
306 return;
307 }
308
309 int rc = nic_iface->autoneg_disable(dev);
310 async_answer_0(callid, rc);
311}
312
313static void remote_nic_autoneg_probe(ddf_fun_t *dev, void *iface,
314 ipc_callid_t callid, ipc_call_t *call)
315{
316 nic_iface_t *nic_iface = (nic_iface_t *) iface;
317 if (nic_iface->autoneg_probe == NULL) {
318 async_answer_0(callid, ENOTSUP);
319 return;
320 }
321
322 uint32_t our_adv = 0;
323 uint32_t their_adv = 0;
324 nic_result_t result = NIC_RESULT_NOT_AVAILABLE;
325 nic_result_t their_result = NIC_RESULT_NOT_AVAILABLE;
326
327 int rc = nic_iface->autoneg_probe(dev, &our_adv, &their_adv, &result,
328 &their_result);
329 async_answer_4(callid, rc, our_adv, their_adv, (sysarg_t) result,
330 (sysarg_t) their_result);
331}
332
333static void remote_nic_autoneg_restart(ddf_fun_t *dev, void *iface,
334 ipc_callid_t callid, ipc_call_t *call)
335{
336 nic_iface_t *nic_iface = (nic_iface_t *) iface;
337 if (nic_iface->autoneg_restart == NULL) {
338 async_answer_0(callid, ENOTSUP);
339 return;
340 }
341
342 int rc = nic_iface->autoneg_restart(dev);
343 async_answer_0(callid, rc);
344}
345
346static void remote_nic_get_pause(ddf_fun_t *dev, void *iface,
347 ipc_callid_t callid, ipc_call_t *call)
348{
349 nic_iface_t *nic_iface = (nic_iface_t *) iface;
350 if (nic_iface->get_pause == NULL) {
351 async_answer_0(callid, ENOTSUP);
352 return;
353 }
354
355 nic_result_t we_send;
356 nic_result_t we_receive;
357 uint16_t pause;
358
359 int rc = nic_iface->get_pause(dev, &we_send, &we_receive, &pause);
360 async_answer_3(callid, rc, we_send, we_receive, pause);
361}
362
363static void remote_nic_set_pause(ddf_fun_t *dev, void *iface,
364 ipc_callid_t callid, ipc_call_t *call)
365{
366 nic_iface_t *nic_iface = (nic_iface_t *) iface;
367 if (nic_iface->set_pause == NULL) {
368 async_answer_0(callid, ENOTSUP);
369 return;
370 }
371
372 int allow_send = (int) IPC_GET_ARG2(*call);
373 int allow_receive = (int) IPC_GET_ARG3(*call);
374 uint16_t pause = (uint16_t) IPC_GET_ARG4(*call);
375
376 int rc = nic_iface->set_pause(dev, allow_send, allow_receive,
377 pause);
378 async_answer_0(callid, rc);
379}
380
381static void remote_nic_unicast_get_mode(ddf_fun_t *dev, void *iface,
382 ipc_callid_t callid, ipc_call_t *call)
383{
384 nic_iface_t *nic_iface = (nic_iface_t *) iface;
385 if (nic_iface->unicast_get_mode == NULL) {
386 async_answer_0(callid, ENOTSUP);
387 return;
388 }
389
390 size_t max_count = IPC_GET_ARG2(*call);
391 nic_address_t *address_list = NULL;
392
393 if (max_count != 0) {
394 address_list = malloc(max_count * sizeof (nic_address_t));
395 if (!address_list) {
396 async_answer_0(callid, ENOMEM);
397 return;
398 }
399 }
400
[acdb5bac]401 memset(address_list, 0, max_count * sizeof(nic_address_t));
[609243f4]402 nic_unicast_mode_t mode = NIC_UNICAST_DEFAULT;
403 size_t address_count = 0;
404
405 int rc = nic_iface->unicast_get_mode(dev, &mode, max_count, address_list,
406 &address_count);
407
408 if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
409 free(address_list);
410 async_answer_2(callid, rc, mode, address_count);
411 return;
412 }
413
414 ipc_callid_t data_callid;
415 size_t max_len;
416 if (!async_data_read_receive(&data_callid, &max_len)) {
417 async_answer_0(data_callid, EINVAL);
418 async_answer_2(callid, rc, mode, address_count);
419 free(address_list);
420 return;
421 }
422
423 if (max_len > address_count * sizeof(nic_address_t))
424 max_len = address_count * sizeof(nic_address_t);
425
426 if (max_len > max_count * sizeof(nic_address_t))
427 max_len = max_count * sizeof(nic_address_t);
428
429 async_data_read_finalize(data_callid, address_list, max_len);
430 async_answer_0(data_callid, EINVAL);
431
432 free(address_list);
433 async_answer_2(callid, rc, mode, address_count);
434}
435
436static void remote_nic_unicast_set_mode(ddf_fun_t *dev, void *iface,
437 ipc_callid_t callid, ipc_call_t *call)
438{
439 nic_iface_t *nic_iface = (nic_iface_t *) iface;
440
441 size_t length;
442 nic_unicast_mode_t mode = IPC_GET_ARG2(*call);
443 size_t address_count = IPC_GET_ARG3(*call);
444 nic_address_t *address_list = NULL;
445
446 if (address_count) {
447 ipc_callid_t data_callid;
448 if (!async_data_write_receive(&data_callid, &length)) {
449 async_answer_0(data_callid, EINVAL);
450 async_answer_0(callid, EINVAL);
451 return;
452 }
453
454 if (length != address_count * sizeof(nic_address_t)) {
455 async_answer_0(data_callid, ELIMIT);
456 async_answer_0(callid, ELIMIT);
457 return;
458 }
459
460 address_list = malloc(length);
461 if (address_list == NULL) {
462 async_answer_0(data_callid, ENOMEM);
463 async_answer_0(callid, ENOMEM);
464 return;
465 }
466
467 if (async_data_write_finalize(data_callid, address_list,
468 length) != EOK) {
469 async_answer_0(callid, EINVAL);
470 free(address_list);
471 return;
472 }
473 }
474
475 if (nic_iface->unicast_set_mode != NULL) {
476 int rc = nic_iface->unicast_set_mode(dev, mode, address_list,
477 address_count);
478 async_answer_0(callid, rc);
479 } else
480 async_answer_0(callid, ENOTSUP);
481
482 free(address_list);
483}
484
485static void remote_nic_multicast_get_mode(ddf_fun_t *dev, void *iface,
486 ipc_callid_t callid, ipc_call_t *call)
487{
488 nic_iface_t *nic_iface = (nic_iface_t *) iface;
489 if (nic_iface->multicast_get_mode == NULL) {
490 async_answer_0(callid, ENOTSUP);
491 return;
492 }
493
494 size_t max_count = IPC_GET_ARG2(*call);
495 nic_address_t *address_list = NULL;
496
497 if (max_count != 0) {
498 address_list = malloc(max_count * sizeof(nic_address_t));
499 if (!address_list) {
500 async_answer_0(callid, ENOMEM);
501 return;
502 }
503 }
504
[acdb5bac]505 memset(address_list, 0, max_count * sizeof(nic_address_t));
[609243f4]506 nic_multicast_mode_t mode = NIC_MULTICAST_BLOCKED;
507 size_t address_count = 0;
508
509 int rc = nic_iface->multicast_get_mode(dev, &mode, max_count, address_list,
510 &address_count);
511
512
513 if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
514 free(address_list);
515 async_answer_2(callid, rc, mode, address_count);
516 return;
517 }
518
519 ipc_callid_t data_callid;
520 size_t max_len;
521 if (!async_data_read_receive(&data_callid, &max_len)) {
522 async_answer_0(data_callid, EINVAL);
523 async_answer_2(callid, rc, mode, address_count);
524 free(address_list);
525 return;
526 }
527
528 if (max_len > address_count * sizeof(nic_address_t))
529 max_len = address_count * sizeof(nic_address_t);
530
531 if (max_len > max_count * sizeof(nic_address_t))
532 max_len = max_count * sizeof(nic_address_t);
533
534 async_data_read_finalize(data_callid, address_list, max_len);
535
536 free(address_list);
537 async_answer_2(callid, rc, mode, address_count);
538}
539
540static void remote_nic_multicast_set_mode(ddf_fun_t *dev, void *iface,
541 ipc_callid_t callid, ipc_call_t *call)
542{
543 nic_iface_t *nic_iface = (nic_iface_t *) iface;
544
545 nic_multicast_mode_t mode = IPC_GET_ARG2(*call);
546 size_t address_count = IPC_GET_ARG3(*call);
547 nic_address_t *address_list = NULL;
548
549 if (address_count) {
550 ipc_callid_t data_callid;
551 size_t length;
552 if (!async_data_write_receive(&data_callid, &length)) {
553 async_answer_0(data_callid, EINVAL);
554 async_answer_0(callid, EINVAL);
555 return;
556 }
557
558 if (length != address_count * sizeof (nic_address_t)) {
559 async_answer_0(data_callid, ELIMIT);
560 async_answer_0(callid, ELIMIT);
561 return;
562 }
563
564 address_list = malloc(length);
565 if (address_list == NULL) {
566 async_answer_0(data_callid, ENOMEM);
567 async_answer_0(callid, ENOMEM);
568 return;
569 }
570
571 if (async_data_write_finalize(data_callid, address_list,
572 length) != EOK) {
573 async_answer_0(callid, EINVAL);
574 free(address_list);
575 return;
576 }
577 }
578
579 if (nic_iface->multicast_set_mode != NULL) {
580 int rc = nic_iface->multicast_set_mode(dev, mode, address_list,
581 address_count);
582 async_answer_0(callid, rc);
583 } else
584 async_answer_0(callid, ENOTSUP);
585
586 free(address_list);
587}
588
589static void remote_nic_broadcast_get_mode(ddf_fun_t *dev, void *iface,
590 ipc_callid_t callid, ipc_call_t *call)
591{
592 nic_iface_t *nic_iface = (nic_iface_t *) iface;
593 if (nic_iface->broadcast_get_mode == NULL) {
594 async_answer_0(callid, ENOTSUP);
595 return;
596 }
597
598 nic_broadcast_mode_t mode = NIC_BROADCAST_ACCEPTED;
599
600 int rc = nic_iface->broadcast_get_mode(dev, &mode);
601 async_answer_1(callid, rc, mode);
602}
603
604static void remote_nic_broadcast_set_mode(ddf_fun_t *dev, void *iface,
605 ipc_callid_t callid, ipc_call_t *call)
606{
607 nic_iface_t *nic_iface = (nic_iface_t *) iface;
608 if (nic_iface->broadcast_set_mode == NULL) {
609 async_answer_0(callid, ENOTSUP);
610 return;
611 }
612
613 nic_broadcast_mode_t mode = IPC_GET_ARG2(*call);
614
615 int rc = nic_iface->broadcast_set_mode(dev, mode);
616 async_answer_0(callid, rc);
617}
618
619static void remote_nic_defective_get_mode(ddf_fun_t *dev, void *iface,
620 ipc_callid_t callid, ipc_call_t *call)
621{
622 nic_iface_t *nic_iface = (nic_iface_t *) iface;
623 if (nic_iface->defective_get_mode == NULL) {
624 async_answer_0(callid, ENOTSUP);
625 return;
626 }
627
628 uint32_t mode = 0;
629
630 int rc = nic_iface->defective_get_mode(dev, &mode);
631 async_answer_1(callid, rc, mode);
632}
633
634static void remote_nic_defective_set_mode(ddf_fun_t *dev, void *iface,
635 ipc_callid_t callid, ipc_call_t *call)
636{
637 nic_iface_t *nic_iface = (nic_iface_t *) iface;
638 if (nic_iface->defective_set_mode == NULL) {
639 async_answer_0(callid, ENOTSUP);
640 return;
641 }
642
643 uint32_t mode = IPC_GET_ARG2(*call);
644
645 int rc = nic_iface->defective_set_mode(dev, mode);
646 async_answer_0(callid, rc);
647}
648
649static void remote_nic_blocked_sources_get(ddf_fun_t *dev, void *iface,
650 ipc_callid_t callid, ipc_call_t *call)
651{
652 nic_iface_t *nic_iface = (nic_iface_t *) iface;
653 if (nic_iface->blocked_sources_get == NULL) {
654 async_answer_0(callid, ENOTSUP);
655 return;
656 }
657
658 size_t max_count = IPC_GET_ARG2(*call);
659 nic_address_t *address_list = NULL;
660
661 if (max_count != 0) {
662 address_list = malloc(max_count * sizeof(nic_address_t));
663 if (!address_list) {
664 async_answer_0(callid, ENOMEM);
665 return;
666 }
667 }
668
[acdb5bac]669 memset(address_list, 0, max_count * sizeof(nic_address_t));
[609243f4]670 size_t address_count = 0;
671
672 int rc = nic_iface->blocked_sources_get(dev, max_count, address_list,
673 &address_count);
674
675 if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
676 async_answer_1(callid, rc, address_count);
677 free(address_list);
678 return;
679 }
680
681 ipc_callid_t data_callid;
682 size_t max_len;
683 if (!async_data_read_receive(&data_callid, &max_len)) {
684 async_answer_0(data_callid, EINVAL);
685 async_answer_1(callid, rc, address_count);
686 free(address_list);
687 return;
688 }
689
690 if (max_len > address_count * sizeof(nic_address_t))
691 max_len = address_count * sizeof(nic_address_t);
692
693 if (max_len > max_count * sizeof(nic_address_t))
694 max_len = max_count * sizeof(nic_address_t);
695
696 async_data_read_finalize(data_callid, address_list, max_len);
697 async_answer_0(data_callid, EINVAL);
698
699 free(address_list);
700 async_answer_1(callid, rc, address_count);
701}
702
703static void remote_nic_blocked_sources_set(ddf_fun_t *dev, void *iface,
704 ipc_callid_t callid, ipc_call_t *call)
705{
706 nic_iface_t *nic_iface = (nic_iface_t *) iface;
707
708 size_t length;
709 size_t address_count = IPC_GET_ARG2(*call);
710 nic_address_t *address_list = NULL;
711
712 if (address_count) {
713 ipc_callid_t data_callid;
714 if (!async_data_write_receive(&data_callid, &length)) {
715 async_answer_0(data_callid, EINVAL);
716 async_answer_0(callid, EINVAL);
717 return;
718 }
719
720 if (length != address_count * sizeof(nic_address_t)) {
721 async_answer_0(data_callid, ELIMIT);
722 async_answer_0(callid, ELIMIT);
723 return;
724 }
725
726 address_list = malloc(length);
727 if (address_list == NULL) {
728 async_answer_0(data_callid, ENOMEM);
729 async_answer_0(callid, ENOMEM);
730 return;
731 }
732
733 if (async_data_write_finalize(data_callid, address_list,
734 length) != EOK) {
735 async_answer_0(callid, EINVAL);
736 free(address_list);
737 return;
738 }
739 }
740
741 if (nic_iface->blocked_sources_set != NULL) {
742 int rc = nic_iface->blocked_sources_set(dev, address_list,
743 address_count);
744 async_answer_0(callid, rc);
745 } else
746 async_answer_0(callid, ENOTSUP);
747
748 free(address_list);
749}
750
751static void remote_nic_vlan_get_mask(ddf_fun_t *dev, void *iface,
752 ipc_callid_t callid, ipc_call_t *call)
753{
754 nic_iface_t *nic_iface = (nic_iface_t *) iface;
755 if (nic_iface->vlan_get_mask == NULL) {
756 async_answer_0(callid, ENOTSUP);
757 return;
758 }
759
760 nic_vlan_mask_t vlan_mask;
[acdb5bac]761 memset(&vlan_mask, 0, sizeof(nic_vlan_mask_t));
[609243f4]762
763 int rc = nic_iface->vlan_get_mask(dev, &vlan_mask);
764 if (rc == EOK) {
765 ipc_callid_t data_callid;
766 size_t max_len;
767 if (!async_data_read_receive(&data_callid, &max_len)) {
768 async_answer_0(data_callid, EINVAL);
769 async_answer_0(callid, EINVAL);
770 return;
771 }
772
773 if (max_len != sizeof(nic_vlan_mask_t)) {
774 async_answer_0(data_callid, EINVAL);
775 async_answer_0(callid, EINVAL);
776 return;
777 }
778
779 async_data_read_finalize(data_callid, &vlan_mask, max_len);
780 }
781
782 async_answer_0(callid, rc);
783}
784
785static void remote_nic_vlan_set_mask(ddf_fun_t *dev, void *iface,
786 ipc_callid_t callid, ipc_call_t *call)
787{
788 nic_iface_t *nic_iface = (nic_iface_t *) iface;
789
790 nic_vlan_mask_t vlan_mask;
791 nic_vlan_mask_t *vlan_mask_pointer = NULL;
792 bool vlan_mask_set = (bool) IPC_GET_ARG2(*call);
793
794 if (vlan_mask_set) {
795 ipc_callid_t data_callid;
796 size_t length;
797 if (!async_data_write_receive(&data_callid, &length)) {
798 async_answer_0(data_callid, EINVAL);
799 async_answer_0(callid, EINVAL);
800 return;
801 }
802
803 if (length != sizeof(nic_vlan_mask_t)) {
804 async_answer_0(data_callid, ELIMIT);
805 async_answer_0(callid, ELIMIT);
806 return;
807 }
808
809 if (async_data_write_finalize(data_callid, &vlan_mask,
810 length) != EOK) {
811 async_answer_0(callid, EINVAL);
812 return;
813 }
814
815 vlan_mask_pointer = &vlan_mask;
816 }
817
818 if (nic_iface->vlan_set_mask != NULL) {
819 int rc = nic_iface->vlan_set_mask(dev, vlan_mask_pointer);
820 async_answer_0(callid, rc);
821 } else
822 async_answer_0(callid, ENOTSUP);
823}
824
825static void remote_nic_vlan_set_tag(ddf_fun_t *dev, void *iface,
826 ipc_callid_t callid, ipc_call_t *call)
827{
828 nic_iface_t *nic_iface = (nic_iface_t *) iface;
829
830 if (nic_iface->vlan_set_tag == NULL) {
831 async_answer_0(callid, ENOTSUP);
832 return;
833 }
834
835 uint16_t tag = (uint16_t) IPC_GET_ARG2(*call);
[fd6bd6d]836 bool add = (int) IPC_GET_ARG3(*call);
837 bool strip = (int) IPC_GET_ARG4(*call);
[609243f4]838
839 int rc = nic_iface->vlan_set_tag(dev, tag, add, strip);
840 async_answer_0(callid, rc);
841}
842
843static void remote_nic_wol_virtue_add(ddf_fun_t *dev, void *iface,
844 ipc_callid_t callid, ipc_call_t *call)
845{
846 nic_iface_t *nic_iface = (nic_iface_t *) iface;
847
848 int send_data = (int) IPC_GET_ARG3(*call);
849 ipc_callid_t data_callid;
850
851 if (nic_iface->wol_virtue_add == NULL) {
852 if (send_data) {
853 async_data_write_receive(&data_callid, NULL);
854 async_answer_0(data_callid, ENOTSUP);
855 }
856
857 async_answer_0(callid, ENOTSUP);
858 }
859
860 size_t length = 0;
861 void *data = NULL;
862
863 if (send_data) {
864 if (!async_data_write_receive(&data_callid, &length)) {
865 async_answer_0(data_callid, EINVAL);
866 async_answer_0(callid, EINVAL);
867 return;
868 }
869
870 data = malloc(length);
871 if (data == NULL) {
872 async_answer_0(data_callid, ENOMEM);
873 async_answer_0(callid, ENOMEM);
874 return;
875 }
876
877 if (async_data_write_finalize(data_callid, data,
878 length) != EOK) {
879 async_answer_0(callid, EINVAL);
880 free(data);
881 return;
882 }
883 }
884
885 nic_wv_id_t id = 0;
886 nic_wv_type_t type = (nic_wv_type_t) IPC_GET_ARG2(*call);
887
888 int rc = nic_iface->wol_virtue_add(dev, type, data, length, &id);
889 async_answer_1(callid, rc, (sysarg_t) id);
890 free(data);
891}
892
893static void remote_nic_wol_virtue_remove(ddf_fun_t *dev, void *iface,
894 ipc_callid_t callid, ipc_call_t *call)
895{
896 nic_iface_t *nic_iface = (nic_iface_t *) iface;
897
898 if (nic_iface->wol_virtue_remove == NULL) {
899 async_answer_0(callid, ENOTSUP);
900 return;
901 }
902
903 nic_wv_id_t id = (nic_wv_id_t) IPC_GET_ARG2(*call);
904
905 int rc = nic_iface->wol_virtue_remove(dev, id);
906 async_answer_0(callid, rc);
907}
908
909static void remote_nic_wol_virtue_probe(ddf_fun_t *dev, void *iface,
910 ipc_callid_t callid, ipc_call_t *call)
911{
912 nic_iface_t *nic_iface = (nic_iface_t *) iface;
913
914 if (nic_iface->wol_virtue_probe == NULL) {
915 async_answer_0(callid, ENOTSUP);
916 return;
917 }
918
919 nic_wv_id_t id = (nic_wv_id_t) IPC_GET_ARG2(*call);
920 size_t max_length = IPC_GET_ARG3(*call);
921 nic_wv_type_t type = NIC_WV_NONE;
922 size_t length = 0;
923 ipc_callid_t data_callid;
924 void *data = NULL;
925
926 if (max_length != 0) {
927 data = malloc(max_length);
928 if (data == NULL) {
929 async_answer_0(callid, ENOMEM);
930 return;
931 }
932 }
933
[acdb5bac]934 memset(data, 0, max_length);
[609243f4]935
936 int rc = nic_iface->wol_virtue_probe(dev, id, &type, max_length,
937 data, &length);
938
939 if ((max_length != 0) && (length != 0)) {
940 size_t req_length;
941 if (!async_data_read_receive(&data_callid, &req_length)) {
942 async_answer_0(data_callid, EINVAL);
943 async_answer_0(callid, EINVAL);
944 free(data);
945 return;
946 }
947
948 if (req_length > length)
949 req_length = length;
950
951 if (req_length > max_length)
952 req_length = max_length;
953
954 async_data_read_finalize(data_callid, data, req_length);
955 }
956
957 async_answer_2(callid, rc, (sysarg_t) type, (sysarg_t) length);
958 free(data);
959}
960
961static void remote_nic_wol_virtue_list(ddf_fun_t *dev, void *iface,
962 ipc_callid_t callid, ipc_call_t *call)
963{
964 nic_iface_t *nic_iface = (nic_iface_t *) iface;
965 if (nic_iface->wol_virtue_list == NULL) {
966 async_answer_0(callid, ENOTSUP);
967 return;
968 }
969
970 nic_wv_type_t type = (nic_wv_type_t) IPC_GET_ARG2(*call);
971 size_t max_count = IPC_GET_ARG3(*call);
972 size_t count = 0;
973 nic_wv_id_t *id_list = NULL;
974 ipc_callid_t data_callid;
975
976 if (max_count != 0) {
977 id_list = malloc(max_count * sizeof(nic_wv_id_t));
978 if (id_list == NULL) {
979 async_answer_0(callid, ENOMEM);
980 return;
981 }
982 }
983
[acdb5bac]984 memset(id_list, 0, max_count * sizeof (nic_wv_id_t));
[609243f4]985
986 int rc = nic_iface->wol_virtue_list(dev, type, max_count, id_list,
987 &count);
988
989 if ((max_count != 0) && (count != 0)) {
990 size_t req_length;
991 if (!async_data_read_receive(&data_callid, &req_length)) {
992 async_answer_0(data_callid, EINVAL);
993 async_answer_0(callid, EINVAL);
994 free(id_list);
995 return;
996 }
997
998 if (req_length > count * sizeof(nic_wv_id_t))
999 req_length = count * sizeof(nic_wv_id_t);
1000
1001 if (req_length > max_count * sizeof(nic_wv_id_t))
1002 req_length = max_count * sizeof(nic_wv_id_t);
1003
1004 rc = async_data_read_finalize(data_callid, id_list, req_length);
1005 }
1006
1007 async_answer_1(callid, rc, (sysarg_t) count);
1008 free(id_list);
1009}
1010
1011static void remote_nic_wol_virtue_get_caps(ddf_fun_t *dev, void *iface,
1012 ipc_callid_t callid, ipc_call_t *call)
1013{
1014 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1015 if (nic_iface->wol_virtue_get_caps == NULL) {
1016 async_answer_0(callid, ENOTSUP);
1017 return;
1018 }
1019
1020 int count = -1;
1021 nic_wv_type_t type = (nic_wv_type_t) IPC_GET_ARG2(*call);
1022
1023 int rc = nic_iface->wol_virtue_get_caps(dev, type, &count);
1024 async_answer_1(callid, rc, (sysarg_t) count);
1025}
1026
1027static void remote_nic_wol_load_info(ddf_fun_t *dev, void *iface,
1028 ipc_callid_t callid, ipc_call_t *call)
1029{
1030 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1031 if (nic_iface->wol_load_info == NULL) {
1032 async_answer_0(callid, ENOTSUP);
1033 return;
1034 }
1035
1036 size_t max_length = (size_t) IPC_GET_ARG2(*call);
1037 size_t frame_length = 0;
1038 nic_wv_type_t type = NIC_WV_NONE;
1039 uint8_t *data = NULL;
1040
1041 if (max_length != 0) {
1042 data = malloc(max_length);
1043 if (data == NULL) {
1044 async_answer_0(callid, ENOMEM);
1045 return;
1046 }
1047 }
1048
[acdb5bac]1049 memset(data, 0, max_length);
[609243f4]1050
1051 int rc = nic_iface->wol_load_info(dev, &type, max_length, data,
1052 &frame_length);
1053 if (rc == EOK) {
1054 ipc_callid_t data_callid;
1055 size_t req_length;
1056 if (!async_data_read_receive(&data_callid, &req_length)) {
1057 async_answer_0(data_callid, EINVAL);
1058 async_answer_0(callid, EINVAL);
1059 free(data);
1060 return;
1061 }
1062
1063 req_length = req_length > max_length ? max_length : req_length;
1064 req_length = req_length > frame_length ? frame_length : req_length;
1065 async_data_read_finalize(data_callid, data, req_length);
1066 }
1067
1068 async_answer_2(callid, rc, (sysarg_t) type, (sysarg_t) frame_length);
1069 free(data);
1070}
1071
1072static void remote_nic_offload_probe(ddf_fun_t *dev, void *iface,
1073 ipc_callid_t callid, ipc_call_t *call)
1074{
1075 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1076 if (nic_iface->offload_probe == NULL) {
1077 async_answer_0(callid, ENOTSUP);
1078 return;
1079 }
1080
1081 uint32_t supported = 0;
1082 uint32_t active = 0;
1083
1084 int rc = nic_iface->offload_probe(dev, &supported, &active);
1085 async_answer_2(callid, rc, supported, active);
1086}
1087
1088static void remote_nic_offload_set(ddf_fun_t *dev, void *iface,
1089 ipc_callid_t callid, ipc_call_t *call)
1090{
1091 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1092 if (nic_iface->offload_set == NULL) {
1093 async_answer_0(callid, ENOTSUP);
1094 return;
1095 }
1096
1097 uint32_t mask = (uint32_t) IPC_GET_ARG2(*call);
1098 uint32_t active = (uint32_t) IPC_GET_ARG3(*call);
1099
1100 int rc = nic_iface->offload_set(dev, mask, active);
1101 async_answer_0(callid, rc);
1102}
1103
1104static void remote_nic_poll_get_mode(ddf_fun_t *dev, void *iface,
1105 ipc_callid_t callid, ipc_call_t *call)
1106{
1107 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1108 if (nic_iface->poll_get_mode == NULL) {
1109 async_answer_0(callid, ENOTSUP);
1110 return;
1111 }
1112
1113 nic_poll_mode_t mode = NIC_POLL_IMMEDIATE;
1114 int request_data = IPC_GET_ARG2(*call);
1115 struct timeval period = {
1116 .tv_sec = 0,
1117 .tv_usec = 0
1118 };
1119
1120 int rc = nic_iface->poll_get_mode(dev, &mode, &period);
1121 if ((rc == EOK) && (request_data)) {
1122 size_t max_len;
1123 ipc_callid_t data_callid;
1124
1125 if (!async_data_read_receive(&data_callid, &max_len)) {
1126 async_answer_0(data_callid, EINVAL);
1127 async_answer_0(callid, EINVAL);
1128 return;
1129 }
1130
1131 if (max_len != sizeof(struct timeval)) {
1132 async_answer_0(data_callid, ELIMIT);
1133 async_answer_0(callid, ELIMIT);
1134 return;
1135 }
1136
1137 async_data_read_finalize(data_callid, &period,
1138 sizeof(struct timeval));
1139 }
1140
1141 async_answer_1(callid, rc, (sysarg_t) mode);
1142}
1143
1144static void remote_nic_poll_set_mode(ddf_fun_t *dev, void *iface,
1145 ipc_callid_t callid, ipc_call_t *call)
1146{
1147 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1148
1149 nic_poll_mode_t mode = IPC_GET_ARG2(*call);
1150 int has_period = IPC_GET_ARG3(*call);
1151 struct timeval period_buf;
1152 struct timeval *period = NULL;
1153 size_t length;
1154
1155 if (has_period) {
1156 ipc_callid_t data_callid;
1157 if (!async_data_write_receive(&data_callid, &length)) {
1158 async_answer_0(data_callid, EINVAL);
1159 async_answer_0(callid, EINVAL);
1160 return;
1161 }
1162
1163 if (length != sizeof(struct timeval)) {
1164 async_answer_0(data_callid, ELIMIT);
1165 async_answer_0(callid, ELIMIT);
1166 return;
1167 }
1168
1169 period = &period_buf;
1170 if (async_data_write_finalize(data_callid, period,
1171 length) != EOK) {
1172 async_answer_0(callid, EINVAL);
1173 return;
1174 }
1175 }
1176
1177 if (nic_iface->poll_set_mode != NULL) {
1178 int rc = nic_iface->poll_set_mode(dev, mode, period);
1179 async_answer_0(callid, rc);
1180 } else
1181 async_answer_0(callid, ENOTSUP);
1182}
1183
1184static void remote_nic_poll_now(ddf_fun_t *dev, void *iface,
1185 ipc_callid_t callid, ipc_call_t *call)
1186{
1187 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1188 if (nic_iface->poll_now == NULL) {
1189 async_answer_0(callid, ENOTSUP);
1190 return;
1191 }
1192
1193 int rc = nic_iface->poll_now(dev);
1194 async_answer_0(callid, rc);
1195}
1196
1197/** Remote NIC interface operations.
1198 *
1199 */
1200static remote_iface_func_ptr_t remote_nic_iface_ops[] = {
[6d8455d]1201 &remote_nic_send_frame,
[8d7ec69d]1202 &remote_nic_callback_create,
[609243f4]1203 &remote_nic_get_state,
1204 &remote_nic_set_state,
1205 &remote_nic_get_address,
1206 &remote_nic_set_address,
1207 &remote_nic_get_stats,
1208 &remote_nic_get_device_info,
1209 &remote_nic_get_cable_state,
1210 &remote_nic_get_operation_mode,
1211 &remote_nic_set_operation_mode,
1212 &remote_nic_autoneg_enable,
1213 &remote_nic_autoneg_disable,
1214 &remote_nic_autoneg_probe,
1215 &remote_nic_autoneg_restart,
1216 &remote_nic_get_pause,
1217 &remote_nic_set_pause,
1218 &remote_nic_unicast_get_mode,
1219 &remote_nic_unicast_set_mode,
1220 &remote_nic_multicast_get_mode,
1221 &remote_nic_multicast_set_mode,
1222 &remote_nic_broadcast_get_mode,
1223 &remote_nic_broadcast_set_mode,
1224 &remote_nic_defective_get_mode,
1225 &remote_nic_defective_set_mode,
1226 &remote_nic_blocked_sources_get,
1227 &remote_nic_blocked_sources_set,
1228 &remote_nic_vlan_get_mask,
1229 &remote_nic_vlan_set_mask,
1230 &remote_nic_vlan_set_tag,
1231 &remote_nic_wol_virtue_add,
1232 &remote_nic_wol_virtue_remove,
1233 &remote_nic_wol_virtue_probe,
1234 &remote_nic_wol_virtue_list,
1235 &remote_nic_wol_virtue_get_caps,
1236 &remote_nic_wol_load_info,
1237 &remote_nic_offload_probe,
1238 &remote_nic_offload_set,
1239 &remote_nic_poll_get_mode,
1240 &remote_nic_poll_set_mode,
1241 &remote_nic_poll_now
1242};
1243
1244/** Remote NIC interface structure.
1245 *
1246 * Interface for processing request from remote
1247 * clients addressed to the NIC interface.
1248 *
1249 */
1250remote_iface_t remote_nic_iface = {
1251 .method_count = sizeof(remote_nic_iface_ops) /
1252 sizeof(remote_iface_func_ptr_t),
1253 .methods = remote_nic_iface_ops
1254};
1255
1256/**
1257 * @}
1258 */
Note: See TracBrowser for help on using the repository browser.