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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since fc22069 was b688fd8, checked in by Martin Decky <martin@…>, 10 years ago

gradually introduce async ports, initial phase

The initial phase is to reimplement the traditional async client connections as an untyped fallback port. This creates the possibility to introduce ports typed by interface type gradually in later changesets.

  • Property mode set to 100644
File size: 65.3 KB
Line 
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 <macros.h>
43
44#include "ops/nic.h"
45#include "nic_iface.h"
46
47typedef enum {
48 NIC_SEND_MESSAGE = 0,
49 NIC_CALLBACK_CREATE,
50 NIC_GET_STATE,
51 NIC_SET_STATE,
52 NIC_GET_ADDRESS,
53 NIC_SET_ADDRESS,
54 NIC_GET_STATS,
55 NIC_GET_DEVICE_INFO,
56 NIC_GET_CABLE_STATE,
57 NIC_GET_OPERATION_MODE,
58 NIC_SET_OPERATION_MODE,
59 NIC_AUTONEG_ENABLE,
60 NIC_AUTONEG_DISABLE,
61 NIC_AUTONEG_PROBE,
62 NIC_AUTONEG_RESTART,
63 NIC_GET_PAUSE,
64 NIC_SET_PAUSE,
65 NIC_UNICAST_GET_MODE,
66 NIC_UNICAST_SET_MODE,
67 NIC_MULTICAST_GET_MODE,
68 NIC_MULTICAST_SET_MODE,
69 NIC_BROADCAST_GET_MODE,
70 NIC_BROADCAST_SET_MODE,
71 NIC_DEFECTIVE_GET_MODE,
72 NIC_DEFECTIVE_SET_MODE,
73 NIC_BLOCKED_SOURCES_GET,
74 NIC_BLOCKED_SOURCES_SET,
75 NIC_VLAN_GET_MASK,
76 NIC_VLAN_SET_MASK,
77 NIC_VLAN_SET_TAG,
78 NIC_WOL_VIRTUE_ADD,
79 NIC_WOL_VIRTUE_REMOVE,
80 NIC_WOL_VIRTUE_PROBE,
81 NIC_WOL_VIRTUE_LIST,
82 NIC_WOL_VIRTUE_GET_CAPS,
83 NIC_WOL_LOAD_INFO,
84 NIC_OFFLOAD_PROBE,
85 NIC_OFFLOAD_SET,
86 NIC_POLL_GET_MODE,
87 NIC_POLL_SET_MODE,
88 NIC_POLL_NOW
89} nic_funcs_t;
90
91/** Send frame from NIC
92 *
93 * @param[in] dev_sess
94 * @param[in] data Frame data
95 * @param[in] size Frame size in bytes
96 *
97 * @return EOK If the operation was successfully completed
98 *
99 */
100int nic_send_frame(async_sess_t *dev_sess, void *data, size_t size)
101{
102 async_exch_t *exch = async_exchange_begin(dev_sess);
103
104 ipc_call_t answer;
105 aid_t req = async_send_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
106 NIC_SEND_MESSAGE, &answer);
107 sysarg_t retval = async_data_write_start(exch, data, size);
108
109 async_exchange_end(exch);
110
111 if (retval != EOK) {
112 async_forget(req);
113 return retval;
114 }
115
116 async_wait_for(req, &retval);
117 return retval;
118}
119
120/** Create callback connection from NIC service
121 *
122 * @param[in] dev_sess
123 * @param[in] device_id
124 *
125 * @return EOK If the operation was successfully completed
126 *
127 */
128int nic_callback_create(async_sess_t *dev_sess, async_port_handler_t cfun,
129 void *carg)
130{
131 ipc_call_t answer;
132 int rc;
133 sysarg_t retval;
134
135 async_exch_t *exch = async_exchange_begin(dev_sess);
136 aid_t req = async_send_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
137 NIC_CALLBACK_CREATE, &answer);
138
139 rc = async_connect_to_me(exch, 0, 0, 0, cfun, carg);
140 if (rc != EOK) {
141 async_forget(req);
142 return rc;
143 }
144 async_exchange_end(exch);
145
146 async_wait_for(req, &retval);
147 return (int) retval;
148}
149
150/** Get the current state of the device
151 *
152 * @param[in] dev_sess
153 * @param[out] state Current state
154 *
155 * @return EOK If the operation was successfully completed
156 *
157 */
158int nic_get_state(async_sess_t *dev_sess, nic_device_state_t *state)
159{
160 assert(state);
161
162 sysarg_t _state;
163
164 async_exch_t *exch = async_exchange_begin(dev_sess);
165 int rc = async_req_1_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
166 NIC_GET_STATE, &_state);
167 async_exchange_end(exch);
168
169 *state = (nic_device_state_t) _state;
170
171 return rc;
172}
173
174/** Request the device to change its state
175 *
176 * @param[in] dev_sess
177 * @param[in] state New state
178 *
179 * @return EOK If the operation was successfully completed
180 *
181 */
182int nic_set_state(async_sess_t *dev_sess, nic_device_state_t state)
183{
184 async_exch_t *exch = async_exchange_begin(dev_sess);
185 int rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
186 NIC_SET_STATE, state);
187 async_exchange_end(exch);
188
189 return rc;
190}
191
192/** Request the MAC address of the device
193 *
194 * @param[in] dev_sess
195 * @param[out] address Structure with buffer for the address
196 *
197 * @return EOK If the operation was successfully completed
198 *
199 */
200int nic_get_address(async_sess_t *dev_sess, nic_address_t *address)
201{
202 assert(address);
203
204 async_exch_t *exch = async_exchange_begin(dev_sess);
205 aid_t aid = async_send_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
206 NIC_GET_ADDRESS, NULL);
207 int rc = async_data_read_start(exch, address, sizeof(nic_address_t));
208 async_exchange_end(exch);
209
210 sysarg_t res;
211 async_wait_for(aid, &res);
212
213 if (rc != EOK)
214 return rc;
215
216 return (int) res;
217}
218
219/** Set the address of the device (e.g. MAC on Ethernet)
220 *
221 * @param[in] dev_sess
222 * @param[in] address Pointer to the address
223 *
224 * @return EOK If the operation was successfully completed
225 *
226 */
227int nic_set_address(async_sess_t *dev_sess, const nic_address_t *address)
228{
229 assert(address);
230
231 async_exch_t *exch = async_exchange_begin(dev_sess);
232 aid_t aid = async_send_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
233 NIC_SET_ADDRESS, NULL);
234 int rc = async_data_write_start(exch, address, sizeof(nic_address_t));
235 async_exchange_end(exch);
236
237 sysarg_t res;
238 async_wait_for(aid, &res);
239
240 if (rc != EOK)
241 return rc;
242
243 return (int) res;
244}
245
246/** Request statistic data about NIC operation.
247 *
248 * @param[in] dev_sess
249 * @param[out] stats Structure with the statistics
250 *
251 * @return EOK If the operation was successfully completed
252 *
253 */
254int nic_get_stats(async_sess_t *dev_sess, nic_device_stats_t *stats)
255{
256 assert(stats);
257
258 async_exch_t *exch = async_exchange_begin(dev_sess);
259
260 int rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
261 NIC_GET_STATS);
262 if (rc != EOK) {
263 async_exchange_end(exch);
264 return rc;
265 }
266
267 rc = async_data_read_start(exch, stats, sizeof(nic_device_stats_t));
268
269 async_exchange_end(exch);
270
271 return rc;
272}
273
274/** Request information about the device.
275 *
276 * @see nic_device_info_t
277 *
278 * @param[in] dev_sess
279 * @param[out] device_info Information about the device
280 *
281 * @return EOK If the operation was successfully completed
282 *
283 */
284int nic_get_device_info(async_sess_t *dev_sess, nic_device_info_t *device_info)
285{
286 assert(device_info);
287
288 async_exch_t *exch = async_exchange_begin(dev_sess);
289
290 aid_t aid = async_send_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
291 NIC_GET_DEVICE_INFO, NULL);
292 int rc = async_data_read_start(exch, device_info, sizeof(nic_device_info_t));
293 async_exchange_end(exch);
294
295 sysarg_t res;
296 async_wait_for(aid, &res);
297
298 if (rc != EOK)
299 return rc;
300
301 return (int) res;
302}
303
304/** Request status of the cable (plugged/unplugged)
305 *
306 * @param[in] dev_sess
307 * @param[out] cable_state Current cable state
308 *
309 * @return EOK If the operation was successfully completed
310 *
311 */
312int nic_get_cable_state(async_sess_t *dev_sess, nic_cable_state_t *cable_state)
313{
314 assert(cable_state);
315
316 sysarg_t _cable_state;
317
318 async_exch_t *exch = async_exchange_begin(dev_sess);
319 int rc = async_req_1_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
320 NIC_GET_CABLE_STATE, &_cable_state);
321 async_exchange_end(exch);
322
323 *cable_state = (nic_cable_state_t) _cable_state;
324
325 return rc;
326}
327
328/** Request current operation mode.
329 *
330 * @param[in] dev_sess
331 * @param[out] speed Current operation speed in Mbps. Can be NULL.
332 * @param[out] duplex Full duplex/half duplex. Can be NULL.
333 * @param[out] role Master/slave/auto. Can be NULL.
334 *
335 * @return EOK If the operation was successfully completed
336 *
337 */
338int nic_get_operation_mode(async_sess_t *dev_sess, int *speed,
339 nic_channel_mode_t *duplex, nic_role_t *role)
340{
341 sysarg_t _speed;
342 sysarg_t _duplex;
343 sysarg_t _role;
344
345 async_exch_t *exch = async_exchange_begin(dev_sess);
346 int rc = async_req_1_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
347 NIC_GET_OPERATION_MODE, &_speed, &_duplex, &_role);
348 async_exchange_end(exch);
349
350 if (speed)
351 *speed = (int) _speed;
352
353 if (duplex)
354 *duplex = (nic_channel_mode_t) _duplex;
355
356 if (role)
357 *role = (nic_role_t) _role;
358
359 return rc;
360}
361
362/** Set current operation mode.
363 *
364 * If the NIC has auto-negotiation enabled, this command
365 * disables auto-negotiation and sets the operation mode.
366 *
367 * @param[in] dev_sess
368 * @param[in] speed Operation speed in Mbps
369 * @param[in] duplex Full duplex/half duplex
370 * @param[in] role Master/slave/auto (e.g. in Gbit Ethernet]
371 *
372 * @return EOK If the operation was successfully completed
373 *
374 */
375int nic_set_operation_mode(async_sess_t *dev_sess, int speed,
376 nic_channel_mode_t duplex, nic_role_t role)
377{
378 async_exch_t *exch = async_exchange_begin(dev_sess);
379 int rc = async_req_4_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
380 NIC_SET_OPERATION_MODE, (sysarg_t) speed, (sysarg_t) duplex,
381 (sysarg_t) role);
382 async_exchange_end(exch);
383
384 return rc;
385}
386
387/** Enable auto-negotiation.
388 *
389 * The advertisement argument can only limit some modes,
390 * it can never force the NIC to advertise unsupported modes.
391 *
392 * The allowed modes are defined in "nic/eth_phys.h" in the C library.
393 *
394 * @param[in] dev_sess
395 * @param[in] advertisement Allowed advertised modes. Use 0 for all modes.
396 *
397 * @return EOK If the operation was successfully completed
398 *
399 */
400int nic_autoneg_enable(async_sess_t *dev_sess, uint32_t advertisement)
401{
402 async_exch_t *exch = async_exchange_begin(dev_sess);
403 int rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
404 NIC_AUTONEG_ENABLE, (sysarg_t) advertisement);
405 async_exchange_end(exch);
406
407 return rc;
408}
409
410/** Disable auto-negotiation.
411 *
412 * @param[in] dev_sess
413 *
414 * @return EOK If the operation was successfully completed
415 *
416 */
417int nic_autoneg_disable(async_sess_t *dev_sess)
418{
419 async_exch_t *exch = async_exchange_begin(dev_sess);
420 int rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
421 NIC_AUTONEG_DISABLE);
422 async_exchange_end(exch);
423
424 return rc;
425}
426
427/** Probe current state of auto-negotiation.
428 *
429 * Modes are defined in the "nic/eth_phys.h" in the C library.
430 *
431 * @param[in] dev_sess
432 * @param[out] our_advertisement Modes advertised by this NIC.
433 * Can be NULL.
434 * @param[out] their_advertisement Modes advertised by the other side.
435 * Can be NULL.
436 * @param[out] result General state of auto-negotiation.
437 * Can be NULL.
438 * @param[out] their_result State of other side auto-negotiation.
439 * Can be NULL.
440 *
441 * @return EOK If the operation was successfully completed
442 *
443 */
444int nic_autoneg_probe(async_sess_t *dev_sess, uint32_t *our_advertisement,
445 uint32_t *their_advertisement, nic_result_t *result,
446 nic_result_t *their_result)
447{
448 sysarg_t _our_advertisement;
449 sysarg_t _their_advertisement;
450 sysarg_t _result;
451 sysarg_t _their_result;
452
453 async_exch_t *exch = async_exchange_begin(dev_sess);
454 int rc = async_req_1_4(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
455 NIC_AUTONEG_PROBE, &_our_advertisement, &_their_advertisement,
456 &_result, &_their_result);
457 async_exchange_end(exch);
458
459 if (our_advertisement)
460 *our_advertisement = (uint32_t) _our_advertisement;
461
462 if (*their_advertisement)
463 *their_advertisement = (uint32_t) _their_advertisement;
464
465 if (result)
466 *result = (nic_result_t) _result;
467
468 if (their_result)
469 *their_result = (nic_result_t) _their_result;
470
471 return rc;
472}
473
474/** Restart the auto-negotiation process.
475 *
476 * @param[in] dev_sess
477 *
478 * @return EOK If the operation was successfully completed
479 *
480 */
481int nic_autoneg_restart(async_sess_t *dev_sess)
482{
483 async_exch_t *exch = async_exchange_begin(dev_sess);
484 int rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
485 NIC_AUTONEG_RESTART);
486 async_exchange_end(exch);
487
488 return rc;
489}
490
491/** Query party's sending and reception of the PAUSE frame.
492 *
493 * @param[in] dev_sess
494 * @param[out] we_send This NIC sends the PAUSE frame (true/false)
495 * @param[out] we_receive This NIC receives the PAUSE frame (true/false)
496 * @param[out] pause The time set to transmitted PAUSE frames.
497 *
498 * @return EOK If the operation was successfully completed
499 *
500 */
501int nic_get_pause(async_sess_t *dev_sess, nic_result_t *we_send,
502 nic_result_t *we_receive, uint16_t *pause)
503{
504 sysarg_t _we_send;
505 sysarg_t _we_receive;
506 sysarg_t _pause;
507
508 async_exch_t *exch = async_exchange_begin(dev_sess);
509 int rc = async_req_1_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
510 NIC_GET_PAUSE, &_we_send, &_we_receive, &_pause);
511 async_exchange_end(exch);
512
513 if (we_send)
514 *we_send = _we_send;
515
516 if (we_receive)
517 *we_receive = _we_receive;
518
519 if (pause)
520 *pause = _pause;
521
522 return rc;
523}
524
525/** Control sending and reception of the PAUSE frame.
526 *
527 * @param[in] dev_sess
528 * @param[in] allow_send Allow sending the PAUSE frame (true/false)
529 * @param[in] allow_receive Allow reception of the PAUSE frame (true/false)
530 * @param[in] pause Pause length in 512 bit units written
531 * to transmitted frames. The value 0 means
532 * auto value (the best). If the requested
533 * time cannot be set the driver is allowed
534 * to set the nearest supported value.
535 *
536 * @return EOK If the operation was successfully completed
537 *
538 */
539int nic_set_pause(async_sess_t *dev_sess, int allow_send, int allow_receive,
540 uint16_t pause)
541{
542 async_exch_t *exch = async_exchange_begin(dev_sess);
543 int rc = async_req_4_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
544 NIC_SET_PAUSE, allow_send, allow_receive, pause);
545 async_exchange_end(exch);
546
547 return rc;
548}
549
550/** Retrieve current settings of unicast frames reception.
551 *
552 * Note: In case of mode != NIC_UNICAST_LIST the contents of
553 * address_list and address_count are undefined.
554 *
555 * @param[in] dev_sess
556 * @param[out] mode Current operation mode
557 * @param[in] max_count Maximal number of addresses that could
558 * be written into the list buffer.
559 * @param[out] address_list Buffer for the list (array). Can be NULL.
560 * @param[out] address_count Number of addresses in the list before
561 * possible truncation due to the max_count.
562 *
563 * @return EOK If the operation was successfully completed
564 *
565 */
566int nic_unicast_get_mode(async_sess_t *dev_sess, nic_unicast_mode_t *mode,
567 size_t max_count, nic_address_t *address_list, size_t *address_count)
568{
569 assert(mode);
570
571 sysarg_t _mode;
572 sysarg_t _address_count;
573
574 if (!address_list)
575 max_count = 0;
576
577 async_exch_t *exch = async_exchange_begin(dev_sess);
578
579 int rc = async_req_2_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
580 NIC_UNICAST_GET_MODE, max_count, &_mode, &_address_count);
581 if (rc != EOK) {
582 async_exchange_end(exch);
583 return rc;
584 }
585
586 *mode = (nic_unicast_mode_t) _mode;
587 if (address_count)
588 *address_count = (size_t) _address_count;
589
590 if ((max_count) && (_address_count))
591 rc = async_data_read_start(exch, address_list,
592 max_count * sizeof(nic_address_t));
593
594 async_exchange_end(exch);
595
596 return rc;
597}
598
599/** Set which unicast frames are received.
600 *
601 * @param[in] dev_sess
602 * @param[in] mode Current operation mode
603 * @param[in] address_list The list of addresses. Can be NULL.
604 * @param[in] address_count Number of addresses in the list.
605 *
606 * @return EOK If the operation was successfully completed
607 *
608 */
609int nic_unicast_set_mode(async_sess_t *dev_sess, nic_unicast_mode_t mode,
610 const nic_address_t *address_list, size_t address_count)
611{
612 if (address_list == NULL)
613 address_count = 0;
614
615 async_exch_t *exch = async_exchange_begin(dev_sess);
616
617 aid_t message_id = async_send_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
618 NIC_UNICAST_SET_MODE, (sysarg_t) mode, address_count, NULL);
619
620 int rc;
621 if (address_count)
622 rc = async_data_write_start(exch, address_list,
623 address_count * sizeof(nic_address_t));
624 else
625 rc = EOK;
626
627 async_exchange_end(exch);
628
629 sysarg_t res;
630 async_wait_for(message_id, &res);
631
632 if (rc != EOK)
633 return rc;
634
635 return (int) res;
636}
637
638/** Retrieve current settings of multicast frames reception.
639 *
640 * Note: In case of mode != NIC_MULTICAST_LIST the contents of
641 * address_list and address_count are undefined.
642 *
643 * @param[in] dev_sess
644 * @param[out] mode Current operation mode
645 * @param[in] max_count Maximal number of addresses that could
646 * be written into the list buffer.
647 * @param[out] address_list Buffer for the list (array). Can be NULL.
648 * @param[out] address_count Number of addresses in the list before
649 * possible truncation due to the max_count.
650 * Can be NULL.
651 *
652 * @return EOK If the operation was successfully completed
653 *
654 */
655int nic_multicast_get_mode(async_sess_t *dev_sess, nic_multicast_mode_t *mode,
656 size_t max_count, nic_address_t *address_list, size_t *address_count)
657{
658 assert(mode);
659
660 sysarg_t _mode;
661
662 if (!address_list)
663 max_count = 0;
664
665 async_exch_t *exch = async_exchange_begin(dev_sess);
666
667 sysarg_t ac;
668 int rc = async_req_2_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
669 NIC_MULTICAST_GET_MODE, max_count, &_mode, &ac);
670 if (rc != EOK) {
671 async_exchange_end(exch);
672 return rc;
673 }
674
675 *mode = (nic_multicast_mode_t) _mode;
676 if (address_count)
677 *address_count = (size_t) ac;
678
679 if ((max_count) && (ac))
680 rc = async_data_read_start(exch, address_list,
681 max_count * sizeof(nic_address_t));
682
683 async_exchange_end(exch);
684 return rc;
685}
686
687/** Set which multicast frames are received.
688 *
689 * @param[in] dev_sess
690 * @param[in] mode Current operation mode
691 * @param[in] address_list The list of addresses. Can be NULL.
692 * @param[in] address_count Number of addresses in the list.
693 *
694 * @return EOK If the operation was successfully completed
695 *
696 */
697int nic_multicast_set_mode(async_sess_t *dev_sess, nic_multicast_mode_t mode,
698 const nic_address_t *address_list, size_t address_count)
699{
700 if (address_list == NULL)
701 address_count = 0;
702
703 async_exch_t *exch = async_exchange_begin(dev_sess);
704
705 aid_t message_id = async_send_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
706 NIC_MULTICAST_SET_MODE, (sysarg_t) mode, address_count, NULL);
707
708 int rc;
709 if (address_count)
710 rc = async_data_write_start(exch, address_list,
711 address_count * sizeof(nic_address_t));
712 else
713 rc = EOK;
714
715 async_exchange_end(exch);
716
717 sysarg_t res;
718 async_wait_for(message_id, &res);
719
720 if (rc != EOK)
721 return rc;
722
723 return (int) res;
724}
725
726/** Determine if broadcast packets are received.
727 *
728 * @param[in] dev_sess
729 * @param[out] mode Current operation mode
730 *
731 * @return EOK If the operation was successfully completed
732 *
733 */
734int nic_broadcast_get_mode(async_sess_t *dev_sess, nic_broadcast_mode_t *mode)
735{
736 assert(mode);
737
738 sysarg_t _mode;
739
740 async_exch_t *exch = async_exchange_begin(dev_sess);
741 int rc = async_req_1_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
742 NIC_BROADCAST_GET_MODE, &_mode);
743 async_exchange_end(exch);
744
745 *mode = (nic_broadcast_mode_t) _mode;
746
747 return rc;
748}
749
750/** Set whether broadcast packets are received.
751 *
752 * @param[in] dev_sess
753 * @param[in] mode Current operation mode
754 *
755 * @return EOK If the operation was successfully completed
756 *
757 */
758int nic_broadcast_set_mode(async_sess_t *dev_sess, nic_broadcast_mode_t mode)
759{
760 async_exch_t *exch = async_exchange_begin(dev_sess);
761 int rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
762 NIC_BROADCAST_SET_MODE, mode);
763 async_exchange_end(exch);
764
765 return rc;
766}
767
768/** Determine if defective (erroneous) packets are received.
769 *
770 * @param[in] dev_sess
771 * @param[out] mode Bitmask specifying allowed errors
772 *
773 * @return EOK If the operation was successfully completed
774 *
775 */
776int nic_defective_get_mode(async_sess_t *dev_sess, uint32_t *mode)
777{
778 assert(mode);
779
780 sysarg_t _mode;
781
782 async_exch_t *exch = async_exchange_begin(dev_sess);
783 int rc = async_req_1_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
784 NIC_DEFECTIVE_GET_MODE, &_mode);
785 async_exchange_end(exch);
786
787 *mode = (uint32_t) _mode;
788
789 return rc;
790}
791
792/** Set whether defective (erroneous) packets are received.
793 *
794 * @param[in] dev_sess
795 * @param[out] mode Bitmask specifying allowed errors
796 *
797 * @return EOK If the operation was successfully completed
798 *
799 */
800int nic_defective_set_mode(async_sess_t *dev_sess, uint32_t mode)
801{
802 async_exch_t *exch = async_exchange_begin(dev_sess);
803 int rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
804 NIC_DEFECTIVE_SET_MODE, mode);
805 async_exchange_end(exch);
806
807 return rc;
808}
809
810/** Retrieve the currently blocked source MAC addresses.
811 *
812 * @param[in] dev_sess
813 * @param[in] max_count Maximal number of addresses that could
814 * be written into the list buffer.
815 * @param[out] address_list Buffer for the list (array). Can be NULL.
816 * @param[out] address_count Number of addresses in the list before
817 * possible truncation due to the max_count.
818 *
819 * @return EOK If the operation was successfully completed
820 *
821 */
822int nic_blocked_sources_get(async_sess_t *dev_sess, size_t max_count,
823 nic_address_t *address_list, size_t *address_count)
824{
825 if (!address_list)
826 max_count = 0;
827
828 async_exch_t *exch = async_exchange_begin(dev_sess);
829
830 sysarg_t ac;
831 int rc = async_req_2_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
832 NIC_BLOCKED_SOURCES_GET, max_count, &ac);
833 if (rc != EOK) {
834 async_exchange_end(exch);
835 return rc;
836 }
837
838 if (address_count)
839 *address_count = (size_t) ac;
840
841 if ((max_count) && (ac))
842 rc = async_data_read_start(exch, address_list,
843 max_count * sizeof(nic_address_t));
844
845 async_exchange_end(exch);
846 return rc;
847}
848
849/** Set which source MACs are blocked
850 *
851 * @param[in] dev_sess
852 * @param[in] address_list The list of addresses. Can be NULL.
853 * @param[in] address_count Number of addresses in the list.
854 *
855 * @return EOK If the operation was successfully completed
856 *
857 */
858int nic_blocked_sources_set(async_sess_t *dev_sess,
859 const nic_address_t *address_list, size_t address_count)
860{
861 if (address_list == NULL)
862 address_count = 0;
863
864 async_exch_t *exch = async_exchange_begin(dev_sess);
865
866 aid_t message_id = async_send_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
867 NIC_BLOCKED_SOURCES_SET, address_count, NULL);
868
869 int rc;
870 if (address_count)
871 rc = async_data_write_start(exch, address_list,
872 address_count * sizeof(nic_address_t));
873 else
874 rc = EOK;
875
876 async_exchange_end(exch);
877
878 sysarg_t res;
879 async_wait_for(message_id, &res);
880
881 if (rc != EOK)
882 return rc;
883
884 return (int) res;
885}
886
887/** Request current VLAN filtering mask.
888 *
889 * @param[in] dev_sess
890 * @param[out] stats Structure with the statistics
891 *
892 * @return EOK If the operation was successfully completed
893 *
894 */
895int nic_vlan_get_mask(async_sess_t *dev_sess, nic_vlan_mask_t *mask)
896{
897 assert(mask);
898
899 async_exch_t *exch = async_exchange_begin(dev_sess);
900 int rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
901 NIC_VLAN_GET_MASK);
902 if (rc != EOK) {
903 async_exchange_end(exch);
904 return rc;
905 }
906
907 rc = async_data_read_start(exch, mask, sizeof(nic_vlan_mask_t));
908 async_exchange_end(exch);
909
910 return rc;
911}
912
913/** Set the mask used for VLAN filtering.
914 *
915 * If NULL, VLAN filtering is disabled.
916 *
917 * @param[in] dev_sess
918 * @param[in] mask Pointer to mask structure or NULL to disable.
919 *
920 * @return EOK If the operation was successfully completed
921 *
922 */
923int nic_vlan_set_mask(async_sess_t *dev_sess, const nic_vlan_mask_t *mask)
924{
925 async_exch_t *exch = async_exchange_begin(dev_sess);
926
927 aid_t message_id = async_send_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
928 NIC_VLAN_SET_MASK, mask != NULL, NULL);
929
930 int rc;
931 if (mask != NULL)
932 rc = async_data_write_start(exch, mask, sizeof(nic_vlan_mask_t));
933 else
934 rc = EOK;
935
936 async_exchange_end(exch);
937
938 sysarg_t res;
939 async_wait_for(message_id, &res);
940
941 if (rc != EOK)
942 return rc;
943
944 return (int) res;
945}
946
947/** Set VLAN (802.1q) tag.
948 *
949 * Set whether the tag is to be signaled in offload info and
950 * if the tag should be stripped from received frames and added
951 * to sent frames automatically. Not every combination of add
952 * and strip must be supported.
953 *
954 * @param[in] dev_sess
955 * @param[in] tag VLAN priority (top 3 bits) and
956 * the VLAN tag (bottom 12 bits)
957 * @param[in] add Add the VLAN tag automatically (boolean)
958 * @param[in] strip Strip the VLAN tag automatically (boolean)
959 *
960 * @return EOK If the operation was successfully completed
961 *
962 */
963int nic_vlan_set_tag(async_sess_t *dev_sess, uint16_t tag, bool add, bool strip)
964{
965 async_exch_t *exch = async_exchange_begin(dev_sess);
966 int rc = async_req_4_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
967 NIC_VLAN_SET_TAG, (sysarg_t) tag, (sysarg_t) add, (sysarg_t) strip);
968 async_exchange_end(exch);
969
970 return rc;
971}
972
973/** Add new Wake-On-LAN virtue.
974 *
975 * @param[in] dev_sess
976 * @param[in] type Type of the virtue
977 * @param[in] data Data required for this virtue
978 * (depends on type)
979 * @param[in] length Length of the data
980 * @param[out] id Identifier of the new virtue
981 *
982 * @return EOK If the operation was successfully completed
983 *
984 */
985int nic_wol_virtue_add(async_sess_t *dev_sess, nic_wv_type_t type,
986 const void *data, size_t length, nic_wv_id_t *id)
987{
988 assert(id);
989
990 bool send_data = ((data != NULL) && (length != 0));
991 async_exch_t *exch = async_exchange_begin(dev_sess);
992
993 ipc_call_t result;
994 aid_t message_id = async_send_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
995 NIC_WOL_VIRTUE_ADD, (sysarg_t) type, send_data, &result);
996
997 sysarg_t res;
998 if (send_data) {
999 int rc = async_data_write_start(exch, data, length);
1000 if (rc != EOK) {
1001 async_exchange_end(exch);
1002 async_wait_for(message_id, &res);
1003 return rc;
1004 }
1005 }
1006
1007 async_exchange_end(exch);
1008 async_wait_for(message_id, &res);
1009
1010 *id = IPC_GET_ARG1(result);
1011 return (int) res;
1012}
1013
1014/** Remove Wake-On-LAN virtue.
1015 *
1016 * @param[in] dev_sess
1017 * @param[in] id Virtue identifier
1018 *
1019 * @return EOK If the operation was successfully completed
1020 *
1021 */
1022int nic_wol_virtue_remove(async_sess_t *dev_sess, nic_wv_id_t id)
1023{
1024 async_exch_t *exch = async_exchange_begin(dev_sess);
1025 int rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1026 NIC_WOL_VIRTUE_REMOVE, (sysarg_t) id);
1027 async_exchange_end(exch);
1028
1029 return rc;
1030}
1031
1032/** Get information about virtue.
1033 *
1034 * @param[in] dev_sess
1035 * @param[in] id Virtue identifier
1036 * @param[out] type Type of the filter. Can be NULL.
1037 * @param[out] max_length Size of the data buffer.
1038 * @param[out] data Buffer for data used when the
1039 * virtue was created. Can be NULL.
1040 * @param[out] length Length of the data. Can be NULL.
1041 *
1042 * @return EOK If the operation was successfully completed
1043 *
1044 */
1045int nic_wol_virtue_probe(async_sess_t *dev_sess, nic_wv_id_t id,
1046 nic_wv_type_t *type, size_t max_length, void *data, size_t *length)
1047{
1048 sysarg_t _type;
1049 sysarg_t _length;
1050
1051 if (data == NULL)
1052 max_length = 0;
1053
1054 async_exch_t *exch = async_exchange_begin(dev_sess);
1055
1056 int rc = async_req_3_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1057 NIC_WOL_VIRTUE_PROBE, (sysarg_t) id, max_length,
1058 &_type, &_length);
1059 if (rc != EOK) {
1060 async_exchange_end(exch);
1061 return rc;
1062 }
1063
1064 if (type)
1065 *type = _type;
1066
1067 if (length)
1068 *length = _length;
1069
1070 if ((max_length) && (_length != 0))
1071 rc = async_data_read_start(exch, data, max_length);
1072
1073 async_exchange_end(exch);
1074 return rc;
1075}
1076
1077/** Get a list of all virtues of the specified type.
1078 *
1079 * When NIC_WV_NONE is specified as the virtue type the function
1080 * lists virtues of all types.
1081 *
1082 * @param[in] dev_sess
1083 * @param[in] type Type of the virtues
1084 * @param[in] max_count Maximum number of ids that can be
1085 * written into the list buffer.
1086 * @param[out] id_list Buffer for to the list of virtue ids.
1087 * Can be NULL.
1088 * @param[out] id_count Number of virtue identifiers in the list
1089 * before possible truncation due to the
1090 * max_count. Can be NULL.
1091 *
1092 * @return EOK If the operation was successfully completed
1093 *
1094 */
1095int nic_wol_virtue_list(async_sess_t *dev_sess, nic_wv_type_t type,
1096 size_t max_count, nic_wv_id_t *id_list, size_t *id_count)
1097{
1098 if (id_list == NULL)
1099 max_count = 0;
1100
1101 async_exch_t *exch = async_exchange_begin(dev_sess);
1102
1103 sysarg_t count;
1104 int rc = async_req_3_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1105 NIC_WOL_VIRTUE_LIST, (sysarg_t) type, max_count, &count);
1106
1107 if (id_count)
1108 *id_count = (size_t) count;
1109
1110 if ((rc != EOK) || (!max_count)) {
1111 async_exchange_end(exch);
1112 return rc;
1113 }
1114
1115 rc = async_data_read_start(exch, id_list,
1116 max_count * sizeof(nic_wv_id_t));
1117
1118 async_exchange_end(exch);
1119 return rc;
1120}
1121
1122/** Get number of virtues that can be enabled yet.
1123 *
1124 * Count: < 0 => Virtue of this type can be never used
1125 * = 0 => No more virtues can be enabled
1126 * > 0 => #count virtues can be enabled yet
1127 *
1128 * @param[in] dev_sess
1129 * @param[in] type Virtue type
1130 * @param[out] count Number of virtues
1131 *
1132 * @return EOK If the operation was successfully completed
1133 *
1134 */
1135int nic_wol_virtue_get_caps(async_sess_t *dev_sess, nic_wv_type_t type,
1136 int *count)
1137{
1138 assert(count);
1139
1140 sysarg_t _count;
1141
1142 async_exch_t *exch = async_exchange_begin(dev_sess);
1143 int rc = async_req_2_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1144 NIC_WOL_VIRTUE_GET_CAPS, (sysarg_t) type, &_count);
1145 async_exchange_end(exch);
1146
1147 *count = (int) _count;
1148 return rc;
1149}
1150
1151/** Load the frame that issued the wakeup.
1152 *
1153 * The NIC can support only matched_type, only part of the frame
1154 * can be available or not at all. Sometimes even the type can be
1155 * uncertain -- in this case the matched_type contains NIC_WV_NONE.
1156 *
1157 * Frame_length can be greater than max_length, but at most max_length
1158 * bytes will be copied into the frame buffer.
1159 *
1160 * Note: Only the type of the filter can be detected, not the concrete
1161 * filter, because the driver is probably not running when the wakeup
1162 * is issued.
1163 *
1164 * @param[in] dev_sess
1165 * @param[out] matched_type Type of the filter that issued wakeup.
1166 * @param[in] max_length Size of the buffer
1167 * @param[out] frame Buffer for the frame. Can be NULL.
1168 * @param[out] frame_length Length of the stored frame. Can be NULL.
1169 *
1170 * @return EOK If the operation was successfully completed
1171 *
1172 */
1173int nic_wol_load_info(async_sess_t *dev_sess, nic_wv_type_t *matched_type,
1174 size_t max_length, uint8_t *frame, size_t *frame_length)
1175{
1176 assert(matched_type);
1177
1178 sysarg_t _matched_type;
1179 sysarg_t _frame_length;
1180
1181 if (frame == NULL)
1182 max_length = 0;
1183
1184 async_exch_t *exch = async_exchange_begin(dev_sess);
1185
1186 int rc = async_req_2_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1187 NIC_WOL_LOAD_INFO, max_length, &_matched_type, &_frame_length);
1188 if (rc != EOK) {
1189 async_exchange_end(exch);
1190 return rc;
1191 }
1192
1193 *matched_type = (nic_wv_type_t) _matched_type;
1194 if (frame_length)
1195 *frame_length = (size_t) _frame_length;
1196
1197 if ((max_length != 0) && (_frame_length != 0))
1198 rc = async_data_read_start(exch, frame, max_length);
1199
1200 async_exchange_end(exch);
1201 return rc;
1202}
1203
1204/** Probe supported options and current setting of offload computations
1205 *
1206 * @param[in] dev_sess
1207 * @param[out] supported Supported offload options
1208 * @param[out] active Currently active offload options
1209 *
1210 * @return EOK If the operation was successfully completed
1211 *
1212 */
1213int nic_offload_probe(async_sess_t *dev_sess, uint32_t *supported,
1214 uint32_t *active)
1215{
1216 assert(supported);
1217 assert(active);
1218
1219 sysarg_t _supported;
1220 sysarg_t _active;
1221
1222 async_exch_t *exch = async_exchange_begin(dev_sess);
1223 int rc = async_req_1_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1224 NIC_OFFLOAD_PROBE, &_supported, &_active);
1225 async_exchange_end(exch);
1226
1227 *supported = (uint32_t) _supported;
1228 *active = (uint32_t) _active;
1229 return rc;
1230}
1231
1232/** Set which offload computations can be performed on the NIC.
1233 *
1234 * @param[in] dev_sess
1235 * @param[in] mask Mask for the options (only those set here will be set)
1236 * @param[in] active Which options should be enabled and which disabled
1237 *
1238 * @return EOK If the operation was successfully completed
1239 *
1240 */
1241int nic_offload_set(async_sess_t *dev_sess, uint32_t mask, uint32_t active)
1242{
1243 async_exch_t *exch = async_exchange_begin(dev_sess);
1244 int rc = async_req_3_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1245 NIC_AUTONEG_RESTART, (sysarg_t) mask, (sysarg_t) active);
1246 async_exchange_end(exch);
1247
1248 return rc;
1249}
1250
1251/** Query the current interrupt/poll mode of the NIC
1252 *
1253 * @param[in] dev_sess
1254 * @param[out] mode Current poll mode
1255 * @param[out] period Period used in periodic polling.
1256 * Can be NULL.
1257 *
1258 * @return EOK If the operation was successfully completed
1259 *
1260 */
1261int nic_poll_get_mode(async_sess_t *dev_sess, nic_poll_mode_t *mode,
1262 struct timeval *period)
1263{
1264 assert(mode);
1265
1266 sysarg_t _mode;
1267
1268 async_exch_t *exch = async_exchange_begin(dev_sess);
1269
1270 int rc = async_req_2_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1271 NIC_POLL_GET_MODE, period != NULL, &_mode);
1272 if (rc != EOK) {
1273 async_exchange_end(exch);
1274 return rc;
1275 }
1276
1277 *mode = (nic_poll_mode_t) _mode;
1278
1279 if (period != NULL)
1280 rc = async_data_read_start(exch, period, sizeof(struct timeval));
1281
1282 async_exchange_end(exch);
1283 return rc;
1284}
1285
1286/** Set the interrupt/poll mode of the NIC.
1287 *
1288 * @param[in] dev_sess
1289 * @param[in] mode New poll mode
1290 * @param[in] period Period used in periodic polling. Can be NULL.
1291 *
1292 * @return EOK If the operation was successfully completed
1293 *
1294 */
1295int nic_poll_set_mode(async_sess_t *dev_sess, nic_poll_mode_t mode,
1296 const struct timeval *period)
1297{
1298 async_exch_t *exch = async_exchange_begin(dev_sess);
1299
1300 aid_t message_id = async_send_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1301 NIC_POLL_SET_MODE, (sysarg_t) mode, period != NULL, NULL);
1302
1303 int rc;
1304 if (period)
1305 rc = async_data_write_start(exch, period, sizeof(struct timeval));
1306 else
1307 rc = EOK;
1308
1309 async_exchange_end(exch);
1310
1311 sysarg_t res;
1312 async_wait_for(message_id, &res);
1313
1314 if (rc != EOK)
1315 return rc;
1316
1317 return (int) res;
1318}
1319
1320/** Request the driver to poll the NIC.
1321 *
1322 * @param[in] dev_sess
1323 *
1324 * @return EOK If the operation was successfully completed
1325 *
1326 */
1327int nic_poll_now(async_sess_t *dev_sess)
1328{
1329 async_exch_t *exch = async_exchange_begin(dev_sess);
1330 int rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE), NIC_POLL_NOW);
1331 async_exchange_end(exch);
1332
1333 return rc;
1334}
1335
1336static void remote_nic_send_frame(ddf_fun_t *dev, void *iface,
1337 ipc_callid_t callid, ipc_call_t *call)
1338{
1339 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1340 assert(nic_iface->send_frame);
1341
1342 void *data;
1343 size_t size;
1344 int rc;
1345
1346 rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
1347 if (rc != EOK) {
1348 async_answer_0(callid, EINVAL);
1349 return;
1350 }
1351
1352 rc = nic_iface->send_frame(dev, data, size);
1353 async_answer_0(callid, rc);
1354 free(data);
1355}
1356
1357static void remote_nic_callback_create(ddf_fun_t *dev, void *iface,
1358 ipc_callid_t callid, ipc_call_t *call)
1359{
1360 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1361 assert(nic_iface->callback_create);
1362
1363 int rc = nic_iface->callback_create(dev);
1364 async_answer_0(callid, rc);
1365}
1366
1367static void remote_nic_get_state(ddf_fun_t *dev, void *iface,
1368 ipc_callid_t callid, ipc_call_t *call)
1369{
1370 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1371 assert(nic_iface->get_state);
1372
1373 nic_device_state_t state = NIC_STATE_MAX;
1374
1375 int rc = nic_iface->get_state(dev, &state);
1376 async_answer_1(callid, rc, state);
1377}
1378
1379static void remote_nic_set_state(ddf_fun_t *dev, void *iface,
1380 ipc_callid_t callid, ipc_call_t *call)
1381{
1382 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1383 assert(nic_iface->set_state);
1384
1385 nic_device_state_t state = (nic_device_state_t) IPC_GET_ARG2(*call);
1386
1387 int rc = nic_iface->set_state(dev, state);
1388 async_answer_0(callid, rc);
1389}
1390
1391static void remote_nic_get_address(ddf_fun_t *dev, void *iface,
1392 ipc_callid_t callid, ipc_call_t *call)
1393{
1394 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1395 assert(nic_iface->get_address);
1396
1397 nic_address_t address;
1398 memset(&address, 0, sizeof(nic_address_t));
1399
1400 int rc = nic_iface->get_address(dev, &address);
1401 if (rc == EOK) {
1402 size_t max_len;
1403 ipc_callid_t data_callid;
1404
1405 /* All errors will be translated into EPARTY anyway */
1406 if (!async_data_read_receive(&data_callid, &max_len)) {
1407 async_answer_0(data_callid, EINVAL);
1408 async_answer_0(callid, EINVAL);
1409 return;
1410 }
1411
1412 if (max_len != sizeof(nic_address_t)) {
1413 async_answer_0(data_callid, ELIMIT);
1414 async_answer_0(callid, ELIMIT);
1415 return;
1416 }
1417
1418 async_data_read_finalize(data_callid, &address,
1419 sizeof(nic_address_t));
1420 }
1421
1422 async_answer_0(callid, rc);
1423}
1424
1425static void remote_nic_set_address(ddf_fun_t *dev, void *iface,
1426 ipc_callid_t callid, ipc_call_t *call)
1427{
1428 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1429
1430 size_t length;
1431 ipc_callid_t data_callid;
1432 if (!async_data_write_receive(&data_callid, &length)) {
1433 async_answer_0(data_callid, EINVAL);
1434 async_answer_0(callid, EINVAL);
1435 return;
1436 }
1437
1438 if (length > sizeof(nic_address_t)) {
1439 async_answer_0(data_callid, ELIMIT);
1440 async_answer_0(callid, ELIMIT);
1441 return;
1442 }
1443
1444 nic_address_t address;
1445 if (async_data_write_finalize(data_callid, &address, length) != EOK) {
1446 async_answer_0(callid, EINVAL);
1447 return;
1448 }
1449
1450 if (nic_iface->set_address != NULL) {
1451 int rc = nic_iface->set_address(dev, &address);
1452 async_answer_0(callid, rc);
1453 } else
1454 async_answer_0(callid, ENOTSUP);
1455}
1456
1457static void remote_nic_get_stats(ddf_fun_t *dev, void *iface,
1458 ipc_callid_t callid, ipc_call_t *call)
1459{
1460 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1461 if (nic_iface->get_stats == NULL) {
1462 async_answer_0(callid, ENOTSUP);
1463 return;
1464 }
1465
1466 nic_device_stats_t stats;
1467 memset(&stats, 0, sizeof(nic_device_stats_t));
1468
1469 int rc = nic_iface->get_stats(dev, &stats);
1470 if (rc == EOK) {
1471 ipc_callid_t data_callid;
1472 size_t max_len;
1473 if (!async_data_read_receive(&data_callid, &max_len)) {
1474 async_answer_0(data_callid, EINVAL);
1475 async_answer_0(callid, EINVAL);
1476 return;
1477 }
1478
1479 if (max_len < sizeof(nic_device_stats_t)) {
1480 async_answer_0(data_callid, ELIMIT);
1481 async_answer_0(callid, ELIMIT);
1482 return;
1483 }
1484
1485 async_data_read_finalize(data_callid, &stats,
1486 sizeof(nic_device_stats_t));
1487 }
1488
1489 async_answer_0(callid, rc);
1490}
1491
1492static void remote_nic_get_device_info(ddf_fun_t *dev, void *iface,
1493 ipc_callid_t callid, ipc_call_t *call)
1494{
1495 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1496 if (nic_iface->get_device_info == NULL) {
1497 async_answer_0(callid, ENOTSUP);
1498 return;
1499 }
1500
1501 nic_device_info_t info;
1502 memset(&info, 0, sizeof(nic_device_info_t));
1503
1504 int rc = nic_iface->get_device_info(dev, &info);
1505 if (rc == EOK) {
1506 ipc_callid_t data_callid;
1507 size_t max_len;
1508 if (!async_data_read_receive(&data_callid, &max_len)) {
1509 async_answer_0(data_callid, EINVAL);
1510 async_answer_0(callid, EINVAL);
1511 return;
1512 }
1513
1514 if (max_len < sizeof (nic_device_info_t)) {
1515 async_answer_0(data_callid, ELIMIT);
1516 async_answer_0(callid, ELIMIT);
1517 return;
1518 }
1519
1520 async_data_read_finalize(data_callid, &info,
1521 sizeof(nic_device_info_t));
1522 }
1523
1524 async_answer_0(callid, rc);
1525}
1526
1527static void remote_nic_get_cable_state(ddf_fun_t *dev, void *iface,
1528 ipc_callid_t callid, ipc_call_t *call)
1529{
1530 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1531 if (nic_iface->get_cable_state == NULL) {
1532 async_answer_0(callid, ENOTSUP);
1533 return;
1534 }
1535
1536 nic_cable_state_t cs = NIC_CS_UNKNOWN;
1537
1538 int rc = nic_iface->get_cable_state(dev, &cs);
1539 async_answer_1(callid, rc, (sysarg_t) cs);
1540}
1541
1542static void remote_nic_get_operation_mode(ddf_fun_t *dev, void *iface,
1543 ipc_callid_t callid, ipc_call_t *call)
1544{
1545 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1546 if (nic_iface->get_operation_mode == NULL) {
1547 async_answer_0(callid, ENOTSUP);
1548 return;
1549 }
1550
1551 int speed = 0;
1552 nic_channel_mode_t duplex = NIC_CM_UNKNOWN;
1553 nic_role_t role = NIC_ROLE_UNKNOWN;
1554
1555 int rc = nic_iface->get_operation_mode(dev, &speed, &duplex, &role);
1556 async_answer_3(callid, rc, (sysarg_t) speed, (sysarg_t) duplex,
1557 (sysarg_t) role);
1558}
1559
1560static void remote_nic_set_operation_mode(ddf_fun_t *dev, void *iface,
1561 ipc_callid_t callid, ipc_call_t *call)
1562{
1563 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1564 if (nic_iface->set_operation_mode == NULL) {
1565 async_answer_0(callid, ENOTSUP);
1566 return;
1567 }
1568
1569 int speed = (int) IPC_GET_ARG2(*call);
1570 nic_channel_mode_t duplex = (nic_channel_mode_t) IPC_GET_ARG3(*call);
1571 nic_role_t role = (nic_role_t) IPC_GET_ARG4(*call);
1572
1573 int rc = nic_iface->set_operation_mode(dev, speed, duplex, role);
1574 async_answer_0(callid, rc);
1575}
1576
1577static void remote_nic_autoneg_enable(ddf_fun_t *dev, void *iface,
1578 ipc_callid_t callid, ipc_call_t *call)
1579{
1580 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1581 if (nic_iface->autoneg_enable == NULL) {
1582 async_answer_0(callid, ENOTSUP);
1583 return;
1584 }
1585
1586 uint32_t advertisement = (uint32_t) IPC_GET_ARG2(*call);
1587
1588 int rc = nic_iface->autoneg_enable(dev, advertisement);
1589 async_answer_0(callid, rc);
1590}
1591
1592static void remote_nic_autoneg_disable(ddf_fun_t *dev, void *iface,
1593 ipc_callid_t callid, ipc_call_t *call)
1594{
1595 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1596 if (nic_iface->autoneg_disable == NULL) {
1597 async_answer_0(callid, ENOTSUP);
1598 return;
1599 }
1600
1601 int rc = nic_iface->autoneg_disable(dev);
1602 async_answer_0(callid, rc);
1603}
1604
1605static void remote_nic_autoneg_probe(ddf_fun_t *dev, void *iface,
1606 ipc_callid_t callid, ipc_call_t *call)
1607{
1608 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1609 if (nic_iface->autoneg_probe == NULL) {
1610 async_answer_0(callid, ENOTSUP);
1611 return;
1612 }
1613
1614 uint32_t our_adv = 0;
1615 uint32_t their_adv = 0;
1616 nic_result_t result = NIC_RESULT_NOT_AVAILABLE;
1617 nic_result_t their_result = NIC_RESULT_NOT_AVAILABLE;
1618
1619 int rc = nic_iface->autoneg_probe(dev, &our_adv, &their_adv, &result,
1620 &their_result);
1621 async_answer_4(callid, rc, our_adv, their_adv, (sysarg_t) result,
1622 (sysarg_t) their_result);
1623}
1624
1625static void remote_nic_autoneg_restart(ddf_fun_t *dev, void *iface,
1626 ipc_callid_t callid, ipc_call_t *call)
1627{
1628 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1629 if (nic_iface->autoneg_restart == NULL) {
1630 async_answer_0(callid, ENOTSUP);
1631 return;
1632 }
1633
1634 int rc = nic_iface->autoneg_restart(dev);
1635 async_answer_0(callid, rc);
1636}
1637
1638static void remote_nic_get_pause(ddf_fun_t *dev, void *iface,
1639 ipc_callid_t callid, ipc_call_t *call)
1640{
1641 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1642 if (nic_iface->get_pause == NULL) {
1643 async_answer_0(callid, ENOTSUP);
1644 return;
1645 }
1646
1647 nic_result_t we_send;
1648 nic_result_t we_receive;
1649 uint16_t pause;
1650
1651 int rc = nic_iface->get_pause(dev, &we_send, &we_receive, &pause);
1652 async_answer_3(callid, rc, we_send, we_receive, pause);
1653}
1654
1655static void remote_nic_set_pause(ddf_fun_t *dev, void *iface,
1656 ipc_callid_t callid, ipc_call_t *call)
1657{
1658 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1659 if (nic_iface->set_pause == NULL) {
1660 async_answer_0(callid, ENOTSUP);
1661 return;
1662 }
1663
1664 int allow_send = (int) IPC_GET_ARG2(*call);
1665 int allow_receive = (int) IPC_GET_ARG3(*call);
1666 uint16_t pause = (uint16_t) IPC_GET_ARG4(*call);
1667
1668 int rc = nic_iface->set_pause(dev, allow_send, allow_receive,
1669 pause);
1670 async_answer_0(callid, rc);
1671}
1672
1673static void remote_nic_unicast_get_mode(ddf_fun_t *dev, void *iface,
1674 ipc_callid_t callid, ipc_call_t *call)
1675{
1676 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1677 if (nic_iface->unicast_get_mode == NULL) {
1678 async_answer_0(callid, ENOTSUP);
1679 return;
1680 }
1681
1682 size_t max_count = IPC_GET_ARG2(*call);
1683 nic_address_t *address_list = NULL;
1684
1685 if (max_count != 0) {
1686 address_list = malloc(max_count * sizeof (nic_address_t));
1687 if (!address_list) {
1688 async_answer_0(callid, ENOMEM);
1689 return;
1690 }
1691 }
1692
1693 memset(address_list, 0, max_count * sizeof(nic_address_t));
1694 nic_unicast_mode_t mode = NIC_UNICAST_DEFAULT;
1695 size_t address_count = 0;
1696
1697 int rc = nic_iface->unicast_get_mode(dev, &mode, max_count, address_list,
1698 &address_count);
1699
1700 if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
1701 free(address_list);
1702 async_answer_2(callid, rc, mode, address_count);
1703 return;
1704 }
1705
1706 ipc_callid_t data_callid;
1707 size_t max_len;
1708 if (!async_data_read_receive(&data_callid, &max_len)) {
1709 async_answer_0(data_callid, EINVAL);
1710 async_answer_2(callid, rc, mode, address_count);
1711 free(address_list);
1712 return;
1713 }
1714
1715 if (max_len > address_count * sizeof(nic_address_t))
1716 max_len = address_count * sizeof(nic_address_t);
1717
1718 if (max_len > max_count * sizeof(nic_address_t))
1719 max_len = max_count * sizeof(nic_address_t);
1720
1721 async_data_read_finalize(data_callid, address_list, max_len);
1722 async_answer_0(data_callid, EINVAL);
1723
1724 free(address_list);
1725 async_answer_2(callid, rc, mode, address_count);
1726}
1727
1728static void remote_nic_unicast_set_mode(ddf_fun_t *dev, void *iface,
1729 ipc_callid_t callid, ipc_call_t *call)
1730{
1731 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1732
1733 size_t length;
1734 nic_unicast_mode_t mode = IPC_GET_ARG2(*call);
1735 size_t address_count = IPC_GET_ARG3(*call);
1736 nic_address_t *address_list = NULL;
1737
1738 if (address_count) {
1739 ipc_callid_t data_callid;
1740 if (!async_data_write_receive(&data_callid, &length)) {
1741 async_answer_0(data_callid, EINVAL);
1742 async_answer_0(callid, EINVAL);
1743 return;
1744 }
1745
1746 if (length != address_count * sizeof(nic_address_t)) {
1747 async_answer_0(data_callid, ELIMIT);
1748 async_answer_0(callid, ELIMIT);
1749 return;
1750 }
1751
1752 address_list = malloc(length);
1753 if (address_list == NULL) {
1754 async_answer_0(data_callid, ENOMEM);
1755 async_answer_0(callid, ENOMEM);
1756 return;
1757 }
1758
1759 if (async_data_write_finalize(data_callid, address_list,
1760 length) != EOK) {
1761 async_answer_0(callid, EINVAL);
1762 free(address_list);
1763 return;
1764 }
1765 }
1766
1767 if (nic_iface->unicast_set_mode != NULL) {
1768 int rc = nic_iface->unicast_set_mode(dev, mode, address_list,
1769 address_count);
1770 async_answer_0(callid, rc);
1771 } else
1772 async_answer_0(callid, ENOTSUP);
1773
1774 free(address_list);
1775}
1776
1777static void remote_nic_multicast_get_mode(ddf_fun_t *dev, void *iface,
1778 ipc_callid_t callid, ipc_call_t *call)
1779{
1780 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1781 if (nic_iface->multicast_get_mode == NULL) {
1782 async_answer_0(callid, ENOTSUP);
1783 return;
1784 }
1785
1786 size_t max_count = IPC_GET_ARG2(*call);
1787 nic_address_t *address_list = NULL;
1788
1789 if (max_count != 0) {
1790 address_list = malloc(max_count * sizeof(nic_address_t));
1791 if (!address_list) {
1792 async_answer_0(callid, ENOMEM);
1793 return;
1794 }
1795 }
1796
1797 memset(address_list, 0, max_count * sizeof(nic_address_t));
1798 nic_multicast_mode_t mode = NIC_MULTICAST_BLOCKED;
1799 size_t address_count = 0;
1800
1801 int rc = nic_iface->multicast_get_mode(dev, &mode, max_count, address_list,
1802 &address_count);
1803
1804
1805 if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
1806 free(address_list);
1807 async_answer_2(callid, rc, mode, address_count);
1808 return;
1809 }
1810
1811 ipc_callid_t data_callid;
1812 size_t max_len;
1813 if (!async_data_read_receive(&data_callid, &max_len)) {
1814 async_answer_0(data_callid, EINVAL);
1815 async_answer_2(callid, rc, mode, address_count);
1816 free(address_list);
1817 return;
1818 }
1819
1820 if (max_len > address_count * sizeof(nic_address_t))
1821 max_len = address_count * sizeof(nic_address_t);
1822
1823 if (max_len > max_count * sizeof(nic_address_t))
1824 max_len = max_count * sizeof(nic_address_t);
1825
1826 async_data_read_finalize(data_callid, address_list, max_len);
1827
1828 free(address_list);
1829 async_answer_2(callid, rc, mode, address_count);
1830}
1831
1832static void remote_nic_multicast_set_mode(ddf_fun_t *dev, void *iface,
1833 ipc_callid_t callid, ipc_call_t *call)
1834{
1835 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1836
1837 nic_multicast_mode_t mode = IPC_GET_ARG2(*call);
1838 size_t address_count = IPC_GET_ARG3(*call);
1839 nic_address_t *address_list = NULL;
1840
1841 if (address_count) {
1842 ipc_callid_t data_callid;
1843 size_t length;
1844 if (!async_data_write_receive(&data_callid, &length)) {
1845 async_answer_0(data_callid, EINVAL);
1846 async_answer_0(callid, EINVAL);
1847 return;
1848 }
1849
1850 if (length != address_count * sizeof (nic_address_t)) {
1851 async_answer_0(data_callid, ELIMIT);
1852 async_answer_0(callid, ELIMIT);
1853 return;
1854 }
1855
1856 address_list = malloc(length);
1857 if (address_list == NULL) {
1858 async_answer_0(data_callid, ENOMEM);
1859 async_answer_0(callid, ENOMEM);
1860 return;
1861 }
1862
1863 if (async_data_write_finalize(data_callid, address_list,
1864 length) != EOK) {
1865 async_answer_0(callid, EINVAL);
1866 free(address_list);
1867 return;
1868 }
1869 }
1870
1871 if (nic_iface->multicast_set_mode != NULL) {
1872 int rc = nic_iface->multicast_set_mode(dev, mode, address_list,
1873 address_count);
1874 async_answer_0(callid, rc);
1875 } else
1876 async_answer_0(callid, ENOTSUP);
1877
1878 free(address_list);
1879}
1880
1881static void remote_nic_broadcast_get_mode(ddf_fun_t *dev, void *iface,
1882 ipc_callid_t callid, ipc_call_t *call)
1883{
1884 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1885 if (nic_iface->broadcast_get_mode == NULL) {
1886 async_answer_0(callid, ENOTSUP);
1887 return;
1888 }
1889
1890 nic_broadcast_mode_t mode = NIC_BROADCAST_ACCEPTED;
1891
1892 int rc = nic_iface->broadcast_get_mode(dev, &mode);
1893 async_answer_1(callid, rc, mode);
1894}
1895
1896static void remote_nic_broadcast_set_mode(ddf_fun_t *dev, void *iface,
1897 ipc_callid_t callid, ipc_call_t *call)
1898{
1899 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1900 if (nic_iface->broadcast_set_mode == NULL) {
1901 async_answer_0(callid, ENOTSUP);
1902 return;
1903 }
1904
1905 nic_broadcast_mode_t mode = IPC_GET_ARG2(*call);
1906
1907 int rc = nic_iface->broadcast_set_mode(dev, mode);
1908 async_answer_0(callid, rc);
1909}
1910
1911static void remote_nic_defective_get_mode(ddf_fun_t *dev, void *iface,
1912 ipc_callid_t callid, ipc_call_t *call)
1913{
1914 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1915 if (nic_iface->defective_get_mode == NULL) {
1916 async_answer_0(callid, ENOTSUP);
1917 return;
1918 }
1919
1920 uint32_t mode = 0;
1921
1922 int rc = nic_iface->defective_get_mode(dev, &mode);
1923 async_answer_1(callid, rc, mode);
1924}
1925
1926static void remote_nic_defective_set_mode(ddf_fun_t *dev, void *iface,
1927 ipc_callid_t callid, ipc_call_t *call)
1928{
1929 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1930 if (nic_iface->defective_set_mode == NULL) {
1931 async_answer_0(callid, ENOTSUP);
1932 return;
1933 }
1934
1935 uint32_t mode = IPC_GET_ARG2(*call);
1936
1937 int rc = nic_iface->defective_set_mode(dev, mode);
1938 async_answer_0(callid, rc);
1939}
1940
1941static void remote_nic_blocked_sources_get(ddf_fun_t *dev, void *iface,
1942 ipc_callid_t callid, ipc_call_t *call)
1943{
1944 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1945 if (nic_iface->blocked_sources_get == NULL) {
1946 async_answer_0(callid, ENOTSUP);
1947 return;
1948 }
1949
1950 size_t max_count = IPC_GET_ARG2(*call);
1951 nic_address_t *address_list = NULL;
1952
1953 if (max_count != 0) {
1954 address_list = malloc(max_count * sizeof(nic_address_t));
1955 if (!address_list) {
1956 async_answer_0(callid, ENOMEM);
1957 return;
1958 }
1959 }
1960
1961 memset(address_list, 0, max_count * sizeof(nic_address_t));
1962 size_t address_count = 0;
1963
1964 int rc = nic_iface->blocked_sources_get(dev, max_count, address_list,
1965 &address_count);
1966
1967 if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
1968 async_answer_1(callid, rc, address_count);
1969 free(address_list);
1970 return;
1971 }
1972
1973 ipc_callid_t data_callid;
1974 size_t max_len;
1975 if (!async_data_read_receive(&data_callid, &max_len)) {
1976 async_answer_0(data_callid, EINVAL);
1977 async_answer_1(callid, rc, address_count);
1978 free(address_list);
1979 return;
1980 }
1981
1982 if (max_len > address_count * sizeof(nic_address_t))
1983 max_len = address_count * sizeof(nic_address_t);
1984
1985 if (max_len > max_count * sizeof(nic_address_t))
1986 max_len = max_count * sizeof(nic_address_t);
1987
1988 async_data_read_finalize(data_callid, address_list, max_len);
1989 async_answer_0(data_callid, EINVAL);
1990
1991 free(address_list);
1992 async_answer_1(callid, rc, address_count);
1993}
1994
1995static void remote_nic_blocked_sources_set(ddf_fun_t *dev, void *iface,
1996 ipc_callid_t callid, ipc_call_t *call)
1997{
1998 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1999
2000 size_t length;
2001 size_t address_count = IPC_GET_ARG2(*call);
2002 nic_address_t *address_list = NULL;
2003
2004 if (address_count) {
2005 ipc_callid_t data_callid;
2006 if (!async_data_write_receive(&data_callid, &length)) {
2007 async_answer_0(data_callid, EINVAL);
2008 async_answer_0(callid, EINVAL);
2009 return;
2010 }
2011
2012 if (length != address_count * sizeof(nic_address_t)) {
2013 async_answer_0(data_callid, ELIMIT);
2014 async_answer_0(callid, ELIMIT);
2015 return;
2016 }
2017
2018 address_list = malloc(length);
2019 if (address_list == NULL) {
2020 async_answer_0(data_callid, ENOMEM);
2021 async_answer_0(callid, ENOMEM);
2022 return;
2023 }
2024
2025 if (async_data_write_finalize(data_callid, address_list,
2026 length) != EOK) {
2027 async_answer_0(callid, EINVAL);
2028 free(address_list);
2029 return;
2030 }
2031 }
2032
2033 if (nic_iface->blocked_sources_set != NULL) {
2034 int rc = nic_iface->blocked_sources_set(dev, address_list,
2035 address_count);
2036 async_answer_0(callid, rc);
2037 } else
2038 async_answer_0(callid, ENOTSUP);
2039
2040 free(address_list);
2041}
2042
2043static void remote_nic_vlan_get_mask(ddf_fun_t *dev, void *iface,
2044 ipc_callid_t callid, ipc_call_t *call)
2045{
2046 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2047 if (nic_iface->vlan_get_mask == NULL) {
2048 async_answer_0(callid, ENOTSUP);
2049 return;
2050 }
2051
2052 nic_vlan_mask_t vlan_mask;
2053 memset(&vlan_mask, 0, sizeof(nic_vlan_mask_t));
2054
2055 int rc = nic_iface->vlan_get_mask(dev, &vlan_mask);
2056 if (rc == EOK) {
2057 ipc_callid_t data_callid;
2058 size_t max_len;
2059 if (!async_data_read_receive(&data_callid, &max_len)) {
2060 async_answer_0(data_callid, EINVAL);
2061 async_answer_0(callid, EINVAL);
2062 return;
2063 }
2064
2065 if (max_len != sizeof(nic_vlan_mask_t)) {
2066 async_answer_0(data_callid, EINVAL);
2067 async_answer_0(callid, EINVAL);
2068 return;
2069 }
2070
2071 async_data_read_finalize(data_callid, &vlan_mask, max_len);
2072 }
2073
2074 async_answer_0(callid, rc);
2075}
2076
2077static void remote_nic_vlan_set_mask(ddf_fun_t *dev, void *iface,
2078 ipc_callid_t callid, ipc_call_t *call)
2079{
2080 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2081
2082 nic_vlan_mask_t vlan_mask;
2083 nic_vlan_mask_t *vlan_mask_pointer = NULL;
2084 bool vlan_mask_set = (bool) IPC_GET_ARG2(*call);
2085
2086 if (vlan_mask_set) {
2087 ipc_callid_t data_callid;
2088 size_t length;
2089 if (!async_data_write_receive(&data_callid, &length)) {
2090 async_answer_0(data_callid, EINVAL);
2091 async_answer_0(callid, EINVAL);
2092 return;
2093 }
2094
2095 if (length != sizeof(nic_vlan_mask_t)) {
2096 async_answer_0(data_callid, ELIMIT);
2097 async_answer_0(callid, ELIMIT);
2098 return;
2099 }
2100
2101 if (async_data_write_finalize(data_callid, &vlan_mask,
2102 length) != EOK) {
2103 async_answer_0(callid, EINVAL);
2104 return;
2105 }
2106
2107 vlan_mask_pointer = &vlan_mask;
2108 }
2109
2110 if (nic_iface->vlan_set_mask != NULL) {
2111 int rc = nic_iface->vlan_set_mask(dev, vlan_mask_pointer);
2112 async_answer_0(callid, rc);
2113 } else
2114 async_answer_0(callid, ENOTSUP);
2115}
2116
2117static void remote_nic_vlan_set_tag(ddf_fun_t *dev, void *iface,
2118 ipc_callid_t callid, ipc_call_t *call)
2119{
2120 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2121
2122 if (nic_iface->vlan_set_tag == NULL) {
2123 async_answer_0(callid, ENOTSUP);
2124 return;
2125 }
2126
2127 uint16_t tag = (uint16_t) IPC_GET_ARG2(*call);
2128 bool add = (int) IPC_GET_ARG3(*call);
2129 bool strip = (int) IPC_GET_ARG4(*call);
2130
2131 int rc = nic_iface->vlan_set_tag(dev, tag, add, strip);
2132 async_answer_0(callid, rc);
2133}
2134
2135static void remote_nic_wol_virtue_add(ddf_fun_t *dev, void *iface,
2136 ipc_callid_t callid, ipc_call_t *call)
2137{
2138 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2139
2140 int send_data = (int) IPC_GET_ARG3(*call);
2141 ipc_callid_t data_callid;
2142
2143 if (nic_iface->wol_virtue_add == NULL) {
2144 if (send_data) {
2145 async_data_write_receive(&data_callid, NULL);
2146 async_answer_0(data_callid, ENOTSUP);
2147 }
2148
2149 async_answer_0(callid, ENOTSUP);
2150 }
2151
2152 size_t length = 0;
2153 void *data = NULL;
2154
2155 if (send_data) {
2156 if (!async_data_write_receive(&data_callid, &length)) {
2157 async_answer_0(data_callid, EINVAL);
2158 async_answer_0(callid, EINVAL);
2159 return;
2160 }
2161
2162 data = malloc(length);
2163 if (data == NULL) {
2164 async_answer_0(data_callid, ENOMEM);
2165 async_answer_0(callid, ENOMEM);
2166 return;
2167 }
2168
2169 if (async_data_write_finalize(data_callid, data,
2170 length) != EOK) {
2171 async_answer_0(callid, EINVAL);
2172 free(data);
2173 return;
2174 }
2175 }
2176
2177 nic_wv_id_t id = 0;
2178 nic_wv_type_t type = (nic_wv_type_t) IPC_GET_ARG2(*call);
2179
2180 int rc = nic_iface->wol_virtue_add(dev, type, data, length, &id);
2181 async_answer_1(callid, rc, (sysarg_t) id);
2182 free(data);
2183}
2184
2185static void remote_nic_wol_virtue_remove(ddf_fun_t *dev, void *iface,
2186 ipc_callid_t callid, ipc_call_t *call)
2187{
2188 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2189
2190 if (nic_iface->wol_virtue_remove == NULL) {
2191 async_answer_0(callid, ENOTSUP);
2192 return;
2193 }
2194
2195 nic_wv_id_t id = (nic_wv_id_t) IPC_GET_ARG2(*call);
2196
2197 int rc = nic_iface->wol_virtue_remove(dev, id);
2198 async_answer_0(callid, rc);
2199}
2200
2201static void remote_nic_wol_virtue_probe(ddf_fun_t *dev, void *iface,
2202 ipc_callid_t callid, ipc_call_t *call)
2203{
2204 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2205
2206 if (nic_iface->wol_virtue_probe == NULL) {
2207 async_answer_0(callid, ENOTSUP);
2208 return;
2209 }
2210
2211 nic_wv_id_t id = (nic_wv_id_t) IPC_GET_ARG2(*call);
2212 size_t max_length = IPC_GET_ARG3(*call);
2213 nic_wv_type_t type = NIC_WV_NONE;
2214 size_t length = 0;
2215 ipc_callid_t data_callid;
2216 void *data = NULL;
2217
2218 if (max_length != 0) {
2219 data = malloc(max_length);
2220 if (data == NULL) {
2221 async_answer_0(callid, ENOMEM);
2222 return;
2223 }
2224 }
2225
2226 memset(data, 0, max_length);
2227
2228 int rc = nic_iface->wol_virtue_probe(dev, id, &type, max_length,
2229 data, &length);
2230
2231 if ((max_length != 0) && (length != 0)) {
2232 size_t req_length;
2233 if (!async_data_read_receive(&data_callid, &req_length)) {
2234 async_answer_0(data_callid, EINVAL);
2235 async_answer_0(callid, EINVAL);
2236 free(data);
2237 return;
2238 }
2239
2240 if (req_length > length)
2241 req_length = length;
2242
2243 if (req_length > max_length)
2244 req_length = max_length;
2245
2246 async_data_read_finalize(data_callid, data, req_length);
2247 }
2248
2249 async_answer_2(callid, rc, (sysarg_t) type, (sysarg_t) length);
2250 free(data);
2251}
2252
2253static void remote_nic_wol_virtue_list(ddf_fun_t *dev, void *iface,
2254 ipc_callid_t callid, ipc_call_t *call)
2255{
2256 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2257 if (nic_iface->wol_virtue_list == NULL) {
2258 async_answer_0(callid, ENOTSUP);
2259 return;
2260 }
2261
2262 nic_wv_type_t type = (nic_wv_type_t) IPC_GET_ARG2(*call);
2263 size_t max_count = IPC_GET_ARG3(*call);
2264 size_t count = 0;
2265 nic_wv_id_t *id_list = NULL;
2266 ipc_callid_t data_callid;
2267
2268 if (max_count != 0) {
2269 id_list = malloc(max_count * sizeof(nic_wv_id_t));
2270 if (id_list == NULL) {
2271 async_answer_0(callid, ENOMEM);
2272 return;
2273 }
2274 }
2275
2276 memset(id_list, 0, max_count * sizeof (nic_wv_id_t));
2277
2278 int rc = nic_iface->wol_virtue_list(dev, type, max_count, id_list,
2279 &count);
2280
2281 if ((max_count != 0) && (count != 0)) {
2282 size_t req_length;
2283 if (!async_data_read_receive(&data_callid, &req_length)) {
2284 async_answer_0(data_callid, EINVAL);
2285 async_answer_0(callid, EINVAL);
2286 free(id_list);
2287 return;
2288 }
2289
2290 if (req_length > count * sizeof(nic_wv_id_t))
2291 req_length = count * sizeof(nic_wv_id_t);
2292
2293 if (req_length > max_count * sizeof(nic_wv_id_t))
2294 req_length = max_count * sizeof(nic_wv_id_t);
2295
2296 rc = async_data_read_finalize(data_callid, id_list, req_length);
2297 }
2298
2299 async_answer_1(callid, rc, (sysarg_t) count);
2300 free(id_list);
2301}
2302
2303static void remote_nic_wol_virtue_get_caps(ddf_fun_t *dev, void *iface,
2304 ipc_callid_t callid, ipc_call_t *call)
2305{
2306 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2307 if (nic_iface->wol_virtue_get_caps == NULL) {
2308 async_answer_0(callid, ENOTSUP);
2309 return;
2310 }
2311
2312 int count = -1;
2313 nic_wv_type_t type = (nic_wv_type_t) IPC_GET_ARG2(*call);
2314
2315 int rc = nic_iface->wol_virtue_get_caps(dev, type, &count);
2316 async_answer_1(callid, rc, (sysarg_t) count);
2317}
2318
2319static void remote_nic_wol_load_info(ddf_fun_t *dev, void *iface,
2320 ipc_callid_t callid, ipc_call_t *call)
2321{
2322 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2323 if (nic_iface->wol_load_info == NULL) {
2324 async_answer_0(callid, ENOTSUP);
2325 return;
2326 }
2327
2328 size_t max_length = (size_t) IPC_GET_ARG2(*call);
2329 size_t frame_length = 0;
2330 nic_wv_type_t type = NIC_WV_NONE;
2331 uint8_t *data = NULL;
2332
2333 if (max_length != 0) {
2334 data = malloc(max_length);
2335 if (data == NULL) {
2336 async_answer_0(callid, ENOMEM);
2337 return;
2338 }
2339 }
2340
2341 memset(data, 0, max_length);
2342
2343 int rc = nic_iface->wol_load_info(dev, &type, max_length, data,
2344 &frame_length);
2345 if (rc == EOK) {
2346 ipc_callid_t data_callid;
2347 size_t req_length;
2348 if (!async_data_read_receive(&data_callid, &req_length)) {
2349 async_answer_0(data_callid, EINVAL);
2350 async_answer_0(callid, EINVAL);
2351 free(data);
2352 return;
2353 }
2354
2355 req_length = req_length > max_length ? max_length : req_length;
2356 req_length = req_length > frame_length ? frame_length : req_length;
2357 async_data_read_finalize(data_callid, data, req_length);
2358 }
2359
2360 async_answer_2(callid, rc, (sysarg_t) type, (sysarg_t) frame_length);
2361 free(data);
2362}
2363
2364static void remote_nic_offload_probe(ddf_fun_t *dev, void *iface,
2365 ipc_callid_t callid, ipc_call_t *call)
2366{
2367 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2368 if (nic_iface->offload_probe == NULL) {
2369 async_answer_0(callid, ENOTSUP);
2370 return;
2371 }
2372
2373 uint32_t supported = 0;
2374 uint32_t active = 0;
2375
2376 int rc = nic_iface->offload_probe(dev, &supported, &active);
2377 async_answer_2(callid, rc, supported, active);
2378}
2379
2380static void remote_nic_offload_set(ddf_fun_t *dev, void *iface,
2381 ipc_callid_t callid, ipc_call_t *call)
2382{
2383 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2384 if (nic_iface->offload_set == NULL) {
2385 async_answer_0(callid, ENOTSUP);
2386 return;
2387 }
2388
2389 uint32_t mask = (uint32_t) IPC_GET_ARG2(*call);
2390 uint32_t active = (uint32_t) IPC_GET_ARG3(*call);
2391
2392 int rc = nic_iface->offload_set(dev, mask, active);
2393 async_answer_0(callid, rc);
2394}
2395
2396static void remote_nic_poll_get_mode(ddf_fun_t *dev, void *iface,
2397 ipc_callid_t callid, ipc_call_t *call)
2398{
2399 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2400 if (nic_iface->poll_get_mode == NULL) {
2401 async_answer_0(callid, ENOTSUP);
2402 return;
2403 }
2404
2405 nic_poll_mode_t mode = NIC_POLL_IMMEDIATE;
2406 int request_data = IPC_GET_ARG2(*call);
2407 struct timeval period = {
2408 .tv_sec = 0,
2409 .tv_usec = 0
2410 };
2411
2412 int rc = nic_iface->poll_get_mode(dev, &mode, &period);
2413 if ((rc == EOK) && (request_data)) {
2414 size_t max_len;
2415 ipc_callid_t data_callid;
2416
2417 if (!async_data_read_receive(&data_callid, &max_len)) {
2418 async_answer_0(data_callid, EINVAL);
2419 async_answer_0(callid, EINVAL);
2420 return;
2421 }
2422
2423 if (max_len != sizeof(struct timeval)) {
2424 async_answer_0(data_callid, ELIMIT);
2425 async_answer_0(callid, ELIMIT);
2426 return;
2427 }
2428
2429 async_data_read_finalize(data_callid, &period,
2430 sizeof(struct timeval));
2431 }
2432
2433 async_answer_1(callid, rc, (sysarg_t) mode);
2434}
2435
2436static void remote_nic_poll_set_mode(ddf_fun_t *dev, void *iface,
2437 ipc_callid_t callid, ipc_call_t *call)
2438{
2439 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2440
2441 nic_poll_mode_t mode = IPC_GET_ARG2(*call);
2442 int has_period = IPC_GET_ARG3(*call);
2443 struct timeval period_buf;
2444 struct timeval *period = NULL;
2445 size_t length;
2446
2447 if (has_period) {
2448 ipc_callid_t data_callid;
2449 if (!async_data_write_receive(&data_callid, &length)) {
2450 async_answer_0(data_callid, EINVAL);
2451 async_answer_0(callid, EINVAL);
2452 return;
2453 }
2454
2455 if (length != sizeof(struct timeval)) {
2456 async_answer_0(data_callid, ELIMIT);
2457 async_answer_0(callid, ELIMIT);
2458 return;
2459 }
2460
2461 period = &period_buf;
2462 if (async_data_write_finalize(data_callid, period,
2463 length) != EOK) {
2464 async_answer_0(callid, EINVAL);
2465 return;
2466 }
2467 }
2468
2469 if (nic_iface->poll_set_mode != NULL) {
2470 int rc = nic_iface->poll_set_mode(dev, mode, period);
2471 async_answer_0(callid, rc);
2472 } else
2473 async_answer_0(callid, ENOTSUP);
2474}
2475
2476static void remote_nic_poll_now(ddf_fun_t *dev, void *iface,
2477 ipc_callid_t callid, ipc_call_t *call)
2478{
2479 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2480 if (nic_iface->poll_now == NULL) {
2481 async_answer_0(callid, ENOTSUP);
2482 return;
2483 }
2484
2485 int rc = nic_iface->poll_now(dev);
2486 async_answer_0(callid, rc);
2487}
2488
2489/** Remote NIC interface operations.
2490 *
2491 */
2492static const remote_iface_func_ptr_t remote_nic_iface_ops[] = {
2493 [NIC_SEND_MESSAGE] = remote_nic_send_frame,
2494 [NIC_CALLBACK_CREATE] = remote_nic_callback_create,
2495 [NIC_GET_STATE] = remote_nic_get_state,
2496 [NIC_SET_STATE] = remote_nic_set_state,
2497 [NIC_GET_ADDRESS] = remote_nic_get_address,
2498 [NIC_SET_ADDRESS] = remote_nic_set_address,
2499 [NIC_GET_STATS] = remote_nic_get_stats,
2500 [NIC_GET_DEVICE_INFO] = remote_nic_get_device_info,
2501 [NIC_GET_CABLE_STATE] = remote_nic_get_cable_state,
2502 [NIC_GET_OPERATION_MODE] = remote_nic_get_operation_mode,
2503 [NIC_SET_OPERATION_MODE] = remote_nic_set_operation_mode,
2504 [NIC_AUTONEG_ENABLE] = remote_nic_autoneg_enable,
2505 [NIC_AUTONEG_DISABLE] = remote_nic_autoneg_disable,
2506 [NIC_AUTONEG_PROBE] = remote_nic_autoneg_probe,
2507 [NIC_AUTONEG_RESTART] = remote_nic_autoneg_restart,
2508 [NIC_GET_PAUSE] = remote_nic_get_pause,
2509 [NIC_SET_PAUSE] = remote_nic_set_pause,
2510 [NIC_UNICAST_GET_MODE] = remote_nic_unicast_get_mode,
2511 [NIC_UNICAST_SET_MODE] = remote_nic_unicast_set_mode,
2512 [NIC_MULTICAST_GET_MODE] = remote_nic_multicast_get_mode,
2513 [NIC_MULTICAST_SET_MODE] = remote_nic_multicast_set_mode,
2514 [NIC_BROADCAST_GET_MODE] = remote_nic_broadcast_get_mode,
2515 [NIC_BROADCAST_SET_MODE] = remote_nic_broadcast_set_mode,
2516 [NIC_DEFECTIVE_GET_MODE] = remote_nic_defective_get_mode,
2517 [NIC_DEFECTIVE_SET_MODE] = remote_nic_defective_set_mode,
2518 [NIC_BLOCKED_SOURCES_GET] = remote_nic_blocked_sources_get,
2519 [NIC_BLOCKED_SOURCES_SET] = remote_nic_blocked_sources_set,
2520 [NIC_VLAN_GET_MASK] = remote_nic_vlan_get_mask,
2521 [NIC_VLAN_SET_MASK] = remote_nic_vlan_set_mask,
2522 [NIC_VLAN_SET_TAG] = remote_nic_vlan_set_tag,
2523 [NIC_WOL_VIRTUE_ADD] = remote_nic_wol_virtue_add,
2524 [NIC_WOL_VIRTUE_REMOVE] = remote_nic_wol_virtue_remove,
2525 [NIC_WOL_VIRTUE_PROBE] = remote_nic_wol_virtue_probe,
2526 [NIC_WOL_VIRTUE_LIST] = remote_nic_wol_virtue_list,
2527 [NIC_WOL_VIRTUE_GET_CAPS] = remote_nic_wol_virtue_get_caps,
2528 [NIC_WOL_LOAD_INFO] = remote_nic_wol_load_info,
2529 [NIC_OFFLOAD_PROBE] = remote_nic_offload_probe,
2530 [NIC_OFFLOAD_SET] = remote_nic_offload_set,
2531 [NIC_POLL_GET_MODE] = remote_nic_poll_get_mode,
2532 [NIC_POLL_SET_MODE] = remote_nic_poll_set_mode,
2533 [NIC_POLL_NOW] = remote_nic_poll_now
2534};
2535
2536/** Remote NIC interface structure.
2537 *
2538 * Interface for processing request from remote
2539 * clients addressed to the NIC interface.
2540 *
2541 */
2542const remote_iface_t remote_nic_iface = {
2543 .method_count = ARRAY_SIZE(remote_nic_iface_ops),
2544 .methods = remote_nic_iface_ops
2545};
2546
2547/**
2548 * @}
2549 */
Note: See TracBrowser for help on using the repository browser.