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

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

networking improvements

  • start the networking stack from init
  • add loopback network interface driver (cherrypicked and sanitized from lp:~helenos-nicf/helenos/nicf)
  • add libnic and various small pieces from lp:~helenos-nicf/helenos/nicf
  • fix client side of NIC_GET_ADDRESS
  • net binary overhaul

Note: "ping 127.0.0.1" works, but the first three pings timeout for some reason

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