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

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

Mechanically lowercase IPC_SET_*/IPC_GET_*

  • 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
[fafb8e5]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
[fafb8e5]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
[fafb8e5]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
[fafb8e5]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
[fafb8e5]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
[fafb8e5]1684 size_t max_count = ipc_get_arg2(call);
[609243f4]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;
[fafb8e5]1735 nic_unicast_mode_t mode = ipc_get_arg2(call);
1736 size_t address_count = ipc_get_arg3(call);
[609243f4]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
[fafb8e5]1787 size_t max_count = ipc_get_arg2(call);
[609243f4]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
[609243f4]1805 if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
1806 free(address_list);
[984a9ba]1807 async_answer_2(call, rc, mode, address_count);
[609243f4]1808 return;
1809 }
[a35b458]1810
[984a9ba]1811 ipc_call_t data;
[609243f4]1812 size_t max_len;
[984a9ba]1813 if (!async_data_read_receive(&data, &max_len)) {
1814 async_answer_0(&data, EINVAL);
1815 async_answer_2(call, rc, mode, address_count);
[609243f4]1816 free(address_list);
1817 return;
1818 }
[a35b458]1819
[609243f4]1820 if (max_len > address_count * sizeof(nic_address_t))
1821 max_len = address_count * sizeof(nic_address_t);
[a35b458]1822
[609243f4]1823 if (max_len > max_count * sizeof(nic_address_t))
1824 max_len = max_count * sizeof(nic_address_t);
[a35b458]1825
[984a9ba]1826 async_data_read_finalize(&data, address_list, max_len);
[a35b458]1827
[609243f4]1828 free(address_list);
[984a9ba]1829 async_answer_2(call, rc, mode, address_count);
[609243f4]1830}
1831
1832static void remote_nic_multicast_set_mode(ddf_fun_t *dev, void *iface,
[984a9ba]1833 ipc_call_t *call)
[609243f4]1834{
1835 nic_iface_t *nic_iface = (nic_iface_t *) iface;
[a35b458]1836
[fafb8e5]1837 nic_multicast_mode_t mode = ipc_get_arg2(call);
1838 size_t address_count = ipc_get_arg3(call);
[609243f4]1839 nic_address_t *address_list = NULL;
[a35b458]1840
[609243f4]1841 if (address_count) {
[984a9ba]1842 ipc_call_t data;
[609243f4]1843 size_t length;
[984a9ba]1844 if (!async_data_write_receive(&data, &length)) {
1845 async_answer_0(&data, EINVAL);
1846 async_answer_0(call, EINVAL);
[609243f4]1847 return;
1848 }
[a35b458]1849
[609243f4]1850 if (length != address_count * sizeof (nic_address_t)) {
[984a9ba]1851 async_answer_0(&data, ELIMIT);
1852 async_answer_0(call, ELIMIT);
[609243f4]1853 return;
1854 }
[a35b458]1855
[609243f4]1856 address_list = malloc(length);
1857 if (address_list == NULL) {
[984a9ba]1858 async_answer_0(&data, ENOMEM);
1859 async_answer_0(call, ENOMEM);
[609243f4]1860 return;
1861 }
[a35b458]1862
[984a9ba]1863 if (async_data_write_finalize(&data, address_list,
[609243f4]1864 length) != EOK) {
[984a9ba]1865 async_answer_0(call, EINVAL);
[609243f4]1866 free(address_list);
1867 return;
1868 }
1869 }
[a35b458]1870
[609243f4]1871 if (nic_iface->multicast_set_mode != NULL) {
[b7fd2a0]1872 errno_t rc = nic_iface->multicast_set_mode(dev, mode, address_list,
[609243f4]1873 address_count);
[984a9ba]1874 async_answer_0(call, rc);
[609243f4]1875 } else
[984a9ba]1876 async_answer_0(call, ENOTSUP);
[a35b458]1877
[609243f4]1878 free(address_list);
1879}
1880
1881static void remote_nic_broadcast_get_mode(ddf_fun_t *dev, void *iface,
[984a9ba]1882 ipc_call_t *call)
[609243f4]1883{
1884 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1885 if (nic_iface->broadcast_get_mode == NULL) {
[984a9ba]1886 async_answer_0(call, ENOTSUP);
[609243f4]1887 return;
1888 }
[a35b458]1889
[609243f4]1890 nic_broadcast_mode_t mode = NIC_BROADCAST_ACCEPTED;
[a35b458]1891
[b7fd2a0]1892 errno_t rc = nic_iface->broadcast_get_mode(dev, &mode);
[984a9ba]1893 async_answer_1(call, rc, mode);
[609243f4]1894}
1895
1896static void remote_nic_broadcast_set_mode(ddf_fun_t *dev, void *iface,
[984a9ba]1897 ipc_call_t *call)
[609243f4]1898{
1899 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1900 if (nic_iface->broadcast_set_mode == NULL) {
[984a9ba]1901 async_answer_0(call, ENOTSUP);
[609243f4]1902 return;
1903 }
[a35b458]1904
[fafb8e5]1905 nic_broadcast_mode_t mode = ipc_get_arg2(call);
[a35b458]1906
[b7fd2a0]1907 errno_t rc = nic_iface->broadcast_set_mode(dev, mode);
[984a9ba]1908 async_answer_0(call, rc);
[609243f4]1909}
1910
1911static void remote_nic_defective_get_mode(ddf_fun_t *dev, void *iface,
[984a9ba]1912 ipc_call_t *call)
[609243f4]1913{
1914 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1915 if (nic_iface->defective_get_mode == NULL) {
[984a9ba]1916 async_answer_0(call, ENOTSUP);
[609243f4]1917 return;
1918 }
[a35b458]1919
[609243f4]1920 uint32_t mode = 0;
[a35b458]1921
[b7fd2a0]1922 errno_t rc = nic_iface->defective_get_mode(dev, &mode);
[984a9ba]1923 async_answer_1(call, rc, mode);
[609243f4]1924}
1925
1926static void remote_nic_defective_set_mode(ddf_fun_t *dev, void *iface,
[984a9ba]1927 ipc_call_t *call)
[609243f4]1928{
1929 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1930 if (nic_iface->defective_set_mode == NULL) {
[984a9ba]1931 async_answer_0(call, ENOTSUP);
[609243f4]1932 return;
1933 }
[a35b458]1934
[fafb8e5]1935 uint32_t mode = ipc_get_arg2(call);
[a35b458]1936
[b7fd2a0]1937 errno_t rc = nic_iface->defective_set_mode(dev, mode);
[984a9ba]1938 async_answer_0(call, rc);
[609243f4]1939}
1940
1941static void remote_nic_blocked_sources_get(ddf_fun_t *dev, void *iface,
[984a9ba]1942 ipc_call_t *call)
[609243f4]1943{
1944 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1945 if (nic_iface->blocked_sources_get == NULL) {
[984a9ba]1946 async_answer_0(call, ENOTSUP);
[609243f4]1947 return;
1948 }
[a35b458]1949
[fafb8e5]1950 size_t max_count = ipc_get_arg2(call);
[609243f4]1951 nic_address_t *address_list = NULL;
[a35b458]1952
[609243f4]1953 if (max_count != 0) {
1954 address_list = malloc(max_count * sizeof(nic_address_t));
1955 if (!address_list) {
[984a9ba]1956 async_answer_0(call, ENOMEM);
[609243f4]1957 return;
1958 }
1959 }
[a35b458]1960
[acdb5bac]1961 memset(address_list, 0, max_count * sizeof(nic_address_t));
[609243f4]1962 size_t address_count = 0;
[a35b458]1963
[b7fd2a0]1964 errno_t rc = nic_iface->blocked_sources_get(dev, max_count, address_list,
[609243f4]1965 &address_count);
[a35b458]1966
[609243f4]1967 if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
[984a9ba]1968 async_answer_1(call, rc, address_count);
[609243f4]1969 free(address_list);
1970 return;
1971 }
[a35b458]1972
[984a9ba]1973 ipc_call_t data;
[609243f4]1974 size_t max_len;
[984a9ba]1975 if (!async_data_read_receive(&data, &max_len)) {
1976 async_answer_0(&data, EINVAL);
1977 async_answer_1(call, rc, address_count);
[609243f4]1978 free(address_list);
1979 return;
1980 }
[a35b458]1981
[609243f4]1982 if (max_len > address_count * sizeof(nic_address_t))
1983 max_len = address_count * sizeof(nic_address_t);
[a35b458]1984
[609243f4]1985 if (max_len > max_count * sizeof(nic_address_t))
1986 max_len = max_count * sizeof(nic_address_t);
[a35b458]1987
[984a9ba]1988 async_data_read_finalize(&data, address_list, max_len);
[a35b458]1989
[609243f4]1990 free(address_list);
[984a9ba]1991 async_answer_1(call, rc, address_count);
[609243f4]1992}
1993
1994static void remote_nic_blocked_sources_set(ddf_fun_t *dev, void *iface,
[984a9ba]1995 ipc_call_t *call)
[609243f4]1996{
1997 nic_iface_t *nic_iface = (nic_iface_t *) iface;
[a35b458]1998
[609243f4]1999 size_t length;
[fafb8e5]2000 size_t address_count = ipc_get_arg2(call);
[609243f4]2001 nic_address_t *address_list = NULL;
[a35b458]2002
[609243f4]2003 if (address_count) {
[984a9ba]2004 ipc_call_t data;
2005 if (!async_data_write_receive(&data, &length)) {
2006 async_answer_0(&data, EINVAL);
2007 async_answer_0(call, EINVAL);
[609243f4]2008 return;
2009 }
[a35b458]2010
[609243f4]2011 if (length != address_count * sizeof(nic_address_t)) {
[984a9ba]2012 async_answer_0(&data, ELIMIT);
2013 async_answer_0(call, ELIMIT);
[609243f4]2014 return;
2015 }
[a35b458]2016
[609243f4]2017 address_list = malloc(length);
2018 if (address_list == NULL) {
[984a9ba]2019 async_answer_0(&data, ENOMEM);
2020 async_answer_0(call, ENOMEM);
[609243f4]2021 return;
2022 }
[a35b458]2023
[984a9ba]2024 if (async_data_write_finalize(&data, address_list,
[609243f4]2025 length) != EOK) {
[984a9ba]2026 async_answer_0(call, EINVAL);
[609243f4]2027 free(address_list);
2028 return;
2029 }
2030 }
[a35b458]2031
[609243f4]2032 if (nic_iface->blocked_sources_set != NULL) {
[b7fd2a0]2033 errno_t rc = nic_iface->blocked_sources_set(dev, address_list,
[609243f4]2034 address_count);
[984a9ba]2035 async_answer_0(call, rc);
[609243f4]2036 } else
[984a9ba]2037 async_answer_0(call, ENOTSUP);
[a35b458]2038
[609243f4]2039 free(address_list);
2040}
2041
2042static void remote_nic_vlan_get_mask(ddf_fun_t *dev, void *iface,
[984a9ba]2043 ipc_call_t *call)
[609243f4]2044{
2045 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2046 if (nic_iface->vlan_get_mask == NULL) {
[984a9ba]2047 async_answer_0(call, ENOTSUP);
[609243f4]2048 return;
2049 }
[a35b458]2050
[609243f4]2051 nic_vlan_mask_t vlan_mask;
[acdb5bac]2052 memset(&vlan_mask, 0, sizeof(nic_vlan_mask_t));
[a35b458]2053
[b7fd2a0]2054 errno_t rc = nic_iface->vlan_get_mask(dev, &vlan_mask);
[609243f4]2055 if (rc == EOK) {
[984a9ba]2056 ipc_call_t data;
[609243f4]2057 size_t max_len;
[984a9ba]2058 if (!async_data_read_receive(&data, &max_len)) {
2059 async_answer_0(&data, EINVAL);
2060 async_answer_0(call, EINVAL);
[609243f4]2061 return;
2062 }
[a35b458]2063
[609243f4]2064 if (max_len != sizeof(nic_vlan_mask_t)) {
[984a9ba]2065 async_answer_0(&data, EINVAL);
2066 async_answer_0(call, EINVAL);
[609243f4]2067 return;
2068 }
[a35b458]2069
[984a9ba]2070 async_data_read_finalize(&data, &vlan_mask, max_len);
[609243f4]2071 }
[a35b458]2072
[984a9ba]2073 async_answer_0(call, rc);
[609243f4]2074}
2075
2076static void remote_nic_vlan_set_mask(ddf_fun_t *dev, void *iface,
[984a9ba]2077 ipc_call_t *call)
[609243f4]2078{
2079 nic_iface_t *nic_iface = (nic_iface_t *) iface;
[a35b458]2080
[609243f4]2081 nic_vlan_mask_t vlan_mask;
2082 nic_vlan_mask_t *vlan_mask_pointer = NULL;
[fafb8e5]2083 bool vlan_mask_set = (bool) ipc_get_arg2(call);
[a35b458]2084
[609243f4]2085 if (vlan_mask_set) {
[984a9ba]2086 ipc_call_t data;
[609243f4]2087 size_t length;
[984a9ba]2088 if (!async_data_write_receive(&data, &length)) {
2089 async_answer_0(&data, EINVAL);
2090 async_answer_0(call, EINVAL);
[609243f4]2091 return;
2092 }
[a35b458]2093
[609243f4]2094 if (length != sizeof(nic_vlan_mask_t)) {
[984a9ba]2095 async_answer_0(&data, ELIMIT);
2096 async_answer_0(call, ELIMIT);
[609243f4]2097 return;
2098 }
[a35b458]2099
[984a9ba]2100 if (async_data_write_finalize(&data, &vlan_mask,
[609243f4]2101 length) != EOK) {
[984a9ba]2102 async_answer_0(call, EINVAL);
[609243f4]2103 return;
2104 }
[a35b458]2105
[609243f4]2106 vlan_mask_pointer = &vlan_mask;
2107 }
[a35b458]2108
[609243f4]2109 if (nic_iface->vlan_set_mask != NULL) {
[b7fd2a0]2110 errno_t rc = nic_iface->vlan_set_mask(dev, vlan_mask_pointer);
[984a9ba]2111 async_answer_0(call, rc);
[609243f4]2112 } else
[984a9ba]2113 async_answer_0(call, ENOTSUP);
[609243f4]2114}
2115
2116static void remote_nic_vlan_set_tag(ddf_fun_t *dev, void *iface,
[984a9ba]2117 ipc_call_t *call)
[609243f4]2118{
2119 nic_iface_t *nic_iface = (nic_iface_t *) iface;
[a35b458]2120
[609243f4]2121 if (nic_iface->vlan_set_tag == NULL) {
[984a9ba]2122 async_answer_0(call, ENOTSUP);
[609243f4]2123 return;
2124 }
[a35b458]2125
[fafb8e5]2126 uint16_t tag = (uint16_t) ipc_get_arg2(call);
2127 bool add = (int) ipc_get_arg3(call);
2128 bool strip = (int) ipc_get_arg4(call);
[a35b458]2129
[b7fd2a0]2130 errno_t rc = nic_iface->vlan_set_tag(dev, tag, add, strip);
[984a9ba]2131 async_answer_0(call, rc);
[609243f4]2132}
2133
2134static void remote_nic_wol_virtue_add(ddf_fun_t *dev, void *iface,
[984a9ba]2135 ipc_call_t *call)
[609243f4]2136{
2137 nic_iface_t *nic_iface = (nic_iface_t *) iface;
[a35b458]2138
[fafb8e5]2139 int send_data = (int) ipc_get_arg3(call);
[984a9ba]2140 ipc_call_t data;
[a35b458]2141
[609243f4]2142 if (nic_iface->wol_virtue_add == NULL) {
2143 if (send_data) {
[984a9ba]2144 async_data_write_receive(&data, NULL);
2145 async_answer_0(&data, ENOTSUP);
[609243f4]2146 }
[a35b458]2147
[984a9ba]2148 async_answer_0(call, ENOTSUP);
[609243f4]2149 }
[a35b458]2150
[609243f4]2151 size_t length = 0;
[984a9ba]2152 void *virtue = NULL;
[a35b458]2153
[609243f4]2154 if (send_data) {
[984a9ba]2155 if (!async_data_write_receive(&data, &length)) {
2156 async_answer_0(&data, EINVAL);
2157 async_answer_0(call, EINVAL);
[609243f4]2158 return;
2159 }
[a35b458]2160
[984a9ba]2161 virtue = malloc(length);
2162 if (virtue == NULL) {
2163 async_answer_0(&data, ENOMEM);
2164 async_answer_0(call, ENOMEM);
[609243f4]2165 return;
2166 }
[a35b458]2167
[984a9ba]2168 if (async_data_write_finalize(&data, virtue,
[609243f4]2169 length) != EOK) {
[984a9ba]2170 async_answer_0(call, EINVAL);
2171 free(virtue);
[609243f4]2172 return;
2173 }
2174 }
[a35b458]2175
[609243f4]2176 nic_wv_id_t id = 0;
[fafb8e5]2177 nic_wv_type_t type = (nic_wv_type_t) ipc_get_arg2(call);
[a35b458]2178
[984a9ba]2179 errno_t rc = nic_iface->wol_virtue_add(dev, type, virtue, length, &id);
2180 async_answer_1(call, rc, (sysarg_t) id);
2181 free(virtue);
[609243f4]2182}
2183
2184static void remote_nic_wol_virtue_remove(ddf_fun_t *dev, void *iface,
[984a9ba]2185 ipc_call_t *call)
[609243f4]2186{
2187 nic_iface_t *nic_iface = (nic_iface_t *) iface;
[a35b458]2188
[609243f4]2189 if (nic_iface->wol_virtue_remove == NULL) {
[984a9ba]2190 async_answer_0(call, ENOTSUP);
[609243f4]2191 return;
2192 }
[a35b458]2193
[fafb8e5]2194 nic_wv_id_t id = (nic_wv_id_t) ipc_get_arg2(call);
[a35b458]2195
[b7fd2a0]2196 errno_t rc = nic_iface->wol_virtue_remove(dev, id);
[984a9ba]2197 async_answer_0(call, rc);
[609243f4]2198}
2199
2200static void remote_nic_wol_virtue_probe(ddf_fun_t *dev, void *iface,
[984a9ba]2201 ipc_call_t *call)
[609243f4]2202{
2203 nic_iface_t *nic_iface = (nic_iface_t *) iface;
[a35b458]2204
[609243f4]2205 if (nic_iface->wol_virtue_probe == NULL) {
[984a9ba]2206 async_answer_0(call, ENOTSUP);
[609243f4]2207 return;
2208 }
[a35b458]2209
[fafb8e5]2210 nic_wv_id_t id = (nic_wv_id_t) ipc_get_arg2(call);
2211 size_t max_length = ipc_get_arg3(call);
[609243f4]2212 nic_wv_type_t type = NIC_WV_NONE;
2213 size_t length = 0;
[984a9ba]2214 ipc_call_t data;
2215 void *virtue = NULL;
[a35b458]2216
[609243f4]2217 if (max_length != 0) {
[984a9ba]2218 virtue = malloc(max_length);
2219 if (virtue == NULL) {
2220 async_answer_0(call, ENOMEM);
[609243f4]2221 return;
2222 }
2223 }
[a35b458]2224
[984a9ba]2225 memset(virtue, 0, max_length);
[a35b458]2226
[b7fd2a0]2227 errno_t rc = nic_iface->wol_virtue_probe(dev, id, &type, max_length,
[984a9ba]2228 virtue, &length);
[a35b458]2229
[609243f4]2230 if ((max_length != 0) && (length != 0)) {
2231 size_t req_length;
[984a9ba]2232 if (!async_data_read_receive(&data, &req_length)) {
2233 async_answer_0(&data, EINVAL);
2234 async_answer_0(call, EINVAL);
2235 free(virtue);
[609243f4]2236 return;
2237 }
[a35b458]2238
[609243f4]2239 if (req_length > length)
2240 req_length = length;
[a35b458]2241
[609243f4]2242 if (req_length > max_length)
2243 req_length = max_length;
[a35b458]2244
[984a9ba]2245 async_data_read_finalize(&data, virtue, req_length);
[609243f4]2246 }
[a35b458]2247
[984a9ba]2248 async_answer_2(call, rc, (sysarg_t) type, (sysarg_t) length);
2249 free(virtue);
[609243f4]2250}
2251
2252static void remote_nic_wol_virtue_list(ddf_fun_t *dev, void *iface,
[984a9ba]2253 ipc_call_t *call)
[609243f4]2254{
2255 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2256 if (nic_iface->wol_virtue_list == NULL) {
[984a9ba]2257 async_answer_0(call, ENOTSUP);
[609243f4]2258 return;
2259 }
[a35b458]2260
[fafb8e5]2261 nic_wv_type_t type = (nic_wv_type_t) ipc_get_arg2(call);
2262 size_t max_count = ipc_get_arg3(call);
[609243f4]2263 size_t count = 0;
2264 nic_wv_id_t *id_list = NULL;
[984a9ba]2265 ipc_call_t data;
[a35b458]2266
[609243f4]2267 if (max_count != 0) {
2268 id_list = malloc(max_count * sizeof(nic_wv_id_t));
2269 if (id_list == NULL) {
[984a9ba]2270 async_answer_0(call, ENOMEM);
[609243f4]2271 return;
2272 }
2273 }
[a35b458]2274
[acdb5bac]2275 memset(id_list, 0, max_count * sizeof (nic_wv_id_t));
[a35b458]2276
[b7fd2a0]2277 errno_t rc = nic_iface->wol_virtue_list(dev, type, max_count, id_list,
[609243f4]2278 &count);
[a35b458]2279
[609243f4]2280 if ((max_count != 0) && (count != 0)) {
2281 size_t req_length;
[984a9ba]2282 if (!async_data_read_receive(&data, &req_length)) {
2283 async_answer_0(&data, EINVAL);
2284 async_answer_0(call, EINVAL);
[609243f4]2285 free(id_list);
2286 return;
2287 }
[a35b458]2288
[609243f4]2289 if (req_length > count * sizeof(nic_wv_id_t))
2290 req_length = count * sizeof(nic_wv_id_t);
[a35b458]2291
[609243f4]2292 if (req_length > max_count * sizeof(nic_wv_id_t))
2293 req_length = max_count * sizeof(nic_wv_id_t);
[a35b458]2294
[984a9ba]2295 rc = async_data_read_finalize(&data, id_list, req_length);
[609243f4]2296 }
[a35b458]2297
[984a9ba]2298 async_answer_1(call, rc, (sysarg_t) count);
[609243f4]2299 free(id_list);
2300}
2301
2302static void remote_nic_wol_virtue_get_caps(ddf_fun_t *dev, void *iface,
[984a9ba]2303 ipc_call_t *call)
[609243f4]2304{
2305 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2306 if (nic_iface->wol_virtue_get_caps == NULL) {
[984a9ba]2307 async_answer_0(call, ENOTSUP);
[609243f4]2308 return;
2309 }
[a35b458]2310
[609243f4]2311 int count = -1;
[fafb8e5]2312 nic_wv_type_t type = (nic_wv_type_t) ipc_get_arg2(call);
[a35b458]2313
[b7fd2a0]2314 errno_t rc = nic_iface->wol_virtue_get_caps(dev, type, &count);
[984a9ba]2315 async_answer_1(call, rc, (sysarg_t) count);
[609243f4]2316}
2317
2318static void remote_nic_wol_load_info(ddf_fun_t *dev, void *iface,
[984a9ba]2319 ipc_call_t *call)
[609243f4]2320{
2321 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2322 if (nic_iface->wol_load_info == NULL) {
[984a9ba]2323 async_answer_0(call, ENOTSUP);
[609243f4]2324 return;
2325 }
[a35b458]2326
[fafb8e5]2327 size_t max_length = (size_t) ipc_get_arg2(call);
[609243f4]2328 size_t frame_length = 0;
2329 nic_wv_type_t type = NIC_WV_NONE;
[984a9ba]2330 uint8_t *info = NULL;
[a35b458]2331
[609243f4]2332 if (max_length != 0) {
[984a9ba]2333 info = malloc(max_length);
2334 if (info == NULL) {
2335 async_answer_0(call, ENOMEM);
[609243f4]2336 return;
2337 }
2338 }
[a35b458]2339
[984a9ba]2340 memset(info, 0, max_length);
[a35b458]2341
[984a9ba]2342 errno_t rc = nic_iface->wol_load_info(dev, &type, max_length, info,
[609243f4]2343 &frame_length);
2344 if (rc == EOK) {
[984a9ba]2345 ipc_call_t data;
[609243f4]2346 size_t req_length;
[984a9ba]2347 if (!async_data_read_receive(&data, &req_length)) {
2348 async_answer_0(&data, EINVAL);
2349 async_answer_0(call, EINVAL);
2350 free(info);
[609243f4]2351 return;
2352 }
[a35b458]2353
[609243f4]2354 req_length = req_length > max_length ? max_length : req_length;
2355 req_length = req_length > frame_length ? frame_length : req_length;
[984a9ba]2356 async_data_read_finalize(&data, info, req_length);
[609243f4]2357 }
[a35b458]2358
[984a9ba]2359 async_answer_2(call, rc, (sysarg_t) type, (sysarg_t) frame_length);
2360 free(info);
[609243f4]2361}
2362
2363static void remote_nic_offload_probe(ddf_fun_t *dev, void *iface,
[984a9ba]2364 ipc_call_t *call)
[609243f4]2365{
2366 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2367 if (nic_iface->offload_probe == NULL) {
[984a9ba]2368 async_answer_0(call, ENOTSUP);
[609243f4]2369 return;
2370 }
[a35b458]2371
[609243f4]2372 uint32_t supported = 0;
2373 uint32_t active = 0;
[a35b458]2374
[b7fd2a0]2375 errno_t rc = nic_iface->offload_probe(dev, &supported, &active);
[984a9ba]2376 async_answer_2(call, rc, supported, active);
[609243f4]2377}
2378
2379static void remote_nic_offload_set(ddf_fun_t *dev, void *iface,
[984a9ba]2380 ipc_call_t *call)
[609243f4]2381{
2382 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2383 if (nic_iface->offload_set == NULL) {
[984a9ba]2384 async_answer_0(call, ENOTSUP);
[609243f4]2385 return;
2386 }
[a35b458]2387
[fafb8e5]2388 uint32_t mask = (uint32_t) ipc_get_arg2(call);
2389 uint32_t active = (uint32_t) ipc_get_arg3(call);
[a35b458]2390
[b7fd2a0]2391 errno_t rc = nic_iface->offload_set(dev, mask, active);
[984a9ba]2392 async_answer_0(call, rc);
[609243f4]2393}
2394
2395static void remote_nic_poll_get_mode(ddf_fun_t *dev, void *iface,
[984a9ba]2396 ipc_call_t *call)
[609243f4]2397{
2398 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2399 if (nic_iface->poll_get_mode == NULL) {
[984a9ba]2400 async_answer_0(call, ENOTSUP);
[609243f4]2401 return;
2402 }
[a35b458]2403
[609243f4]2404 nic_poll_mode_t mode = NIC_POLL_IMMEDIATE;
[fafb8e5]2405 int request_data = ipc_get_arg2(call);
[bd41ac52]2406 struct timespec period = {
[609243f4]2407 .tv_sec = 0,
[bd41ac52]2408 .tv_nsec = 0
[609243f4]2409 };
[a35b458]2410
[b7fd2a0]2411 errno_t rc = nic_iface->poll_get_mode(dev, &mode, &period);
[609243f4]2412 if ((rc == EOK) && (request_data)) {
[984a9ba]2413 ipc_call_t data;
[609243f4]2414 size_t max_len;
[a35b458]2415
[984a9ba]2416 if (!async_data_read_receive(&data, &max_len)) {
2417 async_answer_0(&data, EINVAL);
2418 async_answer_0(call, EINVAL);
[609243f4]2419 return;
2420 }
[a35b458]2421
[bd41ac52]2422 if (max_len != sizeof(struct timespec)) {
[984a9ba]2423 async_answer_0(&data, ELIMIT);
2424 async_answer_0(call, ELIMIT);
[609243f4]2425 return;
2426 }
[a35b458]2427
[984a9ba]2428 async_data_read_finalize(&data, &period,
[bd41ac52]2429 sizeof(struct timespec));
[609243f4]2430 }
[a35b458]2431
[984a9ba]2432 async_answer_1(call, rc, (sysarg_t) mode);
[609243f4]2433}
2434
2435static void remote_nic_poll_set_mode(ddf_fun_t *dev, void *iface,
[984a9ba]2436 ipc_call_t *call)
[609243f4]2437{
2438 nic_iface_t *nic_iface = (nic_iface_t *) iface;
[a35b458]2439
[fafb8e5]2440 nic_poll_mode_t mode = ipc_get_arg2(call);
2441 int has_period = ipc_get_arg3(call);
[bd41ac52]2442 struct timespec period_buf;
2443 struct timespec *period = NULL;
[609243f4]2444 size_t length;
[a35b458]2445
[609243f4]2446 if (has_period) {
[984a9ba]2447 ipc_call_t data;
2448 if (!async_data_write_receive(&data, &length)) {
2449 async_answer_0(&data, EINVAL);
2450 async_answer_0(call, EINVAL);
[609243f4]2451 return;
2452 }
[a35b458]2453
[bd41ac52]2454 if (length != sizeof(struct timespec)) {
[984a9ba]2455 async_answer_0(&data, ELIMIT);
2456 async_answer_0(call, ELIMIT);
[609243f4]2457 return;
2458 }
[a35b458]2459
[609243f4]2460 period = &period_buf;
[984a9ba]2461 if (async_data_write_finalize(&data, period,
[609243f4]2462 length) != EOK) {
[984a9ba]2463 async_answer_0(call, EINVAL);
[609243f4]2464 return;
2465 }
2466 }
[a35b458]2467
[609243f4]2468 if (nic_iface->poll_set_mode != NULL) {
[b7fd2a0]2469 errno_t rc = nic_iface->poll_set_mode(dev, mode, period);
[984a9ba]2470 async_answer_0(call, rc);
[609243f4]2471 } else
[984a9ba]2472 async_answer_0(call, ENOTSUP);
[609243f4]2473}
2474
2475static void remote_nic_poll_now(ddf_fun_t *dev, void *iface,
[984a9ba]2476 ipc_call_t *call)
[609243f4]2477{
2478 nic_iface_t *nic_iface = (nic_iface_t *) iface;
2479 if (nic_iface->poll_now == NULL) {
[984a9ba]2480 async_answer_0(call, ENOTSUP);
[609243f4]2481 return;
2482 }
[a35b458]2483
[b7fd2a0]2484 errno_t rc = nic_iface->poll_now(dev);
[984a9ba]2485 async_answer_0(call, rc);
[609243f4]2486}
2487
2488/** Remote NIC interface operations.
2489 *
2490 */
[9be30cdf]2491static const remote_iface_func_ptr_t remote_nic_iface_ops[] = {
[21ae7ee]2492 [NIC_SEND_MESSAGE] = remote_nic_send_frame,
2493 [NIC_CALLBACK_CREATE] = remote_nic_callback_create,
2494 [NIC_GET_STATE] = remote_nic_get_state,
2495 [NIC_SET_STATE] = remote_nic_set_state,
2496 [NIC_GET_ADDRESS] = remote_nic_get_address,
2497 [NIC_SET_ADDRESS] = remote_nic_set_address,
2498 [NIC_GET_STATS] = remote_nic_get_stats,
2499 [NIC_GET_DEVICE_INFO] = remote_nic_get_device_info,
2500 [NIC_GET_CABLE_STATE] = remote_nic_get_cable_state,
2501 [NIC_GET_OPERATION_MODE] = remote_nic_get_operation_mode,
2502 [NIC_SET_OPERATION_MODE] = remote_nic_set_operation_mode,
2503 [NIC_AUTONEG_ENABLE] = remote_nic_autoneg_enable,
2504 [NIC_AUTONEG_DISABLE] = remote_nic_autoneg_disable,
2505 [NIC_AUTONEG_PROBE] = remote_nic_autoneg_probe,
2506 [NIC_AUTONEG_RESTART] = remote_nic_autoneg_restart,
2507 [NIC_GET_PAUSE] = remote_nic_get_pause,
2508 [NIC_SET_PAUSE] = remote_nic_set_pause,
2509 [NIC_UNICAST_GET_MODE] = remote_nic_unicast_get_mode,
2510 [NIC_UNICAST_SET_MODE] = remote_nic_unicast_set_mode,
2511 [NIC_MULTICAST_GET_MODE] = remote_nic_multicast_get_mode,
2512 [NIC_MULTICAST_SET_MODE] = remote_nic_multicast_set_mode,
2513 [NIC_BROADCAST_GET_MODE] = remote_nic_broadcast_get_mode,
2514 [NIC_BROADCAST_SET_MODE] = remote_nic_broadcast_set_mode,
2515 [NIC_DEFECTIVE_GET_MODE] = remote_nic_defective_get_mode,
2516 [NIC_DEFECTIVE_SET_MODE] = remote_nic_defective_set_mode,
2517 [NIC_BLOCKED_SOURCES_GET] = remote_nic_blocked_sources_get,
2518 [NIC_BLOCKED_SOURCES_SET] = remote_nic_blocked_sources_set,
2519 [NIC_VLAN_GET_MASK] = remote_nic_vlan_get_mask,
2520 [NIC_VLAN_SET_MASK] = remote_nic_vlan_set_mask,
2521 [NIC_VLAN_SET_TAG] = remote_nic_vlan_set_tag,
2522 [NIC_WOL_VIRTUE_ADD] = remote_nic_wol_virtue_add,
2523 [NIC_WOL_VIRTUE_REMOVE] = remote_nic_wol_virtue_remove,
2524 [NIC_WOL_VIRTUE_PROBE] = remote_nic_wol_virtue_probe,
2525 [NIC_WOL_VIRTUE_LIST] = remote_nic_wol_virtue_list,
2526 [NIC_WOL_VIRTUE_GET_CAPS] = remote_nic_wol_virtue_get_caps,
2527 [NIC_WOL_LOAD_INFO] = remote_nic_wol_load_info,
2528 [NIC_OFFLOAD_PROBE] = remote_nic_offload_probe,
2529 [NIC_OFFLOAD_SET] = remote_nic_offload_set,
2530 [NIC_POLL_GET_MODE] = remote_nic_poll_get_mode,
2531 [NIC_POLL_SET_MODE] = remote_nic_poll_set_mode,
2532 [NIC_POLL_NOW] = remote_nic_poll_now
[609243f4]2533};
2534
2535/** Remote NIC interface structure.
2536 *
2537 * Interface for processing request from remote
2538 * clients addressed to the NIC interface.
2539 *
2540 */
[7f80313]2541const remote_iface_t remote_nic_iface = {
[9be30cdf]2542 .method_count = ARRAY_SIZE(remote_nic_iface_ops),
[609243f4]2543 .methods = remote_nic_iface_ops
2544};
2545
2546/**
2547 * @}
2548 */
Note: See TracBrowser for help on using the repository browser.