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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since f1380b7 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 65.4 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_callid_t callid, 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(callid, EINVAL);
1351 return;
1352 }
1353
1354 rc = nic_iface->send_frame(dev, data, size);
1355 async_answer_0(callid, rc);
1356 free(data);
1357}
1358
1359static void remote_nic_callback_create(ddf_fun_t *dev, void *iface,
1360 ipc_callid_t callid, 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(callid, rc);
1367}
1368
1369static void remote_nic_get_state(ddf_fun_t *dev, void *iface,
1370 ipc_callid_t callid, 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(callid, rc, state);
1379}
1380
1381static void remote_nic_set_state(ddf_fun_t *dev, void *iface,
1382 ipc_callid_t callid, 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(callid, rc);
1391}
1392
1393static void remote_nic_get_address(ddf_fun_t *dev, void *iface,
1394 ipc_callid_t callid, 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 size_t max_len;
1405 ipc_callid_t data_callid;
1406
1407 /* All errors will be translated into EPARTY anyway */
1408 if (!async_data_read_receive(&data_callid, &max_len)) {
1409 async_answer_0(data_callid, EINVAL);
1410 async_answer_0(callid, EINVAL);
1411 return;
1412 }
1413
1414 if (max_len != sizeof(nic_address_t)) {
1415 async_answer_0(data_callid, ELIMIT);
1416 async_answer_0(callid, ELIMIT);
1417 return;
1418 }
1419
1420 async_data_read_finalize(data_callid, &address,
1421 sizeof(nic_address_t));
1422 }
1423
1424 async_answer_0(callid, rc);
1425}
1426
1427static void remote_nic_set_address(ddf_fun_t *dev, void *iface,
1428 ipc_callid_t callid, ipc_call_t *call)
1429{
1430 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1431
1432 size_t length;
1433 ipc_callid_t data_callid;
1434 if (!async_data_write_receive(&data_callid, &length)) {
1435 async_answer_0(data_callid, EINVAL);
1436 async_answer_0(callid, EINVAL);
1437 return;
1438 }
1439
1440 if (length > sizeof(nic_address_t)) {
1441 async_answer_0(data_callid, ELIMIT);
1442 async_answer_0(callid, ELIMIT);
1443 return;
1444 }
1445
1446 nic_address_t address;
1447 if (async_data_write_finalize(data_callid, &address, length) != EOK) {
1448 async_answer_0(callid, 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(callid, rc);
1455 } else
1456 async_answer_0(callid, ENOTSUP);
1457}
1458
1459static void remote_nic_get_stats(ddf_fun_t *dev, void *iface,
1460 ipc_callid_t callid, 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(callid, 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_callid_t data_callid;
1474 size_t max_len;
1475 if (!async_data_read_receive(&data_callid, &max_len)) {
1476 async_answer_0(data_callid, EINVAL);
1477 async_answer_0(callid, EINVAL);
1478 return;
1479 }
1480
1481 if (max_len < sizeof(nic_device_stats_t)) {
1482 async_answer_0(data_callid, ELIMIT);
1483 async_answer_0(callid, ELIMIT);
1484 return;
1485 }
1486
1487 async_data_read_finalize(data_callid, &stats,
1488 sizeof(nic_device_stats_t));
1489 }
1490
1491 async_answer_0(callid, rc);
1492}
1493
1494static void remote_nic_get_device_info(ddf_fun_t *dev, void *iface,
1495 ipc_callid_t callid, 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(callid, 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_callid_t data_callid;
1509 size_t max_len;
1510 if (!async_data_read_receive(&data_callid, &max_len)) {
1511 async_answer_0(data_callid, EINVAL);
1512 async_answer_0(callid, EINVAL);
1513 return;
1514 }
1515
1516 if (max_len < sizeof (nic_device_info_t)) {
1517 async_answer_0(data_callid, ELIMIT);
1518 async_answer_0(callid, ELIMIT);
1519 return;
1520 }
1521
1522 async_data_read_finalize(data_callid, &info,
1523 sizeof(nic_device_info_t));
1524 }
1525
1526 async_answer_0(callid, rc);
1527}
1528
1529static void remote_nic_get_cable_state(ddf_fun_t *dev, void *iface,
1530 ipc_callid_t callid, 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(callid, 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(callid, rc, (sysarg_t) cs);
1542}
1543
1544static void remote_nic_get_operation_mode(ddf_fun_t *dev, void *iface,
1545 ipc_callid_t callid, 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(callid, 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(callid, 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_callid_t callid, 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(callid, 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(callid, rc);
1577}
1578
1579static void remote_nic_autoneg_enable(ddf_fun_t *dev, void *iface,
1580 ipc_callid_t callid, 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(callid, 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(callid, rc);
1592}
1593
1594static void remote_nic_autoneg_disable(ddf_fun_t *dev, void *iface,
1595 ipc_callid_t callid, 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(callid, ENOTSUP);
1600 return;
1601 }
1602
1603 errno_t rc = nic_iface->autoneg_disable(dev);
1604 async_answer_0(callid, rc);
1605}
1606
1607static void remote_nic_autoneg_probe(ddf_fun_t *dev, void *iface,
1608 ipc_callid_t callid, 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(callid, 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(callid, 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_callid_t callid, 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(callid, ENOTSUP);
1633 return;
1634 }
1635
1636 errno_t rc = nic_iface->autoneg_restart(dev);
1637 async_answer_0(callid, rc);
1638}
1639
1640static void remote_nic_get_pause(ddf_fun_t *dev, void *iface,
1641 ipc_callid_t callid, 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(callid, 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(callid, rc, we_send, we_receive, pause);
1655}
1656
1657static void remote_nic_set_pause(ddf_fun_t *dev, void *iface,
1658 ipc_callid_t callid, 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(callid, 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(callid, rc);
1673}
1674
1675static void remote_nic_unicast_get_mode(ddf_fun_t *dev, void *iface,
1676 ipc_callid_t callid, 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(callid, 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(callid, 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(callid, rc, mode, address_count);
1705 return;
1706 }
1707
1708 ipc_callid_t data_callid;
1709 size_t max_len;
1710 if (!async_data_read_receive(&data_callid, &max_len)) {
1711 async_answer_0(data_callid, EINVAL);
1712 async_answer_2(callid, 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_callid, address_list, max_len);
1724 async_answer_0(data_callid, EINVAL);
1725
1726 free(address_list);
1727 async_answer_2(callid, rc, mode, address_count);
1728}
1729
1730static void remote_nic_unicast_set_mode(ddf_fun_t *dev, void *iface,
1731 ipc_callid_t callid, ipc_call_t *call)
1732{
1733 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1734
1735 size_t length;
1736 nic_unicast_mode_t mode = IPC_GET_ARG2(*call);
1737 size_t address_count = IPC_GET_ARG3(*call);
1738 nic_address_t *address_list = NULL;
1739
1740 if (address_count) {
1741 ipc_callid_t data_callid;
1742 if (!async_data_write_receive(&data_callid, &length)) {
1743 async_answer_0(data_callid, EINVAL);
1744 async_answer_0(callid, EINVAL);
1745 return;
1746 }
1747
1748 if (length != address_count * sizeof(nic_address_t)) {
1749 async_answer_0(data_callid, ELIMIT);
1750 async_answer_0(callid, ELIMIT);
1751 return;
1752 }
1753
1754 address_list = malloc(length);
1755 if (address_list == NULL) {
1756 async_answer_0(data_callid, ENOMEM);
1757 async_answer_0(callid, ENOMEM);
1758 return;
1759 }
1760
1761 if (async_data_write_finalize(data_callid, address_list,
1762 length) != EOK) {
1763 async_answer_0(callid, EINVAL);
1764 free(address_list);
1765 return;
1766 }
1767 }
1768
1769 if (nic_iface->unicast_set_mode != NULL) {
1770 errno_t rc = nic_iface->unicast_set_mode(dev, mode, address_list,
1771 address_count);
1772 async_answer_0(callid, rc);
1773 } else
1774 async_answer_0(callid, ENOTSUP);
1775
1776 free(address_list);
1777}
1778
1779static void remote_nic_multicast_get_mode(ddf_fun_t *dev, void *iface,
1780 ipc_callid_t callid, ipc_call_t *call)
1781{
1782 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1783 if (nic_iface->multicast_get_mode == NULL) {
1784 async_answer_0(callid, ENOTSUP);
1785 return;
1786 }
1787
1788 size_t max_count = IPC_GET_ARG2(*call);
1789 nic_address_t *address_list = NULL;
1790
1791 if (max_count != 0) {
1792 address_list = malloc(max_count * sizeof(nic_address_t));
1793 if (!address_list) {
1794 async_answer_0(callid, ENOMEM);
1795 return;
1796 }
1797 }
1798
1799 memset(address_list, 0, max_count * sizeof(nic_address_t));
1800 nic_multicast_mode_t mode = NIC_MULTICAST_BLOCKED;
1801 size_t address_count = 0;
1802
1803 errno_t rc = nic_iface->multicast_get_mode(dev, &mode, max_count, address_list,
1804 &address_count);
1805
1806
1807 if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
1808 free(address_list);
1809 async_answer_2(callid, rc, mode, address_count);
1810 return;
1811 }
1812
1813 ipc_callid_t data_callid;
1814 size_t max_len;
1815 if (!async_data_read_receive(&data_callid, &max_len)) {
1816 async_answer_0(data_callid, EINVAL);
1817 async_answer_2(callid, rc, mode, address_count);
1818 free(address_list);
1819 return;
1820 }
1821
1822 if (max_len > address_count * sizeof(nic_address_t))
1823 max_len = address_count * sizeof(nic_address_t);
1824
1825 if (max_len > max_count * sizeof(nic_address_t))
1826 max_len = max_count * sizeof(nic_address_t);
1827
1828 async_data_read_finalize(data_callid, address_list, max_len);
1829
1830 free(address_list);
1831 async_answer_2(callid, rc, mode, address_count);
1832}
1833
1834static void remote_nic_multicast_set_mode(ddf_fun_t *dev, void *iface,
1835 ipc_callid_t callid, ipc_call_t *call)
1836{
1837 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1838
1839 nic_multicast_mode_t mode = IPC_GET_ARG2(*call);
1840 size_t address_count = IPC_GET_ARG3(*call);
1841 nic_address_t *address_list = NULL;
1842
1843 if (address_count) {
1844 ipc_callid_t data_callid;
1845 size_t length;
1846 if (!async_data_write_receive(&data_callid, &length)) {
1847 async_answer_0(data_callid, EINVAL);
1848 async_answer_0(callid, EINVAL);
1849 return;
1850 }
1851
1852 if (length != address_count * sizeof (nic_address_t)) {
1853 async_answer_0(data_callid, ELIMIT);
1854 async_answer_0(callid, ELIMIT);
1855 return;
1856 }
1857
1858 address_list = malloc(length);
1859 if (address_list == NULL) {
1860 async_answer_0(data_callid, ENOMEM);
1861 async_answer_0(callid, ENOMEM);
1862 return;
1863 }
1864
1865 if (async_data_write_finalize(data_callid, address_list,
1866 length) != EOK) {
1867 async_answer_0(callid, EINVAL);
1868 free(address_list);
1869 return;
1870 }
1871 }
1872
1873 if (nic_iface->multicast_set_mode != NULL) {
1874 errno_t rc = nic_iface->multicast_set_mode(dev, mode, address_list,
1875 address_count);
1876 async_answer_0(callid, rc);
1877 } else
1878 async_answer_0(callid, ENOTSUP);
1879
1880 free(address_list);
1881}
1882
1883static void remote_nic_broadcast_get_mode(ddf_fun_t *dev, void *iface,
1884 ipc_callid_t callid, ipc_call_t *call)
1885{
1886 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1887 if (nic_iface->broadcast_get_mode == NULL) {
1888 async_answer_0(callid, ENOTSUP);
1889 return;
1890 }
1891
1892 nic_broadcast_mode_t mode = NIC_BROADCAST_ACCEPTED;
1893
1894 errno_t rc = nic_iface->broadcast_get_mode(dev, &mode);
1895 async_answer_1(callid, rc, mode);
1896}
1897
1898static void remote_nic_broadcast_set_mode(ddf_fun_t *dev, void *iface,
1899 ipc_callid_t callid, ipc_call_t *call)
1900{
1901 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1902 if (nic_iface->broadcast_set_mode == NULL) {
1903 async_answer_0(callid, ENOTSUP);
1904 return;
1905 }
1906
1907 nic_broadcast_mode_t mode = IPC_GET_ARG2(*call);
1908
1909 errno_t rc = nic_iface->broadcast_set_mode(dev, mode);
1910 async_answer_0(callid, rc);
1911}
1912
1913static void remote_nic_defective_get_mode(ddf_fun_t *dev, void *iface,
1914 ipc_callid_t callid, ipc_call_t *call)
1915{
1916 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1917 if (nic_iface->defective_get_mode == NULL) {
1918 async_answer_0(callid, ENOTSUP);
1919 return;
1920 }
1921
1922 uint32_t mode = 0;
1923
1924 errno_t rc = nic_iface->defective_get_mode(dev, &mode);
1925 async_answer_1(callid, rc, mode);
1926}
1927
1928static void remote_nic_defective_set_mode(ddf_fun_t *dev, void *iface,
1929 ipc_callid_t callid, ipc_call_t *call)
1930{
1931 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1932 if (nic_iface->defective_set_mode == NULL) {
1933 async_answer_0(callid, ENOTSUP);
1934 return;
1935 }
1936
1937 uint32_t mode = IPC_GET_ARG2(*call);
1938
1939 errno_t rc = nic_iface->defective_set_mode(dev, mode);
1940 async_answer_0(callid, rc);
1941}
1942
1943static void remote_nic_blocked_sources_get(ddf_fun_t *dev, void *iface,
1944 ipc_callid_t callid, ipc_call_t *call)
1945{
1946 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1947 if (nic_iface->blocked_sources_get == NULL) {
1948 async_answer_0(callid, ENOTSUP);
1949 return;
1950 }
1951
1952 size_t max_count = IPC_GET_ARG2(*call);
1953 nic_address_t *address_list = NULL;
1954
1955 if (max_count != 0) {
1956 address_list = malloc(max_count * sizeof(nic_address_t));
1957 if (!address_list) {
1958 async_answer_0(callid, ENOMEM);
1959 return;
1960 }
1961 }
1962
1963 memset(address_list, 0, max_count * sizeof(nic_address_t));
1964 size_t address_count = 0;
1965
1966 errno_t rc = nic_iface->blocked_sources_get(dev, max_count, address_list,
1967 &address_count);
1968
1969 if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
1970 async_answer_1(callid, rc, address_count);
1971 free(address_list);
1972 return;
1973 }
1974
1975 ipc_callid_t data_callid;
1976 size_t max_len;
1977 if (!async_data_read_receive(&data_callid, &max_len)) {
1978 async_answer_0(data_callid, EINVAL);
1979 async_answer_1(callid, rc, address_count);
1980 free(address_list);
1981 return;
1982 }
1983
1984 if (max_len > address_count * sizeof(nic_address_t))
1985 max_len = address_count * sizeof(nic_address_t);
1986
1987 if (max_len > max_count * sizeof(nic_address_t))
1988 max_len = max_count * sizeof(nic_address_t);
1989
1990 async_data_read_finalize(data_callid, address_list, max_len);
1991 async_answer_0(data_callid, EINVAL);
1992
1993 free(address_list);
1994 async_answer_1(callid, rc, address_count);
1995}
1996
1997static void remote_nic_blocked_sources_set(ddf_fun_t *dev, void *iface,
1998 ipc_callid_t callid, ipc_call_t *call)
1999{
2000 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2001
2002 size_t length;
2003 size_t address_count = IPC_GET_ARG2(*call);
2004 nic_address_t *address_list = NULL;
2005
2006 if (address_count) {
2007 ipc_callid_t data_callid;
2008 if (!async_data_write_receive(&data_callid, &length)) {
2009 async_answer_0(data_callid, EINVAL);
2010 async_answer_0(callid, EINVAL);
2011 return;
2012 }
2013
2014 if (length != address_count * sizeof(nic_address_t)) {
2015 async_answer_0(data_callid, ELIMIT);
2016 async_answer_0(callid, ELIMIT);
2017 return;
2018 }
2019
2020 address_list = malloc(length);
2021 if (address_list == NULL) {
2022 async_answer_0(data_callid, ENOMEM);
2023 async_answer_0(callid, ENOMEM);
2024 return;
2025 }
2026
2027 if (async_data_write_finalize(data_callid, address_list,
2028 length) != EOK) {
2029 async_answer_0(callid, EINVAL);
2030 free(address_list);
2031 return;
2032 }
2033 }
2034
2035 if (nic_iface->blocked_sources_set != NULL) {
2036 errno_t rc = nic_iface->blocked_sources_set(dev, address_list,
2037 address_count);
2038 async_answer_0(callid, rc);
2039 } else
2040 async_answer_0(callid, ENOTSUP);
2041
2042 free(address_list);
2043}
2044
2045static void remote_nic_vlan_get_mask(ddf_fun_t *dev, void *iface,
2046 ipc_callid_t callid, ipc_call_t *call)
2047{
2048 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2049 if (nic_iface->vlan_get_mask == NULL) {
2050 async_answer_0(callid, ENOTSUP);
2051 return;
2052 }
2053
2054 nic_vlan_mask_t vlan_mask;
2055 memset(&vlan_mask, 0, sizeof(nic_vlan_mask_t));
2056
2057 errno_t rc = nic_iface->vlan_get_mask(dev, &vlan_mask);
2058 if (rc == EOK) {
2059 ipc_callid_t data_callid;
2060 size_t max_len;
2061 if (!async_data_read_receive(&data_callid, &max_len)) {
2062 async_answer_0(data_callid, EINVAL);
2063 async_answer_0(callid, EINVAL);
2064 return;
2065 }
2066
2067 if (max_len != sizeof(nic_vlan_mask_t)) {
2068 async_answer_0(data_callid, EINVAL);
2069 async_answer_0(callid, EINVAL);
2070 return;
2071 }
2072
2073 async_data_read_finalize(data_callid, &vlan_mask, max_len);
2074 }
2075
2076 async_answer_0(callid, rc);
2077}
2078
2079static void remote_nic_vlan_set_mask(ddf_fun_t *dev, void *iface,
2080 ipc_callid_t callid, ipc_call_t *call)
2081{
2082 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2083
2084 nic_vlan_mask_t vlan_mask;
2085 nic_vlan_mask_t *vlan_mask_pointer = NULL;
2086 bool vlan_mask_set = (bool) IPC_GET_ARG2(*call);
2087
2088 if (vlan_mask_set) {
2089 ipc_callid_t data_callid;
2090 size_t length;
2091 if (!async_data_write_receive(&data_callid, &length)) {
2092 async_answer_0(data_callid, EINVAL);
2093 async_answer_0(callid, EINVAL);
2094 return;
2095 }
2096
2097 if (length != sizeof(nic_vlan_mask_t)) {
2098 async_answer_0(data_callid, ELIMIT);
2099 async_answer_0(callid, ELIMIT);
2100 return;
2101 }
2102
2103 if (async_data_write_finalize(data_callid, &vlan_mask,
2104 length) != EOK) {
2105 async_answer_0(callid, EINVAL);
2106 return;
2107 }
2108
2109 vlan_mask_pointer = &vlan_mask;
2110 }
2111
2112 if (nic_iface->vlan_set_mask != NULL) {
2113 errno_t rc = nic_iface->vlan_set_mask(dev, vlan_mask_pointer);
2114 async_answer_0(callid, rc);
2115 } else
2116 async_answer_0(callid, ENOTSUP);
2117}
2118
2119static void remote_nic_vlan_set_tag(ddf_fun_t *dev, void *iface,
2120 ipc_callid_t callid, ipc_call_t *call)
2121{
2122 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2123
2124 if (nic_iface->vlan_set_tag == NULL) {
2125 async_answer_0(callid, ENOTSUP);
2126 return;
2127 }
2128
2129 uint16_t tag = (uint16_t) IPC_GET_ARG2(*call);
2130 bool add = (int) IPC_GET_ARG3(*call);
2131 bool strip = (int) IPC_GET_ARG4(*call);
2132
2133 errno_t rc = nic_iface->vlan_set_tag(dev, tag, add, strip);
2134 async_answer_0(callid, rc);
2135}
2136
2137static void remote_nic_wol_virtue_add(ddf_fun_t *dev, void *iface,
2138 ipc_callid_t callid, ipc_call_t *call)
2139{
2140 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2141
2142 int send_data = (int) IPC_GET_ARG3(*call);
2143 ipc_callid_t data_callid;
2144
2145 if (nic_iface->wol_virtue_add == NULL) {
2146 if (send_data) {
2147 async_data_write_receive(&data_callid, NULL);
2148 async_answer_0(data_callid, ENOTSUP);
2149 }
2150
2151 async_answer_0(callid, ENOTSUP);
2152 }
2153
2154 size_t length = 0;
2155 void *data = NULL;
2156
2157 if (send_data) {
2158 if (!async_data_write_receive(&data_callid, &length)) {
2159 async_answer_0(data_callid, EINVAL);
2160 async_answer_0(callid, EINVAL);
2161 return;
2162 }
2163
2164 data = malloc(length);
2165 if (data == NULL) {
2166 async_answer_0(data_callid, ENOMEM);
2167 async_answer_0(callid, ENOMEM);
2168 return;
2169 }
2170
2171 if (async_data_write_finalize(data_callid, data,
2172 length) != EOK) {
2173 async_answer_0(callid, EINVAL);
2174 free(data);
2175 return;
2176 }
2177 }
2178
2179 nic_wv_id_t id = 0;
2180 nic_wv_type_t type = (nic_wv_type_t) IPC_GET_ARG2(*call);
2181
2182 errno_t rc = nic_iface->wol_virtue_add(dev, type, data, length, &id);
2183 async_answer_1(callid, rc, (sysarg_t) id);
2184 free(data);
2185}
2186
2187static void remote_nic_wol_virtue_remove(ddf_fun_t *dev, void *iface,
2188 ipc_callid_t callid, ipc_call_t *call)
2189{
2190 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2191
2192 if (nic_iface->wol_virtue_remove == NULL) {
2193 async_answer_0(callid, ENOTSUP);
2194 return;
2195 }
2196
2197 nic_wv_id_t id = (nic_wv_id_t) IPC_GET_ARG2(*call);
2198
2199 errno_t rc = nic_iface->wol_virtue_remove(dev, id);
2200 async_answer_0(callid, rc);
2201}
2202
2203static void remote_nic_wol_virtue_probe(ddf_fun_t *dev, void *iface,
2204 ipc_callid_t callid, ipc_call_t *call)
2205{
2206 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2207
2208 if (nic_iface->wol_virtue_probe == NULL) {
2209 async_answer_0(callid, ENOTSUP);
2210 return;
2211 }
2212
2213 nic_wv_id_t id = (nic_wv_id_t) IPC_GET_ARG2(*call);
2214 size_t max_length = IPC_GET_ARG3(*call);
2215 nic_wv_type_t type = NIC_WV_NONE;
2216 size_t length = 0;
2217 ipc_callid_t data_callid;
2218 void *data = NULL;
2219
2220 if (max_length != 0) {
2221 data = malloc(max_length);
2222 if (data == NULL) {
2223 async_answer_0(callid, ENOMEM);
2224 return;
2225 }
2226 }
2227
2228 memset(data, 0, max_length);
2229
2230 errno_t rc = nic_iface->wol_virtue_probe(dev, id, &type, max_length,
2231 data, &length);
2232
2233 if ((max_length != 0) && (length != 0)) {
2234 size_t req_length;
2235 if (!async_data_read_receive(&data_callid, &req_length)) {
2236 async_answer_0(data_callid, EINVAL);
2237 async_answer_0(callid, EINVAL);
2238 free(data);
2239 return;
2240 }
2241
2242 if (req_length > length)
2243 req_length = length;
2244
2245 if (req_length > max_length)
2246 req_length = max_length;
2247
2248 async_data_read_finalize(data_callid, data, req_length);
2249 }
2250
2251 async_answer_2(callid, rc, (sysarg_t) type, (sysarg_t) length);
2252 free(data);
2253}
2254
2255static void remote_nic_wol_virtue_list(ddf_fun_t *dev, void *iface,
2256 ipc_callid_t callid, ipc_call_t *call)
2257{
2258 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2259 if (nic_iface->wol_virtue_list == NULL) {
2260 async_answer_0(callid, ENOTSUP);
2261 return;
2262 }
2263
2264 nic_wv_type_t type = (nic_wv_type_t) IPC_GET_ARG2(*call);
2265 size_t max_count = IPC_GET_ARG3(*call);
2266 size_t count = 0;
2267 nic_wv_id_t *id_list = NULL;
2268 ipc_callid_t data_callid;
2269
2270 if (max_count != 0) {
2271 id_list = malloc(max_count * sizeof(nic_wv_id_t));
2272 if (id_list == NULL) {
2273 async_answer_0(callid, ENOMEM);
2274 return;
2275 }
2276 }
2277
2278 memset(id_list, 0, max_count * sizeof (nic_wv_id_t));
2279
2280 errno_t rc = nic_iface->wol_virtue_list(dev, type, max_count, id_list,
2281 &count);
2282
2283 if ((max_count != 0) && (count != 0)) {
2284 size_t req_length;
2285 if (!async_data_read_receive(&data_callid, &req_length)) {
2286 async_answer_0(data_callid, EINVAL);
2287 async_answer_0(callid, EINVAL);
2288 free(id_list);
2289 return;
2290 }
2291
2292 if (req_length > count * sizeof(nic_wv_id_t))
2293 req_length = count * sizeof(nic_wv_id_t);
2294
2295 if (req_length > max_count * sizeof(nic_wv_id_t))
2296 req_length = max_count * sizeof(nic_wv_id_t);
2297
2298 rc = async_data_read_finalize(data_callid, id_list, req_length);
2299 }
2300
2301 async_answer_1(callid, rc, (sysarg_t) count);
2302 free(id_list);
2303}
2304
2305static void remote_nic_wol_virtue_get_caps(ddf_fun_t *dev, void *iface,
2306 ipc_callid_t callid, ipc_call_t *call)
2307{
2308 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2309 if (nic_iface->wol_virtue_get_caps == NULL) {
2310 async_answer_0(callid, ENOTSUP);
2311 return;
2312 }
2313
2314 int count = -1;
2315 nic_wv_type_t type = (nic_wv_type_t) IPC_GET_ARG2(*call);
2316
2317 errno_t rc = nic_iface->wol_virtue_get_caps(dev, type, &count);
2318 async_answer_1(callid, rc, (sysarg_t) count);
2319}
2320
2321static void remote_nic_wol_load_info(ddf_fun_t *dev, void *iface,
2322 ipc_callid_t callid, ipc_call_t *call)
2323{
2324 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2325 if (nic_iface->wol_load_info == NULL) {
2326 async_answer_0(callid, ENOTSUP);
2327 return;
2328 }
2329
2330 size_t max_length = (size_t) IPC_GET_ARG2(*call);
2331 size_t frame_length = 0;
2332 nic_wv_type_t type = NIC_WV_NONE;
2333 uint8_t *data = NULL;
2334
2335 if (max_length != 0) {
2336 data = malloc(max_length);
2337 if (data == NULL) {
2338 async_answer_0(callid, ENOMEM);
2339 return;
2340 }
2341 }
2342
2343 memset(data, 0, max_length);
2344
2345 errno_t rc = nic_iface->wol_load_info(dev, &type, max_length, data,
2346 &frame_length);
2347 if (rc == EOK) {
2348 ipc_callid_t data_callid;
2349 size_t req_length;
2350 if (!async_data_read_receive(&data_callid, &req_length)) {
2351 async_answer_0(data_callid, EINVAL);
2352 async_answer_0(callid, EINVAL);
2353 free(data);
2354 return;
2355 }
2356
2357 req_length = req_length > max_length ? max_length : req_length;
2358 req_length = req_length > frame_length ? frame_length : req_length;
2359 async_data_read_finalize(data_callid, data, req_length);
2360 }
2361
2362 async_answer_2(callid, rc, (sysarg_t) type, (sysarg_t) frame_length);
2363 free(data);
2364}
2365
2366static void remote_nic_offload_probe(ddf_fun_t *dev, void *iface,
2367 ipc_callid_t callid, ipc_call_t *call)
2368{
2369 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2370 if (nic_iface->offload_probe == NULL) {
2371 async_answer_0(callid, ENOTSUP);
2372 return;
2373 }
2374
2375 uint32_t supported = 0;
2376 uint32_t active = 0;
2377
2378 errno_t rc = nic_iface->offload_probe(dev, &supported, &active);
2379 async_answer_2(callid, rc, supported, active);
2380}
2381
2382static void remote_nic_offload_set(ddf_fun_t *dev, void *iface,
2383 ipc_callid_t callid, ipc_call_t *call)
2384{
2385 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2386 if (nic_iface->offload_set == NULL) {
2387 async_answer_0(callid, ENOTSUP);
2388 return;
2389 }
2390
2391 uint32_t mask = (uint32_t) IPC_GET_ARG2(*call);
2392 uint32_t active = (uint32_t) IPC_GET_ARG3(*call);
2393
2394 errno_t rc = nic_iface->offload_set(dev, mask, active);
2395 async_answer_0(callid, rc);
2396}
2397
2398static void remote_nic_poll_get_mode(ddf_fun_t *dev, void *iface,
2399 ipc_callid_t callid, ipc_call_t *call)
2400{
2401 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2402 if (nic_iface->poll_get_mode == NULL) {
2403 async_answer_0(callid, ENOTSUP);
2404 return;
2405 }
2406
2407 nic_poll_mode_t mode = NIC_POLL_IMMEDIATE;
2408 int request_data = IPC_GET_ARG2(*call);
2409 struct timeval period = {
2410 .tv_sec = 0,
2411 .tv_usec = 0
2412 };
2413
2414 errno_t rc = nic_iface->poll_get_mode(dev, &mode, &period);
2415 if ((rc == EOK) && (request_data)) {
2416 size_t max_len;
2417 ipc_callid_t data_callid;
2418
2419 if (!async_data_read_receive(&data_callid, &max_len)) {
2420 async_answer_0(data_callid, EINVAL);
2421 async_answer_0(callid, EINVAL);
2422 return;
2423 }
2424
2425 if (max_len != sizeof(struct timeval)) {
2426 async_answer_0(data_callid, ELIMIT);
2427 async_answer_0(callid, ELIMIT);
2428 return;
2429 }
2430
2431 async_data_read_finalize(data_callid, &period,
2432 sizeof(struct timeval));
2433 }
2434
2435 async_answer_1(callid, rc, (sysarg_t) mode);
2436}
2437
2438static void remote_nic_poll_set_mode(ddf_fun_t *dev, void *iface,
2439 ipc_callid_t callid, ipc_call_t *call)
2440{
2441 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2442
2443 nic_poll_mode_t mode = IPC_GET_ARG2(*call);
2444 int has_period = IPC_GET_ARG3(*call);
2445 struct timeval period_buf;
2446 struct timeval *period = NULL;
2447 size_t length;
2448
2449 if (has_period) {
2450 ipc_callid_t data_callid;
2451 if (!async_data_write_receive(&data_callid, &length)) {
2452 async_answer_0(data_callid, EINVAL);
2453 async_answer_0(callid, EINVAL);
2454 return;
2455 }
2456
2457 if (length != sizeof(struct timeval)) {
2458 async_answer_0(data_callid, ELIMIT);
2459 async_answer_0(callid, ELIMIT);
2460 return;
2461 }
2462
2463 period = &period_buf;
2464 if (async_data_write_finalize(data_callid, period,
2465 length) != EOK) {
2466 async_answer_0(callid, EINVAL);
2467 return;
2468 }
2469 }
2470
2471 if (nic_iface->poll_set_mode != NULL) {
2472 errno_t rc = nic_iface->poll_set_mode(dev, mode, period);
2473 async_answer_0(callid, rc);
2474 } else
2475 async_answer_0(callid, ENOTSUP);
2476}
2477
2478static void remote_nic_poll_now(ddf_fun_t *dev, void *iface,
2479 ipc_callid_t callid, ipc_call_t *call)
2480{
2481 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2482 if (nic_iface->poll_now == NULL) {
2483 async_answer_0(callid, ENOTSUP);
2484 return;
2485 }
2486
2487 errno_t rc = nic_iface->poll_now(dev);
2488 async_answer_0(callid, rc);
2489}
2490
2491/** Remote NIC interface operations.
2492 *
2493 */
2494static const remote_iface_func_ptr_t remote_nic_iface_ops[] = {
2495 [NIC_SEND_MESSAGE] = remote_nic_send_frame,
2496 [NIC_CALLBACK_CREATE] = remote_nic_callback_create,
2497 [NIC_GET_STATE] = remote_nic_get_state,
2498 [NIC_SET_STATE] = remote_nic_set_state,
2499 [NIC_GET_ADDRESS] = remote_nic_get_address,
2500 [NIC_SET_ADDRESS] = remote_nic_set_address,
2501 [NIC_GET_STATS] = remote_nic_get_stats,
2502 [NIC_GET_DEVICE_INFO] = remote_nic_get_device_info,
2503 [NIC_GET_CABLE_STATE] = remote_nic_get_cable_state,
2504 [NIC_GET_OPERATION_MODE] = remote_nic_get_operation_mode,
2505 [NIC_SET_OPERATION_MODE] = remote_nic_set_operation_mode,
2506 [NIC_AUTONEG_ENABLE] = remote_nic_autoneg_enable,
2507 [NIC_AUTONEG_DISABLE] = remote_nic_autoneg_disable,
2508 [NIC_AUTONEG_PROBE] = remote_nic_autoneg_probe,
2509 [NIC_AUTONEG_RESTART] = remote_nic_autoneg_restart,
2510 [NIC_GET_PAUSE] = remote_nic_get_pause,
2511 [NIC_SET_PAUSE] = remote_nic_set_pause,
2512 [NIC_UNICAST_GET_MODE] = remote_nic_unicast_get_mode,
2513 [NIC_UNICAST_SET_MODE] = remote_nic_unicast_set_mode,
2514 [NIC_MULTICAST_GET_MODE] = remote_nic_multicast_get_mode,
2515 [NIC_MULTICAST_SET_MODE] = remote_nic_multicast_set_mode,
2516 [NIC_BROADCAST_GET_MODE] = remote_nic_broadcast_get_mode,
2517 [NIC_BROADCAST_SET_MODE] = remote_nic_broadcast_set_mode,
2518 [NIC_DEFECTIVE_GET_MODE] = remote_nic_defective_get_mode,
2519 [NIC_DEFECTIVE_SET_MODE] = remote_nic_defective_set_mode,
2520 [NIC_BLOCKED_SOURCES_GET] = remote_nic_blocked_sources_get,
2521 [NIC_BLOCKED_SOURCES_SET] = remote_nic_blocked_sources_set,
2522 [NIC_VLAN_GET_MASK] = remote_nic_vlan_get_mask,
2523 [NIC_VLAN_SET_MASK] = remote_nic_vlan_set_mask,
2524 [NIC_VLAN_SET_TAG] = remote_nic_vlan_set_tag,
2525 [NIC_WOL_VIRTUE_ADD] = remote_nic_wol_virtue_add,
2526 [NIC_WOL_VIRTUE_REMOVE] = remote_nic_wol_virtue_remove,
2527 [NIC_WOL_VIRTUE_PROBE] = remote_nic_wol_virtue_probe,
2528 [NIC_WOL_VIRTUE_LIST] = remote_nic_wol_virtue_list,
2529 [NIC_WOL_VIRTUE_GET_CAPS] = remote_nic_wol_virtue_get_caps,
2530 [NIC_WOL_LOAD_INFO] = remote_nic_wol_load_info,
2531 [NIC_OFFLOAD_PROBE] = remote_nic_offload_probe,
2532 [NIC_OFFLOAD_SET] = remote_nic_offload_set,
2533 [NIC_POLL_GET_MODE] = remote_nic_poll_get_mode,
2534 [NIC_POLL_SET_MODE] = remote_nic_poll_set_mode,
2535 [NIC_POLL_NOW] = remote_nic_poll_now
2536};
2537
2538/** Remote NIC interface structure.
2539 *
2540 * Interface for processing request from remote
2541 * clients addressed to the NIC interface.
2542 *
2543 */
2544const remote_iface_t remote_nic_iface = {
2545 .method_count = ARRAY_SIZE(remote_nic_iface_ops),
2546 .methods = remote_nic_iface_ops
2547};
2548
2549/**
2550 * @}
2551 */
Note: See TracBrowser for help on using the repository browser.