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

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

Get rid of sys/time.h

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

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

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

  • Property mode set to 100644
File size: 63.7 KB
RevLine 
[609243f4]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>
[bd41ac52]41#include <time.h>
[9be30cdf]42#include <macros.h>
43
[609243f4]44#include "ops/nic.h"
[7858acbf]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 */
[b7fd2a0]100errno_t nic_send_frame(async_sess_t *dev_sess, void *data, size_t size)
[7858acbf]101{
102 async_exch_t *exch = async_exchange_begin(dev_sess);
[a35b458]103
[7858acbf]104 ipc_call_t answer;
105 aid_t req = async_send_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
106 NIC_SEND_MESSAGE, &answer);
[b7fd2a0]107 errno_t retval = async_data_write_start(exch, data, size);
[a35b458]108
[7858acbf]109 async_exchange_end(exch);
[a35b458]110
[7858acbf]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 */
[b7fd2a0]128errno_t nic_callback_create(async_sess_t *dev_sess, async_port_handler_t cfun,
[7858acbf]129 void *carg)
130{
131 ipc_call_t answer;
[b7fd2a0]132 errno_t rc;
133 errno_t retval;
[a35b458]134
[7858acbf]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);
[a35b458]138
[f9b2cb4c]139 port_id_t port;
140 rc = async_create_callback_port(exch, INTERFACE_NIC_CB, 0, 0,
141 cfun, carg, &port);
[7858acbf]142 if (rc != EOK) {
143 async_forget(req);
144 return rc;
145 }
146 async_exchange_end(exch);
[a35b458]147
[7858acbf]148 async_wait_for(req, &retval);
[25a179e]149 return retval;
[7858acbf]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 */
[b7fd2a0]160errno_t nic_get_state(async_sess_t *dev_sess, nic_device_state_t *state)
[7858acbf]161{
162 assert(state);
[a35b458]163
[7858acbf]164 sysarg_t _state;
[a35b458]165
[7858acbf]166 async_exch_t *exch = async_exchange_begin(dev_sess);
[b7fd2a0]167 errno_t rc = async_req_1_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]168 NIC_GET_STATE, &_state);
169 async_exchange_end(exch);
[a35b458]170
[7858acbf]171 *state = (nic_device_state_t) _state;
[a35b458]172
[7858acbf]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 */
[b7fd2a0]184errno_t nic_set_state(async_sess_t *dev_sess, nic_device_state_t state)
[7858acbf]185{
186 async_exch_t *exch = async_exchange_begin(dev_sess);
[b7fd2a0]187 errno_t rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]188 NIC_SET_STATE, state);
189 async_exchange_end(exch);
[a35b458]190
[7858acbf]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 */
[b7fd2a0]202errno_t nic_get_address(async_sess_t *dev_sess, nic_address_t *address)
[7858acbf]203{
204 assert(address);
[a35b458]205
[7858acbf]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);
[b7fd2a0]209 errno_t rc = async_data_read_start(exch, address, sizeof(nic_address_t));
[7858acbf]210 async_exchange_end(exch);
[a35b458]211
[b7fd2a0]212 errno_t res;
[7858acbf]213 async_wait_for(aid, &res);
[a35b458]214
[7858acbf]215 if (rc != EOK)
216 return rc;
[a35b458]217
[d5c1051]218 return res;
[7858acbf]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 */
[b7fd2a0]229errno_t nic_set_address(async_sess_t *dev_sess, const nic_address_t *address)
[7858acbf]230{
231 assert(address);
[a35b458]232
[7858acbf]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);
[b7fd2a0]236 errno_t rc = async_data_write_start(exch, address, sizeof(nic_address_t));
[7858acbf]237 async_exchange_end(exch);
[a35b458]238
[b7fd2a0]239 errno_t res;
[7858acbf]240 async_wait_for(aid, &res);
[a35b458]241
[7858acbf]242 if (rc != EOK)
243 return rc;
[a35b458]244
[d5c1051]245 return res;
[7858acbf]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 */
[b7fd2a0]256errno_t nic_get_stats(async_sess_t *dev_sess, nic_device_stats_t *stats)
[7858acbf]257{
258 assert(stats);
[a35b458]259
[7858acbf]260 async_exch_t *exch = async_exchange_begin(dev_sess);
[a35b458]261
[b7fd2a0]262 errno_t rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]263 NIC_GET_STATS);
264 if (rc != EOK) {
265 async_exchange_end(exch);
266 return rc;
267 }
[a35b458]268
[7858acbf]269 rc = async_data_read_start(exch, stats, sizeof(nic_device_stats_t));
[a35b458]270
[7858acbf]271 async_exchange_end(exch);
[a35b458]272
[7858acbf]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 */
[b7fd2a0]286errno_t nic_get_device_info(async_sess_t *dev_sess, nic_device_info_t *device_info)
[7858acbf]287{
288 assert(device_info);
[a35b458]289
[7858acbf]290 async_exch_t *exch = async_exchange_begin(dev_sess);
[a35b458]291
[7493e7b]292 aid_t aid = async_send_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
293 NIC_GET_DEVICE_INFO, NULL);
[b7fd2a0]294 errno_t rc = async_data_read_start(exch, device_info, sizeof(nic_device_info_t));
[7858acbf]295 async_exchange_end(exch);
[7493e7b]296
[b7fd2a0]297 errno_t res;
[7493e7b]298 async_wait_for(aid, &res);
[a35b458]299
[7493e7b]300 if (rc != EOK)
301 return rc;
[a35b458]302
[d5c1051]303 return res;
[7858acbf]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 */
[b7fd2a0]314errno_t nic_get_cable_state(async_sess_t *dev_sess, nic_cable_state_t *cable_state)
[7858acbf]315{
316 assert(cable_state);
[a35b458]317
[7858acbf]318 sysarg_t _cable_state;
[a35b458]319
[7858acbf]320 async_exch_t *exch = async_exchange_begin(dev_sess);
[b7fd2a0]321 errno_t rc = async_req_1_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]322 NIC_GET_CABLE_STATE, &_cable_state);
323 async_exchange_end(exch);
[a35b458]324
[7858acbf]325 *cable_state = (nic_cable_state_t) _cable_state;
[a35b458]326
[7858acbf]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 */
[b7fd2a0]340errno_t nic_get_operation_mode(async_sess_t *dev_sess, int *speed,
[3bacee1]341 nic_channel_mode_t *duplex, nic_role_t *role)
[7858acbf]342{
343 sysarg_t _speed;
344 sysarg_t _duplex;
345 sysarg_t _role;
[a35b458]346
[7858acbf]347 async_exch_t *exch = async_exchange_begin(dev_sess);
[b7fd2a0]348 errno_t rc = async_req_1_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]349 NIC_GET_OPERATION_MODE, &_speed, &_duplex, &_role);
350 async_exchange_end(exch);
[a35b458]351
[7858acbf]352 if (speed)
353 *speed = (int) _speed;
[a35b458]354
[7858acbf]355 if (duplex)
356 *duplex = (nic_channel_mode_t) _duplex;
[a35b458]357
[7858acbf]358 if (role)
359 *role = (nic_role_t) _role;
[a35b458]360
[7858acbf]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 */
[b7fd2a0]377errno_t nic_set_operation_mode(async_sess_t *dev_sess, int speed,
[7858acbf]378 nic_channel_mode_t duplex, nic_role_t role)
379{
380 async_exch_t *exch = async_exchange_begin(dev_sess);
[b7fd2a0]381 errno_t rc = async_req_4_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]382 NIC_SET_OPERATION_MODE, (sysarg_t) speed, (sysarg_t) duplex,
383 (sysarg_t) role);
384 async_exchange_end(exch);
[a35b458]385
[7858acbf]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 */
[b7fd2a0]402errno_t nic_autoneg_enable(async_sess_t *dev_sess, uint32_t advertisement)
[7858acbf]403{
404 async_exch_t *exch = async_exchange_begin(dev_sess);
[b7fd2a0]405 errno_t rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]406 NIC_AUTONEG_ENABLE, (sysarg_t) advertisement);
407 async_exchange_end(exch);
[a35b458]408
[7858acbf]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 */
[b7fd2a0]419errno_t nic_autoneg_disable(async_sess_t *dev_sess)
[7858acbf]420{
421 async_exch_t *exch = async_exchange_begin(dev_sess);
[b7fd2a0]422 errno_t rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]423 NIC_AUTONEG_DISABLE);
424 async_exchange_end(exch);
[a35b458]425
[7858acbf]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 */
[b7fd2a0]446errno_t nic_autoneg_probe(async_sess_t *dev_sess, uint32_t *our_advertisement,
[7858acbf]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;
[a35b458]454
[7858acbf]455 async_exch_t *exch = async_exchange_begin(dev_sess);
[b7fd2a0]456 errno_t rc = async_req_1_4(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]457 NIC_AUTONEG_PROBE, &_our_advertisement, &_their_advertisement,
458 &_result, &_their_result);
459 async_exchange_end(exch);
[a35b458]460
[7858acbf]461 if (our_advertisement)
462 *our_advertisement = (uint32_t) _our_advertisement;
[a35b458]463
[7858acbf]464 if (*their_advertisement)
465 *their_advertisement = (uint32_t) _their_advertisement;
[a35b458]466
[7858acbf]467 if (result)
468 *result = (nic_result_t) _result;
[a35b458]469
[7858acbf]470 if (their_result)
471 *their_result = (nic_result_t) _their_result;
[a35b458]472
[7858acbf]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 */
[b7fd2a0]483errno_t nic_autoneg_restart(async_sess_t *dev_sess)
[7858acbf]484{
485 async_exch_t *exch = async_exchange_begin(dev_sess);
[b7fd2a0]486 errno_t rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]487 NIC_AUTONEG_RESTART);
488 async_exchange_end(exch);
[a35b458]489
[7858acbf]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 */
[b7fd2a0]503errno_t nic_get_pause(async_sess_t *dev_sess, nic_result_t *we_send,
[7858acbf]504 nic_result_t *we_receive, uint16_t *pause)
505{
506 sysarg_t _we_send;
507 sysarg_t _we_receive;
508 sysarg_t _pause;
[a35b458]509
[7858acbf]510 async_exch_t *exch = async_exchange_begin(dev_sess);
[b7fd2a0]511 errno_t rc = async_req_1_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]512 NIC_GET_PAUSE, &_we_send, &_we_receive, &_pause);
513 async_exchange_end(exch);
[a35b458]514
[7858acbf]515 if (we_send)
516 *we_send = _we_send;
[a35b458]517
[7858acbf]518 if (we_receive)
519 *we_receive = _we_receive;
[a35b458]520
[7858acbf]521 if (pause)
522 *pause = _pause;
[a35b458]523
[7858acbf]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 */
[b7fd2a0]541errno_t nic_set_pause(async_sess_t *dev_sess, int allow_send, int allow_receive,
[7858acbf]542 uint16_t pause)
543{
544 async_exch_t *exch = async_exchange_begin(dev_sess);
[b7fd2a0]545 errno_t rc = async_req_4_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]546 NIC_SET_PAUSE, allow_send, allow_receive, pause);
547 async_exchange_end(exch);
[a35b458]548
[7858acbf]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 */
[b7fd2a0]568errno_t nic_unicast_get_mode(async_sess_t *dev_sess, nic_unicast_mode_t *mode,
[7858acbf]569 size_t max_count, nic_address_t *address_list, size_t *address_count)
570{
571 assert(mode);
[a35b458]572
[7858acbf]573 sysarg_t _mode;
574 sysarg_t _address_count;
[a35b458]575
[7858acbf]576 if (!address_list)
577 max_count = 0;
[a35b458]578
[7858acbf]579 async_exch_t *exch = async_exchange_begin(dev_sess);
[a35b458]580
[b7fd2a0]581 errno_t rc = async_req_2_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]582 NIC_UNICAST_GET_MODE, max_count, &_mode, &_address_count);
583 if (rc != EOK) {
584 async_exchange_end(exch);
585 return rc;
586 }
[a35b458]587
[7858acbf]588 *mode = (nic_unicast_mode_t) _mode;
589 if (address_count)
590 *address_count = (size_t) _address_count;
[a35b458]591
[7858acbf]592 if ((max_count) && (_address_count))
593 rc = async_data_read_start(exch, address_list,
594 max_count * sizeof(nic_address_t));
[a35b458]595
[7858acbf]596 async_exchange_end(exch);
[a35b458]597
[7858acbf]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 */
[b7fd2a0]611errno_t nic_unicast_set_mode(async_sess_t *dev_sess, nic_unicast_mode_t mode,
[7858acbf]612 const nic_address_t *address_list, size_t address_count)
613{
614 if (address_list == NULL)
615 address_count = 0;
[a35b458]616
[7858acbf]617 async_exch_t *exch = async_exchange_begin(dev_sess);
[a35b458]618
[7858acbf]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);
[a35b458]621
[b7fd2a0]622 errno_t rc;
[7858acbf]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;
[a35b458]628
[7858acbf]629 async_exchange_end(exch);
[a35b458]630
[b7fd2a0]631 errno_t res;
[7858acbf]632 async_wait_for(message_id, &res);
[a35b458]633
[7858acbf]634 if (rc != EOK)
635 return rc;
[a35b458]636
[d5c1051]637 return res;
[7858acbf]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 */
[b7fd2a0]657errno_t nic_multicast_get_mode(async_sess_t *dev_sess, nic_multicast_mode_t *mode,
[7858acbf]658 size_t max_count, nic_address_t *address_list, size_t *address_count)
659{
660 assert(mode);
[a35b458]661
[7858acbf]662 sysarg_t _mode;
[a35b458]663
[7858acbf]664 if (!address_list)
665 max_count = 0;
[a35b458]666
[7858acbf]667 async_exch_t *exch = async_exchange_begin(dev_sess);
[a35b458]668
[7858acbf]669 sysarg_t ac;
[b7fd2a0]670 errno_t rc = async_req_2_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]671 NIC_MULTICAST_GET_MODE, max_count, &_mode, &ac);
672 if (rc != EOK) {
673 async_exchange_end(exch);
674 return rc;
675 }
[a35b458]676
[7858acbf]677 *mode = (nic_multicast_mode_t) _mode;
678 if (address_count)
679 *address_count = (size_t) ac;
[a35b458]680
[7858acbf]681 if ((max_count) && (ac))
682 rc = async_data_read_start(exch, address_list,
683 max_count * sizeof(nic_address_t));
[a35b458]684
[7858acbf]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 */
[b7fd2a0]699errno_t nic_multicast_set_mode(async_sess_t *dev_sess, nic_multicast_mode_t mode,
[7858acbf]700 const nic_address_t *address_list, size_t address_count)
701{
702 if (address_list == NULL)
703 address_count = 0;
[a35b458]704
[7858acbf]705 async_exch_t *exch = async_exchange_begin(dev_sess);
[a35b458]706
[7858acbf]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);
[a35b458]709
[b7fd2a0]710 errno_t rc;
[7858acbf]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;
[a35b458]716
[7858acbf]717 async_exchange_end(exch);
[a35b458]718
[b7fd2a0]719 errno_t res;
[7858acbf]720 async_wait_for(message_id, &res);
[a35b458]721
[7858acbf]722 if (rc != EOK)
723 return rc;
[a35b458]724
[d5c1051]725 return res;
[7858acbf]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 */
[b7fd2a0]736errno_t nic_broadcast_get_mode(async_sess_t *dev_sess, nic_broadcast_mode_t *mode)
[7858acbf]737{
738 assert(mode);
[a35b458]739
[7858acbf]740 sysarg_t _mode;
[a35b458]741
[7858acbf]742 async_exch_t *exch = async_exchange_begin(dev_sess);
[b7fd2a0]743 errno_t rc = async_req_1_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]744 NIC_BROADCAST_GET_MODE, &_mode);
745 async_exchange_end(exch);
[a35b458]746
[7858acbf]747 *mode = (nic_broadcast_mode_t) _mode;
[a35b458]748
[7858acbf]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 */
[b7fd2a0]760errno_t nic_broadcast_set_mode(async_sess_t *dev_sess, nic_broadcast_mode_t mode)
[7858acbf]761{
762 async_exch_t *exch = async_exchange_begin(dev_sess);
[b7fd2a0]763 errno_t rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]764 NIC_BROADCAST_SET_MODE, mode);
765 async_exchange_end(exch);
[a35b458]766
[7858acbf]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 */
[b7fd2a0]778errno_t nic_defective_get_mode(async_sess_t *dev_sess, uint32_t *mode)
[7858acbf]779{
780 assert(mode);
[a35b458]781
[7858acbf]782 sysarg_t _mode;
[a35b458]783
[7858acbf]784 async_exch_t *exch = async_exchange_begin(dev_sess);
[b7fd2a0]785 errno_t rc = async_req_1_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]786 NIC_DEFECTIVE_GET_MODE, &_mode);
787 async_exchange_end(exch);
[a35b458]788
[7858acbf]789 *mode = (uint32_t) _mode;
[a35b458]790
[7858acbf]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 */
[b7fd2a0]802errno_t nic_defective_set_mode(async_sess_t *dev_sess, uint32_t mode)
[7858acbf]803{
804 async_exch_t *exch = async_exchange_begin(dev_sess);
[b7fd2a0]805 errno_t rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]806 NIC_DEFECTIVE_SET_MODE, mode);
807 async_exchange_end(exch);
[a35b458]808
[7858acbf]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 */
[b7fd2a0]824errno_t nic_blocked_sources_get(async_sess_t *dev_sess, size_t max_count,
[7858acbf]825 nic_address_t *address_list, size_t *address_count)
826{
827 if (!address_list)
828 max_count = 0;
[a35b458]829
[7858acbf]830 async_exch_t *exch = async_exchange_begin(dev_sess);
[a35b458]831
[7858acbf]832 sysarg_t ac;
[b7fd2a0]833 errno_t rc = async_req_2_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]834 NIC_BLOCKED_SOURCES_GET, max_count, &ac);
835 if (rc != EOK) {
836 async_exchange_end(exch);
837 return rc;
838 }
[a35b458]839
[7858acbf]840 if (address_count)
841 *address_count = (size_t) ac;
[a35b458]842
[7858acbf]843 if ((max_count) && (ac))
844 rc = async_data_read_start(exch, address_list,
845 max_count * sizeof(nic_address_t));
[a35b458]846
[7858acbf]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 */
[b7fd2a0]860errno_t nic_blocked_sources_set(async_sess_t *dev_sess,
[7858acbf]861 const nic_address_t *address_list, size_t address_count)
862{
863 if (address_list == NULL)
864 address_count = 0;
[a35b458]865
[7858acbf]866 async_exch_t *exch = async_exchange_begin(dev_sess);
[a35b458]867
[7858acbf]868 aid_t message_id = async_send_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
869 NIC_BLOCKED_SOURCES_SET, address_count, NULL);
[a35b458]870
[b7fd2a0]871 errno_t rc;
[7858acbf]872 if (address_count)
873 rc = async_data_write_start(exch, address_list,
[3bacee1]874 address_count * sizeof(nic_address_t));
[7858acbf]875 else
876 rc = EOK;
[a35b458]877
[7858acbf]878 async_exchange_end(exch);
[a35b458]879
[b7fd2a0]880 errno_t res;
[7858acbf]881 async_wait_for(message_id, &res);
[a35b458]882
[7858acbf]883 if (rc != EOK)
884 return rc;
[a35b458]885
[d5c1051]886 return res;
[7858acbf]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 */
[b7fd2a0]897errno_t nic_vlan_get_mask(async_sess_t *dev_sess, nic_vlan_mask_t *mask)
[7858acbf]898{
899 assert(mask);
[a35b458]900
[7858acbf]901 async_exch_t *exch = async_exchange_begin(dev_sess);
[b7fd2a0]902 errno_t rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]903 NIC_VLAN_GET_MASK);
904 if (rc != EOK) {
905 async_exchange_end(exch);
906 return rc;
907 }
[a35b458]908
[7858acbf]909 rc = async_data_read_start(exch, mask, sizeof(nic_vlan_mask_t));
910 async_exchange_end(exch);
[a35b458]911
[7858acbf]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 */
[b7fd2a0]925errno_t nic_vlan_set_mask(async_sess_t *dev_sess, const nic_vlan_mask_t *mask)
[7858acbf]926{
927 async_exch_t *exch = async_exchange_begin(dev_sess);
[a35b458]928
[7858acbf]929 aid_t message_id = async_send_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
930 NIC_VLAN_SET_MASK, mask != NULL, NULL);
[a35b458]931
[b7fd2a0]932 errno_t rc;
[7858acbf]933 if (mask != NULL)
934 rc = async_data_write_start(exch, mask, sizeof(nic_vlan_mask_t));
935 else
936 rc = EOK;
[a35b458]937
[7858acbf]938 async_exchange_end(exch);
[a35b458]939
[b7fd2a0]940 errno_t res;
[7858acbf]941 async_wait_for(message_id, &res);
[a35b458]942
[7858acbf]943 if (rc != EOK)
944 return rc;
[a35b458]945
[d5c1051]946 return res;
[7858acbf]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 */
[b7fd2a0]965errno_t nic_vlan_set_tag(async_sess_t *dev_sess, uint16_t tag, bool add, bool strip)
[7858acbf]966{
967 async_exch_t *exch = async_exchange_begin(dev_sess);
[b7fd2a0]968 errno_t rc = async_req_4_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]969 NIC_VLAN_SET_TAG, (sysarg_t) tag, (sysarg_t) add, (sysarg_t) strip);
970 async_exchange_end(exch);
[a35b458]971
[7858acbf]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 */
[b7fd2a0]987errno_t nic_wol_virtue_add(async_sess_t *dev_sess, nic_wv_type_t type,
[7858acbf]988 const void *data, size_t length, nic_wv_id_t *id)
989{
990 assert(id);
[a35b458]991
[7858acbf]992 bool send_data = ((data != NULL) && (length != 0));
993 async_exch_t *exch = async_exchange_begin(dev_sess);
[a35b458]994
[7858acbf]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);
[a35b458]998
[b7fd2a0]999 errno_t res;
[7858acbf]1000 if (send_data) {
[b7fd2a0]1001 errno_t rc = async_data_write_start(exch, data, length);
[7858acbf]1002 if (rc != EOK) {
1003 async_exchange_end(exch);
1004 async_wait_for(message_id, &res);
1005 return rc;
1006 }
1007 }
[a35b458]1008
[7858acbf]1009 async_exchange_end(exch);
1010 async_wait_for(message_id, &res);
[a35b458]1011
[7858acbf]1012 *id = IPC_GET_ARG1(result);
[d5c1051]1013 return res;
[7858acbf]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 */
[b7fd2a0]1024errno_t nic_wol_virtue_remove(async_sess_t *dev_sess, nic_wv_id_t id)
[7858acbf]1025{
1026 async_exch_t *exch = async_exchange_begin(dev_sess);
[b7fd2a0]1027 errno_t rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]1028 NIC_WOL_VIRTUE_REMOVE, (sysarg_t) id);
1029 async_exchange_end(exch);
[a35b458]1030
[7858acbf]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 */
[b7fd2a0]1047errno_t nic_wol_virtue_probe(async_sess_t *dev_sess, nic_wv_id_t id,
[7858acbf]1048 nic_wv_type_t *type, size_t max_length, void *data, size_t *length)
1049{
1050 sysarg_t _type;
1051 sysarg_t _length;
[a35b458]1052
[7858acbf]1053 if (data == NULL)
1054 max_length = 0;
[a35b458]1055
[7858acbf]1056 async_exch_t *exch = async_exchange_begin(dev_sess);
[a35b458]1057
[b7fd2a0]1058 errno_t rc = async_req_3_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]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 }
[a35b458]1065
[7858acbf]1066 if (type)
1067 *type = _type;
[a35b458]1068
[7858acbf]1069 if (length)
1070 *length = _length;
[a35b458]1071
[7858acbf]1072 if ((max_length) && (_length != 0))
1073 rc = async_data_read_start(exch, data, max_length);
[a35b458]1074
[7858acbf]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 */
[b7fd2a0]1097errno_t nic_wol_virtue_list(async_sess_t *dev_sess, nic_wv_type_t type,
[7858acbf]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;
[a35b458]1102
[7858acbf]1103 async_exch_t *exch = async_exchange_begin(dev_sess);
[a35b458]1104
[7858acbf]1105 sysarg_t count;
[b7fd2a0]1106 errno_t rc = async_req_3_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]1107 NIC_WOL_VIRTUE_LIST, (sysarg_t) type, max_count, &count);
[a35b458]1108
[7858acbf]1109 if (id_count)
1110 *id_count = (size_t) count;
[a35b458]1111
[7858acbf]1112 if ((rc != EOK) || (!max_count)) {
1113 async_exchange_end(exch);
1114 return rc;
1115 }
[a35b458]1116
[7858acbf]1117 rc = async_data_read_start(exch, id_list,
1118 max_count * sizeof(nic_wv_id_t));
[a35b458]1119
[7858acbf]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 */
[b7fd2a0]1137errno_t nic_wol_virtue_get_caps(async_sess_t *dev_sess, nic_wv_type_t type,
[7858acbf]1138 int *count)
1139{
1140 assert(count);
[a35b458]1141
[7858acbf]1142 sysarg_t _count;
[a35b458]1143
[7858acbf]1144 async_exch_t *exch = async_exchange_begin(dev_sess);
[b7fd2a0]1145 errno_t rc = async_req_2_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]1146 NIC_WOL_VIRTUE_GET_CAPS, (sysarg_t) type, &_count);
1147 async_exchange_end(exch);
[a35b458]1148
[7858acbf]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 */
[b7fd2a0]1175errno_t nic_wol_load_info(async_sess_t *dev_sess, nic_wv_type_t *matched_type,
[7858acbf]1176 size_t max_length, uint8_t *frame, size_t *frame_length)
1177{
1178 assert(matched_type);
[a35b458]1179
[7858acbf]1180 sysarg_t _matched_type;
1181 sysarg_t _frame_length;
[a35b458]1182
[7858acbf]1183 if (frame == NULL)
1184 max_length = 0;
[a35b458]1185
[7858acbf]1186 async_exch_t *exch = async_exchange_begin(dev_sess);
[a35b458]1187
[b7fd2a0]1188 errno_t rc = async_req_2_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]1189 NIC_WOL_LOAD_INFO, max_length, &_matched_type, &_frame_length);
1190 if (rc != EOK) {
1191 async_exchange_end(exch);
1192 return rc;
1193 }
[a35b458]1194
[7858acbf]1195 *matched_type = (nic_wv_type_t) _matched_type;
1196 if (frame_length)
1197 *frame_length = (size_t) _frame_length;
[a35b458]1198
[7858acbf]1199 if ((max_length != 0) && (_frame_length != 0))
1200 rc = async_data_read_start(exch, frame, max_length);
[a35b458]1201
[7858acbf]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 */
[b7fd2a0]1215errno_t nic_offload_probe(async_sess_t *dev_sess, uint32_t *supported,
[7858acbf]1216 uint32_t *active)
1217{
1218 assert(supported);
1219 assert(active);
[a35b458]1220
[7858acbf]1221 sysarg_t _supported;
1222 sysarg_t _active;
[a35b458]1223
[7858acbf]1224 async_exch_t *exch = async_exchange_begin(dev_sess);
[b7fd2a0]1225 errno_t rc = async_req_1_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]1226 NIC_OFFLOAD_PROBE, &_supported, &_active);
1227 async_exchange_end(exch);
[a35b458]1228
[7858acbf]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 */
[b7fd2a0]1243errno_t nic_offload_set(async_sess_t *dev_sess, uint32_t mask, uint32_t active)
[7858acbf]1244{
1245 async_exch_t *exch = async_exchange_begin(dev_sess);
[b7fd2a0]1246 errno_t rc = async_req_3_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]1247 NIC_AUTONEG_RESTART, (sysarg_t) mask, (sysarg_t) active);
1248 async_exchange_end(exch);
[a35b458]1249
[7858acbf]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 */
[b7fd2a0]1263errno_t nic_poll_get_mode(async_sess_t *dev_sess, nic_poll_mode_t *mode,
[bd41ac52]1264 struct timespec *period)
[7858acbf]1265{
1266 assert(mode);
[a35b458]1267
[7858acbf]1268 sysarg_t _mode;
[a35b458]1269
[7858acbf]1270 async_exch_t *exch = async_exchange_begin(dev_sess);
[a35b458]1271
[b7fd2a0]1272 errno_t rc = async_req_2_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
[7858acbf]1273 NIC_POLL_GET_MODE, period != NULL, &_mode);
1274 if (rc != EOK) {
1275 async_exchange_end(exch);
1276 return rc;
1277 }
[a35b458]1278
[7858acbf]1279 *mode = (nic_poll_mode_t) _mode;
[a35b458]1280
[7858acbf]1281 if (period != NULL)
[bd41ac52]1282 rc = async_data_read_start(exch, period, sizeof(struct timespec));
[a35b458]1283
[7858acbf]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 */
[b7fd2a0]1297errno_t nic_poll_set_mode(async_sess_t *dev_sess, nic_poll_mode_t mode,
[bd41ac52]1298 const struct timespec *period)
[7858acbf]1299{
1300 async_exch_t *exch = async_exchange_begin(dev_sess);
[a35b458]1301
[7858acbf]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);
[a35b458]1304
[b7fd2a0]1305 errno_t rc;
[7858acbf]1306 if (period)
[bd41ac52]1307 rc = async_data_write_start(exch, period, sizeof(struct timespec));
[7858acbf]1308 else
1309 rc = EOK;
[a35b458]1310
[7858acbf]1311 async_exchange_end(exch);
[a35b458]1312
[b7fd2a0]1313 errno_t res;
[7858acbf]1314 async_wait_for(message_id, &res);
[a35b458]1315
[7858acbf]1316 if (rc != EOK)
1317 return rc;
[a35b458]1318
[d5c1051]1319 return res;
[7858acbf]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 */
[b7fd2a0]1329errno_t nic_poll_now(async_sess_t *dev_sess)
[7858acbf]1330{
1331 async_exch_t *exch = async_exchange_begin(dev_sess);
[b7fd2a0]1332 errno_t rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE), NIC_POLL_NOW);
[7858acbf]1333 async_exchange_end(exch);
[a35b458]1334
[7858acbf]1335 return rc;
1336}
[609243f4]1337
[6d8455d]1338static void remote_nic_send_frame(ddf_fun_t *dev, void *iface,
[984a9ba]1339 ipc_call_t *call)
[609243f4]1340{
1341 nic_iface_t *nic_iface = (nic_iface_t *) iface;
[6d8455d]1342 assert(nic_iface->send_frame);
[a35b458]1343
[6d8455d]1344 void *data;
1345 size_t size;
[b7fd2a0]1346 errno_t rc;
[a35b458]1347
[6d8455d]1348 rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
1349 if (rc != EOK) {
[984a9ba]1350 async_answer_0(call, EINVAL);
[6d8455d]1351 return;
1352 }
[a35b458]1353
[6d8455d]1354 rc = nic_iface->send_frame(dev, data, size);
[984a9ba]1355 async_answer_0(call, rc);
[6d8455d]1356 free(data);
[609243f4]1357}
1358
[8d7ec69d]1359static void remote_nic_callback_create(ddf_fun_t *dev, void *iface,
[984a9ba]1360 ipc_call_t *call)
[609243f4]1361{
1362 nic_iface_t *nic_iface = (nic_iface_t *) iface;
[8d7ec69d]1363 assert(nic_iface->callback_create);
[a35b458]1364
[b7fd2a0]1365 errno_t rc = nic_iface->callback_create(dev);
[984a9ba]1366 async_answer_0(call, rc);
[609243f4]1367}
1368
1369static void remote_nic_get_state(ddf_fun_t *dev, void *iface,
[984a9ba]1370 ipc_call_t *call)
[609243f4]1371{
1372 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1373 assert(nic_iface->get_state);
[a35b458]1374
[609243f4]1375 nic_device_state_t state = NIC_STATE_MAX;
[a35b458]1376
[b7fd2a0]1377 errno_t rc = nic_iface->get_state(dev, &state);
[984a9ba]1378 async_answer_1(call, rc, state);
[609243f4]1379}
1380
1381static void remote_nic_set_state(ddf_fun_t *dev, void *iface,
[984a9ba]1382 ipc_call_t *call)
[609243f4]1383{
1384 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1385 assert(nic_iface->set_state);
[a35b458]1386
[609243f4]1387 nic_device_state_t state = (nic_device_state_t) IPC_GET_ARG2(*call);
[a35b458]1388
[b7fd2a0]1389 errno_t rc = nic_iface->set_state(dev, state);
[984a9ba]1390 async_answer_0(call, rc);
[609243f4]1391}
1392
1393static void remote_nic_get_address(ddf_fun_t *dev, void *iface,
[984a9ba]1394 ipc_call_t *call)
[609243f4]1395{
1396 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1397 assert(nic_iface->get_address);
[a35b458]1398
[609243f4]1399 nic_address_t address;
[acdb5bac]1400 memset(&address, 0, sizeof(nic_address_t));
[a35b458]1401
[b7fd2a0]1402 errno_t rc = nic_iface->get_address(dev, &address);
[609243f4]1403 if (rc == EOK) {
[984a9ba]1404 ipc_call_t data;
[609243f4]1405 size_t max_len;
[a35b458]1406
[609243f4]1407 /* All errors will be translated into EPARTY anyway */
[984a9ba]1408 if (!async_data_read_receive(&data, &max_len)) {
1409 async_answer_0(&data, EINVAL);
1410 async_answer_0(call, EINVAL);
[609243f4]1411 return;
1412 }
[a35b458]1413
[609243f4]1414 if (max_len != sizeof(nic_address_t)) {
[984a9ba]1415 async_answer_0(&data, ELIMIT);
1416 async_answer_0(call, ELIMIT);
[609243f4]1417 return;
1418 }
[a35b458]1419
[984a9ba]1420 async_data_read_finalize(&data, &address,
[609243f4]1421 sizeof(nic_address_t));
1422 }
[a35b458]1423
[984a9ba]1424 async_answer_0(call, rc);
[609243f4]1425}
1426
1427static void remote_nic_set_address(ddf_fun_t *dev, void *iface,
[984a9ba]1428 ipc_call_t *call)
[609243f4]1429{
1430 nic_iface_t *nic_iface = (nic_iface_t *) iface;
[a35b458]1431
[984a9ba]1432 ipc_call_t data;
[609243f4]1433 size_t length;
[984a9ba]1434 if (!async_data_write_receive(&data, &length)) {
1435 async_answer_0(&data, EINVAL);
1436 async_answer_0(call, EINVAL);
[609243f4]1437 return;
1438 }
[a35b458]1439
[609243f4]1440 if (length > sizeof(nic_address_t)) {
[984a9ba]1441 async_answer_0(&data, ELIMIT);
1442 async_answer_0(call, ELIMIT);
[609243f4]1443 return;
1444 }
[a35b458]1445
[609243f4]1446 nic_address_t address;
[984a9ba]1447 if (async_data_write_finalize(&data, &address, length) != EOK) {
1448 async_answer_0(call, EINVAL);
[609243f4]1449 return;
1450 }
[a35b458]1451
[609243f4]1452 if (nic_iface->set_address != NULL) {
[b7fd2a0]1453 errno_t rc = nic_iface->set_address(dev, &address);
[984a9ba]1454 async_answer_0(call, rc);
[609243f4]1455 } else
[984a9ba]1456 async_answer_0(call, ENOTSUP);
[609243f4]1457}
1458
1459static void remote_nic_get_stats(ddf_fun_t *dev, void *iface,
[984a9ba]1460 ipc_call_t *call)
[609243f4]1461{
1462 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1463 if (nic_iface->get_stats == NULL) {
[984a9ba]1464 async_answer_0(call, ENOTSUP);
[609243f4]1465 return;
1466 }
[a35b458]1467
[609243f4]1468 nic_device_stats_t stats;
[acdb5bac]1469 memset(&stats, 0, sizeof(nic_device_stats_t));
[a35b458]1470
[b7fd2a0]1471 errno_t rc = nic_iface->get_stats(dev, &stats);
[609243f4]1472 if (rc == EOK) {
[984a9ba]1473 ipc_call_t data;
[609243f4]1474 size_t max_len;
[984a9ba]1475 if (!async_data_read_receive(&data, &max_len)) {
1476 async_answer_0(&data, EINVAL);
1477 async_answer_0(call, EINVAL);
[609243f4]1478 return;
1479 }
[a35b458]1480
[609243f4]1481 if (max_len < sizeof(nic_device_stats_t)) {
[984a9ba]1482 async_answer_0(&data, ELIMIT);
1483 async_answer_0(call, ELIMIT);
[609243f4]1484 return;
1485 }
[a35b458]1486
[984a9ba]1487 async_data_read_finalize(&data, &stats,
[609243f4]1488 sizeof(nic_device_stats_t));
1489 }
[a35b458]1490
[984a9ba]1491 async_answer_0(call, rc);
[609243f4]1492}
1493
1494static void remote_nic_get_device_info(ddf_fun_t *dev, void *iface,
[984a9ba]1495 ipc_call_t *call)
[609243f4]1496{
1497 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1498 if (nic_iface->get_device_info == NULL) {
[984a9ba]1499 async_answer_0(call, ENOTSUP);
[609243f4]1500 return;
1501 }
[a35b458]1502
[609243f4]1503 nic_device_info_t info;
[acdb5bac]1504 memset(&info, 0, sizeof(nic_device_info_t));
[a35b458]1505
[b7fd2a0]1506 errno_t rc = nic_iface->get_device_info(dev, &info);
[609243f4]1507 if (rc == EOK) {
[984a9ba]1508 ipc_call_t data;
[609243f4]1509 size_t max_len;
[984a9ba]1510 if (!async_data_read_receive(&data, &max_len)) {
1511 async_answer_0(&data, EINVAL);
1512 async_answer_0(call, EINVAL);
[609243f4]1513 return;
1514 }
[a35b458]1515
[609243f4]1516 if (max_len < sizeof (nic_device_info_t)) {
[984a9ba]1517 async_answer_0(&data, ELIMIT);
1518 async_answer_0(call, ELIMIT);
[609243f4]1519 return;
1520 }
[a35b458]1521
[984a9ba]1522 async_data_read_finalize(&data, &info,
[609243f4]1523 sizeof(nic_device_info_t));
1524 }
[a35b458]1525
[984a9ba]1526 async_answer_0(call, rc);
[609243f4]1527}
1528
1529static void remote_nic_get_cable_state(ddf_fun_t *dev, void *iface,
[984a9ba]1530 ipc_call_t *call)
[609243f4]1531{
1532 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1533 if (nic_iface->get_cable_state == NULL) {
[984a9ba]1534 async_answer_0(call, ENOTSUP);
[609243f4]1535 return;
1536 }
[a35b458]1537
[609243f4]1538 nic_cable_state_t cs = NIC_CS_UNKNOWN;
[a35b458]1539
[b7fd2a0]1540 errno_t rc = nic_iface->get_cable_state(dev, &cs);
[984a9ba]1541 async_answer_1(call, rc, (sysarg_t) cs);
[609243f4]1542}
1543
1544static void remote_nic_get_operation_mode(ddf_fun_t *dev, void *iface,
[984a9ba]1545 ipc_call_t *call)
[609243f4]1546{
1547 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1548 if (nic_iface->get_operation_mode == NULL) {
[984a9ba]1549 async_answer_0(call, ENOTSUP);
[609243f4]1550 return;
1551 }
[a35b458]1552
[609243f4]1553 int speed = 0;
1554 nic_channel_mode_t duplex = NIC_CM_UNKNOWN;
1555 nic_role_t role = NIC_ROLE_UNKNOWN;
[a35b458]1556
[b7fd2a0]1557 errno_t rc = nic_iface->get_operation_mode(dev, &speed, &duplex, &role);
[984a9ba]1558 async_answer_3(call, rc, (sysarg_t) speed, (sysarg_t) duplex,
[609243f4]1559 (sysarg_t) role);
1560}
1561
1562static void remote_nic_set_operation_mode(ddf_fun_t *dev, void *iface,
[984a9ba]1563 ipc_call_t *call)
[609243f4]1564{
1565 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1566 if (nic_iface->set_operation_mode == NULL) {
[984a9ba]1567 async_answer_0(call, ENOTSUP);
[609243f4]1568 return;
1569 }
[a35b458]1570
[609243f4]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);
[a35b458]1574
[b7fd2a0]1575 errno_t rc = nic_iface->set_operation_mode(dev, speed, duplex, role);
[984a9ba]1576 async_answer_0(call, rc);
[609243f4]1577}
1578
1579static void remote_nic_autoneg_enable(ddf_fun_t *dev, void *iface,
[984a9ba]1580 ipc_call_t *call)
[609243f4]1581{
1582 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1583 if (nic_iface->autoneg_enable == NULL) {
[984a9ba]1584 async_answer_0(call, ENOTSUP);
[609243f4]1585 return;
1586 }
[a35b458]1587
[609243f4]1588 uint32_t advertisement = (uint32_t) IPC_GET_ARG2(*call);
[a35b458]1589
[b7fd2a0]1590 errno_t rc = nic_iface->autoneg_enable(dev, advertisement);
[984a9ba]1591 async_answer_0(call, rc);
[609243f4]1592}
1593
1594static void remote_nic_autoneg_disable(ddf_fun_t *dev, void *iface,
[984a9ba]1595 ipc_call_t *call)
[609243f4]1596{
1597 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1598 if (nic_iface->autoneg_disable == NULL) {
[984a9ba]1599 async_answer_0(call, ENOTSUP);
[609243f4]1600 return;
1601 }
[a35b458]1602
[b7fd2a0]1603 errno_t rc = nic_iface->autoneg_disable(dev);
[984a9ba]1604 async_answer_0(call, rc);
[609243f4]1605}
1606
1607static void remote_nic_autoneg_probe(ddf_fun_t *dev, void *iface,
[984a9ba]1608 ipc_call_t *call)
[609243f4]1609{
1610 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1611 if (nic_iface->autoneg_probe == NULL) {
[984a9ba]1612 async_answer_0(call, ENOTSUP);
[609243f4]1613 return;
1614 }
[a35b458]1615
[609243f4]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;
[a35b458]1620
[b7fd2a0]1621 errno_t rc = nic_iface->autoneg_probe(dev, &our_adv, &their_adv, &result,
[609243f4]1622 &their_result);
[984a9ba]1623 async_answer_4(call, rc, our_adv, their_adv, (sysarg_t) result,
[609243f4]1624 (sysarg_t) their_result);
1625}
1626
1627static void remote_nic_autoneg_restart(ddf_fun_t *dev, void *iface,
[984a9ba]1628 ipc_call_t *call)
[609243f4]1629{
1630 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1631 if (nic_iface->autoneg_restart == NULL) {
[984a9ba]1632 async_answer_0(call, ENOTSUP);
[609243f4]1633 return;
1634 }
[a35b458]1635
[b7fd2a0]1636 errno_t rc = nic_iface->autoneg_restart(dev);
[984a9ba]1637 async_answer_0(call, rc);
[609243f4]1638}
1639
1640static void remote_nic_get_pause(ddf_fun_t *dev, void *iface,
[984a9ba]1641 ipc_call_t *call)
[609243f4]1642{
1643 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1644 if (nic_iface->get_pause == NULL) {
[984a9ba]1645 async_answer_0(call, ENOTSUP);
[609243f4]1646 return;
1647 }
[a35b458]1648
[609243f4]1649 nic_result_t we_send;
1650 nic_result_t we_receive;
1651 uint16_t pause;
[a35b458]1652
[b7fd2a0]1653 errno_t rc = nic_iface->get_pause(dev, &we_send, &we_receive, &pause);
[984a9ba]1654 async_answer_3(call, rc, we_send, we_receive, pause);
[609243f4]1655}
1656
1657static void remote_nic_set_pause(ddf_fun_t *dev, void *iface,
[984a9ba]1658 ipc_call_t *call)
[609243f4]1659{
1660 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1661 if (nic_iface->set_pause == NULL) {
[984a9ba]1662 async_answer_0(call, ENOTSUP);
[609243f4]1663 return;
1664 }
[a35b458]1665
[609243f4]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);
[a35b458]1669
[b7fd2a0]1670 errno_t rc = nic_iface->set_pause(dev, allow_send, allow_receive,
[609243f4]1671 pause);
[984a9ba]1672 async_answer_0(call, rc);
[609243f4]1673}
1674
1675static void remote_nic_unicast_get_mode(ddf_fun_t *dev, void *iface,
[984a9ba]1676 ipc_call_t *call)
[609243f4]1677{
1678 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1679 if (nic_iface->unicast_get_mode == NULL) {
[984a9ba]1680 async_answer_0(call, ENOTSUP);
[609243f4]1681 return;
1682 }
[a35b458]1683
[609243f4]1684 size_t max_count = IPC_GET_ARG2(*call);
1685 nic_address_t *address_list = NULL;
[a35b458]1686
[609243f4]1687 if (max_count != 0) {
1688 address_list = malloc(max_count * sizeof (nic_address_t));
1689 if (!address_list) {
[984a9ba]1690 async_answer_0(call, ENOMEM);
[609243f4]1691 return;
1692 }
1693 }
[a35b458]1694
[acdb5bac]1695 memset(address_list, 0, max_count * sizeof(nic_address_t));
[609243f4]1696 nic_unicast_mode_t mode = NIC_UNICAST_DEFAULT;
1697 size_t address_count = 0;
[a35b458]1698
[b7fd2a0]1699 errno_t rc = nic_iface->unicast_get_mode(dev, &mode, max_count, address_list,
[609243f4]1700 &address_count);
[a35b458]1701
[609243f4]1702 if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
1703 free(address_list);
[984a9ba]1704 async_answer_2(call, rc, mode, address_count);
[609243f4]1705 return;
1706 }
[a35b458]1707
[984a9ba]1708 ipc_call_t data;
[609243f4]1709 size_t max_len;
[984a9ba]1710 if (!async_data_read_receive(&data, &max_len)) {
1711 async_answer_0(&data, EINVAL);
1712 async_answer_2(call, rc, mode, address_count);
[609243f4]1713 free(address_list);
1714 return;
1715 }
[a35b458]1716
[609243f4]1717 if (max_len > address_count * sizeof(nic_address_t))
1718 max_len = address_count * sizeof(nic_address_t);
[a35b458]1719
[609243f4]1720 if (max_len > max_count * sizeof(nic_address_t))
1721 max_len = max_count * sizeof(nic_address_t);
[a35b458]1722
[984a9ba]1723 async_data_read_finalize(&data, address_list, max_len);
[a35b458]1724
[609243f4]1725 free(address_list);
[984a9ba]1726 async_answer_2(call, rc, mode, address_count);
[609243f4]1727}
1728
1729static void remote_nic_unicast_set_mode(ddf_fun_t *dev, void *iface,
[984a9ba]1730 ipc_call_t *call)
[609243f4]1731{
1732 nic_iface_t *nic_iface = (nic_iface_t *) iface;
[a35b458]1733
[609243f4]1734 size_t length;
1735 nic_unicast_mode_t mode = IPC_GET_ARG2(*call);
1736 size_t address_count = IPC_GET_ARG3(*call);
1737 nic_address_t *address_list = NULL;
[a35b458]1738
[609243f4]1739 if (address_count) {
[984a9ba]1740 ipc_call_t data;
1741 if (!async_data_write_receive(&data, &length)) {
1742 async_answer_0(&data, EINVAL);
1743 async_answer_0(call, EINVAL);
[609243f4]1744 return;
1745 }
[a35b458]1746
[609243f4]1747 if (length != address_count * sizeof(nic_address_t)) {
[984a9ba]1748 async_answer_0(&data, ELIMIT);
1749 async_answer_0(call, ELIMIT);
[609243f4]1750 return;
1751 }
[a35b458]1752
[609243f4]1753 address_list = malloc(length);
1754 if (address_list == NULL) {
[984a9ba]1755 async_answer_0(&data, ENOMEM);
1756 async_answer_0(call, ENOMEM);
[609243f4]1757 return;
1758 }
[a35b458]1759
[984a9ba]1760 if (async_data_write_finalize(&data, address_list,
[609243f4]1761 length) != EOK) {
[984a9ba]1762 async_answer_0(call, EINVAL);
[609243f4]1763 free(address_list);
1764 return;
1765 }
1766 }
[a35b458]1767
[609243f4]1768 if (nic_iface->unicast_set_mode != NULL) {
[b7fd2a0]1769 errno_t rc = nic_iface->unicast_set_mode(dev, mode, address_list,
[609243f4]1770 address_count);
[984a9ba]1771 async_answer_0(call, rc);
[609243f4]1772 } else
[984a9ba]1773 async_answer_0(call, ENOTSUP);
[a35b458]1774
[609243f4]1775 free(address_list);
1776}
1777
1778static void remote_nic_multicast_get_mode(ddf_fun_t *dev, void *iface,
[984a9ba]1779 ipc_call_t *call)
[609243f4]1780{
1781 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1782 if (nic_iface->multicast_get_mode == NULL) {
[984a9ba]1783 async_answer_0(call, ENOTSUP);
[609243f4]1784 return;
1785 }
[a35b458]1786
[609243f4]1787 size_t max_count = IPC_GET_ARG2(*call);
1788 nic_address_t *address_list = NULL;
[a35b458]1789
[609243f4]1790 if (max_count != 0) {
1791 address_list = malloc(max_count * sizeof(nic_address_t));
1792 if (!address_list) {
[984a9ba]1793 async_answer_0(call, ENOMEM);
[609243f4]1794 return;
1795 }
1796 }
[a35b458]1797
[acdb5bac]1798 memset(address_list, 0, max_count * sizeof(nic_address_t));
[609243f4]1799 nic_multicast_mode_t mode = NIC_MULTICAST_BLOCKED;
1800 size_t address_count = 0;
[a35b458]1801
[b7fd2a0]1802 errno_t rc = nic_iface->multicast_get_mode(dev, &mode, max_count, address_list,
[609243f4]1803 &address_count);
[a35b458]1804
1805
[609243f4]1806 if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
1807 free(address_list);
[984a9ba]1808 async_answer_2(call, rc, mode, address_count);
[609243f4]1809 return;
1810 }
[a35b458]1811
[984a9ba]1812 ipc_call_t data;
[609243f4]1813 size_t max_len;
[984a9ba]1814 if (!async_data_read_receive(&data, &max_len)) {
1815 async_answer_0(&data, EINVAL);
1816 async_answer_2(call, rc, mode, address_count);
[609243f4]1817 free(address_list);
1818 return;
1819 }
[a35b458]1820
[609243f4]1821 if (max_len > address_count * sizeof(nic_address_t))
1822 max_len = address_count * sizeof(nic_address_t);
[a35b458]1823
[609243f4]1824 if (max_len > max_count * sizeof(nic_address_t))
1825 max_len = max_count * sizeof(nic_address_t);
[a35b458]1826
[984a9ba]1827 async_data_read_finalize(&data, address_list, max_len);
[a35b458]1828
[609243f4]1829 free(address_list);
[984a9ba]1830 async_answer_2(call, rc, mode, address_count);
[609243f4]1831}
1832
1833static void remote_nic_multicast_set_mode(ddf_fun_t *dev, void *iface,
[984a9ba]1834 ipc_call_t *call)
[609243f4]1835{
1836 nic_iface_t *nic_iface = (nic_iface_t *) iface;
[a35b458]1837
[609243f4]1838 nic_multicast_mode_t mode = IPC_GET_ARG2(*call);
1839 size_t address_count = IPC_GET_ARG3(*call);
1840 nic_address_t *address_list = NULL;
[a35b458]1841
[609243f4]1842 if (address_count) {
[984a9ba]1843 ipc_call_t data;
[609243f4]1844 size_t length;
[984a9ba]1845 if (!async_data_write_receive(&data, &length)) {
1846 async_answer_0(&data, EINVAL);
1847 async_answer_0(call, EINVAL);
[609243f4]1848 return;
1849 }
[a35b458]1850
[609243f4]1851 if (length != address_count * sizeof (nic_address_t)) {
[984a9ba]1852 async_answer_0(&data, ELIMIT);
1853 async_answer_0(call, ELIMIT);
[609243f4]1854 return;
1855 }
[a35b458]1856
[609243f4]1857 address_list = malloc(length);
1858 if (address_list == NULL) {
[984a9ba]1859 async_answer_0(&data, ENOMEM);
1860 async_answer_0(call, ENOMEM);
[609243f4]1861 return;
1862 }
[a35b458]1863
[984a9ba]1864 if (async_data_write_finalize(&data, address_list,
[609243f4]1865 length) != EOK) {
[984a9ba]1866 async_answer_0(call, EINVAL);
[609243f4]1867 free(address_list);
1868 return;
1869 }
1870 }
[a35b458]1871
[609243f4]1872 if (nic_iface->multicast_set_mode != NULL) {
[b7fd2a0]1873 errno_t rc = nic_iface->multicast_set_mode(dev, mode, address_list,
[609243f4]1874 address_count);
[984a9ba]1875 async_answer_0(call, rc);
[609243f4]1876 } else
[984a9ba]1877 async_answer_0(call, ENOTSUP);
[a35b458]1878
[609243f4]1879 free(address_list);
1880}
1881
1882static void remote_nic_broadcast_get_mode(ddf_fun_t *dev, void *iface,
[984a9ba]1883 ipc_call_t *call)
[609243f4]1884{
1885 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1886 if (nic_iface->broadcast_get_mode == NULL) {
[984a9ba]1887 async_answer_0(call, ENOTSUP);
[609243f4]1888 return;
1889 }
[a35b458]1890
[609243f4]1891 nic_broadcast_mode_t mode = NIC_BROADCAST_ACCEPTED;
[a35b458]1892
[b7fd2a0]1893 errno_t rc = nic_iface->broadcast_get_mode(dev, &mode);
[984a9ba]1894 async_answer_1(call, rc, mode);
[609243f4]1895}
1896
1897static void remote_nic_broadcast_set_mode(ddf_fun_t *dev, void *iface,
[984a9ba]1898 ipc_call_t *call)
[609243f4]1899{
1900 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1901 if (nic_iface->broadcast_set_mode == NULL) {
[984a9ba]1902 async_answer_0(call, ENOTSUP);
[609243f4]1903 return;
1904 }
[a35b458]1905
[609243f4]1906 nic_broadcast_mode_t mode = IPC_GET_ARG2(*call);
[a35b458]1907
[b7fd2a0]1908 errno_t rc = nic_iface->broadcast_set_mode(dev, mode);
[984a9ba]1909 async_answer_0(call, rc);
[609243f4]1910}
1911
1912static void remote_nic_defective_get_mode(ddf_fun_t *dev, void *iface,
[984a9ba]1913 ipc_call_t *call)
[609243f4]1914{
1915 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1916 if (nic_iface->defective_get_mode == NULL) {
[984a9ba]1917 async_answer_0(call, ENOTSUP);
[609243f4]1918 return;
1919 }
[a35b458]1920
[609243f4]1921 uint32_t mode = 0;
[a35b458]1922
[b7fd2a0]1923 errno_t rc = nic_iface->defective_get_mode(dev, &mode);
[984a9ba]1924 async_answer_1(call, rc, mode);
[609243f4]1925}
1926
1927static void remote_nic_defective_set_mode(ddf_fun_t *dev, void *iface,
[984a9ba]1928 ipc_call_t *call)
[609243f4]1929{
1930 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1931 if (nic_iface->defective_set_mode == NULL) {
[984a9ba]1932 async_answer_0(call, ENOTSUP);
[609243f4]1933 return;
1934 }
[a35b458]1935
[609243f4]1936 uint32_t mode = IPC_GET_ARG2(*call);
[a35b458]1937
[b7fd2a0]1938 errno_t rc = nic_iface->defective_set_mode(dev, mode);
[984a9ba]1939 async_answer_0(call, rc);
[609243f4]1940}
1941
1942static void remote_nic_blocked_sources_get(ddf_fun_t *dev, void *iface,
[984a9ba]1943 ipc_call_t *call)
[609243f4]1944{
1945 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1946 if (nic_iface->blocked_sources_get == NULL) {
[984a9ba]1947 async_answer_0(call, ENOTSUP);
[609243f4]1948 return;
1949 }
[a35b458]1950
[609243f4]1951 size_t max_count = IPC_GET_ARG2(*call);
1952 nic_address_t *address_list = NULL;
[a35b458]1953
[609243f4]1954 if (max_count != 0) {
1955 address_list = malloc(max_count * sizeof(nic_address_t));
1956 if (!address_list) {
[984a9ba]1957 async_answer_0(call, ENOMEM);
[609243f4]1958 return;
1959 }
1960 }
[a35b458]1961
[acdb5bac]1962 memset(address_list, 0, max_count * sizeof(nic_address_t));
[609243f4]1963 size_t address_count = 0;
[a35b458]1964
[b7fd2a0]1965 errno_t rc = nic_iface->blocked_sources_get(dev, max_count, address_list,
[609243f4]1966 &address_count);
[a35b458]1967
[609243f4]1968 if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
[984a9ba]1969 async_answer_1(call, rc, address_count);
[609243f4]1970 free(address_list);
1971 return;
1972 }
[a35b458]1973
[984a9ba]1974 ipc_call_t data;
[609243f4]1975 size_t max_len;
[984a9ba]1976 if (!async_data_read_receive(&data, &max_len)) {
1977 async_answer_0(&data, EINVAL);
1978 async_answer_1(call, rc, address_count);
[609243f4]1979 free(address_list);
1980 return;
1981 }
[a35b458]1982
[609243f4]1983 if (max_len > address_count * sizeof(nic_address_t))
1984 max_len = address_count * sizeof(nic_address_t);
[a35b458]1985
[609243f4]1986 if (max_len > max_count * sizeof(nic_address_t))
1987 max_len = max_count * sizeof(nic_address_t);
[a35b458]1988
[984a9ba]1989 async_data_read_finalize(&data, address_list, max_len);
[a35b458]1990
[609243f4]1991 free(address_list);
[984a9ba]1992 async_answer_1(call, rc, address_count);
[609243f4]1993}
1994
1995static void remote_nic_blocked_sources_set(ddf_fun_t *dev, void *iface,
[984a9ba]1996 ipc_call_t *call)
[609243f4]1997{
1998 nic_iface_t *nic_iface = (nic_iface_t *) iface;
[a35b458]1999
[609243f4]2000 size_t length;
2001 size_t address_count = IPC_GET_ARG2(*call);
2002 nic_address_t *address_list = NULL;
[a35b458]2003
[609243f4]2004 if (address_count) {
[984a9ba]2005 ipc_call_t data;
2006 if (!async_data_write_receive(&data, &length)) {
2007 async_answer_0(&data, EINVAL);
2008 async_answer_0(call, EINVAL);
[609243f4]2009 return;
2010 }
[a35b458]2011
[609243f4]2012 if (length != address_count * sizeof(nic_address_t)) {
[984a9ba]2013 async_answer_0(&data, ELIMIT);
2014 async_answer_0(call, ELIMIT);
[609243f4]2015 return;
2016 }
[a35b458]2017
[609243f4]2018 address_list = malloc(length);
2019 if (address_list == NULL) {
[984a9ba]2020 async_answer_0(&data, ENOMEM);
2021 async_answer_0(call, ENOMEM);
[609243f4]2022 return;
2023 }
[a35b458]2024
[984a9ba]2025 if (async_data_write_finalize(&data, address_list,
[609243f4]2026 length) != EOK) {
[984a9ba]2027 async_answer_0(call, EINVAL);
[609243f4]2028 free(address_list);
2029 return;
2030 }
2031 }
[a35b458]2032
[609243f4]2033 if (nic_iface->blocked_sources_set != NULL) {
[b7fd2a0]2034 errno_t rc = nic_iface->blocked_sources_set(dev, address_list,
[609243f4]2035 address_count);
[984a9ba]2036 async_answer_0(call, rc);
[609243f4]2037 } else
[984a9ba]2038 async_answer_0(call, ENOTSUP);
[a35b458]2039
[609243f4]2040 free(address_list);
2041}
2042
2043static void remote_nic_vlan_get_mask(ddf_fun_t *dev, void *iface,
[984a9ba]2044 ipc_call_t *call)
[609243f4]2045{
2046 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2047 if (nic_iface->vlan_get_mask == NULL) {
[984a9ba]2048 async_answer_0(call, ENOTSUP);
[609243f4]2049 return;
2050 }
[a35b458]2051
[609243f4]2052 nic_vlan_mask_t vlan_mask;
[acdb5bac]2053 memset(&vlan_mask, 0, sizeof(nic_vlan_mask_t));
[a35b458]2054
[b7fd2a0]2055 errno_t rc = nic_iface->vlan_get_mask(dev, &vlan_mask);
[609243f4]2056 if (rc == EOK) {
[984a9ba]2057 ipc_call_t data;
[609243f4]2058 size_t max_len;
[984a9ba]2059 if (!async_data_read_receive(&data, &max_len)) {
2060 async_answer_0(&data, EINVAL);
2061 async_answer_0(call, EINVAL);
[609243f4]2062 return;
2063 }
[a35b458]2064
[609243f4]2065 if (max_len != sizeof(nic_vlan_mask_t)) {
[984a9ba]2066 async_answer_0(&data, EINVAL);
2067 async_answer_0(call, EINVAL);
[609243f4]2068 return;
2069 }
[a35b458]2070
[984a9ba]2071 async_data_read_finalize(&data, &vlan_mask, max_len);
[609243f4]2072 }
[a35b458]2073
[984a9ba]2074 async_answer_0(call, rc);
[609243f4]2075}
2076
2077static void remote_nic_vlan_set_mask(ddf_fun_t *dev, void *iface,
[984a9ba]2078 ipc_call_t *call)
[609243f4]2079{
2080 nic_iface_t *nic_iface = (nic_iface_t *) iface;
[a35b458]2081
[609243f4]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);
[a35b458]2085
[609243f4]2086 if (vlan_mask_set) {
[984a9ba]2087 ipc_call_t data;
[609243f4]2088 size_t length;
[984a9ba]2089 if (!async_data_write_receive(&data, &length)) {
2090 async_answer_0(&data, EINVAL);
2091 async_answer_0(call, EINVAL);
[609243f4]2092 return;
2093 }
[a35b458]2094
[609243f4]2095 if (length != sizeof(nic_vlan_mask_t)) {
[984a9ba]2096 async_answer_0(&data, ELIMIT);
2097 async_answer_0(call, ELIMIT);
[609243f4]2098 return;
2099 }
[a35b458]2100
[984a9ba]2101 if (async_data_write_finalize(&data, &vlan_mask,
[609243f4]2102 length) != EOK) {
[984a9ba]2103 async_answer_0(call, EINVAL);
[609243f4]2104 return;
2105 }
[a35b458]2106
[609243f4]2107 vlan_mask_pointer = &vlan_mask;
2108 }
[a35b458]2109
[609243f4]2110 if (nic_iface->vlan_set_mask != NULL) {
[b7fd2a0]2111 errno_t rc = nic_iface->vlan_set_mask(dev, vlan_mask_pointer);
[984a9ba]2112 async_answer_0(call, rc);
[609243f4]2113 } else
[984a9ba]2114 async_answer_0(call, ENOTSUP);
[609243f4]2115}
2116
2117static void remote_nic_vlan_set_tag(ddf_fun_t *dev, void *iface,
[984a9ba]2118 ipc_call_t *call)
[609243f4]2119{
2120 nic_iface_t *nic_iface = (nic_iface_t *) iface;
[a35b458]2121
[609243f4]2122 if (nic_iface->vlan_set_tag == NULL) {
[984a9ba]2123 async_answer_0(call, ENOTSUP);
[609243f4]2124 return;
2125 }
[a35b458]2126
[609243f4]2127 uint16_t tag = (uint16_t) IPC_GET_ARG2(*call);
[fd6bd6d]2128 bool add = (int) IPC_GET_ARG3(*call);
2129 bool strip = (int) IPC_GET_ARG4(*call);
[a35b458]2130
[b7fd2a0]2131 errno_t rc = nic_iface->vlan_set_tag(dev, tag, add, strip);
[984a9ba]2132 async_answer_0(call, rc);
[609243f4]2133}
2134
2135static void remote_nic_wol_virtue_add(ddf_fun_t *dev, void *iface,
[984a9ba]2136 ipc_call_t *call)
[609243f4]2137{
2138 nic_iface_t *nic_iface = (nic_iface_t *) iface;
[a35b458]2139
[609243f4]2140 int send_data = (int) IPC_GET_ARG3(*call);
[984a9ba]2141 ipc_call_t data;
[a35b458]2142
[609243f4]2143 if (nic_iface->wol_virtue_add == NULL) {
2144 if (send_data) {
[984a9ba]2145 async_data_write_receive(&data, NULL);
2146 async_answer_0(&data, ENOTSUP);
[609243f4]2147 }
[a35b458]2148
[984a9ba]2149 async_answer_0(call, ENOTSUP);
[609243f4]2150 }
[a35b458]2151
[609243f4]2152 size_t length = 0;
[984a9ba]2153 void *virtue = NULL;
[a35b458]2154
[609243f4]2155 if (send_data) {
[984a9ba]2156 if (!async_data_write_receive(&data, &length)) {
2157 async_answer_0(&data, EINVAL);
2158 async_answer_0(call, EINVAL);
[609243f4]2159 return;
2160 }
[a35b458]2161
[984a9ba]2162 virtue = malloc(length);
2163 if (virtue == NULL) {
2164 async_answer_0(&data, ENOMEM);
2165 async_answer_0(call, ENOMEM);
[609243f4]2166 return;
2167 }
[a35b458]2168
[984a9ba]2169 if (async_data_write_finalize(&data, virtue,
[609243f4]2170 length) != EOK) {
[984a9ba]2171 async_answer_0(call, EINVAL);
2172 free(virtue);
[609243f4]2173 return;
2174 }
2175 }
[a35b458]2176
[609243f4]2177 nic_wv_id_t id = 0;
2178 nic_wv_type_t type = (nic_wv_type_t) IPC_GET_ARG2(*call);
[a35b458]2179
[984a9ba]2180 errno_t rc = nic_iface->wol_virtue_add(dev, type, virtue, length, &id);
2181 async_answer_1(call, rc, (sysarg_t) id);
2182 free(virtue);
[609243f4]2183}
2184
2185static void remote_nic_wol_virtue_remove(ddf_fun_t *dev, void *iface,
[984a9ba]2186 ipc_call_t *call)
[609243f4]2187{
2188 nic_iface_t *nic_iface = (nic_iface_t *) iface;
[a35b458]2189
[609243f4]2190 if (nic_iface->wol_virtue_remove == NULL) {
[984a9ba]2191 async_answer_0(call, ENOTSUP);
[609243f4]2192 return;
2193 }
[a35b458]2194
[609243f4]2195 nic_wv_id_t id = (nic_wv_id_t) IPC_GET_ARG2(*call);
[a35b458]2196
[b7fd2a0]2197 errno_t rc = nic_iface->wol_virtue_remove(dev, id);
[984a9ba]2198 async_answer_0(call, rc);
[609243f4]2199}
2200
2201static void remote_nic_wol_virtue_probe(ddf_fun_t *dev, void *iface,
[984a9ba]2202 ipc_call_t *call)
[609243f4]2203{
2204 nic_iface_t *nic_iface = (nic_iface_t *) iface;
[a35b458]2205
[609243f4]2206 if (nic_iface->wol_virtue_probe == NULL) {
[984a9ba]2207 async_answer_0(call, ENOTSUP);
[609243f4]2208 return;
2209 }
[a35b458]2210
[609243f4]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;
[984a9ba]2215 ipc_call_t data;
2216 void *virtue = NULL;
[a35b458]2217
[609243f4]2218 if (max_length != 0) {
[984a9ba]2219 virtue = malloc(max_length);
2220 if (virtue == NULL) {
2221 async_answer_0(call, ENOMEM);
[609243f4]2222 return;
2223 }
2224 }
[a35b458]2225
[984a9ba]2226 memset(virtue, 0, max_length);
[a35b458]2227
[b7fd2a0]2228 errno_t rc = nic_iface->wol_virtue_probe(dev, id, &type, max_length,
[984a9ba]2229 virtue, &length);
[a35b458]2230
[609243f4]2231 if ((max_length != 0) && (length != 0)) {
2232 size_t req_length;
[984a9ba]2233 if (!async_data_read_receive(&data, &req_length)) {
2234 async_answer_0(&data, EINVAL);
2235 async_answer_0(call, EINVAL);
2236 free(virtue);
[609243f4]2237 return;
2238 }
[a35b458]2239
[609243f4]2240 if (req_length > length)
2241 req_length = length;
[a35b458]2242
[609243f4]2243 if (req_length > max_length)
2244 req_length = max_length;
[a35b458]2245
[984a9ba]2246 async_data_read_finalize(&data, virtue, req_length);
[609243f4]2247 }
[a35b458]2248
[984a9ba]2249 async_answer_2(call, rc, (sysarg_t) type, (sysarg_t) length);
2250 free(virtue);
[609243f4]2251}
2252
2253static void remote_nic_wol_virtue_list(ddf_fun_t *dev, void *iface,
[984a9ba]2254 ipc_call_t *call)
[609243f4]2255{
2256 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2257 if (nic_iface->wol_virtue_list == NULL) {
[984a9ba]2258 async_answer_0(call, ENOTSUP);
[609243f4]2259 return;
2260 }
[a35b458]2261
[609243f4]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;
[984a9ba]2266 ipc_call_t data;
[a35b458]2267
[609243f4]2268 if (max_count != 0) {
2269 id_list = malloc(max_count * sizeof(nic_wv_id_t));
2270 if (id_list == NULL) {
[984a9ba]2271 async_answer_0(call, ENOMEM);
[609243f4]2272 return;
2273 }
2274 }
[a35b458]2275
[acdb5bac]2276 memset(id_list, 0, max_count * sizeof (nic_wv_id_t));
[a35b458]2277
[b7fd2a0]2278 errno_t rc = nic_iface->wol_virtue_list(dev, type, max_count, id_list,
[609243f4]2279 &count);
[a35b458]2280
[609243f4]2281 if ((max_count != 0) && (count != 0)) {
2282 size_t req_length;
[984a9ba]2283 if (!async_data_read_receive(&data, &req_length)) {
2284 async_answer_0(&data, EINVAL);
2285 async_answer_0(call, EINVAL);
[609243f4]2286 free(id_list);
2287 return;
2288 }
[a35b458]2289
[609243f4]2290 if (req_length > count * sizeof(nic_wv_id_t))
2291 req_length = count * sizeof(nic_wv_id_t);
[a35b458]2292
[609243f4]2293 if (req_length > max_count * sizeof(nic_wv_id_t))
2294 req_length = max_count * sizeof(nic_wv_id_t);
[a35b458]2295
[984a9ba]2296 rc = async_data_read_finalize(&data, id_list, req_length);
[609243f4]2297 }
[a35b458]2298
[984a9ba]2299 async_answer_1(call, rc, (sysarg_t) count);
[609243f4]2300 free(id_list);
2301}
2302
2303static void remote_nic_wol_virtue_get_caps(ddf_fun_t *dev, void *iface,
[984a9ba]2304 ipc_call_t *call)
[609243f4]2305{
2306 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2307 if (nic_iface->wol_virtue_get_caps == NULL) {
[984a9ba]2308 async_answer_0(call, ENOTSUP);
[609243f4]2309 return;
2310 }
[a35b458]2311
[609243f4]2312 int count = -1;
2313 nic_wv_type_t type = (nic_wv_type_t) IPC_GET_ARG2(*call);
[a35b458]2314
[b7fd2a0]2315 errno_t rc = nic_iface->wol_virtue_get_caps(dev, type, &count);
[984a9ba]2316 async_answer_1(call, rc, (sysarg_t) count);
[609243f4]2317}
2318
2319static void remote_nic_wol_load_info(ddf_fun_t *dev, void *iface,
[984a9ba]2320 ipc_call_t *call)
[609243f4]2321{
2322 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2323 if (nic_iface->wol_load_info == NULL) {
[984a9ba]2324 async_answer_0(call, ENOTSUP);
[609243f4]2325 return;
2326 }
[a35b458]2327
[609243f4]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;
[984a9ba]2331 uint8_t *info = NULL;
[a35b458]2332
[609243f4]2333 if (max_length != 0) {
[984a9ba]2334 info = malloc(max_length);
2335 if (info == NULL) {
2336 async_answer_0(call, ENOMEM);
[609243f4]2337 return;
2338 }
2339 }
[a35b458]2340
[984a9ba]2341 memset(info, 0, max_length);
[a35b458]2342
[984a9ba]2343 errno_t rc = nic_iface->wol_load_info(dev, &type, max_length, info,
[609243f4]2344 &frame_length);
2345 if (rc == EOK) {
[984a9ba]2346 ipc_call_t data;
[609243f4]2347 size_t req_length;
[984a9ba]2348 if (!async_data_read_receive(&data, &req_length)) {
2349 async_answer_0(&data, EINVAL);
2350 async_answer_0(call, EINVAL);
2351 free(info);
[609243f4]2352 return;
2353 }
[a35b458]2354
[609243f4]2355 req_length = req_length > max_length ? max_length : req_length;
2356 req_length = req_length > frame_length ? frame_length : req_length;
[984a9ba]2357 async_data_read_finalize(&data, info, req_length);
[609243f4]2358 }
[a35b458]2359
[984a9ba]2360 async_answer_2(call, rc, (sysarg_t) type, (sysarg_t) frame_length);
2361 free(info);
[609243f4]2362}
2363
2364static void remote_nic_offload_probe(ddf_fun_t *dev, void *iface,
[984a9ba]2365 ipc_call_t *call)
[609243f4]2366{
2367 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2368 if (nic_iface->offload_probe == NULL) {
[984a9ba]2369 async_answer_0(call, ENOTSUP);
[609243f4]2370 return;
2371 }
[a35b458]2372
[609243f4]2373 uint32_t supported = 0;
2374 uint32_t active = 0;
[a35b458]2375
[b7fd2a0]2376 errno_t rc = nic_iface->offload_probe(dev, &supported, &active);
[984a9ba]2377 async_answer_2(call, rc, supported, active);
[609243f4]2378}
2379
2380static void remote_nic_offload_set(ddf_fun_t *dev, void *iface,
[984a9ba]2381 ipc_call_t *call)
[609243f4]2382{
2383 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2384 if (nic_iface->offload_set == NULL) {
[984a9ba]2385 async_answer_0(call, ENOTSUP);
[609243f4]2386 return;
2387 }
[a35b458]2388
[609243f4]2389 uint32_t mask = (uint32_t) IPC_GET_ARG2(*call);
2390 uint32_t active = (uint32_t) IPC_GET_ARG3(*call);
[a35b458]2391
[b7fd2a0]2392 errno_t rc = nic_iface->offload_set(dev, mask, active);
[984a9ba]2393 async_answer_0(call, rc);
[609243f4]2394}
2395
2396static void remote_nic_poll_get_mode(ddf_fun_t *dev, void *iface,
[984a9ba]2397 ipc_call_t *call)
[609243f4]2398{
2399 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2400 if (nic_iface->poll_get_mode == NULL) {
[984a9ba]2401 async_answer_0(call, ENOTSUP);
[609243f4]2402 return;
2403 }
[a35b458]2404
[609243f4]2405 nic_poll_mode_t mode = NIC_POLL_IMMEDIATE;
2406 int request_data = IPC_GET_ARG2(*call);
[bd41ac52]2407 struct timespec period = {
[609243f4]2408 .tv_sec = 0,
[bd41ac52]2409 .tv_nsec = 0
[609243f4]2410 };
[a35b458]2411
[b7fd2a0]2412 errno_t rc = nic_iface->poll_get_mode(dev, &mode, &period);
[609243f4]2413 if ((rc == EOK) && (request_data)) {
[984a9ba]2414 ipc_call_t data;
[609243f4]2415 size_t max_len;
[a35b458]2416
[984a9ba]2417 if (!async_data_read_receive(&data, &max_len)) {
2418 async_answer_0(&data, EINVAL);
2419 async_answer_0(call, EINVAL);
[609243f4]2420 return;
2421 }
[a35b458]2422
[bd41ac52]2423 if (max_len != sizeof(struct timespec)) {
[984a9ba]2424 async_answer_0(&data, ELIMIT);
2425 async_answer_0(call, ELIMIT);
[609243f4]2426 return;
2427 }
[a35b458]2428
[984a9ba]2429 async_data_read_finalize(&data, &period,
[bd41ac52]2430 sizeof(struct timespec));
[609243f4]2431 }
[a35b458]2432
[984a9ba]2433 async_answer_1(call, rc, (sysarg_t) mode);
[609243f4]2434}
2435
2436static void remote_nic_poll_set_mode(ddf_fun_t *dev, void *iface,
[984a9ba]2437 ipc_call_t *call)
[609243f4]2438{
2439 nic_iface_t *nic_iface = (nic_iface_t *) iface;
[a35b458]2440
[609243f4]2441 nic_poll_mode_t mode = IPC_GET_ARG2(*call);
2442 int has_period = IPC_GET_ARG3(*call);
[bd41ac52]2443 struct timespec period_buf;
2444 struct timespec *period = NULL;
[609243f4]2445 size_t length;
[a35b458]2446
[609243f4]2447 if (has_period) {
[984a9ba]2448 ipc_call_t data;
2449 if (!async_data_write_receive(&data, &length)) {
2450 async_answer_0(&data, EINVAL);
2451 async_answer_0(call, EINVAL);
[609243f4]2452 return;
2453 }
[a35b458]2454
[bd41ac52]2455 if (length != sizeof(struct timespec)) {
[984a9ba]2456 async_answer_0(&data, ELIMIT);
2457 async_answer_0(call, ELIMIT);
[609243f4]2458 return;
2459 }
[a35b458]2460
[609243f4]2461 period = &period_buf;
[984a9ba]2462 if (async_data_write_finalize(&data, period,
[609243f4]2463 length) != EOK) {
[984a9ba]2464 async_answer_0(call, EINVAL);
[609243f4]2465 return;
2466 }
2467 }
[a35b458]2468
[609243f4]2469 if (nic_iface->poll_set_mode != NULL) {
[b7fd2a0]2470 errno_t rc = nic_iface->poll_set_mode(dev, mode, period);
[984a9ba]2471 async_answer_0(call, rc);
[609243f4]2472 } else
[984a9ba]2473 async_answer_0(call, ENOTSUP);
[609243f4]2474}
2475
2476static void remote_nic_poll_now(ddf_fun_t *dev, void *iface,
[984a9ba]2477 ipc_call_t *call)
[609243f4]2478{
2479 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2480 if (nic_iface->poll_now == NULL) {
[984a9ba]2481 async_answer_0(call, ENOTSUP);
[609243f4]2482 return;
2483 }
[a35b458]2484
[b7fd2a0]2485 errno_t rc = nic_iface->poll_now(dev);
[984a9ba]2486 async_answer_0(call, rc);
[609243f4]2487}
2488
2489/** Remote NIC interface operations.
2490 *
2491 */
[9be30cdf]2492static const remote_iface_func_ptr_t remote_nic_iface_ops[] = {
[21ae7ee]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
[609243f4]2534};
2535
2536/** Remote NIC interface structure.
2537 *
2538 * Interface for processing request from remote
2539 * clients addressed to the NIC interface.
2540 *
2541 */
[7f80313]2542const remote_iface_t remote_nic_iface = {
[9be30cdf]2543 .method_count = ARRAY_SIZE(remote_nic_iface_ops),
[609243f4]2544 .methods = remote_nic_iface_ops
2545};
2546
2547/**
2548 * @}
2549 */
Note: See TracBrowser for help on using the repository browser.