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

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

do not expose the call capability handler from the async framework

Keep the call capability handler encapsulated within the async framework
and do not expose it explicitly via its API. Use the pointer to
ipc_call_t as the sole object identifying an IPC call in the code that
uses the async framework.

This plugs a major leak in the abstraction and also simplifies both the
async framework (slightly) and all IPC servers.

  • Property mode set to 100644
File size: 63.7 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 */
100errno_t 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 errno_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 */
128errno_t nic_callback_create(async_sess_t *dev_sess, async_port_handler_t cfun,
129 void *carg)
130{
131 ipc_call_t answer;
132 errno_t rc;
133 errno_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 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;
145 }
146 async_exchange_end(exch);
147
148 async_wait_for(req, &retval);
149 return retval;
150}
151
152/** Get the current state of the device
153 *
154 * @param[in] dev_sess
155 * @param[out] state Current state
156 *
157 * @return EOK If the operation was successfully completed
158 *
159 */
160errno_t nic_get_state(async_sess_t *dev_sess, nic_device_state_t *state)
161{
162 assert(state);
163
164 sysarg_t _state;
165
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);
170
171 *state = (nic_device_state_t) _state;
172
173 return rc;
174}
175
176/** Request the device to change its state
177 *
178 * @param[in] dev_sess
179 * @param[in] state New state
180 *
181 * @return EOK If the operation was successfully completed
182 *
183 */
184errno_t nic_set_state(async_sess_t *dev_sess, nic_device_state_t state)
185{
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);
190
191 return rc;
192}
193
194/** Request the MAC address of the device
195 *
196 * @param[in] dev_sess
197 * @param[out] address Structure with buffer for the address
198 *
199 * @return EOK If the operation was successfully completed
200 *
201 */
202errno_t nic_get_address(async_sess_t *dev_sess, nic_address_t *address)
203{
204 assert(address);
205
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);
211
212 errno_t res;
213 async_wait_for(aid, &res);
214
215 if (rc != EOK)
216 return rc;
217
218 return res;
219}
220
221/** Set the address of the device (e.g. MAC on Ethernet)
222 *
223 * @param[in] dev_sess
224 * @param[in] address Pointer to the address
225 *
226 * @return EOK If the operation was successfully completed
227 *
228 */
229errno_t nic_set_address(async_sess_t *dev_sess, const nic_address_t *address)
230{
231 assert(address);
232
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);
238
239 errno_t res;
240 async_wait_for(aid, &res);
241
242 if (rc != EOK)
243 return rc;
244
245 return res;
246}
247
248/** Request statistic data about NIC operation.
249 *
250 * @param[in] dev_sess
251 * @param[out] stats Structure with the statistics
252 *
253 * @return EOK If the operation was successfully completed
254 *
255 */
256errno_t nic_get_stats(async_sess_t *dev_sess, nic_device_stats_t *stats)
257{
258 assert(stats);
259
260 async_exch_t *exch = async_exchange_begin(dev_sess);
261
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;
267 }
268
269 rc = async_data_read_start(exch, stats, sizeof(nic_device_stats_t));
270
271 async_exchange_end(exch);
272
273 return rc;
274}
275
276/** Request information about the device.
277 *
278 * @see nic_device_info_t
279 *
280 * @param[in] dev_sess
281 * @param[out] device_info Information about the device
282 *
283 * @return EOK If the operation was successfully completed
284 *
285 */
286errno_t nic_get_device_info(async_sess_t *dev_sess, nic_device_info_t *device_info)
287{
288 assert(device_info);
289
290 async_exch_t *exch = async_exchange_begin(dev_sess);
291
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);
296
297 errno_t res;
298 async_wait_for(aid, &res);
299
300 if (rc != EOK)
301 return rc;
302
303 return res;
304}
305
306/** Request status of the cable (plugged/unplugged)
307 *
308 * @param[in] dev_sess
309 * @param[out] cable_state Current cable state
310 *
311 * @return EOK If the operation was successfully completed
312 *
313 */
314errno_t nic_get_cable_state(async_sess_t *dev_sess, nic_cable_state_t *cable_state)
315{
316 assert(cable_state);
317
318 sysarg_t _cable_state;
319
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);
324
325 *cable_state = (nic_cable_state_t) _cable_state;
326
327 return rc;
328}
329
330/** Request current operation mode.
331 *
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.
336 *
337 * @return EOK If the operation was successfully completed
338 *
339 */
340errno_t nic_get_operation_mode(async_sess_t *dev_sess, int *speed,
341 nic_channel_mode_t *duplex, nic_role_t *role)
342{
343 sysarg_t _speed;
344 sysarg_t _duplex;
345 sysarg_t _role;
346
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);
351
352 if (speed)
353 *speed = (int) _speed;
354
355 if (duplex)
356 *duplex = (nic_channel_mode_t) _duplex;
357
358 if (role)
359 *role = (nic_role_t) _role;
360
361 return rc;
362}
363
364/** Set current operation mode.
365 *
366 * If the NIC has auto-negotiation enabled, this command
367 * disables auto-negotiation and sets the operation mode.
368 *
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]
373 *
374 * @return EOK If the operation was successfully completed
375 *
376 */
377errno_t nic_set_operation_mode(async_sess_t *dev_sess, int speed,
378 nic_channel_mode_t duplex, nic_role_t role)
379{
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);
385
386 return rc;
387}
388
389/** Enable auto-negotiation.
390 *
391 * The advertisement argument can only limit some modes,
392 * it can never force the NIC to advertise unsupported modes.
393 *
394 * The allowed modes are defined in "nic/eth_phys.h" in the C library.
395 *
396 * @param[in] dev_sess
397 * @param[in] advertisement Allowed advertised modes. Use 0 for all modes.
398 *
399 * @return EOK If the operation was successfully completed
400 *
401 */
402errno_t nic_autoneg_enable(async_sess_t *dev_sess, uint32_t advertisement)
403{
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);
408
409 return rc;
410}
411
412/** Disable auto-negotiation.
413 *
414 * @param[in] dev_sess
415 *
416 * @return EOK If the operation was successfully completed
417 *
418 */
419errno_t nic_autoneg_disable(async_sess_t *dev_sess)
420{
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);
425
426 return rc;
427}
428
429/** Probe current state of auto-negotiation.
430 *
431 * Modes are defined in the "nic/eth_phys.h" in the C library.
432 *
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.
442 *
443 * @return EOK If the operation was successfully completed
444 *
445 */
446errno_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)
449{
450 sysarg_t _our_advertisement;
451 sysarg_t _their_advertisement;
452 sysarg_t _result;
453 sysarg_t _their_result;
454
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);
460
461 if (our_advertisement)
462 *our_advertisement = (uint32_t) _our_advertisement;
463
464 if (*their_advertisement)
465 *their_advertisement = (uint32_t) _their_advertisement;
466
467 if (result)
468 *result = (nic_result_t) _result;
469
470 if (their_result)
471 *their_result = (nic_result_t) _their_result;
472
473 return rc;
474}
475
476/** Restart the auto-negotiation process.
477 *
478 * @param[in] dev_sess
479 *
480 * @return EOK If the operation was successfully completed
481 *
482 */
483errno_t nic_autoneg_restart(async_sess_t *dev_sess)
484{
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);
489
490 return rc;
491}
492
493/** Query party's sending and reception of the PAUSE frame.
494 *
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.
499 *
500 * @return EOK If the operation was successfully completed
501 *
502 */
503errno_t nic_get_pause(async_sess_t *dev_sess, nic_result_t *we_send,
504 nic_result_t *we_receive, uint16_t *pause)
505{
506 sysarg_t _we_send;
507 sysarg_t _we_receive;
508 sysarg_t _pause;
509
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);
514
515 if (we_send)
516 *we_send = _we_send;
517
518 if (we_receive)
519 *we_receive = _we_receive;
520
521 if (pause)
522 *pause = _pause;
523
524 return rc;
525}
526
527/** Control sending and reception of the PAUSE frame.
528 *
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.
537 *
538 * @return EOK If the operation was successfully completed
539 *
540 */
541errno_t nic_set_pause(async_sess_t *dev_sess, int allow_send, int allow_receive,
542 uint16_t pause)
543{
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);
548
549 return rc;
550}
551
552/** Retrieve current settings of unicast frames reception.
553 *
554 * Note: In case of mode != NIC_UNICAST_LIST the contents of
555 * address_list and address_count are undefined.
556 *
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.
564 *
565 * @return EOK If the operation was successfully completed
566 *
567 */
568errno_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)
570{
571 assert(mode);
572
573 sysarg_t _mode;
574 sysarg_t _address_count;
575
576 if (!address_list)
577 max_count = 0;
578
579 async_exch_t *exch = async_exchange_begin(dev_sess);
580
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;
586 }
587
588 *mode = (nic_unicast_mode_t) _mode;
589 if (address_count)
590 *address_count = (size_t) _address_count;
591
592 if ((max_count) && (_address_count))
593 rc = async_data_read_start(exch, address_list,
594 max_count * sizeof(nic_address_t));
595
596 async_exchange_end(exch);
597
598 return rc;
599}
600
601/** Set which unicast frames are received.
602 *
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.
607 *
608 * @return EOK If the operation was successfully completed
609 *
610 */
611errno_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)
613{
614 if (address_list == NULL)
615 address_count = 0;
616
617 async_exch_t *exch = async_exchange_begin(dev_sess);
618
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);
621
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;
628
629 async_exchange_end(exch);
630
631 errno_t res;
632 async_wait_for(message_id, &res);
633
634 if (rc != EOK)
635 return rc;
636
637 return res;
638}
639
640/** Retrieve current settings of multicast frames reception.
641 *
642 * Note: In case of mode != NIC_MULTICAST_LIST the contents of
643 * address_list and address_count are undefined.
644 *
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.
653 *
654 * @return EOK If the operation was successfully completed
655 *
656 */
657errno_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)
659{
660 assert(mode);
661
662 sysarg_t _mode;
663
664 if (!address_list)
665 max_count = 0;
666
667 async_exch_t *exch = async_exchange_begin(dev_sess);
668
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;
675 }
676
677 *mode = (nic_multicast_mode_t) _mode;
678 if (address_count)
679 *address_count = (size_t) ac;
680
681 if ((max_count) && (ac))
682 rc = async_data_read_start(exch, address_list,
683 max_count * sizeof(nic_address_t));
684
685 async_exchange_end(exch);
686 return rc;
687}
688
689/** Set which multicast frames are received.
690 *
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.
695 *
696 * @return EOK If the operation was successfully completed
697 *
698 */
699errno_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)
701{
702 if (address_list == NULL)
703 address_count = 0;
704
705 async_exch_t *exch = async_exchange_begin(dev_sess);
706
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);
709
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;
716
717 async_exchange_end(exch);
718
719 errno_t res;
720 async_wait_for(message_id, &res);
721
722 if (rc != EOK)
723 return rc;
724
725 return res;
726}
727
728/** Determine if broadcast packets are received.
729 *
730 * @param[in] dev_sess
731 * @param[out] mode Current operation mode
732 *
733 * @return EOK If the operation was successfully completed
734 *
735 */
736errno_t nic_broadcast_get_mode(async_sess_t *dev_sess, nic_broadcast_mode_t *mode)
737{
738 assert(mode);
739
740 sysarg_t _mode;
741
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);
746
747 *mode = (nic_broadcast_mode_t) _mode;
748
749 return rc;
750}
751
752/** Set whether broadcast packets are received.
753 *
754 * @param[in] dev_sess
755 * @param[in] mode Current operation mode
756 *
757 * @return EOK If the operation was successfully completed
758 *
759 */
760errno_t nic_broadcast_set_mode(async_sess_t *dev_sess, nic_broadcast_mode_t mode)
761{
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);
766
767 return rc;
768}
769
770/** Determine if defective (erroneous) packets are received.
771 *
772 * @param[in] dev_sess
773 * @param[out] mode Bitmask specifying allowed errors
774 *
775 * @return EOK If the operation was successfully completed
776 *
777 */
778errno_t nic_defective_get_mode(async_sess_t *dev_sess, uint32_t *mode)
779{
780 assert(mode);
781
782 sysarg_t _mode;
783
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);
788
789 *mode = (uint32_t) _mode;
790
791 return rc;
792}
793
794/** Set whether defective (erroneous) packets are received.
795 *
796 * @param[in] dev_sess
797 * @param[out] mode Bitmask specifying allowed errors
798 *
799 * @return EOK If the operation was successfully completed
800 *
801 */
802errno_t nic_defective_set_mode(async_sess_t *dev_sess, uint32_t mode)
803{
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);
808
809 return rc;
810}
811
812/** Retrieve the currently blocked source MAC addresses.
813 *
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.
820 *
821 * @return EOK If the operation was successfully completed
822 *
823 */
824errno_t nic_blocked_sources_get(async_sess_t *dev_sess, size_t max_count,
825 nic_address_t *address_list, size_t *address_count)
826{
827 if (!address_list)
828 max_count = 0;
829
830 async_exch_t *exch = async_exchange_begin(dev_sess);
831
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;
838 }
839
840 if (address_count)
841 *address_count = (size_t) ac;
842
843 if ((max_count) && (ac))
844 rc = async_data_read_start(exch, address_list,
845 max_count * sizeof(nic_address_t));
846
847 async_exchange_end(exch);
848 return rc;
849}
850
851/** Set which source MACs are blocked
852 *
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.
856 *
857 * @return EOK If the operation was successfully completed
858 *
859 */
860errno_t nic_blocked_sources_set(async_sess_t *dev_sess,
861 const nic_address_t *address_list, size_t address_count)
862{
863 if (address_list == NULL)
864 address_count = 0;
865
866 async_exch_t *exch = async_exchange_begin(dev_sess);
867
868 aid_t message_id = async_send_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
869 NIC_BLOCKED_SOURCES_SET, address_count, NULL);
870
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;
877
878 async_exchange_end(exch);
879
880 errno_t res;
881 async_wait_for(message_id, &res);
882
883 if (rc != EOK)
884 return rc;
885
886 return res;
887}
888
889/** Request current VLAN filtering mask.
890 *
891 * @param[in] dev_sess
892 * @param[out] stats Structure with the statistics
893 *
894 * @return EOK If the operation was successfully completed
895 *
896 */
897errno_t nic_vlan_get_mask(async_sess_t *dev_sess, nic_vlan_mask_t *mask)
898{
899 assert(mask);
900
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;
907 }
908
909 rc = async_data_read_start(exch, mask, sizeof(nic_vlan_mask_t));
910 async_exchange_end(exch);
911
912 return rc;
913}
914
915/** Set the mask used for VLAN filtering.
916 *
917 * If NULL, VLAN filtering is disabled.
918 *
919 * @param[in] dev_sess
920 * @param[in] mask Pointer to mask structure or NULL to disable.
921 *
922 * @return EOK If the operation was successfully completed
923 *
924 */
925errno_t nic_vlan_set_mask(async_sess_t *dev_sess, const nic_vlan_mask_t *mask)
926{
927 async_exch_t *exch = async_exchange_begin(dev_sess);
928
929 aid_t message_id = async_send_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
930 NIC_VLAN_SET_MASK, mask != NULL, NULL);
931
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;
937
938 async_exchange_end(exch);
939
940 errno_t res;
941 async_wait_for(message_id, &res);
942
943 if (rc != EOK)
944 return rc;
945
946 return res;
947}
948
949/** Set VLAN (802.1q) tag.
950 *
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.
955 *
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)
961 *
962 * @return EOK If the operation was successfully completed
963 *
964 */
965errno_t nic_vlan_set_tag(async_sess_t *dev_sess, uint16_t tag, bool add, bool strip)
966{
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);
971
972 return rc;
973}
974
975/** Add new Wake-On-LAN virtue.
976 *
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
983 *
984 * @return EOK If the operation was successfully completed
985 *
986 */
987errno_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)
989{
990 assert(id);
991
992 bool send_data = ((data != NULL) && (length != 0));
993 async_exch_t *exch = async_exchange_begin(dev_sess);
994
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);
998
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;
1006 }
1007 }
1008
1009 async_exchange_end(exch);
1010 async_wait_for(message_id, &res);
1011
1012 *id = IPC_GET_ARG1(result);
1013 return res;
1014}
1015
1016/** Remove Wake-On-LAN virtue.
1017 *
1018 * @param[in] dev_sess
1019 * @param[in] id Virtue identifier
1020 *
1021 * @return EOK If the operation was successfully completed
1022 *
1023 */
1024errno_t nic_wol_virtue_remove(async_sess_t *dev_sess, nic_wv_id_t id)
1025{
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);
1030
1031 return rc;
1032}
1033
1034/** Get information about virtue.
1035 *
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.
1043 *
1044 * @return EOK If the operation was successfully completed
1045 *
1046 */
1047errno_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)
1049{
1050 sysarg_t _type;
1051 sysarg_t _length;
1052
1053 if (data == NULL)
1054 max_length = 0;
1055
1056 async_exch_t *exch = async_exchange_begin(dev_sess);
1057
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;
1064 }
1065
1066 if (type)
1067 *type = _type;
1068
1069 if (length)
1070 *length = _length;
1071
1072 if ((max_length) && (_length != 0))
1073 rc = async_data_read_start(exch, data, max_length);
1074
1075 async_exchange_end(exch);
1076 return rc;
1077}
1078
1079/** Get a list of all virtues of the specified type.
1080 *
1081 * When NIC_WV_NONE is specified as the virtue type the function
1082 * lists virtues of all types.
1083 *
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.
1093 *
1094 * @return EOK If the operation was successfully completed
1095 *
1096 */
1097errno_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)
1099{
1100 if (id_list == NULL)
1101 max_count = 0;
1102
1103 async_exch_t *exch = async_exchange_begin(dev_sess);
1104
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);
1108
1109 if (id_count)
1110 *id_count = (size_t) count;
1111
1112 if ((rc != EOK) || (!max_count)) {
1113 async_exchange_end(exch);
1114 return rc;
1115 }
1116
1117 rc = async_data_read_start(exch, id_list,
1118 max_count * sizeof(nic_wv_id_t));
1119
1120 async_exchange_end(exch);
1121 return rc;
1122}
1123
1124/** Get number of virtues that can be enabled yet.
1125 *
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
1129 *
1130 * @param[in] dev_sess
1131 * @param[in] type Virtue type
1132 * @param[out] count Number of virtues
1133 *
1134 * @return EOK If the operation was successfully completed
1135 *
1136 */
1137errno_t nic_wol_virtue_get_caps(async_sess_t *dev_sess, nic_wv_type_t type,
1138 int *count)
1139{
1140 assert(count);
1141
1142 sysarg_t _count;
1143
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);
1148
1149 *count = (int) _count;
1150 return rc;
1151}
1152
1153/** Load the frame that issued the wakeup.
1154 *
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.
1158 *
1159 * Frame_length can be greater than max_length, but at most max_length
1160 * bytes will be copied into the frame buffer.
1161 *
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.
1165 *
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.
1171 *
1172 * @return EOK If the operation was successfully completed
1173 *
1174 */
1175errno_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)
1177{
1178 assert(matched_type);
1179
1180 sysarg_t _matched_type;
1181 sysarg_t _frame_length;
1182
1183 if (frame == NULL)
1184 max_length = 0;
1185
1186 async_exch_t *exch = async_exchange_begin(dev_sess);
1187
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;
1193 }
1194
1195 *matched_type = (nic_wv_type_t) _matched_type;
1196 if (frame_length)
1197 *frame_length = (size_t) _frame_length;
1198
1199 if ((max_length != 0) && (_frame_length != 0))
1200 rc = async_data_read_start(exch, frame, max_length);
1201
1202 async_exchange_end(exch);
1203 return rc;
1204}
1205
1206/** Probe supported options and current setting of offload computations
1207 *
1208 * @param[in] dev_sess
1209 * @param[out] supported Supported offload options
1210 * @param[out] active Currently active offload options
1211 *
1212 * @return EOK If the operation was successfully completed
1213 *
1214 */
1215errno_t nic_offload_probe(async_sess_t *dev_sess, uint32_t *supported,
1216 uint32_t *active)
1217{
1218 assert(supported);
1219 assert(active);
1220
1221 sysarg_t _supported;
1222 sysarg_t _active;
1223
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);
1228
1229 *supported = (uint32_t) _supported;
1230 *active = (uint32_t) _active;
1231 return rc;
1232}
1233
1234/** Set which offload computations can be performed on the NIC.
1235 *
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
1239 *
1240 * @return EOK If the operation was successfully completed
1241 *
1242 */
1243errno_t nic_offload_set(async_sess_t *dev_sess, uint32_t mask, uint32_t active)
1244{
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);
1249
1250 return rc;
1251}
1252
1253/** Query the current interrupt/poll mode of the NIC
1254 *
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.
1259 *
1260 * @return EOK If the operation was successfully completed
1261 *
1262 */
1263errno_t nic_poll_get_mode(async_sess_t *dev_sess, nic_poll_mode_t *mode,
1264 struct timeval *period)
1265{
1266 assert(mode);
1267
1268 sysarg_t _mode;
1269
1270 async_exch_t *exch = async_exchange_begin(dev_sess);
1271
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;
1277 }
1278
1279 *mode = (nic_poll_mode_t) _mode;
1280
1281 if (period != NULL)
1282 rc = async_data_read_start(exch, period, sizeof(struct timeval));
1283
1284 async_exchange_end(exch);
1285 return rc;
1286}
1287
1288/** Set the interrupt/poll mode of the NIC.
1289 *
1290 * @param[in] dev_sess
1291 * @param[in] mode New poll mode
1292 * @param[in] period Period used in periodic polling. Can be NULL.
1293 *
1294 * @return EOK If the operation was successfully completed
1295 *
1296 */
1297errno_t nic_poll_set_mode(async_sess_t *dev_sess, nic_poll_mode_t mode,
1298 const struct timeval *period)
1299{
1300 async_exch_t *exch = async_exchange_begin(dev_sess);
1301
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);
1304
1305 errno_t rc;
1306 if (period)
1307 rc = async_data_write_start(exch, period, sizeof(struct timeval));
1308 else
1309 rc = EOK;
1310
1311 async_exchange_end(exch);
1312
1313 errno_t res;
1314 async_wait_for(message_id, &res);
1315
1316 if (rc != EOK)
1317 return rc;
1318
1319 return res;
1320}
1321
1322/** Request the driver to poll the NIC.
1323 *
1324 * @param[in] dev_sess
1325 *
1326 * @return EOK If the operation was successfully completed
1327 *
1328 */
1329errno_t nic_poll_now(async_sess_t *dev_sess)
1330{
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);
1334
1335 return rc;
1336}
1337
1338static void remote_nic_send_frame(ddf_fun_t *dev, void *iface,
1339 ipc_call_t *call)
1340{
1341 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1342 assert(nic_iface->send_frame);
1343
1344 void *data;
1345 size_t size;
1346 errno_t rc;
1347
1348 rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
1349 if (rc != EOK) {
1350 async_answer_0(call, EINVAL);
1351 return;
1352 }
1353
1354 rc = nic_iface->send_frame(dev, data, size);
1355 async_answer_0(call, rc);
1356 free(data);
1357}
1358
1359static void remote_nic_callback_create(ddf_fun_t *dev, void *iface,
1360 ipc_call_t *call)
1361{
1362 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1363 assert(nic_iface->callback_create);
1364
1365 errno_t rc = nic_iface->callback_create(dev);
1366 async_answer_0(call, rc);
1367}
1368
1369static void remote_nic_get_state(ddf_fun_t *dev, void *iface,
1370 ipc_call_t *call)
1371{
1372 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1373 assert(nic_iface->get_state);
1374
1375 nic_device_state_t state = NIC_STATE_MAX;
1376
1377 errno_t rc = nic_iface->get_state(dev, &state);
1378 async_answer_1(call, rc, state);
1379}
1380
1381static void remote_nic_set_state(ddf_fun_t *dev, void *iface,
1382 ipc_call_t *call)
1383{
1384 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1385 assert(nic_iface->set_state);
1386
1387 nic_device_state_t state = (nic_device_state_t) IPC_GET_ARG2(*call);
1388
1389 errno_t rc = nic_iface->set_state(dev, state);
1390 async_answer_0(call, rc);
1391}
1392
1393static void remote_nic_get_address(ddf_fun_t *dev, void *iface,
1394 ipc_call_t *call)
1395{
1396 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1397 assert(nic_iface->get_address);
1398
1399 nic_address_t address;
1400 memset(&address, 0, sizeof(nic_address_t));
1401
1402 errno_t rc = nic_iface->get_address(dev, &address);
1403 if (rc == EOK) {
1404 ipc_call_t data;
1405 size_t max_len;
1406
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;
1412 }
1413
1414 if (max_len != sizeof(nic_address_t)) {
1415 async_answer_0(&data, ELIMIT);
1416 async_answer_0(call, ELIMIT);
1417 return;
1418 }
1419
1420 async_data_read_finalize(&data, &address,
1421 sizeof(nic_address_t));
1422 }
1423
1424 async_answer_0(call, rc);
1425}
1426
1427static void remote_nic_set_address(ddf_fun_t *dev, void *iface,
1428 ipc_call_t *call)
1429{
1430 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1431
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;
1438 }
1439
1440 if (length > sizeof(nic_address_t)) {
1441 async_answer_0(&data, ELIMIT);
1442 async_answer_0(call, ELIMIT);
1443 return;
1444 }
1445
1446 nic_address_t address;
1447 if (async_data_write_finalize(&data, &address, length) != EOK) {
1448 async_answer_0(call, EINVAL);
1449 return;
1450 }
1451
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);
1457}
1458
1459static void remote_nic_get_stats(ddf_fun_t *dev, void *iface,
1460 ipc_call_t *call)
1461{
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;
1466 }
1467
1468 nic_device_stats_t stats;
1469 memset(&stats, 0, sizeof(nic_device_stats_t));
1470
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;
1479 }
1480
1481 if (max_len < sizeof(nic_device_stats_t)) {
1482 async_answer_0(&data, ELIMIT);
1483 async_answer_0(call, ELIMIT);
1484 return;
1485 }
1486
1487 async_data_read_finalize(&data, &stats,
1488 sizeof(nic_device_stats_t));
1489 }
1490
1491 async_answer_0(call, rc);
1492}
1493
1494static void remote_nic_get_device_info(ddf_fun_t *dev, void *iface,
1495 ipc_call_t *call)
1496{
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;
1501 }
1502
1503 nic_device_info_t info;
1504 memset(&info, 0, sizeof(nic_device_info_t));
1505
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;
1514 }
1515
1516 if (max_len < sizeof (nic_device_info_t)) {
1517 async_answer_0(&data, ELIMIT);
1518 async_answer_0(call, ELIMIT);
1519 return;
1520 }
1521
1522 async_data_read_finalize(&data, &info,
1523 sizeof(nic_device_info_t));
1524 }
1525
1526 async_answer_0(call, rc);
1527}
1528
1529static void remote_nic_get_cable_state(ddf_fun_t *dev, void *iface,
1530 ipc_call_t *call)
1531{
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;
1536 }
1537
1538 nic_cable_state_t cs = NIC_CS_UNKNOWN;
1539
1540 errno_t rc = nic_iface->get_cable_state(dev, &cs);
1541 async_answer_1(call, rc, (sysarg_t) cs);
1542}
1543
1544static void remote_nic_get_operation_mode(ddf_fun_t *dev, void *iface,
1545 ipc_call_t *call)
1546{
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;
1551 }
1552
1553 int speed = 0;
1554 nic_channel_mode_t duplex = NIC_CM_UNKNOWN;
1555 nic_role_t role = NIC_ROLE_UNKNOWN;
1556
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);
1560}
1561
1562static void remote_nic_set_operation_mode(ddf_fun_t *dev, void *iface,
1563 ipc_call_t *call)
1564{
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;
1569 }
1570
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);
1574
1575 errno_t rc = nic_iface->set_operation_mode(dev, speed, duplex, role);
1576 async_answer_0(call, rc);
1577}
1578
1579static void remote_nic_autoneg_enable(ddf_fun_t *dev, void *iface,
1580 ipc_call_t *call)
1581{
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;
1586 }
1587
1588 uint32_t advertisement = (uint32_t) IPC_GET_ARG2(*call);
1589
1590 errno_t rc = nic_iface->autoneg_enable(dev, advertisement);
1591 async_answer_0(call, rc);
1592}
1593
1594static void remote_nic_autoneg_disable(ddf_fun_t *dev, void *iface,
1595 ipc_call_t *call)
1596{
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;
1601 }
1602
1603 errno_t rc = nic_iface->autoneg_disable(dev);
1604 async_answer_0(call, rc);
1605}
1606
1607static void remote_nic_autoneg_probe(ddf_fun_t *dev, void *iface,
1608 ipc_call_t *call)
1609{
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;
1614 }
1615
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;
1620
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);
1625}
1626
1627static void remote_nic_autoneg_restart(ddf_fun_t *dev, void *iface,
1628 ipc_call_t *call)
1629{
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;
1634 }
1635
1636 errno_t rc = nic_iface->autoneg_restart(dev);
1637 async_answer_0(call, rc);
1638}
1639
1640static void remote_nic_get_pause(ddf_fun_t *dev, void *iface,
1641 ipc_call_t *call)
1642{
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;
1647 }
1648
1649 nic_result_t we_send;
1650 nic_result_t we_receive;
1651 uint16_t pause;
1652
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);
1655}
1656
1657static void remote_nic_set_pause(ddf_fun_t *dev, void *iface,
1658 ipc_call_t *call)
1659{
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;
1664 }
1665
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);
1669
1670 errno_t rc = nic_iface->set_pause(dev, allow_send, allow_receive,
1671 pause);
1672 async_answer_0(call, rc);
1673}
1674
1675static void remote_nic_unicast_get_mode(ddf_fun_t *dev, void *iface,
1676 ipc_call_t *call)
1677{
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;
1682 }
1683
1684 size_t max_count = IPC_GET_ARG2(*call);
1685 nic_address_t *address_list = NULL;
1686
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;
1692 }
1693 }
1694
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;
1698
1699 errno_t rc = nic_iface->unicast_get_mode(dev, &mode, max_count, address_list,
1700 &address_count);
1701
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;
1706 }
1707
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;
1715 }
1716
1717 if (max_len > address_count * sizeof(nic_address_t))
1718 max_len = address_count * sizeof(nic_address_t);
1719
1720 if (max_len > max_count * sizeof(nic_address_t))
1721 max_len = max_count * sizeof(nic_address_t);
1722
1723 async_data_read_finalize(&data, address_list, max_len);
1724
1725 free(address_list);
1726 async_answer_2(call, rc, mode, address_count);
1727}
1728
1729static void remote_nic_unicast_set_mode(ddf_fun_t *dev, void *iface,
1730 ipc_call_t *call)
1731{
1732 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1733
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;
1738
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;
1745 }
1746
1747 if (length != address_count * sizeof(nic_address_t)) {
1748 async_answer_0(&data, ELIMIT);
1749 async_answer_0(call, ELIMIT);
1750 return;
1751 }
1752
1753 address_list = malloc(length);
1754 if (address_list == NULL) {
1755 async_answer_0(&data, ENOMEM);
1756 async_answer_0(call, ENOMEM);
1757 return;
1758 }
1759
1760 if (async_data_write_finalize(&data, address_list,
1761 length) != EOK) {
1762 async_answer_0(call, EINVAL);
1763 free(address_list);
1764 return;
1765 }
1766 }
1767
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);
1774
1775 free(address_list);
1776}
1777
1778static void remote_nic_multicast_get_mode(ddf_fun_t *dev, void *iface,
1779 ipc_call_t *call)
1780{
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;
1785 }
1786
1787 size_t max_count = IPC_GET_ARG2(*call);
1788 nic_address_t *address_list = NULL;
1789
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;
1795 }
1796 }
1797
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;
1801
1802 errno_t rc = nic_iface->multicast_get_mode(dev, &mode, max_count, address_list,
1803 &address_count);
1804
1805
1806 if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
1807 free(address_list);
1808 async_answer_2(call, rc, mode, address_count);
1809 return;
1810 }
1811
1812 ipc_call_t data;
1813 size_t max_len;
1814 if (!async_data_read_receive(&data, &max_len)) {
1815 async_answer_0(&data, EINVAL);
1816 async_answer_2(call, rc, mode, address_count);
1817 free(address_list);
1818 return;
1819 }
1820
1821 if (max_len > address_count * sizeof(nic_address_t))
1822 max_len = address_count * sizeof(nic_address_t);
1823
1824 if (max_len > max_count * sizeof(nic_address_t))
1825 max_len = max_count * sizeof(nic_address_t);
1826
1827 async_data_read_finalize(&data, address_list, max_len);
1828
1829 free(address_list);
1830 async_answer_2(call, rc, mode, address_count);
1831}
1832
1833static void remote_nic_multicast_set_mode(ddf_fun_t *dev, void *iface,
1834 ipc_call_t *call)
1835{
1836 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1837
1838 nic_multicast_mode_t mode = IPC_GET_ARG2(*call);
1839 size_t address_count = IPC_GET_ARG3(*call);
1840 nic_address_t *address_list = NULL;
1841
1842 if (address_count) {
1843 ipc_call_t data;
1844 size_t length;
1845 if (!async_data_write_receive(&data, &length)) {
1846 async_answer_0(&data, EINVAL);
1847 async_answer_0(call, EINVAL);
1848 return;
1849 }
1850
1851 if (length != address_count * sizeof (nic_address_t)) {
1852 async_answer_0(&data, ELIMIT);
1853 async_answer_0(call, ELIMIT);
1854 return;
1855 }
1856
1857 address_list = malloc(length);
1858 if (address_list == NULL) {
1859 async_answer_0(&data, ENOMEM);
1860 async_answer_0(call, ENOMEM);
1861 return;
1862 }
1863
1864 if (async_data_write_finalize(&data, address_list,
1865 length) != EOK) {
1866 async_answer_0(call, EINVAL);
1867 free(address_list);
1868 return;
1869 }
1870 }
1871
1872 if (nic_iface->multicast_set_mode != NULL) {
1873 errno_t rc = nic_iface->multicast_set_mode(dev, mode, address_list,
1874 address_count);
1875 async_answer_0(call, rc);
1876 } else
1877 async_answer_0(call, ENOTSUP);
1878
1879 free(address_list);
1880}
1881
1882static void remote_nic_broadcast_get_mode(ddf_fun_t *dev, void *iface,
1883 ipc_call_t *call)
1884{
1885 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1886 if (nic_iface->broadcast_get_mode == NULL) {
1887 async_answer_0(call, ENOTSUP);
1888 return;
1889 }
1890
1891 nic_broadcast_mode_t mode = NIC_BROADCAST_ACCEPTED;
1892
1893 errno_t rc = nic_iface->broadcast_get_mode(dev, &mode);
1894 async_answer_1(call, rc, mode);
1895}
1896
1897static void remote_nic_broadcast_set_mode(ddf_fun_t *dev, void *iface,
1898 ipc_call_t *call)
1899{
1900 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1901 if (nic_iface->broadcast_set_mode == NULL) {
1902 async_answer_0(call, ENOTSUP);
1903 return;
1904 }
1905
1906 nic_broadcast_mode_t mode = IPC_GET_ARG2(*call);
1907
1908 errno_t rc = nic_iface->broadcast_set_mode(dev, mode);
1909 async_answer_0(call, rc);
1910}
1911
1912static void remote_nic_defective_get_mode(ddf_fun_t *dev, void *iface,
1913 ipc_call_t *call)
1914{
1915 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1916 if (nic_iface->defective_get_mode == NULL) {
1917 async_answer_0(call, ENOTSUP);
1918 return;
1919 }
1920
1921 uint32_t mode = 0;
1922
1923 errno_t rc = nic_iface->defective_get_mode(dev, &mode);
1924 async_answer_1(call, rc, mode);
1925}
1926
1927static void remote_nic_defective_set_mode(ddf_fun_t *dev, void *iface,
1928 ipc_call_t *call)
1929{
1930 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1931 if (nic_iface->defective_set_mode == NULL) {
1932 async_answer_0(call, ENOTSUP);
1933 return;
1934 }
1935
1936 uint32_t mode = IPC_GET_ARG2(*call);
1937
1938 errno_t rc = nic_iface->defective_set_mode(dev, mode);
1939 async_answer_0(call, rc);
1940}
1941
1942static void remote_nic_blocked_sources_get(ddf_fun_t *dev, void *iface,
1943 ipc_call_t *call)
1944{
1945 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1946 if (nic_iface->blocked_sources_get == NULL) {
1947 async_answer_0(call, ENOTSUP);
1948 return;
1949 }
1950
1951 size_t max_count = IPC_GET_ARG2(*call);
1952 nic_address_t *address_list = NULL;
1953
1954 if (max_count != 0) {
1955 address_list = malloc(max_count * sizeof(nic_address_t));
1956 if (!address_list) {
1957 async_answer_0(call, ENOMEM);
1958 return;
1959 }
1960 }
1961
1962 memset(address_list, 0, max_count * sizeof(nic_address_t));
1963 size_t address_count = 0;
1964
1965 errno_t rc = nic_iface->blocked_sources_get(dev, max_count, address_list,
1966 &address_count);
1967
1968 if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
1969 async_answer_1(call, rc, address_count);
1970 free(address_list);
1971 return;
1972 }
1973
1974 ipc_call_t data;
1975 size_t max_len;
1976 if (!async_data_read_receive(&data, &max_len)) {
1977 async_answer_0(&data, EINVAL);
1978 async_answer_1(call, rc, address_count);
1979 free(address_list);
1980 return;
1981 }
1982
1983 if (max_len > address_count * sizeof(nic_address_t))
1984 max_len = address_count * sizeof(nic_address_t);
1985
1986 if (max_len > max_count * sizeof(nic_address_t))
1987 max_len = max_count * sizeof(nic_address_t);
1988
1989 async_data_read_finalize(&data, address_list, max_len);
1990
1991 free(address_list);
1992 async_answer_1(call, rc, address_count);
1993}
1994
1995static void remote_nic_blocked_sources_set(ddf_fun_t *dev, void *iface,
1996 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_call_t data;
2006 if (!async_data_write_receive(&data, &length)) {
2007 async_answer_0(&data, EINVAL);
2008 async_answer_0(call, EINVAL);
2009 return;
2010 }
2011
2012 if (length != address_count * sizeof(nic_address_t)) {
2013 async_answer_0(&data, ELIMIT);
2014 async_answer_0(call, ELIMIT);
2015 return;
2016 }
2017
2018 address_list = malloc(length);
2019 if (address_list == NULL) {
2020 async_answer_0(&data, ENOMEM);
2021 async_answer_0(call, ENOMEM);
2022 return;
2023 }
2024
2025 if (async_data_write_finalize(&data, address_list,
2026 length) != EOK) {
2027 async_answer_0(call, EINVAL);
2028 free(address_list);
2029 return;
2030 }
2031 }
2032
2033 if (nic_iface->blocked_sources_set != NULL) {
2034 errno_t rc = nic_iface->blocked_sources_set(dev, address_list,
2035 address_count);
2036 async_answer_0(call, rc);
2037 } else
2038 async_answer_0(call, ENOTSUP);
2039
2040 free(address_list);
2041}
2042
2043static void remote_nic_vlan_get_mask(ddf_fun_t *dev, void *iface,
2044 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(call, ENOTSUP);
2049 return;
2050 }
2051
2052 nic_vlan_mask_t vlan_mask;
2053 memset(&vlan_mask, 0, sizeof(nic_vlan_mask_t));
2054
2055 errno_t rc = nic_iface->vlan_get_mask(dev, &vlan_mask);
2056 if (rc == EOK) {
2057 ipc_call_t data;
2058 size_t max_len;
2059 if (!async_data_read_receive(&data, &max_len)) {
2060 async_answer_0(&data, EINVAL);
2061 async_answer_0(call, EINVAL);
2062 return;
2063 }
2064
2065 if (max_len != sizeof(nic_vlan_mask_t)) {
2066 async_answer_0(&data, EINVAL);
2067 async_answer_0(call, EINVAL);
2068 return;
2069 }
2070
2071 async_data_read_finalize(&data, &vlan_mask, max_len);
2072 }
2073
2074 async_answer_0(call, rc);
2075}
2076
2077static void remote_nic_vlan_set_mask(ddf_fun_t *dev, void *iface,
2078 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_call_t data;
2088 size_t length;
2089 if (!async_data_write_receive(&data, &length)) {
2090 async_answer_0(&data, EINVAL);
2091 async_answer_0(call, EINVAL);
2092 return;
2093 }
2094
2095 if (length != sizeof(nic_vlan_mask_t)) {
2096 async_answer_0(&data, ELIMIT);
2097 async_answer_0(call, ELIMIT);
2098 return;
2099 }
2100
2101 if (async_data_write_finalize(&data, &vlan_mask,
2102 length) != EOK) {
2103 async_answer_0(call, EINVAL);
2104 return;
2105 }
2106
2107 vlan_mask_pointer = &vlan_mask;
2108 }
2109
2110 if (nic_iface->vlan_set_mask != NULL) {
2111 errno_t rc = nic_iface->vlan_set_mask(dev, vlan_mask_pointer);
2112 async_answer_0(call, rc);
2113 } else
2114 async_answer_0(call, ENOTSUP);
2115}
2116
2117static void remote_nic_vlan_set_tag(ddf_fun_t *dev, void *iface,
2118 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(call, 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 errno_t rc = nic_iface->vlan_set_tag(dev, tag, add, strip);
2132 async_answer_0(call, rc);
2133}
2134
2135static void remote_nic_wol_virtue_add(ddf_fun_t *dev, void *iface,
2136 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_call_t data;
2142
2143 if (nic_iface->wol_virtue_add == NULL) {
2144 if (send_data) {
2145 async_data_write_receive(&data, NULL);
2146 async_answer_0(&data, ENOTSUP);
2147 }
2148
2149 async_answer_0(call, ENOTSUP);
2150 }
2151
2152 size_t length = 0;
2153 void *virtue = NULL;
2154
2155 if (send_data) {
2156 if (!async_data_write_receive(&data, &length)) {
2157 async_answer_0(&data, EINVAL);
2158 async_answer_0(call, EINVAL);
2159 return;
2160 }
2161
2162 virtue = malloc(length);
2163 if (virtue == NULL) {
2164 async_answer_0(&data, ENOMEM);
2165 async_answer_0(call, ENOMEM);
2166 return;
2167 }
2168
2169 if (async_data_write_finalize(&data, virtue,
2170 length) != EOK) {
2171 async_answer_0(call, EINVAL);
2172 free(virtue);
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 errno_t rc = nic_iface->wol_virtue_add(dev, type, virtue, length, &id);
2181 async_answer_1(call, rc, (sysarg_t) id);
2182 free(virtue);
2183}
2184
2185static void remote_nic_wol_virtue_remove(ddf_fun_t *dev, void *iface,
2186 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(call, ENOTSUP);
2192 return;
2193 }
2194
2195 nic_wv_id_t id = (nic_wv_id_t) IPC_GET_ARG2(*call);
2196
2197 errno_t rc = nic_iface->wol_virtue_remove(dev, id);
2198 async_answer_0(call, rc);
2199}
2200
2201static void remote_nic_wol_virtue_probe(ddf_fun_t *dev, void *iface,
2202 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(call, 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_call_t data;
2216 void *virtue = NULL;
2217
2218 if (max_length != 0) {
2219 virtue = malloc(max_length);
2220 if (virtue == NULL) {
2221 async_answer_0(call, ENOMEM);
2222 return;
2223 }
2224 }
2225
2226 memset(virtue, 0, max_length);
2227
2228 errno_t rc = nic_iface->wol_virtue_probe(dev, id, &type, max_length,
2229 virtue, &length);
2230
2231 if ((max_length != 0) && (length != 0)) {
2232 size_t req_length;
2233 if (!async_data_read_receive(&data, &req_length)) {
2234 async_answer_0(&data, EINVAL);
2235 async_answer_0(call, EINVAL);
2236 free(virtue);
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, virtue, req_length);
2247 }
2248
2249 async_answer_2(call, rc, (sysarg_t) type, (sysarg_t) length);
2250 free(virtue);
2251}
2252
2253static void remote_nic_wol_virtue_list(ddf_fun_t *dev, void *iface,
2254 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(call, 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_call_t data;
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(call, ENOMEM);
2272 return;
2273 }
2274 }
2275
2276 memset(id_list, 0, max_count * sizeof (nic_wv_id_t));
2277
2278 errno_t 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, &req_length)) {
2284 async_answer_0(&data, EINVAL);
2285 async_answer_0(call, 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, id_list, req_length);
2297 }
2298
2299 async_answer_1(call, 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_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(call, 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 errno_t rc = nic_iface->wol_virtue_get_caps(dev, type, &count);
2316 async_answer_1(call, rc, (sysarg_t) count);
2317}
2318
2319static void remote_nic_wol_load_info(ddf_fun_t *dev, void *iface,
2320 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(call, 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 *info = NULL;
2332
2333 if (max_length != 0) {
2334 info = malloc(max_length);
2335 if (info == NULL) {
2336 async_answer_0(call, ENOMEM);
2337 return;
2338 }
2339 }
2340
2341 memset(info, 0, max_length);
2342
2343 errno_t rc = nic_iface->wol_load_info(dev, &type, max_length, info,
2344 &frame_length);
2345 if (rc == EOK) {
2346 ipc_call_t data;
2347 size_t req_length;
2348 if (!async_data_read_receive(&data, &req_length)) {
2349 async_answer_0(&data, EINVAL);
2350 async_answer_0(call, EINVAL);
2351 free(info);
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, info, req_length);
2358 }
2359
2360 async_answer_2(call, rc, (sysarg_t) type, (sysarg_t) frame_length);
2361 free(info);
2362}
2363
2364static void remote_nic_offload_probe(ddf_fun_t *dev, void *iface,
2365 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(call, ENOTSUP);
2370 return;
2371 }
2372
2373 uint32_t supported = 0;
2374 uint32_t active = 0;
2375
2376 errno_t rc = nic_iface->offload_probe(dev, &supported, &active);
2377 async_answer_2(call, rc, supported, active);
2378}
2379
2380static void remote_nic_offload_set(ddf_fun_t *dev, void *iface,
2381 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(call, 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 errno_t rc = nic_iface->offload_set(dev, mask, active);
2393 async_answer_0(call, rc);
2394}
2395
2396static void remote_nic_poll_get_mode(ddf_fun_t *dev, void *iface,
2397 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(call, 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 errno_t rc = nic_iface->poll_get_mode(dev, &mode, &period);
2413 if ((rc == EOK) && (request_data)) {
2414 ipc_call_t data;
2415 size_t max_len;
2416
2417 if (!async_data_read_receive(&data, &max_len)) {
2418 async_answer_0(&data, EINVAL);
2419 async_answer_0(call, EINVAL);
2420 return;
2421 }
2422
2423 if (max_len != sizeof(struct timeval)) {
2424 async_answer_0(&data, ELIMIT);
2425 async_answer_0(call, ELIMIT);
2426 return;
2427 }
2428
2429 async_data_read_finalize(&data, &period,
2430 sizeof(struct timeval));
2431 }
2432
2433 async_answer_1(call, rc, (sysarg_t) mode);
2434}
2435
2436static void remote_nic_poll_set_mode(ddf_fun_t *dev, void *iface,
2437 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_call_t data;
2449 if (!async_data_write_receive(&data, &length)) {
2450 async_answer_0(&data, EINVAL);
2451 async_answer_0(call, EINVAL);
2452 return;
2453 }
2454
2455 if (length != sizeof(struct timeval)) {
2456 async_answer_0(&data, ELIMIT);
2457 async_answer_0(call, ELIMIT);
2458 return;
2459 }
2460
2461 period = &period_buf;
2462 if (async_data_write_finalize(&data, period,
2463 length) != EOK) {
2464 async_answer_0(call, EINVAL);
2465 return;
2466 }
2467 }
2468
2469 if (nic_iface->poll_set_mode != NULL) {
2470 errno_t rc = nic_iface->poll_set_mode(dev, mode, period);
2471 async_answer_0(call, rc);
2472 } else
2473 async_answer_0(call, ENOTSUP);
2474}
2475
2476static void remote_nic_poll_now(ddf_fun_t *dev, void *iface,
2477 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(call, ENOTSUP);
2482 return;
2483 }
2484
2485 errno_t rc = nic_iface->poll_now(dev);
2486 async_answer_0(call, 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.