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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since bd41ac52 was bd41ac52, checked in by Jakub Jermar <jakub@…>, 7 years ago

Get rid of sys/time.h

This commit moves the POSIX-like time functionality from libc's
sys/time.h to libposix and introduces C11-like or HelenOS-specific
interfaces to libc.

Specifically, use of sys/time.h, struct timeval, suseconds_t and
gettimeofday is replaced by time.h (C11), struct timespec (C11), usec_t
(HelenOS) and getuptime / getrealtime (HelenOS).

Also attempt to fix the implementation of clock() to return microseconds
(clocks) rather than processor cycles and move it to libc.

  • 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 <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 timespec *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 timespec));
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 timespec *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 timespec));
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 timespec period = {
2408 .tv_sec = 0,
2409 .tv_nsec = 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 timespec)) {
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 timespec));
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 timespec period_buf;
2444 struct timespec *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 timespec)) {
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.