source: mainline/uspace/lib/c/generic/device/nic.c@ 9cd8165

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 9cd8165 was 9cd8165, checked in by Jiri Svoboda <jiri@…>, 13 years ago

NIC does not need nic_device_id_t. Now it exists just inside net. Not sure if
we care to rename it since net is going away soon, anyway.

  • Property mode set to 100644
File size: 33.3 KB
Line 
1/*
2 * Copyright (c) 2011 Radim Vansa
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libc
30 * @{
31 */
32/**
33 * @file
34 * @brief Client-side RPC stubs for DDF NIC
35 */
36
37#include <ipc/dev_iface.h>
38#include <assert.h>
39#include <device/nic.h>
40#include <errno.h>
41#include <async.h>
42#include <malloc.h>
43#include <stdio.h>
44#include <ipc/services.h>
45
46/** Send frame from NIC
47 *
48 * @param[in] dev_sess
49 * @param[in] data Frame data
50 * @param[in] size Frame size in bytes
51 *
52 * @return EOK If the operation was successfully completed
53 *
54 */
55int nic_send_frame(async_sess_t *dev_sess, void *data, size_t size)
56{
57 async_exch_t *exch = async_exchange_begin(dev_sess);
58
59 ipc_call_t answer;
60 aid_t req = async_send_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
61 NIC_SEND_MESSAGE, &answer);
62 sysarg_t retval = async_data_write_start(exch, data, size);
63
64 async_exchange_end(exch);
65
66 if (retval != EOK) {
67 async_wait_for(req, NULL);
68 return retval;
69 }
70
71 async_wait_for(req, &retval);
72 return retval;
73}
74
75/** Create callback connection from NIC service
76 *
77 * @param[in] dev_sess
78 * @param[in] device_id
79 *
80 * @return EOK If the operation was successfully completed
81 *
82 */
83int nic_callback_create(async_sess_t *dev_sess, async_client_conn_t cfun,
84 void *carg)
85{
86 ipc_call_t answer;
87 int rc;
88 sysarg_t retval;
89
90 async_exch_t *exch = async_exchange_begin(dev_sess);
91 aid_t req = async_send_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
92 NIC_CALLBACK_CREATE, &answer);
93
94 rc = async_connect_to_me(exch, 0, 0, 0, cfun, carg);
95 if (rc != EOK) {
96 async_wait_for(req, NULL);
97 return rc;
98 }
99 async_exchange_end(exch);
100
101 async_wait_for(req, &retval);
102 return (int) retval;
103}
104
105/** Get the current state of the device
106 *
107 * @param[in] dev_sess
108 * @param[out] state Current state
109 *
110 * @return EOK If the operation was successfully completed
111 *
112 */
113int nic_get_state(async_sess_t *dev_sess, nic_device_state_t *state)
114{
115 assert(state);
116
117 sysarg_t _state;
118
119 async_exch_t *exch = async_exchange_begin(dev_sess);
120 int rc = async_req_1_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
121 NIC_GET_STATE, &_state);
122 async_exchange_end(exch);
123
124 *state = (nic_device_state_t) _state;
125
126 return rc;
127}
128
129/** Request the device to change its state
130 *
131 * @param[in] dev_sess
132 * @param[in] state New state
133 *
134 * @return EOK If the operation was successfully completed
135 *
136 */
137int nic_set_state(async_sess_t *dev_sess, nic_device_state_t state)
138{
139 async_exch_t *exch = async_exchange_begin(dev_sess);
140 int rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
141 NIC_SET_STATE, state);
142 async_exchange_end(exch);
143
144 return rc;
145}
146
147/** Request the MAC address of the device
148 *
149 * @param[in] dev_sess
150 * @param[out] address Structure with buffer for the address
151 *
152 * @return EOK If the operation was successfully completed
153 *
154 */
155int nic_get_address(async_sess_t *dev_sess, nic_address_t *address)
156{
157 assert(address);
158
159 async_exch_t *exch = async_exchange_begin(dev_sess);
160 aid_t aid = async_send_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
161 NIC_GET_ADDRESS, NULL);
162 int rc = async_data_read_start(exch, address, sizeof(nic_address_t));
163 async_exchange_end(exch);
164
165 sysarg_t res;
166 async_wait_for(aid, &res);
167
168 if (rc != EOK)
169 return rc;
170
171 return (int) res;
172}
173
174/** Set the address of the device (e.g. MAC on Ethernet)
175 *
176 * @param[in] dev_sess
177 * @param[in] address Pointer to the address
178 *
179 * @return EOK If the operation was successfully completed
180 *
181 */
182int nic_set_address(async_sess_t *dev_sess, const nic_address_t *address)
183{
184 assert(address);
185
186 async_exch_t *exch = async_exchange_begin(dev_sess);
187 aid_t aid = async_send_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
188 NIC_SET_ADDRESS, NULL);
189 int rc = async_data_write_start(exch, address, sizeof(nic_address_t));
190 async_exchange_end(exch);
191
192 sysarg_t res;
193 async_wait_for(aid, &res);
194
195 if (rc != EOK)
196 return rc;
197
198 return (int) res;
199}
200
201/** Request statistic data about NIC operation.
202 *
203 * @param[in] dev_sess
204 * @param[out] stats Structure with the statistics
205 *
206 * @return EOK If the operation was successfully completed
207 *
208 */
209int nic_get_stats(async_sess_t *dev_sess, nic_device_stats_t *stats)
210{
211 assert(stats);
212
213 async_exch_t *exch = async_exchange_begin(dev_sess);
214
215 int rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
216 NIC_GET_STATS);
217 if (rc != EOK) {
218 async_exchange_end(exch);
219 return rc;
220 }
221
222 rc = async_data_read_start(exch, stats, sizeof(nic_device_stats_t));
223
224 async_exchange_end(exch);
225
226 return rc;
227}
228
229/** Request information about the device.
230 *
231 * @see nic_device_info_t
232 *
233 * @param[in] dev_sess
234 * @param[out] device_info Information about the device
235 *
236 * @return EOK If the operation was successfully completed
237 *
238 */
239int nic_get_device_info(async_sess_t *dev_sess, nic_device_info_t *device_info)
240{
241 assert(device_info);
242
243 async_exch_t *exch = async_exchange_begin(dev_sess);
244
245 int rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
246 NIC_GET_DEVICE_INFO);
247 if (rc != EOK) {
248 async_exchange_end(exch);
249 return rc;
250 }
251
252 rc = async_data_read_start(exch, device_info, sizeof(nic_device_info_t));
253
254 async_exchange_end(exch);
255
256 return rc;
257}
258
259/** Request status of the cable (plugged/unplugged)
260 *
261 * @param[in] dev_sess
262 * @param[out] cable_state Current cable state
263 *
264 * @return EOK If the operation was successfully completed
265 *
266 */
267int nic_get_cable_state(async_sess_t *dev_sess, nic_cable_state_t *cable_state)
268{
269 assert(cable_state);
270
271 sysarg_t _cable_state;
272
273 async_exch_t *exch = async_exchange_begin(dev_sess);
274 int rc = async_req_1_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
275 NIC_GET_CABLE_STATE, &_cable_state);
276 async_exchange_end(exch);
277
278 *cable_state = (nic_cable_state_t) _cable_state;
279
280 return rc;
281}
282
283/** Request current operation mode.
284 *
285 * @param[in] dev_sess
286 * @param[out] speed Current operation speed in Mbps. Can be NULL.
287 * @param[out] duplex Full duplex/half duplex. Can be NULL.
288 * @param[out] role Master/slave/auto. Can be NULL.
289 *
290 * @return EOK If the operation was successfully completed
291 *
292 */
293int nic_get_operation_mode(async_sess_t *dev_sess, int *speed,
294 nic_channel_mode_t *duplex, nic_role_t *role)
295{
296 sysarg_t _speed;
297 sysarg_t _duplex;
298 sysarg_t _role;
299
300 async_exch_t *exch = async_exchange_begin(dev_sess);
301 int rc = async_req_1_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
302 NIC_GET_OPERATION_MODE, &_speed, &_duplex, &_role);
303 async_exchange_end(exch);
304
305 if (speed)
306 *speed = (int) _speed;
307
308 if (duplex)
309 *duplex = (nic_channel_mode_t) _duplex;
310
311 if (role)
312 *role = (nic_role_t) _role;
313
314 return rc;
315}
316
317/** Set current operation mode.
318 *
319 * If the NIC has auto-negotiation enabled, this command
320 * disables auto-negotiation and sets the operation mode.
321 *
322 * @param[in] dev_sess
323 * @param[in] speed Operation speed in Mbps
324 * @param[in] duplex Full duplex/half duplex
325 * @param[in] role Master/slave/auto (e.g. in Gbit Ethernet]
326 *
327 * @return EOK If the operation was successfully completed
328 *
329 */
330int nic_set_operation_mode(async_sess_t *dev_sess, int speed,
331 nic_channel_mode_t duplex, nic_role_t role)
332{
333 async_exch_t *exch = async_exchange_begin(dev_sess);
334 int rc = async_req_4_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
335 NIC_SET_OPERATION_MODE, (sysarg_t) speed, (sysarg_t) duplex,
336 (sysarg_t) role);
337 async_exchange_end(exch);
338
339 return rc;
340}
341
342/** Enable auto-negotiation.
343 *
344 * The advertisement argument can only limit some modes,
345 * it can never force the NIC to advertise unsupported modes.
346 *
347 * The allowed modes are defined in "nic/eth_phys.h" in the C library.
348 *
349 * @param[in] dev_sess
350 * @param[in] advertisement Allowed advertised modes. Use 0 for all modes.
351 *
352 * @return EOK If the operation was successfully completed
353 *
354 */
355int nic_autoneg_enable(async_sess_t *dev_sess, uint32_t advertisement)
356{
357 async_exch_t *exch = async_exchange_begin(dev_sess);
358 int rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
359 NIC_AUTONEG_ENABLE, (sysarg_t) advertisement);
360 async_exchange_end(exch);
361
362 return rc;
363}
364
365/** Disable auto-negotiation.
366 *
367 * @param[in] dev_sess
368 *
369 * @return EOK If the operation was successfully completed
370 *
371 */
372int nic_autoneg_disable(async_sess_t *dev_sess)
373{
374 async_exch_t *exch = async_exchange_begin(dev_sess);
375 int rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
376 NIC_AUTONEG_DISABLE);
377 async_exchange_end(exch);
378
379 return rc;
380}
381
382/** Probe current state of auto-negotiation.
383 *
384 * Modes are defined in the "nic/eth_phys.h" in the C library.
385 *
386 * @param[in] dev_sess
387 * @param[out] our_advertisement Modes advertised by this NIC.
388 * Can be NULL.
389 * @param[out] their_advertisement Modes advertised by the other side.
390 * Can be NULL.
391 * @param[out] result General state of auto-negotiation.
392 * Can be NULL.
393 * @param[out] their_result State of other side auto-negotiation.
394 * Can be NULL.
395 *
396 * @return EOK If the operation was successfully completed
397 *
398 */
399int nic_autoneg_probe(async_sess_t *dev_sess, uint32_t *our_advertisement,
400 uint32_t *their_advertisement, nic_result_t *result,
401 nic_result_t *their_result)
402{
403 sysarg_t _our_advertisement;
404 sysarg_t _their_advertisement;
405 sysarg_t _result;
406 sysarg_t _their_result;
407
408 async_exch_t *exch = async_exchange_begin(dev_sess);
409 int rc = async_req_1_4(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
410 NIC_AUTONEG_PROBE, &_our_advertisement, &_their_advertisement,
411 &_result, &_their_result);
412 async_exchange_end(exch);
413
414 if (our_advertisement)
415 *our_advertisement = (uint32_t) _our_advertisement;
416
417 if (*their_advertisement)
418 *their_advertisement = (uint32_t) _their_advertisement;
419
420 if (result)
421 *result = (nic_result_t) _result;
422
423 if (their_result)
424 *their_result = (nic_result_t) _their_result;
425
426 return rc;
427}
428
429/** Restart the auto-negotiation process.
430 *
431 * @param[in] dev_sess
432 *
433 * @return EOK If the operation was successfully completed
434 *
435 */
436int nic_autoneg_restart(async_sess_t *dev_sess)
437{
438 async_exch_t *exch = async_exchange_begin(dev_sess);
439 int rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
440 NIC_AUTONEG_RESTART);
441 async_exchange_end(exch);
442
443 return rc;
444}
445
446/** Query party's sending and reception of the PAUSE frame.
447 *
448 * @param[in] dev_sess
449 * @param[out] we_send This NIC sends the PAUSE frame (true/false)
450 * @param[out] we_receive This NIC receives the PAUSE frame (true/false)
451 * @param[out] pause The time set to transmitted PAUSE frames.
452 *
453 * @return EOK If the operation was successfully completed
454 *
455 */
456int nic_get_pause(async_sess_t *dev_sess, nic_result_t *we_send,
457 nic_result_t *we_receive, uint16_t *pause)
458{
459 sysarg_t _we_send;
460 sysarg_t _we_receive;
461 sysarg_t _pause;
462
463 async_exch_t *exch = async_exchange_begin(dev_sess);
464 int rc = async_req_1_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
465 NIC_GET_PAUSE, &_we_send, &_we_receive, &_pause);
466 async_exchange_end(exch);
467
468 if (we_send)
469 *we_send = _we_send;
470
471 if (we_receive)
472 *we_receive = _we_receive;
473
474 if (pause)
475 *pause = _pause;
476
477 return rc;
478}
479
480/** Control sending and reception of the PAUSE frame.
481 *
482 * @param[in] dev_sess
483 * @param[in] allow_send Allow sending the PAUSE frame (true/false)
484 * @param[in] allow_receive Allow reception of the PAUSE frame (true/false)
485 * @param[in] pause Pause length in 512 bit units written
486 * to transmitted frames. The value 0 means
487 * auto value (the best). If the requested
488 * time cannot be set the driver is allowed
489 * to set the nearest supported value.
490 *
491 * @return EOK If the operation was successfully completed
492 *
493 */
494int nic_set_pause(async_sess_t *dev_sess, int allow_send, int allow_receive,
495 uint16_t pause)
496{
497 async_exch_t *exch = async_exchange_begin(dev_sess);
498 int rc = async_req_4_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
499 NIC_SET_PAUSE, allow_send, allow_receive, pause);
500 async_exchange_end(exch);
501
502 return rc;
503}
504
505/** Retrieve current settings of unicast frames reception.
506 *
507 * Note: In case of mode != NIC_UNICAST_LIST the contents of
508 * address_list and address_count are undefined.
509 *
510 * @param[in] dev_sess
511 * @param[out] mode Current operation mode
512 * @param[in] max_count Maximal number of addresses that could
513 * be written into the list buffer.
514 * @param[out] address_list Buffer for the list (array). Can be NULL.
515 * @param[out] address_count Number of addresses in the list before
516 * possible truncation due to the max_count.
517 *
518 * @return EOK If the operation was successfully completed
519 *
520 */
521int nic_unicast_get_mode(async_sess_t *dev_sess, nic_unicast_mode_t *mode,
522 size_t max_count, nic_address_t *address_list, size_t *address_count)
523{
524 assert(mode);
525
526 sysarg_t _mode;
527 sysarg_t _address_count;
528
529 if (!address_list)
530 max_count = 0;
531
532 async_exch_t *exch = async_exchange_begin(dev_sess);
533
534 int rc = async_req_2_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
535 NIC_UNICAST_GET_MODE, max_count, &_mode, &_address_count);
536 if (rc != EOK) {
537 async_exchange_end(exch);
538 return rc;
539 }
540
541 *mode = (nic_unicast_mode_t) _mode;
542 if (address_count)
543 *address_count = (size_t) _address_count;
544
545 if ((max_count) && (_address_count))
546 rc = async_data_read_start(exch, address_list,
547 max_count * sizeof(nic_address_t));
548
549 async_exchange_end(exch);
550
551 return rc;
552}
553
554/** Set which unicast frames are received.
555 *
556 * @param[in] dev_sess
557 * @param[in] mode Current operation mode
558 * @param[in] address_list The list of addresses. Can be NULL.
559 * @param[in] address_count Number of addresses in the list.
560 *
561 * @return EOK If the operation was successfully completed
562 *
563 */
564int nic_unicast_set_mode(async_sess_t *dev_sess, nic_unicast_mode_t mode,
565 const nic_address_t *address_list, size_t address_count)
566{
567 if (address_list == NULL)
568 address_count = 0;
569
570 async_exch_t *exch = async_exchange_begin(dev_sess);
571
572 aid_t message_id = async_send_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
573 NIC_UNICAST_SET_MODE, (sysarg_t) mode, address_count, NULL);
574
575 int rc;
576 if (address_count)
577 rc = async_data_write_start(exch, address_list,
578 address_count * sizeof(nic_address_t));
579 else
580 rc = EOK;
581
582 async_exchange_end(exch);
583
584 sysarg_t res;
585 async_wait_for(message_id, &res);
586
587 if (rc != EOK)
588 return rc;
589
590 return (int) res;
591}
592
593/** Retrieve current settings of multicast frames reception.
594 *
595 * Note: In case of mode != NIC_MULTICAST_LIST the contents of
596 * address_list and address_count are undefined.
597 *
598 * @param[in] dev_sess
599 * @param[out] mode Current operation mode
600 * @param[in] max_count Maximal number of addresses that could
601 * be written into the list buffer.
602 * @param[out] address_list Buffer for the list (array). Can be NULL.
603 * @param[out] address_count Number of addresses in the list before
604 * possible truncation due to the max_count.
605 * Can be NULL.
606 *
607 * @return EOK If the operation was successfully completed
608 *
609 */
610int nic_multicast_get_mode(async_sess_t *dev_sess, nic_multicast_mode_t *mode,
611 size_t max_count, nic_address_t *address_list, size_t *address_count)
612{
613 assert(mode);
614
615 sysarg_t _mode;
616
617 if (!address_list)
618 max_count = 0;
619
620 async_exch_t *exch = async_exchange_begin(dev_sess);
621
622 sysarg_t ac;
623 int rc = async_req_2_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
624 NIC_MULTICAST_GET_MODE, max_count, &_mode, &ac);
625 if (rc != EOK) {
626 async_exchange_end(exch);
627 return rc;
628 }
629
630 *mode = (nic_multicast_mode_t) _mode;
631 if (address_count)
632 *address_count = (size_t) ac;
633
634 if ((max_count) && (ac))
635 rc = async_data_read_start(exch, address_list,
636 max_count * sizeof(nic_address_t));
637
638 async_exchange_end(exch);
639 return rc;
640}
641
642/** Set which multicast frames are received.
643 *
644 * @param[in] dev_sess
645 * @param[in] mode Current operation mode
646 * @param[in] address_list The list of addresses. Can be NULL.
647 * @param[in] address_count Number of addresses in the list.
648 *
649 * @return EOK If the operation was successfully completed
650 *
651 */
652int nic_multicast_set_mode(async_sess_t *dev_sess, nic_multicast_mode_t mode,
653 const nic_address_t *address_list, size_t address_count)
654{
655 if (address_list == NULL)
656 address_count = 0;
657
658 async_exch_t *exch = async_exchange_begin(dev_sess);
659
660 aid_t message_id = async_send_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
661 NIC_MULTICAST_SET_MODE, (sysarg_t) mode, address_count, NULL);
662
663 int rc;
664 if (address_count)
665 rc = async_data_write_start(exch, address_list,
666 address_count * sizeof(nic_address_t));
667 else
668 rc = EOK;
669
670 async_exchange_end(exch);
671
672 sysarg_t res;
673 async_wait_for(message_id, &res);
674
675 if (rc != EOK)
676 return rc;
677
678 return (int) res;
679}
680
681/** Determine if broadcast packets are received.
682 *
683 * @param[in] dev_sess
684 * @param[out] mode Current operation mode
685 *
686 * @return EOK If the operation was successfully completed
687 *
688 */
689int nic_broadcast_get_mode(async_sess_t *dev_sess, nic_broadcast_mode_t *mode)
690{
691 assert(mode);
692
693 sysarg_t _mode;
694
695 async_exch_t *exch = async_exchange_begin(dev_sess);
696 int rc = async_req_1_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
697 NIC_BROADCAST_GET_MODE, &_mode);
698 async_exchange_end(exch);
699
700 *mode = (nic_broadcast_mode_t) _mode;
701
702 return rc;
703}
704
705/** Set whether broadcast packets are received.
706 *
707 * @param[in] dev_sess
708 * @param[in] mode Current operation mode
709 *
710 * @return EOK If the operation was successfully completed
711 *
712 */
713int nic_broadcast_set_mode(async_sess_t *dev_sess, nic_broadcast_mode_t mode)
714{
715 async_exch_t *exch = async_exchange_begin(dev_sess);
716 int rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
717 NIC_BROADCAST_SET_MODE, mode);
718 async_exchange_end(exch);
719
720 return rc;
721}
722
723/** Determine if defective (erroneous) packets are received.
724 *
725 * @param[in] dev_sess
726 * @param[out] mode Bitmask specifying allowed errors
727 *
728 * @return EOK If the operation was successfully completed
729 *
730 */
731int nic_defective_get_mode(async_sess_t *dev_sess, uint32_t *mode)
732{
733 assert(mode);
734
735 sysarg_t _mode;
736
737 async_exch_t *exch = async_exchange_begin(dev_sess);
738 int rc = async_req_1_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
739 NIC_DEFECTIVE_GET_MODE, &_mode);
740 async_exchange_end(exch);
741
742 *mode = (uint32_t) _mode;
743
744 return rc;
745}
746
747/** Set whether defective (erroneous) packets are received.
748 *
749 * @param[in] dev_sess
750 * @param[out] mode Bitmask specifying allowed errors
751 *
752 * @return EOK If the operation was successfully completed
753 *
754 */
755int nic_defective_set_mode(async_sess_t *dev_sess, uint32_t mode)
756{
757 async_exch_t *exch = async_exchange_begin(dev_sess);
758 int rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
759 NIC_DEFECTIVE_SET_MODE, mode);
760 async_exchange_end(exch);
761
762 return rc;
763}
764
765/** Retrieve the currently blocked source MAC addresses.
766 *
767 * @param[in] dev_sess
768 * @param[in] max_count Maximal number of addresses that could
769 * be written into the list buffer.
770 * @param[out] address_list Buffer for the list (array). Can be NULL.
771 * @param[out] address_count Number of addresses in the list before
772 * possible truncation due to the max_count.
773 *
774 * @return EOK If the operation was successfully completed
775 *
776 */
777int nic_blocked_sources_get(async_sess_t *dev_sess, size_t max_count,
778 nic_address_t *address_list, size_t *address_count)
779{
780 if (!address_list)
781 max_count = 0;
782
783 async_exch_t *exch = async_exchange_begin(dev_sess);
784
785 sysarg_t ac;
786 int rc = async_req_2_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
787 NIC_BLOCKED_SOURCES_GET, max_count, &ac);
788 if (rc != EOK) {
789 async_exchange_end(exch);
790 return rc;
791 }
792
793 if (address_count)
794 *address_count = (size_t) ac;
795
796 if ((max_count) && (ac))
797 rc = async_data_read_start(exch, address_list,
798 max_count * sizeof(nic_address_t));
799
800 async_exchange_end(exch);
801 return rc;
802}
803
804/** Set which source MACs are blocked
805 *
806 * @param[in] dev_sess
807 * @param[in] address_list The list of addresses. Can be NULL.
808 * @param[in] address_count Number of addresses in the list.
809 *
810 * @return EOK If the operation was successfully completed
811 *
812 */
813int nic_blocked_sources_set(async_sess_t *dev_sess,
814 const nic_address_t *address_list, size_t address_count)
815{
816 if (address_list == NULL)
817 address_count = 0;
818
819 async_exch_t *exch = async_exchange_begin(dev_sess);
820
821 aid_t message_id = async_send_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
822 NIC_BLOCKED_SOURCES_SET, address_count, NULL);
823
824 int rc;
825 if (address_count)
826 rc = async_data_write_start(exch, address_list,
827 address_count * sizeof(nic_address_t));
828 else
829 rc = EOK;
830
831 async_exchange_end(exch);
832
833 sysarg_t res;
834 async_wait_for(message_id, &res);
835
836 if (rc != EOK)
837 return rc;
838
839 return (int) res;
840}
841
842/** Request current VLAN filtering mask.
843 *
844 * @param[in] dev_sess
845 * @param[out] stats Structure with the statistics
846 *
847 * @return EOK If the operation was successfully completed
848 *
849 */
850int nic_vlan_get_mask(async_sess_t *dev_sess, nic_vlan_mask_t *mask)
851{
852 assert(mask);
853
854 async_exch_t *exch = async_exchange_begin(dev_sess);
855 int rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
856 NIC_VLAN_GET_MASK);
857 if (rc != EOK) {
858 async_exchange_end(exch);
859 return rc;
860 }
861
862 rc = async_data_read_start(exch, mask, sizeof(nic_vlan_mask_t));
863 async_exchange_end(exch);
864
865 return rc;
866}
867
868/** Set the mask used for VLAN filtering.
869 *
870 * If NULL, VLAN filtering is disabled.
871 *
872 * @param[in] dev_sess
873 * @param[in] mask Pointer to mask structure or NULL to disable.
874 *
875 * @return EOK If the operation was successfully completed
876 *
877 */
878int nic_vlan_set_mask(async_sess_t *dev_sess, const nic_vlan_mask_t *mask)
879{
880 async_exch_t *exch = async_exchange_begin(dev_sess);
881
882 aid_t message_id = async_send_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
883 NIC_VLAN_SET_MASK, mask != NULL, NULL);
884
885 int rc;
886 if (mask != NULL)
887 rc = async_data_write_start(exch, mask, sizeof(nic_vlan_mask_t));
888 else
889 rc = EOK;
890
891 async_exchange_end(exch);
892
893 sysarg_t res;
894 async_wait_for(message_id, &res);
895
896 if (rc != EOK)
897 return rc;
898
899 return (int) res;
900}
901
902/** Set VLAN (802.1q) tag.
903 *
904 * Set whether the tag is to be signaled in offload info and
905 * if the tag should be stripped from received frames and added
906 * to sent frames automatically. Not every combination of add
907 * and strip must be supported.
908 *
909 * @param[in] dev_sess
910 * @param[in] tag VLAN priority (top 3 bits) and
911 * the VLAN tag (bottom 12 bits)
912 * @param[in] add Add the VLAN tag automatically (boolean)
913 * @param[in] strip Strip the VLAN tag automatically (boolean)
914 *
915 * @return EOK If the operation was successfully completed
916 *
917 */
918int nic_vlan_set_tag(async_sess_t *dev_sess, uint16_t tag, bool add, bool strip)
919{
920 async_exch_t *exch = async_exchange_begin(dev_sess);
921 int rc = async_req_4_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
922 NIC_VLAN_SET_TAG, (sysarg_t) tag, (sysarg_t) add, (sysarg_t) strip);
923 async_exchange_end(exch);
924
925 return rc;
926}
927
928/** Add new Wake-On-LAN virtue.
929 *
930 * @param[in] dev_sess
931 * @param[in] type Type of the virtue
932 * @param[in] data Data required for this virtue
933 * (depends on type)
934 * @param[in] length Length of the data
935 * @param[out] id Identifier of the new virtue
936 *
937 * @return EOK If the operation was successfully completed
938 *
939 */
940int nic_wol_virtue_add(async_sess_t *dev_sess, nic_wv_type_t type,
941 const void *data, size_t length, nic_wv_id_t *id)
942{
943 assert(id);
944
945 bool send_data = ((data != NULL) && (length != 0));
946 async_exch_t *exch = async_exchange_begin(dev_sess);
947
948 ipc_call_t result;
949 aid_t message_id = async_send_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
950 NIC_WOL_VIRTUE_ADD, (sysarg_t) type, send_data, &result);
951
952 sysarg_t res;
953 if (send_data) {
954 int rc = async_data_write_start(exch, data, length);
955 if (rc != EOK) {
956 async_exchange_end(exch);
957 async_wait_for(message_id, &res);
958 return rc;
959 }
960 }
961
962 async_exchange_end(exch);
963 async_wait_for(message_id, &res);
964
965 *id = IPC_GET_ARG1(result);
966 return (int) res;
967}
968
969/** Remove Wake-On-LAN virtue.
970 *
971 * @param[in] dev_sess
972 * @param[in] id Virtue identifier
973 *
974 * @return EOK If the operation was successfully completed
975 *
976 */
977int nic_wol_virtue_remove(async_sess_t *dev_sess, nic_wv_id_t id)
978{
979 async_exch_t *exch = async_exchange_begin(dev_sess);
980 int rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
981 NIC_WOL_VIRTUE_REMOVE, (sysarg_t) id);
982 async_exchange_end(exch);
983
984 return rc;
985}
986
987/** Get information about virtue.
988 *
989 * @param[in] dev_sess
990 * @param[in] id Virtue identifier
991 * @param[out] type Type of the filter. Can be NULL.
992 * @param[out] max_length Size of the data buffer.
993 * @param[out] data Buffer for data used when the
994 * virtue was created. Can be NULL.
995 * @param[out] length Length of the data. Can be NULL.
996 *
997 * @return EOK If the operation was successfully completed
998 *
999 */
1000int nic_wol_virtue_probe(async_sess_t *dev_sess, nic_wv_id_t id,
1001 nic_wv_type_t *type, size_t max_length, void *data, size_t *length)
1002{
1003 sysarg_t _type;
1004 sysarg_t _length;
1005
1006 if (data == NULL)
1007 max_length = 0;
1008
1009 async_exch_t *exch = async_exchange_begin(dev_sess);
1010
1011 int rc = async_req_3_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1012 NIC_WOL_VIRTUE_PROBE, (sysarg_t) id, max_length,
1013 &_type, &_length);
1014 if (rc != EOK) {
1015 async_exchange_end(exch);
1016 return rc;
1017 }
1018
1019 if (type)
1020 *type = _type;
1021
1022 if (length)
1023 *length = _length;
1024
1025 if ((max_length) && (_length != 0))
1026 rc = async_data_read_start(exch, data, max_length);
1027
1028 async_exchange_end(exch);
1029 return rc;
1030}
1031
1032/** Get a list of all virtues of the specified type.
1033 *
1034 * When NIC_WV_NONE is specified as the virtue type the function
1035 * lists virtues of all types.
1036 *
1037 * @param[in] dev_sess
1038 * @param[in] type Type of the virtues
1039 * @param[in] max_count Maximum number of ids that can be
1040 * written into the list buffer.
1041 * @param[out] id_list Buffer for to the list of virtue ids.
1042 * Can be NULL.
1043 * @param[out] id_count Number of virtue identifiers in the list
1044 * before possible truncation due to the
1045 * max_count. Can be NULL.
1046 *
1047 * @return EOK If the operation was successfully completed
1048 *
1049 */
1050int nic_wol_virtue_list(async_sess_t *dev_sess, nic_wv_type_t type,
1051 size_t max_count, nic_wv_id_t *id_list, size_t *id_count)
1052{
1053 if (id_list == NULL)
1054 max_count = 0;
1055
1056 async_exch_t *exch = async_exchange_begin(dev_sess);
1057
1058 sysarg_t count;
1059 int rc = async_req_3_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1060 NIC_WOL_VIRTUE_LIST, (sysarg_t) type, max_count, &count);
1061
1062 if (id_count)
1063 *id_count = (size_t) count;
1064
1065 if ((rc != EOK) || (!max_count)) {
1066 async_exchange_end(exch);
1067 return rc;
1068 }
1069
1070 rc = async_data_read_start(exch, id_list,
1071 max_count * sizeof(nic_wv_id_t));
1072
1073 async_exchange_end(exch);
1074 return rc;
1075}
1076
1077/** Get number of virtues that can be enabled yet.
1078 *
1079 * Count: < 0 => Virtue of this type can be never used
1080 * = 0 => No more virtues can be enabled
1081 * > 0 => #count virtues can be enabled yet
1082 *
1083 * @param[in] dev_sess
1084 * @param[in] type Virtue type
1085 * @param[out] count Number of virtues
1086 *
1087 * @return EOK If the operation was successfully completed
1088 *
1089 */
1090int nic_wol_virtue_get_caps(async_sess_t *dev_sess, nic_wv_type_t type,
1091 int *count)
1092{
1093 assert(count);
1094
1095 sysarg_t _count;
1096
1097 async_exch_t *exch = async_exchange_begin(dev_sess);
1098 int rc = async_req_2_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1099 NIC_WOL_VIRTUE_GET_CAPS, (sysarg_t) type, &_count);
1100 async_exchange_end(exch);
1101
1102 *count = (int) _count;
1103 return rc;
1104}
1105
1106/** Load the frame that issued the wakeup.
1107 *
1108 * The NIC can support only matched_type, only part of the frame
1109 * can be available or not at all. Sometimes even the type can be
1110 * uncertain -- in this case the matched_type contains NIC_WV_NONE.
1111 *
1112 * Frame_length can be greater than max_length, but at most max_length
1113 * bytes will be copied into the frame buffer.
1114 *
1115 * Note: Only the type of the filter can be detected, not the concrete
1116 * filter, because the driver is probably not running when the wakeup
1117 * is issued.
1118 *
1119 * @param[in] dev_sess
1120 * @param[out] matched_type Type of the filter that issued wakeup.
1121 * @param[in] max_length Size of the buffer
1122 * @param[out] frame Buffer for the frame. Can be NULL.
1123 * @param[out] frame_length Length of the stored frame. Can be NULL.
1124 *
1125 * @return EOK If the operation was successfully completed
1126 *
1127 */
1128int nic_wol_load_info(async_sess_t *dev_sess, nic_wv_type_t *matched_type,
1129 size_t max_length, uint8_t *frame, size_t *frame_length)
1130{
1131 assert(matched_type);
1132
1133 sysarg_t _matched_type;
1134 sysarg_t _frame_length;
1135
1136 if (frame == NULL)
1137 max_length = 0;
1138
1139 async_exch_t *exch = async_exchange_begin(dev_sess);
1140
1141 int rc = async_req_2_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1142 NIC_WOL_LOAD_INFO, max_length, &_matched_type, &_frame_length);
1143 if (rc != EOK) {
1144 async_exchange_end(exch);
1145 return rc;
1146 }
1147
1148 *matched_type = (nic_wv_type_t) _matched_type;
1149 if (frame_length)
1150 *frame_length = (size_t) _frame_length;
1151
1152 if ((max_length != 0) && (_frame_length != 0))
1153 rc = async_data_read_start(exch, frame, max_length);
1154
1155 async_exchange_end(exch);
1156 return rc;
1157}
1158
1159/** Probe supported options and current setting of offload computations
1160 *
1161 * @param[in] dev_sess
1162 * @param[out] supported Supported offload options
1163 * @param[out] active Currently active offload options
1164 *
1165 * @return EOK If the operation was successfully completed
1166 *
1167 */
1168int nic_offload_probe(async_sess_t *dev_sess, uint32_t *supported,
1169 uint32_t *active)
1170{
1171 assert(supported);
1172 assert(active);
1173
1174 sysarg_t _supported;
1175 sysarg_t _active;
1176
1177 async_exch_t *exch = async_exchange_begin(dev_sess);
1178 int rc = async_req_1_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1179 NIC_OFFLOAD_PROBE, &_supported, &_active);
1180 async_exchange_end(exch);
1181
1182 *supported = (uint32_t) _supported;
1183 *active = (uint32_t) _active;
1184 return rc;
1185}
1186
1187/** Set which offload computations can be performed on the NIC.
1188 *
1189 * @param[in] dev_sess
1190 * @param[in] mask Mask for the options (only those set here will be set)
1191 * @param[in] active Which options should be enabled and which disabled
1192 *
1193 * @return EOK If the operation was successfully completed
1194 *
1195 */
1196int nic_offload_set(async_sess_t *dev_sess, uint32_t mask, uint32_t active)
1197{
1198 async_exch_t *exch = async_exchange_begin(dev_sess);
1199 int rc = async_req_3_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1200 NIC_AUTONEG_RESTART, (sysarg_t) mask, (sysarg_t) active);
1201 async_exchange_end(exch);
1202
1203 return rc;
1204}
1205
1206/** Query the current interrupt/poll mode of the NIC
1207 *
1208 * @param[in] dev_sess
1209 * @param[out] mode Current poll mode
1210 * @param[out] period Period used in periodic polling.
1211 * Can be NULL.
1212 *
1213 * @return EOK If the operation was successfully completed
1214 *
1215 */
1216int nic_poll_get_mode(async_sess_t *dev_sess, nic_poll_mode_t *mode,
1217 struct timeval *period)
1218{
1219 assert(mode);
1220
1221 sysarg_t _mode;
1222
1223 async_exch_t *exch = async_exchange_begin(dev_sess);
1224
1225 int rc = async_req_2_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1226 NIC_POLL_GET_MODE, period != NULL, &_mode);
1227 if (rc != EOK) {
1228 async_exchange_end(exch);
1229 return rc;
1230 }
1231
1232 *mode = (nic_poll_mode_t) _mode;
1233
1234 if (period != NULL)
1235 rc = async_data_read_start(exch, period, sizeof(struct timeval));
1236
1237 async_exchange_end(exch);
1238 return rc;
1239}
1240
1241/** Set the interrupt/poll mode of the NIC.
1242 *
1243 * @param[in] dev_sess
1244 * @param[in] mode New poll mode
1245 * @param[in] period Period used in periodic polling. Can be NULL.
1246 *
1247 * @return EOK If the operation was successfully completed
1248 *
1249 */
1250int nic_poll_set_mode(async_sess_t *dev_sess, nic_poll_mode_t mode,
1251 const struct timeval *period)
1252{
1253 async_exch_t *exch = async_exchange_begin(dev_sess);
1254
1255 aid_t message_id = async_send_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
1256 NIC_POLL_SET_MODE, (sysarg_t) mode, period != NULL, NULL);
1257
1258 int rc;
1259 if (period)
1260 rc = async_data_write_start(exch, period, sizeof(struct timeval));
1261 else
1262 rc = EOK;
1263
1264 async_exchange_end(exch);
1265
1266 sysarg_t res;
1267 async_wait_for(message_id, &res);
1268
1269 if (rc != EOK)
1270 return rc;
1271
1272 return (int) res;
1273}
1274
1275/** Request the driver to poll the NIC.
1276 *
1277 * @param[in] dev_sess
1278 *
1279 * @return EOK If the operation was successfully completed
1280 *
1281 */
1282int nic_poll_now(async_sess_t *dev_sess)
1283{
1284 async_exch_t *exch = async_exchange_begin(dev_sess);
1285 int rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE), NIC_POLL_NOW);
1286 async_exchange_end(exch);
1287
1288 return rc;
1289}
1290
1291/** @}
1292 */
Note: See TracBrowser for help on using the repository browser.