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

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

Eliminate packet_t from sending direction of NIC interface.

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