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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 7edfde9 was 7493e7b, checked in by Agnieszka Tabaka <nufcia@…>, 11 years ago

Add more information about NIC in 'nic' utility. Fix nic_get_device_info
function in lib/drv.

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