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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since c4049e6 was 984a9ba, checked in by Martin Decky <martin@…>, 7 years ago

do not expose the call capability handler from the async framework

Keep the call capability handler encapsulated within the async framework
and do not expose it explicitly via its API. Use the pointer to
ipc_call_t as the sole object identifying an IPC call in the code that
uses the async framework.

This plugs a major leak in the abstraction and also simplifies both the
async framework (slightly) and all IPC servers.

  • 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>
41#include <sys/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,
[7858acbf]1264 struct timeval *period)
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)
1282 rc = async_data_read_start(exch, period, sizeof(struct timeval));
[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,
[7858acbf]1298 const struct timeval *period)
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)
1307 rc = async_data_write_start(exch, period, sizeof(struct timeval));
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);
2407 struct timeval period = {
2408 .tv_sec = 0,
2409 .tv_usec = 0
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
[609243f4]2423 if (max_len != sizeof(struct timeval)) {
[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,
[609243f4]2430 sizeof(struct timeval));
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);
2443 struct timeval period_buf;
2444 struct timeval *period = NULL;
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
[609243f4]2455 if (length != sizeof(struct timeval)) {
[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.