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

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

"Obviously harmless" error handling tweaks.

  • 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 int 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_port_handler_t cfun,
129 void *carg)
130{
131 ipc_call_t answer;
132 int rc;
133 int 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 */
160int 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 int 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 */
184int 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 int 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 */
202int 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 int rc = async_data_read_start(exch, address, sizeof(nic_address_t));
210 async_exchange_end(exch);
211
212 int 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 */
229int 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 int rc = async_data_write_start(exch, address, sizeof(nic_address_t));
237 async_exchange_end(exch);
238
239 int 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 */
256int 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 int 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 */
286int 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 int rc = async_data_read_start(exch, device_info, sizeof(nic_device_info_t));
295 async_exchange_end(exch);
296
297 int 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 */
314int 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 int 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 */
340int 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 int 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 */
377int 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 int 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 */
402int nic_autoneg_enable(async_sess_t *dev_sess, uint32_t advertisement)
403{
404 async_exch_t *exch = async_exchange_begin(dev_sess);
405 int 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 */
419int nic_autoneg_disable(async_sess_t *dev_sess)
420{
421 async_exch_t *exch = async_exchange_begin(dev_sess);
422 int 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 */
446int 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 int 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 */
483int nic_autoneg_restart(async_sess_t *dev_sess)
484{
485 async_exch_t *exch = async_exchange_begin(dev_sess);
486 int 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 */
503int 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 int 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 */
541int 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 int 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 */
568int 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 int 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 */
611int 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 int 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 int 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 */
657int 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 int 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 */
699int 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 int 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 int 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 */
736int 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 int 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 */
760int 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 int 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 */
778int 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 int 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 */
802int nic_defective_set_mode(async_sess_t *dev_sess, uint32_t mode)
803{
804 async_exch_t *exch = async_exchange_begin(dev_sess);
805 int 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 */
824int 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 int 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 */
860int 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 int 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 int 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 */
897int 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 int 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 */
925int 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 int 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 int 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 */
965int 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 int 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 */
987int 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 int res;
1000 if (send_data) {
1001 int 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 */
1024int 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 int 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 */
1047int 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 int 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 */
1097int 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 int 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 */
1137int 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 int 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 */
1175int 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 int 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 */
1215int 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 int 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 */
1243int 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 int 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 */
1263int 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 int 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 */
1297int 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 int 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 int 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 */
1329int nic_poll_now(async_sess_t *dev_sess)
1330{
1331 async_exch_t *exch = async_exchange_begin(dev_sess);
1332 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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.