Add missing calls to refcount_init()
[helenos.git] / uspace / lib / drv / generic / remote_nic.c
blob172374043fb5cd6dce3098dc584b03e95ae24b14
1 /*
2 * Copyright (c) 2011 Radim Vansa
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
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.
29 /** @addtogroup libdrv
30 * @{
32 /**
33 * @file
34 * @brief Driver-side RPC skeletons for DDF NIC interface
37 #include <assert.h>
38 #include <async.h>
39 #include <errno.h>
40 #include <ipc/services.h>
41 #include <time.h>
42 #include <macros.h>
44 #include "ops/nic.h"
45 #include "nic_iface.h"
47 typedef 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;
91 /** Send frame from NIC
93 * @param[in] dev_sess
94 * @param[in] data Frame data
95 * @param[in] size Frame size in bytes
97 * @return EOK If the operation was successfully completed
100 errno_t nic_send_frame(async_sess_t *dev_sess, void *data, size_t size)
102 async_exch_t *exch = async_exchange_begin(dev_sess);
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 errno_t retval = async_data_write_start(exch, data, size);
109 async_exchange_end(exch);
111 if (retval != EOK) {
112 async_forget(req);
113 return retval;
116 async_wait_for(req, &retval);
117 return retval;
120 /** Create callback connection from NIC service
122 * @param[in] dev_sess
123 * @param[in] device_id
125 * @return EOK If the operation was successfully completed
128 errno_t nic_callback_create(async_sess_t *dev_sess, async_port_handler_t cfun,
129 void *carg)
131 ipc_call_t answer;
132 errno_t rc;
133 errno_t retval;
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);
139 port_id_t port;
140 rc = async_create_callback_port(exch, INTERFACE_NIC_CB, 0, 0,
141 cfun, carg, &port);
142 if (rc != EOK) {
143 async_forget(req);
144 return rc;
146 async_exchange_end(exch);
148 async_wait_for(req, &retval);
149 return retval;
152 /** Get the current state of the device
154 * @param[in] dev_sess
155 * @param[out] state Current state
157 * @return EOK If the operation was successfully completed
160 errno_t nic_get_state(async_sess_t *dev_sess, nic_device_state_t *state)
162 assert(state);
164 sysarg_t _state;
166 async_exch_t *exch = async_exchange_begin(dev_sess);
167 errno_t rc = async_req_1_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
168 NIC_GET_STATE, &_state);
169 async_exchange_end(exch);
171 *state = (nic_device_state_t) _state;
173 return rc;
176 /** Request the device to change its state
178 * @param[in] dev_sess
179 * @param[in] state New state
181 * @return EOK If the operation was successfully completed
184 errno_t nic_set_state(async_sess_t *dev_sess, nic_device_state_t state)
186 async_exch_t *exch = async_exchange_begin(dev_sess);
187 errno_t rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
188 NIC_SET_STATE, state);
189 async_exchange_end(exch);
191 return rc;
194 /** Request the MAC address of the device
196 * @param[in] dev_sess
197 * @param[out] address Structure with buffer for the address
199 * @return EOK If the operation was successfully completed
202 errno_t nic_get_address(async_sess_t *dev_sess, nic_address_t *address)
204 assert(address);
206 async_exch_t *exch = async_exchange_begin(dev_sess);
207 aid_t aid = async_send_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
208 NIC_GET_ADDRESS, NULL);
209 errno_t rc = async_data_read_start(exch, address, sizeof(nic_address_t));
210 async_exchange_end(exch);
212 errno_t res;
213 async_wait_for(aid, &res);
215 if (rc != EOK)
216 return rc;
218 return res;
221 /** Set the address of the device (e.g. MAC on Ethernet)
223 * @param[in] dev_sess
224 * @param[in] address Pointer to the address
226 * @return EOK If the operation was successfully completed
229 errno_t nic_set_address(async_sess_t *dev_sess, const nic_address_t *address)
231 assert(address);
233 async_exch_t *exch = async_exchange_begin(dev_sess);
234 aid_t aid = async_send_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
235 NIC_SET_ADDRESS, NULL);
236 errno_t rc = async_data_write_start(exch, address, sizeof(nic_address_t));
237 async_exchange_end(exch);
239 errno_t res;
240 async_wait_for(aid, &res);
242 if (rc != EOK)
243 return rc;
245 return res;
248 /** Request statistic data about NIC operation.
250 * @param[in] dev_sess
251 * @param[out] stats Structure with the statistics
253 * @return EOK If the operation was successfully completed
256 errno_t nic_get_stats(async_sess_t *dev_sess, nic_device_stats_t *stats)
258 assert(stats);
260 async_exch_t *exch = async_exchange_begin(dev_sess);
262 errno_t rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
263 NIC_GET_STATS);
264 if (rc != EOK) {
265 async_exchange_end(exch);
266 return rc;
269 rc = async_data_read_start(exch, stats, sizeof(nic_device_stats_t));
271 async_exchange_end(exch);
273 return rc;
276 /** Request information about the device.
278 * @see nic_device_info_t
280 * @param[in] dev_sess
281 * @param[out] device_info Information about the device
283 * @return EOK If the operation was successfully completed
286 errno_t nic_get_device_info(async_sess_t *dev_sess, nic_device_info_t *device_info)
288 assert(device_info);
290 async_exch_t *exch = async_exchange_begin(dev_sess);
292 aid_t aid = async_send_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
293 NIC_GET_DEVICE_INFO, NULL);
294 errno_t rc = async_data_read_start(exch, device_info, sizeof(nic_device_info_t));
295 async_exchange_end(exch);
297 errno_t res;
298 async_wait_for(aid, &res);
300 if (rc != EOK)
301 return rc;
303 return res;
306 /** Request status of the cable (plugged/unplugged)
308 * @param[in] dev_sess
309 * @param[out] cable_state Current cable state
311 * @return EOK If the operation was successfully completed
314 errno_t nic_get_cable_state(async_sess_t *dev_sess, nic_cable_state_t *cable_state)
316 assert(cable_state);
318 sysarg_t _cable_state;
320 async_exch_t *exch = async_exchange_begin(dev_sess);
321 errno_t rc = async_req_1_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
322 NIC_GET_CABLE_STATE, &_cable_state);
323 async_exchange_end(exch);
325 *cable_state = (nic_cable_state_t) _cable_state;
327 return rc;
330 /** Request current operation mode.
332 * @param[in] dev_sess
333 * @param[out] speed Current operation speed in Mbps. Can be NULL.
334 * @param[out] duplex Full duplex/half duplex. Can be NULL.
335 * @param[out] role Master/slave/auto. Can be NULL.
337 * @return EOK If the operation was successfully completed
340 errno_t nic_get_operation_mode(async_sess_t *dev_sess, int *speed,
341 nic_channel_mode_t *duplex, nic_role_t *role)
343 sysarg_t _speed;
344 sysarg_t _duplex;
345 sysarg_t _role;
347 async_exch_t *exch = async_exchange_begin(dev_sess);
348 errno_t rc = async_req_1_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
349 NIC_GET_OPERATION_MODE, &_speed, &_duplex, &_role);
350 async_exchange_end(exch);
352 if (speed)
353 *speed = (int) _speed;
355 if (duplex)
356 *duplex = (nic_channel_mode_t) _duplex;
358 if (role)
359 *role = (nic_role_t) _role;
361 return rc;
364 /** Set current operation mode.
366 * If the NIC has auto-negotiation enabled, this command
367 * disables auto-negotiation and sets the operation mode.
369 * @param[in] dev_sess
370 * @param[in] speed Operation speed in Mbps
371 * @param[in] duplex Full duplex/half duplex
372 * @param[in] role Master/slave/auto (e.g. in Gbit Ethernet]
374 * @return EOK If the operation was successfully completed
377 errno_t nic_set_operation_mode(async_sess_t *dev_sess, int speed,
378 nic_channel_mode_t duplex, nic_role_t role)
380 async_exch_t *exch = async_exchange_begin(dev_sess);
381 errno_t rc = async_req_4_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
382 NIC_SET_OPERATION_MODE, (sysarg_t) speed, (sysarg_t) duplex,
383 (sysarg_t) role);
384 async_exchange_end(exch);
386 return rc;
389 /** Enable auto-negotiation.
391 * The advertisement argument can only limit some modes,
392 * it can never force the NIC to advertise unsupported modes.
394 * The allowed modes are defined in "nic/eth_phys.h" in the C library.
396 * @param[in] dev_sess
397 * @param[in] advertisement Allowed advertised modes. Use 0 for all modes.
399 * @return EOK If the operation was successfully completed
402 errno_t nic_autoneg_enable(async_sess_t *dev_sess, uint32_t advertisement)
404 async_exch_t *exch = async_exchange_begin(dev_sess);
405 errno_t rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
406 NIC_AUTONEG_ENABLE, (sysarg_t) advertisement);
407 async_exchange_end(exch);
409 return rc;
412 /** Disable auto-negotiation.
414 * @param[in] dev_sess
416 * @return EOK If the operation was successfully completed
419 errno_t nic_autoneg_disable(async_sess_t *dev_sess)
421 async_exch_t *exch = async_exchange_begin(dev_sess);
422 errno_t rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
423 NIC_AUTONEG_DISABLE);
424 async_exchange_end(exch);
426 return rc;
429 /** Probe current state of auto-negotiation.
431 * Modes are defined in the "nic/eth_phys.h" in the C library.
433 * @param[in] dev_sess
434 * @param[out] our_advertisement Modes advertised by this NIC.
435 * Can be NULL.
436 * @param[out] their_advertisement Modes advertised by the other side.
437 * Can be NULL.
438 * @param[out] result General state of auto-negotiation.
439 * Can be NULL.
440 * @param[out] their_result State of other side auto-negotiation.
441 * Can be NULL.
443 * @return EOK If the operation was successfully completed
446 errno_t nic_autoneg_probe(async_sess_t *dev_sess, uint32_t *our_advertisement,
447 uint32_t *their_advertisement, nic_result_t *result,
448 nic_result_t *their_result)
450 sysarg_t _our_advertisement;
451 sysarg_t _their_advertisement;
452 sysarg_t _result;
453 sysarg_t _their_result;
455 async_exch_t *exch = async_exchange_begin(dev_sess);
456 errno_t rc = async_req_1_4(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
457 NIC_AUTONEG_PROBE, &_our_advertisement, &_their_advertisement,
458 &_result, &_their_result);
459 async_exchange_end(exch);
461 if (our_advertisement)
462 *our_advertisement = (uint32_t) _our_advertisement;
464 if (*their_advertisement)
465 *their_advertisement = (uint32_t) _their_advertisement;
467 if (result)
468 *result = (nic_result_t) _result;
470 if (their_result)
471 *their_result = (nic_result_t) _their_result;
473 return rc;
476 /** Restart the auto-negotiation process.
478 * @param[in] dev_sess
480 * @return EOK If the operation was successfully completed
483 errno_t nic_autoneg_restart(async_sess_t *dev_sess)
485 async_exch_t *exch = async_exchange_begin(dev_sess);
486 errno_t rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
487 NIC_AUTONEG_RESTART);
488 async_exchange_end(exch);
490 return rc;
493 /** Query party's sending and reception of the PAUSE frame.
495 * @param[in] dev_sess
496 * @param[out] we_send This NIC sends the PAUSE frame (true/false)
497 * @param[out] we_receive This NIC receives the PAUSE frame (true/false)
498 * @param[out] pause The time set to transmitted PAUSE frames.
500 * @return EOK If the operation was successfully completed
503 errno_t nic_get_pause(async_sess_t *dev_sess, nic_result_t *we_send,
504 nic_result_t *we_receive, uint16_t *pause)
506 sysarg_t _we_send;
507 sysarg_t _we_receive;
508 sysarg_t _pause;
510 async_exch_t *exch = async_exchange_begin(dev_sess);
511 errno_t rc = async_req_1_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
512 NIC_GET_PAUSE, &_we_send, &_we_receive, &_pause);
513 async_exchange_end(exch);
515 if (we_send)
516 *we_send = _we_send;
518 if (we_receive)
519 *we_receive = _we_receive;
521 if (pause)
522 *pause = _pause;
524 return rc;
527 /** Control sending and reception of the PAUSE frame.
529 * @param[in] dev_sess
530 * @param[in] allow_send Allow sending the PAUSE frame (true/false)
531 * @param[in] allow_receive Allow reception of the PAUSE frame (true/false)
532 * @param[in] pause Pause length in 512 bit units written
533 * to transmitted frames. The value 0 means
534 * auto value (the best). If the requested
535 * time cannot be set the driver is allowed
536 * to set the nearest supported value.
538 * @return EOK If the operation was successfully completed
541 errno_t nic_set_pause(async_sess_t *dev_sess, int allow_send, int allow_receive,
542 uint16_t pause)
544 async_exch_t *exch = async_exchange_begin(dev_sess);
545 errno_t rc = async_req_4_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
546 NIC_SET_PAUSE, allow_send, allow_receive, pause);
547 async_exchange_end(exch);
549 return rc;
552 /** Retrieve current settings of unicast frames reception.
554 * Note: In case of mode != NIC_UNICAST_LIST the contents of
555 * address_list and address_count are undefined.
557 * @param[in] dev_sess
558 * @param[out] mode Current operation mode
559 * @param[in] max_count Maximal number of addresses that could
560 * be written into the list buffer.
561 * @param[out] address_list Buffer for the list (array). Can be NULL.
562 * @param[out] address_count Number of addresses in the list before
563 * possible truncation due to the max_count.
565 * @return EOK If the operation was successfully completed
568 errno_t nic_unicast_get_mode(async_sess_t *dev_sess, nic_unicast_mode_t *mode,
569 size_t max_count, nic_address_t *address_list, size_t *address_count)
571 assert(mode);
573 sysarg_t _mode;
574 sysarg_t _address_count;
576 if (!address_list)
577 max_count = 0;
579 async_exch_t *exch = async_exchange_begin(dev_sess);
581 errno_t rc = async_req_2_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
582 NIC_UNICAST_GET_MODE, max_count, &_mode, &_address_count);
583 if (rc != EOK) {
584 async_exchange_end(exch);
585 return rc;
588 *mode = (nic_unicast_mode_t) _mode;
589 if (address_count)
590 *address_count = (size_t) _address_count;
592 if ((max_count) && (_address_count))
593 rc = async_data_read_start(exch, address_list,
594 max_count * sizeof(nic_address_t));
596 async_exchange_end(exch);
598 return rc;
601 /** Set which unicast frames are received.
603 * @param[in] dev_sess
604 * @param[in] mode Current operation mode
605 * @param[in] address_list The list of addresses. Can be NULL.
606 * @param[in] address_count Number of addresses in the list.
608 * @return EOK If the operation was successfully completed
611 errno_t nic_unicast_set_mode(async_sess_t *dev_sess, nic_unicast_mode_t mode,
612 const nic_address_t *address_list, size_t address_count)
614 if (address_list == NULL)
615 address_count = 0;
617 async_exch_t *exch = async_exchange_begin(dev_sess);
619 aid_t message_id = async_send_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
620 NIC_UNICAST_SET_MODE, (sysarg_t) mode, address_count, NULL);
622 errno_t rc;
623 if (address_count)
624 rc = async_data_write_start(exch, address_list,
625 address_count * sizeof(nic_address_t));
626 else
627 rc = EOK;
629 async_exchange_end(exch);
631 errno_t res;
632 async_wait_for(message_id, &res);
634 if (rc != EOK)
635 return rc;
637 return res;
640 /** Retrieve current settings of multicast frames reception.
642 * Note: In case of mode != NIC_MULTICAST_LIST the contents of
643 * address_list and address_count are undefined.
645 * @param[in] dev_sess
646 * @param[out] mode Current operation mode
647 * @param[in] max_count Maximal number of addresses that could
648 * be written into the list buffer.
649 * @param[out] address_list Buffer for the list (array). Can be NULL.
650 * @param[out] address_count Number of addresses in the list before
651 * possible truncation due to the max_count.
652 * Can be NULL.
654 * @return EOK If the operation was successfully completed
657 errno_t nic_multicast_get_mode(async_sess_t *dev_sess, nic_multicast_mode_t *mode,
658 size_t max_count, nic_address_t *address_list, size_t *address_count)
660 assert(mode);
662 sysarg_t _mode;
664 if (!address_list)
665 max_count = 0;
667 async_exch_t *exch = async_exchange_begin(dev_sess);
669 sysarg_t ac;
670 errno_t rc = async_req_2_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
671 NIC_MULTICAST_GET_MODE, max_count, &_mode, &ac);
672 if (rc != EOK) {
673 async_exchange_end(exch);
674 return rc;
677 *mode = (nic_multicast_mode_t) _mode;
678 if (address_count)
679 *address_count = (size_t) ac;
681 if ((max_count) && (ac))
682 rc = async_data_read_start(exch, address_list,
683 max_count * sizeof(nic_address_t));
685 async_exchange_end(exch);
686 return rc;
689 /** Set which multicast frames are received.
691 * @param[in] dev_sess
692 * @param[in] mode Current operation mode
693 * @param[in] address_list The list of addresses. Can be NULL.
694 * @param[in] address_count Number of addresses in the list.
696 * @return EOK If the operation was successfully completed
699 errno_t nic_multicast_set_mode(async_sess_t *dev_sess, nic_multicast_mode_t mode,
700 const nic_address_t *address_list, size_t address_count)
702 if (address_list == NULL)
703 address_count = 0;
705 async_exch_t *exch = async_exchange_begin(dev_sess);
707 aid_t message_id = async_send_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
708 NIC_MULTICAST_SET_MODE, (sysarg_t) mode, address_count, NULL);
710 errno_t rc;
711 if (address_count)
712 rc = async_data_write_start(exch, address_list,
713 address_count * sizeof(nic_address_t));
714 else
715 rc = EOK;
717 async_exchange_end(exch);
719 errno_t res;
720 async_wait_for(message_id, &res);
722 if (rc != EOK)
723 return rc;
725 return res;
728 /** Determine if broadcast packets are received.
730 * @param[in] dev_sess
731 * @param[out] mode Current operation mode
733 * @return EOK If the operation was successfully completed
736 errno_t nic_broadcast_get_mode(async_sess_t *dev_sess, nic_broadcast_mode_t *mode)
738 assert(mode);
740 sysarg_t _mode;
742 async_exch_t *exch = async_exchange_begin(dev_sess);
743 errno_t rc = async_req_1_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
744 NIC_BROADCAST_GET_MODE, &_mode);
745 async_exchange_end(exch);
747 *mode = (nic_broadcast_mode_t) _mode;
749 return rc;
752 /** Set whether broadcast packets are received.
754 * @param[in] dev_sess
755 * @param[in] mode Current operation mode
757 * @return EOK If the operation was successfully completed
760 errno_t nic_broadcast_set_mode(async_sess_t *dev_sess, nic_broadcast_mode_t mode)
762 async_exch_t *exch = async_exchange_begin(dev_sess);
763 errno_t rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
764 NIC_BROADCAST_SET_MODE, mode);
765 async_exchange_end(exch);
767 return rc;
770 /** Determine if defective (erroneous) packets are received.
772 * @param[in] dev_sess
773 * @param[out] mode Bitmask specifying allowed errors
775 * @return EOK If the operation was successfully completed
778 errno_t nic_defective_get_mode(async_sess_t *dev_sess, uint32_t *mode)
780 assert(mode);
782 sysarg_t _mode;
784 async_exch_t *exch = async_exchange_begin(dev_sess);
785 errno_t rc = async_req_1_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
786 NIC_DEFECTIVE_GET_MODE, &_mode);
787 async_exchange_end(exch);
789 *mode = (uint32_t) _mode;
791 return rc;
794 /** Set whether defective (erroneous) packets are received.
796 * @param[in] dev_sess
797 * @param[out] mode Bitmask specifying allowed errors
799 * @return EOK If the operation was successfully completed
802 errno_t nic_defective_set_mode(async_sess_t *dev_sess, uint32_t mode)
804 async_exch_t *exch = async_exchange_begin(dev_sess);
805 errno_t rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
806 NIC_DEFECTIVE_SET_MODE, mode);
807 async_exchange_end(exch);
809 return rc;
812 /** Retrieve the currently blocked source MAC addresses.
814 * @param[in] dev_sess
815 * @param[in] max_count Maximal number of addresses that could
816 * be written into the list buffer.
817 * @param[out] address_list Buffer for the list (array). Can be NULL.
818 * @param[out] address_count Number of addresses in the list before
819 * possible truncation due to the max_count.
821 * @return EOK If the operation was successfully completed
824 errno_t nic_blocked_sources_get(async_sess_t *dev_sess, size_t max_count,
825 nic_address_t *address_list, size_t *address_count)
827 if (!address_list)
828 max_count = 0;
830 async_exch_t *exch = async_exchange_begin(dev_sess);
832 sysarg_t ac;
833 errno_t rc = async_req_2_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
834 NIC_BLOCKED_SOURCES_GET, max_count, &ac);
835 if (rc != EOK) {
836 async_exchange_end(exch);
837 return rc;
840 if (address_count)
841 *address_count = (size_t) ac;
843 if ((max_count) && (ac))
844 rc = async_data_read_start(exch, address_list,
845 max_count * sizeof(nic_address_t));
847 async_exchange_end(exch);
848 return rc;
851 /** Set which source MACs are blocked
853 * @param[in] dev_sess
854 * @param[in] address_list The list of addresses. Can be NULL.
855 * @param[in] address_count Number of addresses in the list.
857 * @return EOK If the operation was successfully completed
860 errno_t nic_blocked_sources_set(async_sess_t *dev_sess,
861 const nic_address_t *address_list, size_t address_count)
863 if (address_list == NULL)
864 address_count = 0;
866 async_exch_t *exch = async_exchange_begin(dev_sess);
868 aid_t message_id = async_send_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
869 NIC_BLOCKED_SOURCES_SET, address_count, NULL);
871 errno_t rc;
872 if (address_count)
873 rc = async_data_write_start(exch, address_list,
874 address_count * sizeof(nic_address_t));
875 else
876 rc = EOK;
878 async_exchange_end(exch);
880 errno_t res;
881 async_wait_for(message_id, &res);
883 if (rc != EOK)
884 return rc;
886 return res;
889 /** Request current VLAN filtering mask.
891 * @param[in] dev_sess
892 * @param[out] stats Structure with the statistics
894 * @return EOK If the operation was successfully completed
897 errno_t nic_vlan_get_mask(async_sess_t *dev_sess, nic_vlan_mask_t *mask)
899 assert(mask);
901 async_exch_t *exch = async_exchange_begin(dev_sess);
902 errno_t rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
903 NIC_VLAN_GET_MASK);
904 if (rc != EOK) {
905 async_exchange_end(exch);
906 return rc;
909 rc = async_data_read_start(exch, mask, sizeof(nic_vlan_mask_t));
910 async_exchange_end(exch);
912 return rc;
915 /** Set the mask used for VLAN filtering.
917 * If NULL, VLAN filtering is disabled.
919 * @param[in] dev_sess
920 * @param[in] mask Pointer to mask structure or NULL to disable.
922 * @return EOK If the operation was successfully completed
925 errno_t nic_vlan_set_mask(async_sess_t *dev_sess, const nic_vlan_mask_t *mask)
927 async_exch_t *exch = async_exchange_begin(dev_sess);
929 aid_t message_id = async_send_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
930 NIC_VLAN_SET_MASK, mask != NULL, NULL);
932 errno_t rc;
933 if (mask != NULL)
934 rc = async_data_write_start(exch, mask, sizeof(nic_vlan_mask_t));
935 else
936 rc = EOK;
938 async_exchange_end(exch);
940 errno_t res;
941 async_wait_for(message_id, &res);
943 if (rc != EOK)
944 return rc;
946 return res;
949 /** Set VLAN (802.1q) tag.
951 * Set whether the tag is to be signaled in offload info and
952 * if the tag should be stripped from received frames and added
953 * to sent frames automatically. Not every combination of add
954 * and strip must be supported.
956 * @param[in] dev_sess
957 * @param[in] tag VLAN priority (top 3 bits) and
958 * the VLAN tag (bottom 12 bits)
959 * @param[in] add Add the VLAN tag automatically (boolean)
960 * @param[in] strip Strip the VLAN tag automatically (boolean)
962 * @return EOK If the operation was successfully completed
965 errno_t nic_vlan_set_tag(async_sess_t *dev_sess, uint16_t tag, bool add, bool strip)
967 async_exch_t *exch = async_exchange_begin(dev_sess);
968 errno_t rc = async_req_4_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
969 NIC_VLAN_SET_TAG, (sysarg_t) tag, (sysarg_t) add, (sysarg_t) strip);
970 async_exchange_end(exch);
972 return rc;
975 /** Add new Wake-On-LAN virtue.
977 * @param[in] dev_sess
978 * @param[in] type Type of the virtue
979 * @param[in] data Data required for this virtue
980 * (depends on type)
981 * @param[in] length Length of the data
982 * @param[out] id Identifier of the new virtue
984 * @return EOK If the operation was successfully completed
987 errno_t nic_wol_virtue_add(async_sess_t *dev_sess, nic_wv_type_t type,
988 const void *data, size_t length, nic_wv_id_t *id)
990 assert(id);
992 bool send_data = ((data != NULL) && (length != 0));
993 async_exch_t *exch = async_exchange_begin(dev_sess);
995 ipc_call_t result;
996 aid_t message_id = async_send_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
997 NIC_WOL_VIRTUE_ADD, (sysarg_t) type, send_data, &result);
999 errno_t res;
1000 if (send_data) {
1001 errno_t rc = async_data_write_start(exch, data, length);
1002 if (rc != EOK) {
1003 async_exchange_end(exch);
1004 async_wait_for(message_id, &res);
1005 return rc;
1009 async_exchange_end(exch);
1010 async_wait_for(message_id, &res);
1012 *id = IPC_GET_ARG1(result);
1013 return res;
1016 /** Remove Wake-On-LAN virtue.
1018 * @param[in] dev_sess
1019 * @param[in] id Virtue identifier
1021 * @return EOK If the operation was successfully completed
1024 errno_t nic_wol_virtue_remove(async_sess_t *dev_sess, nic_wv_id_t id)
1026 async_exch_t *exch = async_exchange_begin(dev_sess);
1027 errno_t rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1028 NIC_WOL_VIRTUE_REMOVE, (sysarg_t) id);
1029 async_exchange_end(exch);
1031 return rc;
1034 /** Get information about virtue.
1036 * @param[in] dev_sess
1037 * @param[in] id Virtue identifier
1038 * @param[out] type Type of the filter. Can be NULL.
1039 * @param[out] max_length Size of the data buffer.
1040 * @param[out] data Buffer for data used when the
1041 * virtue was created. Can be NULL.
1042 * @param[out] length Length of the data. Can be NULL.
1044 * @return EOK If the operation was successfully completed
1047 errno_t nic_wol_virtue_probe(async_sess_t *dev_sess, nic_wv_id_t id,
1048 nic_wv_type_t *type, size_t max_length, void *data, size_t *length)
1050 sysarg_t _type;
1051 sysarg_t _length;
1053 if (data == NULL)
1054 max_length = 0;
1056 async_exch_t *exch = async_exchange_begin(dev_sess);
1058 errno_t rc = async_req_3_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1059 NIC_WOL_VIRTUE_PROBE, (sysarg_t) id, max_length,
1060 &_type, &_length);
1061 if (rc != EOK) {
1062 async_exchange_end(exch);
1063 return rc;
1066 if (type)
1067 *type = _type;
1069 if (length)
1070 *length = _length;
1072 if ((max_length) && (_length != 0))
1073 rc = async_data_read_start(exch, data, max_length);
1075 async_exchange_end(exch);
1076 return rc;
1079 /** Get a list of all virtues of the specified type.
1081 * When NIC_WV_NONE is specified as the virtue type the function
1082 * lists virtues of all types.
1084 * @param[in] dev_sess
1085 * @param[in] type Type of the virtues
1086 * @param[in] max_count Maximum number of ids that can be
1087 * written into the list buffer.
1088 * @param[out] id_list Buffer for to the list of virtue ids.
1089 * Can be NULL.
1090 * @param[out] id_count Number of virtue identifiers in the list
1091 * before possible truncation due to the
1092 * max_count. Can be NULL.
1094 * @return EOK If the operation was successfully completed
1097 errno_t nic_wol_virtue_list(async_sess_t *dev_sess, nic_wv_type_t type,
1098 size_t max_count, nic_wv_id_t *id_list, size_t *id_count)
1100 if (id_list == NULL)
1101 max_count = 0;
1103 async_exch_t *exch = async_exchange_begin(dev_sess);
1105 sysarg_t count;
1106 errno_t rc = async_req_3_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1107 NIC_WOL_VIRTUE_LIST, (sysarg_t) type, max_count, &count);
1109 if (id_count)
1110 *id_count = (size_t) count;
1112 if ((rc != EOK) || (!max_count)) {
1113 async_exchange_end(exch);
1114 return rc;
1117 rc = async_data_read_start(exch, id_list,
1118 max_count * sizeof(nic_wv_id_t));
1120 async_exchange_end(exch);
1121 return rc;
1124 /** Get number of virtues that can be enabled yet.
1126 * Count: < 0 => Virtue of this type can be never used
1127 * = 0 => No more virtues can be enabled
1128 * > 0 => #count virtues can be enabled yet
1130 * @param[in] dev_sess
1131 * @param[in] type Virtue type
1132 * @param[out] count Number of virtues
1134 * @return EOK If the operation was successfully completed
1137 errno_t nic_wol_virtue_get_caps(async_sess_t *dev_sess, nic_wv_type_t type,
1138 int *count)
1140 assert(count);
1142 sysarg_t _count;
1144 async_exch_t *exch = async_exchange_begin(dev_sess);
1145 errno_t rc = async_req_2_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1146 NIC_WOL_VIRTUE_GET_CAPS, (sysarg_t) type, &_count);
1147 async_exchange_end(exch);
1149 *count = (int) _count;
1150 return rc;
1153 /** Load the frame that issued the wakeup.
1155 * The NIC can support only matched_type, only part of the frame
1156 * can be available or not at all. Sometimes even the type can be
1157 * uncertain -- in this case the matched_type contains NIC_WV_NONE.
1159 * Frame_length can be greater than max_length, but at most max_length
1160 * bytes will be copied into the frame buffer.
1162 * Note: Only the type of the filter can be detected, not the concrete
1163 * filter, because the driver is probably not running when the wakeup
1164 * is issued.
1166 * @param[in] dev_sess
1167 * @param[out] matched_type Type of the filter that issued wakeup.
1168 * @param[in] max_length Size of the buffer
1169 * @param[out] frame Buffer for the frame. Can be NULL.
1170 * @param[out] frame_length Length of the stored frame. Can be NULL.
1172 * @return EOK If the operation was successfully completed
1175 errno_t nic_wol_load_info(async_sess_t *dev_sess, nic_wv_type_t *matched_type,
1176 size_t max_length, uint8_t *frame, size_t *frame_length)
1178 assert(matched_type);
1180 sysarg_t _matched_type;
1181 sysarg_t _frame_length;
1183 if (frame == NULL)
1184 max_length = 0;
1186 async_exch_t *exch = async_exchange_begin(dev_sess);
1188 errno_t rc = async_req_2_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1189 NIC_WOL_LOAD_INFO, max_length, &_matched_type, &_frame_length);
1190 if (rc != EOK) {
1191 async_exchange_end(exch);
1192 return rc;
1195 *matched_type = (nic_wv_type_t) _matched_type;
1196 if (frame_length)
1197 *frame_length = (size_t) _frame_length;
1199 if ((max_length != 0) && (_frame_length != 0))
1200 rc = async_data_read_start(exch, frame, max_length);
1202 async_exchange_end(exch);
1203 return rc;
1206 /** Probe supported options and current setting of offload computations
1208 * @param[in] dev_sess
1209 * @param[out] supported Supported offload options
1210 * @param[out] active Currently active offload options
1212 * @return EOK If the operation was successfully completed
1215 errno_t nic_offload_probe(async_sess_t *dev_sess, uint32_t *supported,
1216 uint32_t *active)
1218 assert(supported);
1219 assert(active);
1221 sysarg_t _supported;
1222 sysarg_t _active;
1224 async_exch_t *exch = async_exchange_begin(dev_sess);
1225 errno_t rc = async_req_1_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1226 NIC_OFFLOAD_PROBE, &_supported, &_active);
1227 async_exchange_end(exch);
1229 *supported = (uint32_t) _supported;
1230 *active = (uint32_t) _active;
1231 return rc;
1234 /** Set which offload computations can be performed on the NIC.
1236 * @param[in] dev_sess
1237 * @param[in] mask Mask for the options (only those set here will be set)
1238 * @param[in] active Which options should be enabled and which disabled
1240 * @return EOK If the operation was successfully completed
1243 errno_t nic_offload_set(async_sess_t *dev_sess, uint32_t mask, uint32_t active)
1245 async_exch_t *exch = async_exchange_begin(dev_sess);
1246 errno_t rc = async_req_3_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1247 NIC_AUTONEG_RESTART, (sysarg_t) mask, (sysarg_t) active);
1248 async_exchange_end(exch);
1250 return rc;
1253 /** Query the current interrupt/poll mode of the NIC
1255 * @param[in] dev_sess
1256 * @param[out] mode Current poll mode
1257 * @param[out] period Period used in periodic polling.
1258 * Can be NULL.
1260 * @return EOK If the operation was successfully completed
1263 errno_t nic_poll_get_mode(async_sess_t *dev_sess, nic_poll_mode_t *mode,
1264 struct timespec *period)
1266 assert(mode);
1268 sysarg_t _mode;
1270 async_exch_t *exch = async_exchange_begin(dev_sess);
1272 errno_t rc = async_req_2_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1273 NIC_POLL_GET_MODE, period != NULL, &_mode);
1274 if (rc != EOK) {
1275 async_exchange_end(exch);
1276 return rc;
1279 *mode = (nic_poll_mode_t) _mode;
1281 if (period != NULL)
1282 rc = async_data_read_start(exch, period, sizeof(struct timespec));
1284 async_exchange_end(exch);
1285 return rc;
1288 /** Set the interrupt/poll mode of the NIC.
1290 * @param[in] dev_sess
1291 * @param[in] mode New poll mode
1292 * @param[in] period Period used in periodic polling. Can be NULL.
1294 * @return EOK If the operation was successfully completed
1297 errno_t nic_poll_set_mode(async_sess_t *dev_sess, nic_poll_mode_t mode,
1298 const struct timespec *period)
1300 async_exch_t *exch = async_exchange_begin(dev_sess);
1302 aid_t message_id = async_send_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1303 NIC_POLL_SET_MODE, (sysarg_t) mode, period != NULL, NULL);
1305 errno_t rc;
1306 if (period)
1307 rc = async_data_write_start(exch, period, sizeof(struct timespec));
1308 else
1309 rc = EOK;
1311 async_exchange_end(exch);
1313 errno_t res;
1314 async_wait_for(message_id, &res);
1316 if (rc != EOK)
1317 return rc;
1319 return res;
1322 /** Request the driver to poll the NIC.
1324 * @param[in] dev_sess
1326 * @return EOK If the operation was successfully completed
1329 errno_t nic_poll_now(async_sess_t *dev_sess)
1331 async_exch_t *exch = async_exchange_begin(dev_sess);
1332 errno_t rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE), NIC_POLL_NOW);
1333 async_exchange_end(exch);
1335 return rc;
1338 static void remote_nic_send_frame(ddf_fun_t *dev, void *iface,
1339 ipc_call_t *call)
1341 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1342 assert(nic_iface->send_frame);
1344 void *data;
1345 size_t size;
1346 errno_t rc;
1348 rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
1349 if (rc != EOK) {
1350 async_answer_0(call, EINVAL);
1351 return;
1354 rc = nic_iface->send_frame(dev, data, size);
1355 async_answer_0(call, rc);
1356 free(data);
1359 static void remote_nic_callback_create(ddf_fun_t *dev, void *iface,
1360 ipc_call_t *call)
1362 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1363 assert(nic_iface->callback_create);
1365 errno_t rc = nic_iface->callback_create(dev);
1366 async_answer_0(call, rc);
1369 static void remote_nic_get_state(ddf_fun_t *dev, void *iface,
1370 ipc_call_t *call)
1372 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1373 assert(nic_iface->get_state);
1375 nic_device_state_t state = NIC_STATE_MAX;
1377 errno_t rc = nic_iface->get_state(dev, &state);
1378 async_answer_1(call, rc, state);
1381 static void remote_nic_set_state(ddf_fun_t *dev, void *iface,
1382 ipc_call_t *call)
1384 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1385 assert(nic_iface->set_state);
1387 nic_device_state_t state = (nic_device_state_t) IPC_GET_ARG2(*call);
1389 errno_t rc = nic_iface->set_state(dev, state);
1390 async_answer_0(call, rc);
1393 static void remote_nic_get_address(ddf_fun_t *dev, void *iface,
1394 ipc_call_t *call)
1396 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1397 assert(nic_iface->get_address);
1399 nic_address_t address;
1400 memset(&address, 0, sizeof(nic_address_t));
1402 errno_t rc = nic_iface->get_address(dev, &address);
1403 if (rc == EOK) {
1404 ipc_call_t data;
1405 size_t max_len;
1407 /* All errors will be translated into EPARTY anyway */
1408 if (!async_data_read_receive(&data, &max_len)) {
1409 async_answer_0(&data, EINVAL);
1410 async_answer_0(call, EINVAL);
1411 return;
1414 if (max_len != sizeof(nic_address_t)) {
1415 async_answer_0(&data, ELIMIT);
1416 async_answer_0(call, ELIMIT);
1417 return;
1420 async_data_read_finalize(&data, &address,
1421 sizeof(nic_address_t));
1424 async_answer_0(call, rc);
1427 static void remote_nic_set_address(ddf_fun_t *dev, void *iface,
1428 ipc_call_t *call)
1430 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1432 ipc_call_t data;
1433 size_t length;
1434 if (!async_data_write_receive(&data, &length)) {
1435 async_answer_0(&data, EINVAL);
1436 async_answer_0(call, EINVAL);
1437 return;
1440 if (length > sizeof(nic_address_t)) {
1441 async_answer_0(&data, ELIMIT);
1442 async_answer_0(call, ELIMIT);
1443 return;
1446 nic_address_t address;
1447 if (async_data_write_finalize(&data, &address, length) != EOK) {
1448 async_answer_0(call, EINVAL);
1449 return;
1452 if (nic_iface->set_address != NULL) {
1453 errno_t rc = nic_iface->set_address(dev, &address);
1454 async_answer_0(call, rc);
1455 } else
1456 async_answer_0(call, ENOTSUP);
1459 static void remote_nic_get_stats(ddf_fun_t *dev, void *iface,
1460 ipc_call_t *call)
1462 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1463 if (nic_iface->get_stats == NULL) {
1464 async_answer_0(call, ENOTSUP);
1465 return;
1468 nic_device_stats_t stats;
1469 memset(&stats, 0, sizeof(nic_device_stats_t));
1471 errno_t rc = nic_iface->get_stats(dev, &stats);
1472 if (rc == EOK) {
1473 ipc_call_t data;
1474 size_t max_len;
1475 if (!async_data_read_receive(&data, &max_len)) {
1476 async_answer_0(&data, EINVAL);
1477 async_answer_0(call, EINVAL);
1478 return;
1481 if (max_len < sizeof(nic_device_stats_t)) {
1482 async_answer_0(&data, ELIMIT);
1483 async_answer_0(call, ELIMIT);
1484 return;
1487 async_data_read_finalize(&data, &stats,
1488 sizeof(nic_device_stats_t));
1491 async_answer_0(call, rc);
1494 static void remote_nic_get_device_info(ddf_fun_t *dev, void *iface,
1495 ipc_call_t *call)
1497 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1498 if (nic_iface->get_device_info == NULL) {
1499 async_answer_0(call, ENOTSUP);
1500 return;
1503 nic_device_info_t info;
1504 memset(&info, 0, sizeof(nic_device_info_t));
1506 errno_t rc = nic_iface->get_device_info(dev, &info);
1507 if (rc == EOK) {
1508 ipc_call_t data;
1509 size_t max_len;
1510 if (!async_data_read_receive(&data, &max_len)) {
1511 async_answer_0(&data, EINVAL);
1512 async_answer_0(call, EINVAL);
1513 return;
1516 if (max_len < sizeof (nic_device_info_t)) {
1517 async_answer_0(&data, ELIMIT);
1518 async_answer_0(call, ELIMIT);
1519 return;
1522 async_data_read_finalize(&data, &info,
1523 sizeof(nic_device_info_t));
1526 async_answer_0(call, rc);
1529 static void remote_nic_get_cable_state(ddf_fun_t *dev, void *iface,
1530 ipc_call_t *call)
1532 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1533 if (nic_iface->get_cable_state == NULL) {
1534 async_answer_0(call, ENOTSUP);
1535 return;
1538 nic_cable_state_t cs = NIC_CS_UNKNOWN;
1540 errno_t rc = nic_iface->get_cable_state(dev, &cs);
1541 async_answer_1(call, rc, (sysarg_t) cs);
1544 static void remote_nic_get_operation_mode(ddf_fun_t *dev, void *iface,
1545 ipc_call_t *call)
1547 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1548 if (nic_iface->get_operation_mode == NULL) {
1549 async_answer_0(call, ENOTSUP);
1550 return;
1553 int speed = 0;
1554 nic_channel_mode_t duplex = NIC_CM_UNKNOWN;
1555 nic_role_t role = NIC_ROLE_UNKNOWN;
1557 errno_t rc = nic_iface->get_operation_mode(dev, &speed, &duplex, &role);
1558 async_answer_3(call, rc, (sysarg_t) speed, (sysarg_t) duplex,
1559 (sysarg_t) role);
1562 static void remote_nic_set_operation_mode(ddf_fun_t *dev, void *iface,
1563 ipc_call_t *call)
1565 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1566 if (nic_iface->set_operation_mode == NULL) {
1567 async_answer_0(call, ENOTSUP);
1568 return;
1571 int speed = (int) IPC_GET_ARG2(*call);
1572 nic_channel_mode_t duplex = (nic_channel_mode_t) IPC_GET_ARG3(*call);
1573 nic_role_t role = (nic_role_t) IPC_GET_ARG4(*call);
1575 errno_t rc = nic_iface->set_operation_mode(dev, speed, duplex, role);
1576 async_answer_0(call, rc);
1579 static void remote_nic_autoneg_enable(ddf_fun_t *dev, void *iface,
1580 ipc_call_t *call)
1582 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1583 if (nic_iface->autoneg_enable == NULL) {
1584 async_answer_0(call, ENOTSUP);
1585 return;
1588 uint32_t advertisement = (uint32_t) IPC_GET_ARG2(*call);
1590 errno_t rc = nic_iface->autoneg_enable(dev, advertisement);
1591 async_answer_0(call, rc);
1594 static void remote_nic_autoneg_disable(ddf_fun_t *dev, void *iface,
1595 ipc_call_t *call)
1597 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1598 if (nic_iface->autoneg_disable == NULL) {
1599 async_answer_0(call, ENOTSUP);
1600 return;
1603 errno_t rc = nic_iface->autoneg_disable(dev);
1604 async_answer_0(call, rc);
1607 static void remote_nic_autoneg_probe(ddf_fun_t *dev, void *iface,
1608 ipc_call_t *call)
1610 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1611 if (nic_iface->autoneg_probe == NULL) {
1612 async_answer_0(call, ENOTSUP);
1613 return;
1616 uint32_t our_adv = 0;
1617 uint32_t their_adv = 0;
1618 nic_result_t result = NIC_RESULT_NOT_AVAILABLE;
1619 nic_result_t their_result = NIC_RESULT_NOT_AVAILABLE;
1621 errno_t rc = nic_iface->autoneg_probe(dev, &our_adv, &their_adv, &result,
1622 &their_result);
1623 async_answer_4(call, rc, our_adv, their_adv, (sysarg_t) result,
1624 (sysarg_t) their_result);
1627 static void remote_nic_autoneg_restart(ddf_fun_t *dev, void *iface,
1628 ipc_call_t *call)
1630 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1631 if (nic_iface->autoneg_restart == NULL) {
1632 async_answer_0(call, ENOTSUP);
1633 return;
1636 errno_t rc = nic_iface->autoneg_restart(dev);
1637 async_answer_0(call, rc);
1640 static void remote_nic_get_pause(ddf_fun_t *dev, void *iface,
1641 ipc_call_t *call)
1643 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1644 if (nic_iface->get_pause == NULL) {
1645 async_answer_0(call, ENOTSUP);
1646 return;
1649 nic_result_t we_send;
1650 nic_result_t we_receive;
1651 uint16_t pause;
1653 errno_t rc = nic_iface->get_pause(dev, &we_send, &we_receive, &pause);
1654 async_answer_3(call, rc, we_send, we_receive, pause);
1657 static void remote_nic_set_pause(ddf_fun_t *dev, void *iface,
1658 ipc_call_t *call)
1660 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1661 if (nic_iface->set_pause == NULL) {
1662 async_answer_0(call, ENOTSUP);
1663 return;
1666 int allow_send = (int) IPC_GET_ARG2(*call);
1667 int allow_receive = (int) IPC_GET_ARG3(*call);
1668 uint16_t pause = (uint16_t) IPC_GET_ARG4(*call);
1670 errno_t rc = nic_iface->set_pause(dev, allow_send, allow_receive,
1671 pause);
1672 async_answer_0(call, rc);
1675 static void remote_nic_unicast_get_mode(ddf_fun_t *dev, void *iface,
1676 ipc_call_t *call)
1678 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1679 if (nic_iface->unicast_get_mode == NULL) {
1680 async_answer_0(call, ENOTSUP);
1681 return;
1684 size_t max_count = IPC_GET_ARG2(*call);
1685 nic_address_t *address_list = NULL;
1687 if (max_count != 0) {
1688 address_list = malloc(max_count * sizeof (nic_address_t));
1689 if (!address_list) {
1690 async_answer_0(call, ENOMEM);
1691 return;
1695 memset(address_list, 0, max_count * sizeof(nic_address_t));
1696 nic_unicast_mode_t mode = NIC_UNICAST_DEFAULT;
1697 size_t address_count = 0;
1699 errno_t rc = nic_iface->unicast_get_mode(dev, &mode, max_count, address_list,
1700 &address_count);
1702 if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
1703 free(address_list);
1704 async_answer_2(call, rc, mode, address_count);
1705 return;
1708 ipc_call_t data;
1709 size_t max_len;
1710 if (!async_data_read_receive(&data, &max_len)) {
1711 async_answer_0(&data, EINVAL);
1712 async_answer_2(call, rc, mode, address_count);
1713 free(address_list);
1714 return;
1717 if (max_len > address_count * sizeof(nic_address_t))
1718 max_len = address_count * sizeof(nic_address_t);
1720 if (max_len > max_count * sizeof(nic_address_t))
1721 max_len = max_count * sizeof(nic_address_t);
1723 async_data_read_finalize(&data, address_list, max_len);
1725 free(address_list);
1726 async_answer_2(call, rc, mode, address_count);
1729 static void remote_nic_unicast_set_mode(ddf_fun_t *dev, void *iface,
1730 ipc_call_t *call)
1732 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1734 size_t length;
1735 nic_unicast_mode_t mode = IPC_GET_ARG2(*call);
1736 size_t address_count = IPC_GET_ARG3(*call);
1737 nic_address_t *address_list = NULL;
1739 if (address_count) {
1740 ipc_call_t data;
1741 if (!async_data_write_receive(&data, &length)) {
1742 async_answer_0(&data, EINVAL);
1743 async_answer_0(call, EINVAL);
1744 return;
1747 if (length != address_count * sizeof(nic_address_t)) {
1748 async_answer_0(&data, ELIMIT);
1749 async_answer_0(call, ELIMIT);
1750 return;
1753 address_list = malloc(length);
1754 if (address_list == NULL) {
1755 async_answer_0(&data, ENOMEM);
1756 async_answer_0(call, ENOMEM);
1757 return;
1760 if (async_data_write_finalize(&data, address_list,
1761 length) != EOK) {
1762 async_answer_0(call, EINVAL);
1763 free(address_list);
1764 return;
1768 if (nic_iface->unicast_set_mode != NULL) {
1769 errno_t rc = nic_iface->unicast_set_mode(dev, mode, address_list,
1770 address_count);
1771 async_answer_0(call, rc);
1772 } else
1773 async_answer_0(call, ENOTSUP);
1775 free(address_list);
1778 static void remote_nic_multicast_get_mode(ddf_fun_t *dev, void *iface,
1779 ipc_call_t *call)
1781 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1782 if (nic_iface->multicast_get_mode == NULL) {
1783 async_answer_0(call, ENOTSUP);
1784 return;
1787 size_t max_count = IPC_GET_ARG2(*call);
1788 nic_address_t *address_list = NULL;
1790 if (max_count != 0) {
1791 address_list = malloc(max_count * sizeof(nic_address_t));
1792 if (!address_list) {
1793 async_answer_0(call, ENOMEM);
1794 return;
1798 memset(address_list, 0, max_count * sizeof(nic_address_t));
1799 nic_multicast_mode_t mode = NIC_MULTICAST_BLOCKED;
1800 size_t address_count = 0;
1802 errno_t rc = nic_iface->multicast_get_mode(dev, &mode, max_count, address_list,
1803 &address_count);
1805 if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
1806 free(address_list);
1807 async_answer_2(call, rc, mode, address_count);
1808 return;
1811 ipc_call_t data;
1812 size_t max_len;
1813 if (!async_data_read_receive(&data, &max_len)) {
1814 async_answer_0(&data, EINVAL);
1815 async_answer_2(call, rc, mode, address_count);
1816 free(address_list);
1817 return;
1820 if (max_len > address_count * sizeof(nic_address_t))
1821 max_len = address_count * sizeof(nic_address_t);
1823 if (max_len > max_count * sizeof(nic_address_t))
1824 max_len = max_count * sizeof(nic_address_t);
1826 async_data_read_finalize(&data, address_list, max_len);
1828 free(address_list);
1829 async_answer_2(call, rc, mode, address_count);
1832 static void remote_nic_multicast_set_mode(ddf_fun_t *dev, void *iface,
1833 ipc_call_t *call)
1835 nic_iface_t *nic_iface = (nic_iface_t *) iface;
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;
1841 if (address_count) {
1842 ipc_call_t data;
1843 size_t length;
1844 if (!async_data_write_receive(&data, &length)) {
1845 async_answer_0(&data, EINVAL);
1846 async_answer_0(call, EINVAL);
1847 return;
1850 if (length != address_count * sizeof (nic_address_t)) {
1851 async_answer_0(&data, ELIMIT);
1852 async_answer_0(call, ELIMIT);
1853 return;
1856 address_list = malloc(length);
1857 if (address_list == NULL) {
1858 async_answer_0(&data, ENOMEM);
1859 async_answer_0(call, ENOMEM);
1860 return;
1863 if (async_data_write_finalize(&data, address_list,
1864 length) != EOK) {
1865 async_answer_0(call, EINVAL);
1866 free(address_list);
1867 return;
1871 if (nic_iface->multicast_set_mode != NULL) {
1872 errno_t rc = nic_iface->multicast_set_mode(dev, mode, address_list,
1873 address_count);
1874 async_answer_0(call, rc);
1875 } else
1876 async_answer_0(call, ENOTSUP);
1878 free(address_list);
1881 static void remote_nic_broadcast_get_mode(ddf_fun_t *dev, void *iface,
1882 ipc_call_t *call)
1884 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1885 if (nic_iface->broadcast_get_mode == NULL) {
1886 async_answer_0(call, ENOTSUP);
1887 return;
1890 nic_broadcast_mode_t mode = NIC_BROADCAST_ACCEPTED;
1892 errno_t rc = nic_iface->broadcast_get_mode(dev, &mode);
1893 async_answer_1(call, rc, mode);
1896 static void remote_nic_broadcast_set_mode(ddf_fun_t *dev, void *iface,
1897 ipc_call_t *call)
1899 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1900 if (nic_iface->broadcast_set_mode == NULL) {
1901 async_answer_0(call, ENOTSUP);
1902 return;
1905 nic_broadcast_mode_t mode = IPC_GET_ARG2(*call);
1907 errno_t rc = nic_iface->broadcast_set_mode(dev, mode);
1908 async_answer_0(call, rc);
1911 static void remote_nic_defective_get_mode(ddf_fun_t *dev, void *iface,
1912 ipc_call_t *call)
1914 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1915 if (nic_iface->defective_get_mode == NULL) {
1916 async_answer_0(call, ENOTSUP);
1917 return;
1920 uint32_t mode = 0;
1922 errno_t rc = nic_iface->defective_get_mode(dev, &mode);
1923 async_answer_1(call, rc, mode);
1926 static void remote_nic_defective_set_mode(ddf_fun_t *dev, void *iface,
1927 ipc_call_t *call)
1929 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1930 if (nic_iface->defective_set_mode == NULL) {
1931 async_answer_0(call, ENOTSUP);
1932 return;
1935 uint32_t mode = IPC_GET_ARG2(*call);
1937 errno_t rc = nic_iface->defective_set_mode(dev, mode);
1938 async_answer_0(call, rc);
1941 static void remote_nic_blocked_sources_get(ddf_fun_t *dev, void *iface,
1942 ipc_call_t *call)
1944 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1945 if (nic_iface->blocked_sources_get == NULL) {
1946 async_answer_0(call, ENOTSUP);
1947 return;
1950 size_t max_count = IPC_GET_ARG2(*call);
1951 nic_address_t *address_list = NULL;
1953 if (max_count != 0) {
1954 address_list = malloc(max_count * sizeof(nic_address_t));
1955 if (!address_list) {
1956 async_answer_0(call, ENOMEM);
1957 return;
1961 memset(address_list, 0, max_count * sizeof(nic_address_t));
1962 size_t address_count = 0;
1964 errno_t rc = nic_iface->blocked_sources_get(dev, max_count, address_list,
1965 &address_count);
1967 if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
1968 async_answer_1(call, rc, address_count);
1969 free(address_list);
1970 return;
1973 ipc_call_t data;
1974 size_t max_len;
1975 if (!async_data_read_receive(&data, &max_len)) {
1976 async_answer_0(&data, EINVAL);
1977 async_answer_1(call, rc, address_count);
1978 free(address_list);
1979 return;
1982 if (max_len > address_count * sizeof(nic_address_t))
1983 max_len = address_count * sizeof(nic_address_t);
1985 if (max_len > max_count * sizeof(nic_address_t))
1986 max_len = max_count * sizeof(nic_address_t);
1988 async_data_read_finalize(&data, address_list, max_len);
1990 free(address_list);
1991 async_answer_1(call, rc, address_count);
1994 static void remote_nic_blocked_sources_set(ddf_fun_t *dev, void *iface,
1995 ipc_call_t *call)
1997 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1999 size_t length;
2000 size_t address_count = IPC_GET_ARG2(*call);
2001 nic_address_t *address_list = NULL;
2003 if (address_count) {
2004 ipc_call_t data;
2005 if (!async_data_write_receive(&data, &length)) {
2006 async_answer_0(&data, EINVAL);
2007 async_answer_0(call, EINVAL);
2008 return;
2011 if (length != address_count * sizeof(nic_address_t)) {
2012 async_answer_0(&data, ELIMIT);
2013 async_answer_0(call, ELIMIT);
2014 return;
2017 address_list = malloc(length);
2018 if (address_list == NULL) {
2019 async_answer_0(&data, ENOMEM);
2020 async_answer_0(call, ENOMEM);
2021 return;
2024 if (async_data_write_finalize(&data, address_list,
2025 length) != EOK) {
2026 async_answer_0(call, EINVAL);
2027 free(address_list);
2028 return;
2032 if (nic_iface->blocked_sources_set != NULL) {
2033 errno_t rc = nic_iface->blocked_sources_set(dev, address_list,
2034 address_count);
2035 async_answer_0(call, rc);
2036 } else
2037 async_answer_0(call, ENOTSUP);
2039 free(address_list);
2042 static void remote_nic_vlan_get_mask(ddf_fun_t *dev, void *iface,
2043 ipc_call_t *call)
2045 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2046 if (nic_iface->vlan_get_mask == NULL) {
2047 async_answer_0(call, ENOTSUP);
2048 return;
2051 nic_vlan_mask_t vlan_mask;
2052 memset(&vlan_mask, 0, sizeof(nic_vlan_mask_t));
2054 errno_t rc = nic_iface->vlan_get_mask(dev, &vlan_mask);
2055 if (rc == EOK) {
2056 ipc_call_t data;
2057 size_t max_len;
2058 if (!async_data_read_receive(&data, &max_len)) {
2059 async_answer_0(&data, EINVAL);
2060 async_answer_0(call, EINVAL);
2061 return;
2064 if (max_len != sizeof(nic_vlan_mask_t)) {
2065 async_answer_0(&data, EINVAL);
2066 async_answer_0(call, EINVAL);
2067 return;
2070 async_data_read_finalize(&data, &vlan_mask, max_len);
2073 async_answer_0(call, rc);
2076 static void remote_nic_vlan_set_mask(ddf_fun_t *dev, void *iface,
2077 ipc_call_t *call)
2079 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2081 nic_vlan_mask_t vlan_mask;
2082 nic_vlan_mask_t *vlan_mask_pointer = NULL;
2083 bool vlan_mask_set = (bool) IPC_GET_ARG2(*call);
2085 if (vlan_mask_set) {
2086 ipc_call_t data;
2087 size_t length;
2088 if (!async_data_write_receive(&data, &length)) {
2089 async_answer_0(&data, EINVAL);
2090 async_answer_0(call, EINVAL);
2091 return;
2094 if (length != sizeof(nic_vlan_mask_t)) {
2095 async_answer_0(&data, ELIMIT);
2096 async_answer_0(call, ELIMIT);
2097 return;
2100 if (async_data_write_finalize(&data, &vlan_mask,
2101 length) != EOK) {
2102 async_answer_0(call, EINVAL);
2103 return;
2106 vlan_mask_pointer = &vlan_mask;
2109 if (nic_iface->vlan_set_mask != NULL) {
2110 errno_t rc = nic_iface->vlan_set_mask(dev, vlan_mask_pointer);
2111 async_answer_0(call, rc);
2112 } else
2113 async_answer_0(call, ENOTSUP);
2116 static void remote_nic_vlan_set_tag(ddf_fun_t *dev, void *iface,
2117 ipc_call_t *call)
2119 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2121 if (nic_iface->vlan_set_tag == NULL) {
2122 async_answer_0(call, ENOTSUP);
2123 return;
2126 uint16_t tag = (uint16_t) IPC_GET_ARG2(*call);
2127 bool add = (int) IPC_GET_ARG3(*call);
2128 bool strip = (int) IPC_GET_ARG4(*call);
2130 errno_t rc = nic_iface->vlan_set_tag(dev, tag, add, strip);
2131 async_answer_0(call, rc);
2134 static void remote_nic_wol_virtue_add(ddf_fun_t *dev, void *iface,
2135 ipc_call_t *call)
2137 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2139 int send_data = (int) IPC_GET_ARG3(*call);
2140 ipc_call_t data;
2142 if (nic_iface->wol_virtue_add == NULL) {
2143 if (send_data) {
2144 async_data_write_receive(&data, NULL);
2145 async_answer_0(&data, ENOTSUP);
2148 async_answer_0(call, ENOTSUP);
2151 size_t length = 0;
2152 void *virtue = NULL;
2154 if (send_data) {
2155 if (!async_data_write_receive(&data, &length)) {
2156 async_answer_0(&data, EINVAL);
2157 async_answer_0(call, EINVAL);
2158 return;
2161 virtue = malloc(length);
2162 if (virtue == NULL) {
2163 async_answer_0(&data, ENOMEM);
2164 async_answer_0(call, ENOMEM);
2165 return;
2168 if (async_data_write_finalize(&data, virtue,
2169 length) != EOK) {
2170 async_answer_0(call, EINVAL);
2171 free(virtue);
2172 return;
2176 nic_wv_id_t id = 0;
2177 nic_wv_type_t type = (nic_wv_type_t) IPC_GET_ARG2(*call);
2179 errno_t rc = nic_iface->wol_virtue_add(dev, type, virtue, length, &id);
2180 async_answer_1(call, rc, (sysarg_t) id);
2181 free(virtue);
2184 static void remote_nic_wol_virtue_remove(ddf_fun_t *dev, void *iface,
2185 ipc_call_t *call)
2187 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2189 if (nic_iface->wol_virtue_remove == NULL) {
2190 async_answer_0(call, ENOTSUP);
2191 return;
2194 nic_wv_id_t id = (nic_wv_id_t) IPC_GET_ARG2(*call);
2196 errno_t rc = nic_iface->wol_virtue_remove(dev, id);
2197 async_answer_0(call, rc);
2200 static void remote_nic_wol_virtue_probe(ddf_fun_t *dev, void *iface,
2201 ipc_call_t *call)
2203 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2205 if (nic_iface->wol_virtue_probe == NULL) {
2206 async_answer_0(call, ENOTSUP);
2207 return;
2210 nic_wv_id_t id = (nic_wv_id_t) IPC_GET_ARG2(*call);
2211 size_t max_length = IPC_GET_ARG3(*call);
2212 nic_wv_type_t type = NIC_WV_NONE;
2213 size_t length = 0;
2214 ipc_call_t data;
2215 void *virtue = NULL;
2217 if (max_length != 0) {
2218 virtue = malloc(max_length);
2219 if (virtue == NULL) {
2220 async_answer_0(call, ENOMEM);
2221 return;
2225 memset(virtue, 0, max_length);
2227 errno_t rc = nic_iface->wol_virtue_probe(dev, id, &type, max_length,
2228 virtue, &length);
2230 if ((max_length != 0) && (length != 0)) {
2231 size_t req_length;
2232 if (!async_data_read_receive(&data, &req_length)) {
2233 async_answer_0(&data, EINVAL);
2234 async_answer_0(call, EINVAL);
2235 free(virtue);
2236 return;
2239 if (req_length > length)
2240 req_length = length;
2242 if (req_length > max_length)
2243 req_length = max_length;
2245 async_data_read_finalize(&data, virtue, req_length);
2248 async_answer_2(call, rc, (sysarg_t) type, (sysarg_t) length);
2249 free(virtue);
2252 static void remote_nic_wol_virtue_list(ddf_fun_t *dev, void *iface,
2253 ipc_call_t *call)
2255 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2256 if (nic_iface->wol_virtue_list == NULL) {
2257 async_answer_0(call, ENOTSUP);
2258 return;
2261 nic_wv_type_t type = (nic_wv_type_t) IPC_GET_ARG2(*call);
2262 size_t max_count = IPC_GET_ARG3(*call);
2263 size_t count = 0;
2264 nic_wv_id_t *id_list = NULL;
2265 ipc_call_t data;
2267 if (max_count != 0) {
2268 id_list = malloc(max_count * sizeof(nic_wv_id_t));
2269 if (id_list == NULL) {
2270 async_answer_0(call, ENOMEM);
2271 return;
2275 memset(id_list, 0, max_count * sizeof (nic_wv_id_t));
2277 errno_t rc = nic_iface->wol_virtue_list(dev, type, max_count, id_list,
2278 &count);
2280 if ((max_count != 0) && (count != 0)) {
2281 size_t req_length;
2282 if (!async_data_read_receive(&data, &req_length)) {
2283 async_answer_0(&data, EINVAL);
2284 async_answer_0(call, EINVAL);
2285 free(id_list);
2286 return;
2289 if (req_length > count * sizeof(nic_wv_id_t))
2290 req_length = count * sizeof(nic_wv_id_t);
2292 if (req_length > max_count * sizeof(nic_wv_id_t))
2293 req_length = max_count * sizeof(nic_wv_id_t);
2295 rc = async_data_read_finalize(&data, id_list, req_length);
2298 async_answer_1(call, rc, (sysarg_t) count);
2299 free(id_list);
2302 static void remote_nic_wol_virtue_get_caps(ddf_fun_t *dev, void *iface,
2303 ipc_call_t *call)
2305 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2306 if (nic_iface->wol_virtue_get_caps == NULL) {
2307 async_answer_0(call, ENOTSUP);
2308 return;
2311 int count = -1;
2312 nic_wv_type_t type = (nic_wv_type_t) IPC_GET_ARG2(*call);
2314 errno_t rc = nic_iface->wol_virtue_get_caps(dev, type, &count);
2315 async_answer_1(call, rc, (sysarg_t) count);
2318 static void remote_nic_wol_load_info(ddf_fun_t *dev, void *iface,
2319 ipc_call_t *call)
2321 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2322 if (nic_iface->wol_load_info == NULL) {
2323 async_answer_0(call, ENOTSUP);
2324 return;
2327 size_t max_length = (size_t) IPC_GET_ARG2(*call);
2328 size_t frame_length = 0;
2329 nic_wv_type_t type = NIC_WV_NONE;
2330 uint8_t *info = NULL;
2332 if (max_length != 0) {
2333 info = malloc(max_length);
2334 if (info == NULL) {
2335 async_answer_0(call, ENOMEM);
2336 return;
2340 memset(info, 0, max_length);
2342 errno_t rc = nic_iface->wol_load_info(dev, &type, max_length, info,
2343 &frame_length);
2344 if (rc == EOK) {
2345 ipc_call_t data;
2346 size_t req_length;
2347 if (!async_data_read_receive(&data, &req_length)) {
2348 async_answer_0(&data, EINVAL);
2349 async_answer_0(call, EINVAL);
2350 free(info);
2351 return;
2354 req_length = req_length > max_length ? max_length : req_length;
2355 req_length = req_length > frame_length ? frame_length : req_length;
2356 async_data_read_finalize(&data, info, req_length);
2359 async_answer_2(call, rc, (sysarg_t) type, (sysarg_t) frame_length);
2360 free(info);
2363 static void remote_nic_offload_probe(ddf_fun_t *dev, void *iface,
2364 ipc_call_t *call)
2366 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2367 if (nic_iface->offload_probe == NULL) {
2368 async_answer_0(call, ENOTSUP);
2369 return;
2372 uint32_t supported = 0;
2373 uint32_t active = 0;
2375 errno_t rc = nic_iface->offload_probe(dev, &supported, &active);
2376 async_answer_2(call, rc, supported, active);
2379 static void remote_nic_offload_set(ddf_fun_t *dev, void *iface,
2380 ipc_call_t *call)
2382 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2383 if (nic_iface->offload_set == NULL) {
2384 async_answer_0(call, ENOTSUP);
2385 return;
2388 uint32_t mask = (uint32_t) IPC_GET_ARG2(*call);
2389 uint32_t active = (uint32_t) IPC_GET_ARG3(*call);
2391 errno_t rc = nic_iface->offload_set(dev, mask, active);
2392 async_answer_0(call, rc);
2395 static void remote_nic_poll_get_mode(ddf_fun_t *dev, void *iface,
2396 ipc_call_t *call)
2398 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2399 if (nic_iface->poll_get_mode == NULL) {
2400 async_answer_0(call, ENOTSUP);
2401 return;
2404 nic_poll_mode_t mode = NIC_POLL_IMMEDIATE;
2405 int request_data = IPC_GET_ARG2(*call);
2406 struct timespec period = {
2407 .tv_sec = 0,
2408 .tv_nsec = 0
2411 errno_t rc = nic_iface->poll_get_mode(dev, &mode, &period);
2412 if ((rc == EOK) && (request_data)) {
2413 ipc_call_t data;
2414 size_t max_len;
2416 if (!async_data_read_receive(&data, &max_len)) {
2417 async_answer_0(&data, EINVAL);
2418 async_answer_0(call, EINVAL);
2419 return;
2422 if (max_len != sizeof(struct timespec)) {
2423 async_answer_0(&data, ELIMIT);
2424 async_answer_0(call, ELIMIT);
2425 return;
2428 async_data_read_finalize(&data, &period,
2429 sizeof(struct timespec));
2432 async_answer_1(call, rc, (sysarg_t) mode);
2435 static void remote_nic_poll_set_mode(ddf_fun_t *dev, void *iface,
2436 ipc_call_t *call)
2438 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2440 nic_poll_mode_t mode = IPC_GET_ARG2(*call);
2441 int has_period = IPC_GET_ARG3(*call);
2442 struct timespec period_buf;
2443 struct timespec *period = NULL;
2444 size_t length;
2446 if (has_period) {
2447 ipc_call_t data;
2448 if (!async_data_write_receive(&data, &length)) {
2449 async_answer_0(&data, EINVAL);
2450 async_answer_0(call, EINVAL);
2451 return;
2454 if (length != sizeof(struct timespec)) {
2455 async_answer_0(&data, ELIMIT);
2456 async_answer_0(call, ELIMIT);
2457 return;
2460 period = &period_buf;
2461 if (async_data_write_finalize(&data, period,
2462 length) != EOK) {
2463 async_answer_0(call, EINVAL);
2464 return;
2468 if (nic_iface->poll_set_mode != NULL) {
2469 errno_t rc = nic_iface->poll_set_mode(dev, mode, period);
2470 async_answer_0(call, rc);
2471 } else
2472 async_answer_0(call, ENOTSUP);
2475 static void remote_nic_poll_now(ddf_fun_t *dev, void *iface,
2476 ipc_call_t *call)
2478 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2479 if (nic_iface->poll_now == NULL) {
2480 async_answer_0(call, ENOTSUP);
2481 return;
2484 errno_t rc = nic_iface->poll_now(dev);
2485 async_answer_0(call, rc);
2488 /** Remote NIC interface operations.
2491 static const remote_iface_func_ptr_t remote_nic_iface_ops[] = {
2492 [NIC_SEND_MESSAGE] = remote_nic_send_frame,
2493 [NIC_CALLBACK_CREATE] = remote_nic_callback_create,
2494 [NIC_GET_STATE] = remote_nic_get_state,
2495 [NIC_SET_STATE] = remote_nic_set_state,
2496 [NIC_GET_ADDRESS] = remote_nic_get_address,
2497 [NIC_SET_ADDRESS] = remote_nic_set_address,
2498 [NIC_GET_STATS] = remote_nic_get_stats,
2499 [NIC_GET_DEVICE_INFO] = remote_nic_get_device_info,
2500 [NIC_GET_CABLE_STATE] = remote_nic_get_cable_state,
2501 [NIC_GET_OPERATION_MODE] = remote_nic_get_operation_mode,
2502 [NIC_SET_OPERATION_MODE] = remote_nic_set_operation_mode,
2503 [NIC_AUTONEG_ENABLE] = remote_nic_autoneg_enable,
2504 [NIC_AUTONEG_DISABLE] = remote_nic_autoneg_disable,
2505 [NIC_AUTONEG_PROBE] = remote_nic_autoneg_probe,
2506 [NIC_AUTONEG_RESTART] = remote_nic_autoneg_restart,
2507 [NIC_GET_PAUSE] = remote_nic_get_pause,
2508 [NIC_SET_PAUSE] = remote_nic_set_pause,
2509 [NIC_UNICAST_GET_MODE] = remote_nic_unicast_get_mode,
2510 [NIC_UNICAST_SET_MODE] = remote_nic_unicast_set_mode,
2511 [NIC_MULTICAST_GET_MODE] = remote_nic_multicast_get_mode,
2512 [NIC_MULTICAST_SET_MODE] = remote_nic_multicast_set_mode,
2513 [NIC_BROADCAST_GET_MODE] = remote_nic_broadcast_get_mode,
2514 [NIC_BROADCAST_SET_MODE] = remote_nic_broadcast_set_mode,
2515 [NIC_DEFECTIVE_GET_MODE] = remote_nic_defective_get_mode,
2516 [NIC_DEFECTIVE_SET_MODE] = remote_nic_defective_set_mode,
2517 [NIC_BLOCKED_SOURCES_GET] = remote_nic_blocked_sources_get,
2518 [NIC_BLOCKED_SOURCES_SET] = remote_nic_blocked_sources_set,
2519 [NIC_VLAN_GET_MASK] = remote_nic_vlan_get_mask,
2520 [NIC_VLAN_SET_MASK] = remote_nic_vlan_set_mask,
2521 [NIC_VLAN_SET_TAG] = remote_nic_vlan_set_tag,
2522 [NIC_WOL_VIRTUE_ADD] = remote_nic_wol_virtue_add,
2523 [NIC_WOL_VIRTUE_REMOVE] = remote_nic_wol_virtue_remove,
2524 [NIC_WOL_VIRTUE_PROBE] = remote_nic_wol_virtue_probe,
2525 [NIC_WOL_VIRTUE_LIST] = remote_nic_wol_virtue_list,
2526 [NIC_WOL_VIRTUE_GET_CAPS] = remote_nic_wol_virtue_get_caps,
2527 [NIC_WOL_LOAD_INFO] = remote_nic_wol_load_info,
2528 [NIC_OFFLOAD_PROBE] = remote_nic_offload_probe,
2529 [NIC_OFFLOAD_SET] = remote_nic_offload_set,
2530 [NIC_POLL_GET_MODE] = remote_nic_poll_get_mode,
2531 [NIC_POLL_SET_MODE] = remote_nic_poll_set_mode,
2532 [NIC_POLL_NOW] = remote_nic_poll_now
2535 /** Remote NIC interface structure.
2537 * Interface for processing request from remote
2538 * clients addressed to the NIC interface.
2541 const remote_iface_t remote_nic_iface = {
2542 .method_count = ARRAY_SIZE(remote_nic_iface_ops),
2543 .methods = remote_nic_iface_ops
2547 * @}