source: mainline/uspace/lib/nic/src/nic_impl.c@ 3d95c9d

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

Fix comments to stop referring to error codes as negative.

  • Property mode set to 100644
File size: 24.1 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/**
30 * @addtogroup libnic
31 * @{
32 */
33/**
34 * @file
35 * @brief Default DDF NIC interface methods implementations
36 */
37
38#include <errno.h>
39#include <str_error.h>
40#include <ipc/services.h>
41#include <ns.h>
42#include "nic_driver.h"
43#include "nic_ev.h"
44#include "nic_impl.h"
45
46/**
47 * Default implementation of the set_state method. Trivial.
48 *
49 * @param fun
50 * @param[out] state
51 *
52 * @return EOK always.
53 */
54int nic_get_state_impl(ddf_fun_t *fun, nic_device_state_t *state)
55{
56 nic_t *nic_data = nic_get_from_ddf_fun(fun);
57 fibril_rwlock_read_lock(&nic_data->main_lock);
58 *state = nic_data->state;
59 fibril_rwlock_read_unlock(&nic_data->main_lock);
60 return EOK;
61}
62
63/**
64 * Default implementation of the set_state method. Changes the internal
65 * driver's state, calls the appropriate callback and notifies the NIL service
66 * about this change.
67 *
68 * @param fun
69 * @param state The new device's state
70 *
71 * @return EOK If the state was changed
72 * @return EINVAL If the state cannot be changed
73 */
74int nic_set_state_impl(ddf_fun_t *fun, nic_device_state_t state)
75{
76 if (state >= NIC_STATE_MAX) {
77 return EINVAL;
78 }
79
80 nic_t *nic_data = nic_get_from_ddf_fun(fun);
81
82 fibril_rwlock_write_lock(&nic_data->main_lock);
83 if (nic_data->state == state) {
84 /* No change, nothing to do */
85 fibril_rwlock_write_unlock(&nic_data->main_lock);
86 return EOK;
87 }
88 if (state == NIC_STATE_ACTIVE) {
89 if (nic_data->client_session == NULL) {
90 fibril_rwlock_write_unlock(&nic_data->main_lock);
91 return EINVAL;
92 }
93 }
94
95 state_change_handler event_handler = NULL;
96 switch (state) {
97 case NIC_STATE_STOPPED:
98 event_handler = nic_data->on_stopping;
99 break;
100 case NIC_STATE_DOWN:
101 event_handler = nic_data->on_going_down;
102 break;
103 case NIC_STATE_ACTIVE:
104 event_handler = nic_data->on_activating;
105 break;
106 default:
107 break;
108 }
109 if (event_handler != NULL) {
110 int rc = event_handler(nic_data);
111 if (rc != EOK) {
112 fibril_rwlock_write_unlock(&nic_data->main_lock);
113 return EINVAL;
114 }
115 }
116
117 if (state == NIC_STATE_STOPPED) {
118 /* Notify upper layers that we are reseting the MAC */
119 int rc = nic_ev_addr_changed(nic_data->client_session,
120 &nic_data->default_mac);
121 nic_data->poll_mode = nic_data->default_poll_mode;
122 memcpy(&nic_data->poll_period, &nic_data->default_poll_period,
123 sizeof (struct timeval));
124 if (rc != EOK) {
125 /* We have already ran the on stopped handler, even if we
126 * terminated the state change we would end up in undefined state.
127 * Therefore we just log the problem. */
128 }
129
130 fibril_rwlock_write_lock(&nic_data->stats_lock);
131 memset(&nic_data->stats, 0, sizeof(nic_device_stats_t));
132 fibril_rwlock_write_unlock(&nic_data->stats_lock);
133
134 fibril_rwlock_write_lock(&nic_data->rxc_lock);
135 nic_rxc_clear(&nic_data->rx_control);
136 /* Reinsert device's default MAC */
137 nic_rxc_set_addr(&nic_data->rx_control, NULL,
138 &nic_data->default_mac);
139 fibril_rwlock_write_unlock(&nic_data->rxc_lock);
140 memcpy(&nic_data->mac, &nic_data->default_mac, sizeof (nic_address_t));
141
142 fibril_rwlock_write_lock(&nic_data->wv_lock);
143 nic_wol_virtues_clear(&nic_data->wol_virtues);
144 fibril_rwlock_write_unlock(&nic_data->wv_lock);
145
146 /* Ensure stopping period of NIC_POLL_SOFTWARE_PERIODIC */
147 nic_sw_period_stop(nic_data);
148 }
149
150 nic_data->state = state;
151
152 nic_ev_device_state(nic_data->client_session, state);
153
154 fibril_rwlock_write_unlock(&nic_data->main_lock);
155
156 return EOK;
157}
158
159/**
160 * Default implementation of the send_frame method.
161 * Send messages to the network.
162 *
163 * @param fun
164 * @param data Frame data
165 * @param size Frame size in bytes
166 *
167 * @return EOK If the message was sent
168 * @return EBUSY If the device is not in state when the frame can be sent.
169 */
170int nic_send_frame_impl(ddf_fun_t *fun, void *data, size_t size)
171{
172 nic_t *nic_data = nic_get_from_ddf_fun(fun);
173
174 fibril_rwlock_read_lock(&nic_data->main_lock);
175 if (nic_data->state != NIC_STATE_ACTIVE || nic_data->tx_busy) {
176 fibril_rwlock_read_unlock(&nic_data->main_lock);
177 return EBUSY;
178 }
179
180 nic_data->send_frame(nic_data, data, size);
181 fibril_rwlock_read_unlock(&nic_data->main_lock);
182 return EOK;
183}
184
185/**
186 * Default implementation of the connect_client method.
187 * Creates callback connection to the client.
188 *
189 * @param fun
190 *
191 * @return EOK On success, or an error code.
192 */
193int nic_callback_create_impl(ddf_fun_t *fun)
194{
195 nic_t *nic = nic_get_from_ddf_fun(fun);
196 fibril_rwlock_write_lock(&nic->main_lock);
197
198 nic->client_session = async_callback_receive(EXCHANGE_SERIALIZE);
199 if (nic->client_session == NULL) {
200 fibril_rwlock_write_unlock(&nic->main_lock);
201 return ENOMEM;
202 }
203
204 fibril_rwlock_write_unlock(&nic->main_lock);
205 return EOK;
206}
207
208/**
209 * Default implementation of the get_address method.
210 * Retrieves the NIC's physical address.
211 *
212 * @param fun
213 * @param address Pointer to the structure where the address will be stored.
214 *
215 * @return EOK If the services were bound
216 * @return ELIMIT If the buffer is too short
217 */
218int nic_get_address_impl(ddf_fun_t *fun, nic_address_t *address)
219{
220 assert(address);
221 nic_t *nic_data = nic_get_from_ddf_fun(fun);
222 fibril_rwlock_read_lock(&nic_data->main_lock);
223 memcpy(address, &nic_data->mac, sizeof (nic_address_t));
224 fibril_rwlock_read_unlock(&nic_data->main_lock);
225 return EOK;
226}
227
228/**
229 * Default implementation of the get_stats method. Copies the statistics from
230 * the drivers data to supplied buffer.
231 *
232 * @param fun
233 * @param[out] stats The buffer for statistics
234 *
235 * @return EOK (cannot fail)
236 */
237int nic_get_stats_impl(ddf_fun_t *fun, nic_device_stats_t *stats)
238{
239 nic_t *nic_data = nic_get_from_ddf_fun(fun);
240 assert (stats != NULL);
241 fibril_rwlock_read_lock(&nic_data->stats_lock);
242 memcpy(stats, &nic_data->stats, sizeof (nic_device_stats_t));
243 fibril_rwlock_read_unlock(&nic_data->stats_lock);
244 return EOK;
245}
246
247/**
248 * Default implementation of unicast_get_mode method.
249 *
250 * @param fun
251 * @param[out] mode Current operation mode
252 * @param[in] max_count Max number of addresses that can be written into the
253 * buffer (addr_list).
254 * @param[out] addr_list Buffer for addresses
255 * @param[out] addr_count Number of addresses written into the list
256 *
257 * @return EOK
258 */
259int nic_unicast_get_mode_impl(ddf_fun_t *fun, nic_unicast_mode_t *mode,
260 size_t max_count, nic_address_t *addr_list, size_t *addr_count)
261{
262 nic_t *nic_data = nic_get_from_ddf_fun(fun);
263 fibril_rwlock_read_lock(&nic_data->rxc_lock);
264 nic_rxc_unicast_get_mode(&nic_data->rx_control, mode, max_count,
265 addr_list, addr_count);
266 fibril_rwlock_read_unlock(&nic_data->rxc_lock);
267 return EOK;
268}
269
270/**
271 * Default implementation of unicast_set_mode method.
272 *
273 * @param fun
274 * @param[in] mode New operation mode
275 * @param[in] addr_list List of unicast addresses
276 * @param[in] addr_count Number of addresses in the list
277 *
278 * @return EOK
279 * @return EINVAL
280 * @return ENOTSUP
281 * @return ENOMEM
282 */
283int nic_unicast_set_mode_impl(ddf_fun_t *fun,
284 nic_unicast_mode_t mode, const nic_address_t *addr_list, size_t addr_count)
285{
286 assert((addr_count == 0 && addr_list == NULL)
287 || (addr_count != 0 && addr_list != NULL));
288 size_t i;
289 for (i = 0; i < addr_count; ++i) {
290 if (addr_list[i].address[0] & 1)
291 return EINVAL;
292 }
293
294 nic_t *nic_data = nic_get_from_ddf_fun(fun);
295 fibril_rwlock_write_lock(&nic_data->rxc_lock);
296 int rc = ENOTSUP;
297 if (nic_data->on_unicast_mode_change) {
298 rc = nic_data->on_unicast_mode_change(nic_data,
299 mode, addr_list, addr_count);
300 }
301 if (rc == EOK) {
302 rc = nic_rxc_unicast_set_mode(&nic_data->rx_control, mode,
303 addr_list, addr_count);
304 /* After changing the mode the addr db gets cleared, therefore we have
305 * to reinsert also the physical address of NIC.
306 */
307 nic_rxc_set_addr(&nic_data->rx_control, NULL, &nic_data->mac);
308 }
309 fibril_rwlock_write_unlock(&nic_data->rxc_lock);
310 return rc;
311}
312
313
314/**
315 * Default implementation of multicast_get_mode method.
316 *
317 * @param fun
318 * @param[out] mode Current operation mode
319 * @param[in] max_count Max number of addresses that can be written into the
320 * buffer (addr_list).
321 * @param[out] addr_list Buffer for addresses
322 * @param[out] addr_count Number of addresses written into the list
323 *
324 * @return EOK
325 */
326int nic_multicast_get_mode_impl(ddf_fun_t *fun, nic_multicast_mode_t *mode,
327 size_t max_count, nic_address_t *addr_list, size_t *addr_count)
328{
329 nic_t *nic_data = nic_get_from_ddf_fun(fun);
330 fibril_rwlock_read_lock(&nic_data->rxc_lock);
331 nic_rxc_multicast_get_mode(&nic_data->rx_control, mode, max_count,
332 addr_list, addr_count);
333 fibril_rwlock_read_unlock(&nic_data->rxc_lock);
334 return EOK;
335}
336
337/**
338 * Default implementation of multicast_set_mode method.
339 *
340 * @param fun
341 * @param[in] mode New operation mode
342 * @param[in] addr_list List of multicast addresses
343 * @param[in] addr_count Number of addresses in the list
344 *
345 * @return EOK
346 * @return EINVAL
347 * @return ENOTSUP
348 * @return ENOMEM
349 */
350int nic_multicast_set_mode_impl(ddf_fun_t *fun, nic_multicast_mode_t mode,
351 const nic_address_t *addr_list, size_t addr_count)
352{
353 assert((addr_count == 0 && addr_list == NULL)
354 || (addr_count != 0 && addr_list != NULL));
355 size_t i;
356 for (i = 0; i < addr_count; ++i) {
357 if (!(addr_list[i].address[0] & 1))
358 return EINVAL;
359 }
360
361 nic_t *nic_data = nic_get_from_ddf_fun(fun);
362 fibril_rwlock_write_lock(&nic_data->rxc_lock);
363 int rc = ENOTSUP;
364 if (nic_data->on_multicast_mode_change) {
365 rc = nic_data->on_multicast_mode_change(nic_data, mode, addr_list, addr_count);
366 }
367 if (rc == EOK) {
368 rc = nic_rxc_multicast_set_mode(&nic_data->rx_control, mode,
369 addr_list, addr_count);
370 }
371 fibril_rwlock_write_unlock(&nic_data->rxc_lock);
372 return rc;
373}
374
375/**
376 * Default implementation of broadcast_get_mode method.
377 *
378 * @param fun
379 * @param[out] mode Current operation mode
380 *
381 * @return EOK
382 */
383int nic_broadcast_get_mode_impl(ddf_fun_t *fun, nic_broadcast_mode_t *mode)
384{
385 nic_t *nic_data = nic_get_from_ddf_fun(fun);
386 fibril_rwlock_read_lock(&nic_data->rxc_lock);
387 nic_rxc_broadcast_get_mode(&nic_data->rx_control, mode);
388 fibril_rwlock_read_unlock(&nic_data->rxc_lock);
389 return EOK;
390}
391
392/**
393 * Default implementation of broadcast_set_mode method.
394 *
395 * @param fun
396 * @param[in] mode New operation mode
397 *
398 * @return EOK
399 * @return EINVAL
400 * @return ENOTSUP
401 * @return ENOMEM
402 */
403int nic_broadcast_set_mode_impl(ddf_fun_t *fun, nic_broadcast_mode_t mode)
404{
405 nic_t *nic_data = nic_get_from_ddf_fun(fun);
406 fibril_rwlock_write_lock(&nic_data->rxc_lock);
407 int rc = ENOTSUP;
408 if (nic_data->on_broadcast_mode_change) {
409 rc = nic_data->on_broadcast_mode_change(nic_data, mode);
410 }
411 if (rc == EOK) {
412 rc = nic_rxc_broadcast_set_mode(&nic_data->rx_control, mode);
413 }
414 fibril_rwlock_write_unlock(&nic_data->rxc_lock);
415 return rc;
416}
417
418/**
419 * Default implementation of blocked_sources_get method.
420 *
421 * @param fun
422 * @param[in] max_count Max number of addresses that can be written into the
423 * buffer (addr_list).
424 * @param[out] addr_list Buffer for addresses
425 * @param[out] addr_count Number of addresses written into the list
426 *
427 * @return EOK
428 */
429int nic_blocked_sources_get_impl(ddf_fun_t *fun,
430 size_t max_count, nic_address_t *addr_list, size_t *addr_count)
431{
432 nic_t *nic_data = nic_get_from_ddf_fun(fun);
433 fibril_rwlock_read_lock(&nic_data->rxc_lock);
434 nic_rxc_blocked_sources_get(&nic_data->rx_control,
435 max_count, addr_list, addr_count);
436 fibril_rwlock_read_unlock(&nic_data->rxc_lock);
437 return EOK;
438}
439
440/**
441 * Default implementation of blocked_sources_set method.
442 *
443 * @param fun
444 * @param[in] addr_list List of blocked addresses
445 * @param[in] addr_count Number of addresses in the list
446 *
447 * @return EOK
448 * @return EINVAL
449 * @return ENOTSUP
450 * @return ENOMEM
451 */
452int nic_blocked_sources_set_impl(ddf_fun_t *fun,
453 const nic_address_t *addr_list, size_t addr_count)
454{
455 nic_t *nic_data = nic_get_from_ddf_fun(fun);
456 fibril_rwlock_write_lock(&nic_data->rxc_lock);
457 if (nic_data->on_blocked_sources_change) {
458 nic_data->on_blocked_sources_change(nic_data, addr_list, addr_count);
459 }
460 int rc = nic_rxc_blocked_sources_set(&nic_data->rx_control,
461 addr_list, addr_count);
462 fibril_rwlock_write_unlock(&nic_data->rxc_lock);
463 return rc;
464}
465
466/**
467 * Default implementation of vlan_get_mask method.
468 *
469 * @param fun
470 * @param[out] mask Current VLAN mask
471 *
472 * @return EOK
473 * @return ENOENT If the mask is not set
474 */
475int nic_vlan_get_mask_impl(ddf_fun_t *fun, nic_vlan_mask_t *mask)
476{
477 nic_t *nic_data = nic_get_from_ddf_fun(fun);
478 fibril_rwlock_read_lock(&nic_data->rxc_lock);
479 int rc = nic_rxc_vlan_get_mask(&nic_data->rx_control, mask);
480 fibril_rwlock_read_unlock(&nic_data->rxc_lock);
481 return rc;
482}
483
484/**
485 * Default implementation of vlan_set_mask method.
486 *
487 * @param fun
488 * @param[in] mask The new VLAN mask
489 *
490 * @return EOK
491 * @return ENOMEM
492 */
493int nic_vlan_set_mask_impl(ddf_fun_t *fun, const nic_vlan_mask_t *mask)
494{
495 nic_t *nic_data = nic_get_from_ddf_fun(fun);
496 fibril_rwlock_write_lock(&nic_data->rxc_lock);
497 int rc = nic_rxc_vlan_set_mask(&nic_data->rx_control, mask);
498 if (rc == EOK && nic_data->on_vlan_mask_change) {
499 nic_data->on_vlan_mask_change(nic_data, mask);
500 }
501 fibril_rwlock_write_unlock(&nic_data->rxc_lock);
502 return rc;
503}
504
505/**
506 * Default implementation of the wol_virtue_add method.
507 * Create a new WOL virtue.
508 *
509 * @param[in] fun
510 * @param[in] type Type of the virtue
511 * @param[in] data Data required for this virtue (depends on type)
512 * @param[in] length Length of the data
513 * @param[out] filter Identifier of the new virtue
514 *
515 * @return EOK If the operation was successfully completed
516 * @return EINVAL If virtue type is not supported or the data are invalid
517 * @return ELIMIT If the driver does not allow to create more virtues
518 * @return ENOMEM If there was not enough memory to complete the operation
519 */
520int nic_wol_virtue_add_impl(ddf_fun_t *fun, nic_wv_type_t type,
521 const void *data, size_t length, nic_wv_id_t *new_id)
522{
523 nic_t *nic_data = nic_get_from_ddf_fun(fun);
524 if (nic_data->on_wol_virtue_add == NULL
525 || nic_data->on_wol_virtue_remove == NULL) {
526 return ENOTSUP;
527 }
528 if (type == NIC_WV_NONE || type >= NIC_WV_MAX) {
529 return EINVAL;
530 }
531 if (nic_wol_virtues_verify(type, data, length) != EOK) {
532 return EINVAL;
533 }
534 nic_wol_virtue_t *virtue = malloc(sizeof (nic_wol_virtue_t));
535 if (virtue == NULL) {
536 return ENOMEM;
537 }
538 memset(virtue, 0, sizeof(nic_wol_virtue_t));
539 if (length != 0) {
540 virtue->data = malloc(length);
541 if (virtue->data == NULL) {
542 free(virtue);
543 return ENOMEM;
544 }
545 memcpy((void *) virtue->data, data, length);
546 }
547 virtue->type = type;
548 virtue->length = length;
549
550 fibril_rwlock_write_lock(&nic_data->wv_lock);
551 /* Check if we haven't reached the maximum */
552 if (nic_data->wol_virtues.caps_max[type] < 0) {
553 fibril_rwlock_write_unlock(&nic_data->wv_lock);
554 return EINVAL;
555 }
556 if ((int) nic_data->wol_virtues.lists_sizes[type] >=
557 nic_data->wol_virtues.caps_max[type]) {
558 fibril_rwlock_write_unlock(&nic_data->wv_lock);
559 return ELIMIT;
560 }
561 /* Call the user-defined add callback */
562 int rc = nic_data->on_wol_virtue_add(nic_data, virtue);
563 if (rc != EOK) {
564 free(virtue->data);
565 free(virtue);
566 fibril_rwlock_write_unlock(&nic_data->wv_lock);
567 return rc;
568 }
569 rc = nic_wol_virtues_add(&nic_data->wol_virtues, virtue);
570 if (rc != EOK) {
571 /* If the adding fails, call user-defined remove callback */
572 nic_data->on_wol_virtue_remove(nic_data, virtue);
573 fibril_rwlock_write_unlock(&nic_data->wv_lock);
574 free(virtue->data);
575 free(virtue);
576 return rc;
577 } else {
578 *new_id = virtue->id;
579 fibril_rwlock_write_unlock(&nic_data->wv_lock);
580 }
581 return EOK;
582}
583
584/**
585 * Default implementation of the wol_virtue_remove method.
586 * Destroys the WOL virtue.
587 *
588 * @param[in] fun
589 * @param[in] id WOL virtue identification
590 *
591 * @return EOK If the operation was successfully completed
592 * @return ENOTSUP If the function is not supported by the driver or device
593 * @return ENOENT If the virtue identifier is not valid.
594 */
595int nic_wol_virtue_remove_impl(ddf_fun_t *fun, nic_wv_id_t id)
596{
597 nic_t *nic_data = nic_get_from_ddf_fun(fun);
598 if (nic_data->on_wol_virtue_add == NULL
599 || nic_data->on_wol_virtue_remove == NULL) {
600 return ENOTSUP;
601 }
602 fibril_rwlock_write_lock(&nic_data->wv_lock);
603 nic_wol_virtue_t *virtue =
604 nic_wol_virtues_remove(&nic_data->wol_virtues, id);
605 if (virtue == NULL) {
606 fibril_rwlock_write_unlock(&nic_data->wv_lock);
607 return ENOENT;
608 }
609 /* The event handler is called after the filter was removed */
610 nic_data->on_wol_virtue_remove(nic_data, virtue);
611 fibril_rwlock_write_unlock(&nic_data->wv_lock);
612 free(virtue->data);
613 free(virtue);
614 return EOK;
615}
616
617/**
618 * Default implementation of the wol_virtue_probe method.
619 * Queries the type and data of the virtue.
620 *
621 * @param[in] fun
622 * @param[in] id Virtue identifier
623 * @param[out] type Type of the virtue. Can be NULL.
624 * @param[out] data Data used when the virtue was created. Can be NULL.
625 * @param[out] length Length of the data. Can be NULL.
626 *
627 * @return EOK If the operation was successfully completed
628 * @return ENOENT If the virtue identifier is not valid.
629 * @return ENOMEM If there was not enough memory to complete the operation
630 */
631int nic_wol_virtue_probe_impl(ddf_fun_t *fun, nic_wv_id_t id,
632 nic_wv_type_t *type, size_t max_length, void *data, size_t *length)
633{
634 nic_t *nic_data = nic_get_from_ddf_fun(fun);
635 fibril_rwlock_read_lock(&nic_data->wv_lock);
636 const nic_wol_virtue_t *virtue =
637 nic_wol_virtues_find(&nic_data->wol_virtues, id);
638 if (virtue == NULL) {
639 *type = NIC_WV_NONE;
640 *length = 0;
641 fibril_rwlock_read_unlock(&nic_data->wv_lock);
642 return ENOENT;
643 } else {
644 *type = virtue->type;
645 if (max_length > virtue->length) {
646 max_length = virtue->length;
647 }
648 memcpy(data, virtue->data, max_length);
649 *length = virtue->length;
650 fibril_rwlock_read_unlock(&nic_data->wv_lock);
651 return EOK;
652 }
653}
654
655/**
656 * Default implementation of the wol_virtue_list method.
657 * List filters of the specified type. If NIC_WV_NONE is the type, it lists all
658 * filters.
659 *
660 * @param[in] fun
661 * @param[in] type Type of the virtues
662 * @param[out] virtues Vector of virtue ID's.
663 * @param[out] count Length of the data. Can be NULL.
664 *
665 * @return EOK If the operation was successfully completed
666 * @return ENOENT If the filter identification is not valid.
667 * @return ENOMEM If there was not enough memory to complete the operation
668 */
669int nic_wol_virtue_list_impl(ddf_fun_t *fun, nic_wv_type_t type,
670 size_t max_count, nic_wv_id_t *id_list, size_t *id_count)
671{
672 nic_t *nic_data = nic_get_from_ddf_fun(fun);
673 fibril_rwlock_read_lock(&nic_data->wv_lock);
674 int rc = nic_wol_virtues_list(&nic_data->wol_virtues, type,
675 max_count, id_list, id_count);
676 fibril_rwlock_read_unlock(&nic_data->wv_lock);
677 return rc;
678}
679
680/**
681 * Default implementation of the wol_virtue_get_caps method.
682 * Queries for the current capabilities for some type of filter.
683 *
684 * @param[in] fun
685 * @param[in] type Type of the virtues
686 * @param[out] count Number of virtues of this type that can be currently set
687 *
688 * @return EOK If the operation was successfully completed
689 */
690int nic_wol_virtue_get_caps_impl(ddf_fun_t *fun, nic_wv_type_t type, int *count)
691{
692 nic_t *nic_data = nic_get_from_ddf_fun(fun);
693 fibril_rwlock_read_lock(&nic_data->wv_lock);
694 *count = nic_data->wol_virtues.caps_max[type]
695 - (int) nic_data->wol_virtues.lists_sizes[type];
696 fibril_rwlock_read_unlock(&nic_data->wv_lock);
697 return EOK;
698}
699
700/**
701 * Default implementation of the poll_get_mode method.
702 * Queries the current interrupt/poll mode of the NIC
703 *
704 * @param[in] fun
705 * @param[out] mode Current poll mode
706 * @param[out] period Period used in periodic polling. Can be NULL.
707 *
708 * @return EOK If the operation was successfully completed
709 * @return ENOTSUP This function is not supported.
710 * @return EPARTY Error in communication protocol
711 */
712int nic_poll_get_mode_impl(ddf_fun_t *fun,
713 nic_poll_mode_t *mode, struct timeval *period)
714{
715 nic_t *nic_data = nic_get_from_ddf_fun(fun);
716 fibril_rwlock_read_lock(&nic_data->main_lock);
717 *mode = nic_data->poll_mode;
718 memcpy(period, &nic_data->poll_period, sizeof (struct timeval));
719 fibril_rwlock_read_unlock(&nic_data->main_lock);
720 return EOK;
721}
722
723/**
724 * Default implementation of the poll_set_mode_impl method.
725 * Sets the interrupt/poll mode of the NIC.
726 *
727 * @param[in] fun
728 * @param[in] mode The new poll mode
729 * @param[in] period Period used in periodic polling. Can be NULL.
730 *
731 * @return EOK If the operation was successfully completed
732 * @return ENOTSUP This operation is not supported.
733 * @return EPARTY Error in communication protocol
734 */
735int nic_poll_set_mode_impl(ddf_fun_t *fun,
736 nic_poll_mode_t mode, const struct timeval *period)
737{
738 nic_t *nic_data = nic_get_from_ddf_fun(fun);
739 /* If the driver does not implement the poll mode change handler it cannot
740 * switch off interrupts and this is not supported. */
741 if (nic_data->on_poll_mode_change == NULL)
742 return ENOTSUP;
743
744 if ((mode == NIC_POLL_ON_DEMAND) && nic_data->on_poll_request == NULL)
745 return ENOTSUP;
746
747 if (mode == NIC_POLL_PERIODIC || mode == NIC_POLL_SOFTWARE_PERIODIC) {
748 if (period == NULL)
749 return EINVAL;
750 if (period->tv_sec == 0 && period->tv_usec == 0)
751 return EINVAL;
752 if (period->tv_sec < 0 || period->tv_usec < 0)
753 return EINVAL;
754 }
755 fibril_rwlock_write_lock(&nic_data->main_lock);
756 int rc = nic_data->on_poll_mode_change(nic_data, mode, period);
757 assert(rc == EOK || rc == ENOTSUP || rc == EINVAL);
758 if (rc == ENOTSUP && (nic_data->on_poll_request != NULL) &&
759 (mode == NIC_POLL_PERIODIC || mode == NIC_POLL_SOFTWARE_PERIODIC) ) {
760
761 rc = nic_data->on_poll_mode_change(nic_data, NIC_POLL_ON_DEMAND, NULL);
762 assert(rc == EOK || rc == ENOTSUP);
763 if (rc == EOK)
764 nic_sw_period_start(nic_data);
765 }
766 if (rc == EOK) {
767 nic_data->poll_mode = mode;
768 if (period)
769 nic_data->poll_period = *period;
770 }
771 fibril_rwlock_write_unlock(&nic_data->main_lock);
772 return rc;
773}
774
775/**
776 * Default implementation of the poll_now method.
777 * Wrapper for the actual poll implementation.
778 *
779 * @param[in] fun
780 *
781 * @return EOK If the NIC was polled
782 * @return ENOTSUP If the function is not supported
783 * @return EINVAL If the NIC is not in state where it allows on demand polling
784 */
785int nic_poll_now_impl(ddf_fun_t *fun) {
786 nic_t *nic_data = nic_get_from_ddf_fun(fun);
787 fibril_rwlock_read_lock(&nic_data->main_lock);
788 if (nic_data->poll_mode != NIC_POLL_ON_DEMAND) {
789 fibril_rwlock_read_unlock(&nic_data->main_lock);
790 return EINVAL;
791 }
792 if (nic_data->on_poll_request != NULL) {
793 nic_data->on_poll_request(nic_data);
794 fibril_rwlock_read_unlock(&nic_data->main_lock);
795 return EOK;
796 } else {
797 fibril_rwlock_read_unlock(&nic_data->main_lock);
798 return ENOTSUP;
799 }
800}
801
802/**
803 * Default handler for unknown methods (outside of the NIC interface).
804 * Logs a warning message and returns ENOTSUP to the caller.
805 *
806 * @param fun The DDF function where the method should be called.
807 * @param callid IPC call identifier
808 * @param call IPC call data
809 */
810void nic_default_handler_impl(ddf_fun_t *fun, ipc_callid_t callid,
811 ipc_call_t *call)
812{
813 async_answer_0(callid, ENOTSUP);
814}
815
816/**
817 * Default (empty) OPEN function implementation.
818 *
819 * @param fun The DDF function
820 *
821 * @return EOK always.
822 */
823int nic_open_impl(ddf_fun_t *fun)
824{
825 return EOK;
826}
827
828/**
829 * Default (empty) OPEN function implementation.
830 *
831 * @param fun The DDF function
832 */
833void nic_close_impl(ddf_fun_t *fun)
834{
835}
836
837/** @}
838 */
Note: See TracBrowser for help on using the repository browser.