Get rid of sys/time.h
[helenos.git] / uspace / lib / nic / src / nic_impl.c
blobff29f041f6b918194d0c72091c1dde91de239fa7
1 /*
2 * Copyright (c) 2011 Radim Vansa
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
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.
29 /**
30 * @addtogroup libnic
31 * @{
33 /**
34 * @file
35 * @brief Default DDF NIC interface methods implementations
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"
46 /**
47 * Default implementation of the set_state method. Trivial.
49 * @param fun
50 * @param[out] state
52 * @return EOK always.
54 errno_t nic_get_state_impl(ddf_fun_t *fun, nic_device_state_t *state)
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;
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.
68 * @param fun
69 * @param state The new device's state
71 * @return EOK If the state was changed
72 * @return EINVAL If the state cannot be changed
74 errno_t nic_set_state_impl(ddf_fun_t *fun, nic_device_state_t state)
76 if (state >= NIC_STATE_MAX) {
77 return EINVAL;
80 nic_t *nic_data = nic_get_from_ddf_fun(fun);
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;
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;
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;
109 if (event_handler != NULL) {
110 errno_t rc = event_handler(nic_data);
111 if (rc != EOK) {
112 fibril_rwlock_write_unlock(&nic_data->main_lock);
113 return EINVAL;
117 if (state == NIC_STATE_STOPPED) {
118 /* Notify upper layers that we are reseting the MAC */
119 errno_t 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 timespec));
124 if (rc != EOK) {
126 * We have already ran the on stopped handler, even if we
127 * terminated the state change we would end up in undefined state.
128 * Therefore we just log the problem.
132 fibril_rwlock_write_lock(&nic_data->stats_lock);
133 memset(&nic_data->stats, 0, sizeof(nic_device_stats_t));
134 fibril_rwlock_write_unlock(&nic_data->stats_lock);
136 fibril_rwlock_write_lock(&nic_data->rxc_lock);
137 nic_rxc_clear(&nic_data->rx_control);
138 /* Reinsert device's default MAC */
139 nic_rxc_set_addr(&nic_data->rx_control, NULL,
140 &nic_data->default_mac);
141 fibril_rwlock_write_unlock(&nic_data->rxc_lock);
142 memcpy(&nic_data->mac, &nic_data->default_mac, sizeof (nic_address_t));
144 fibril_rwlock_write_lock(&nic_data->wv_lock);
145 nic_wol_virtues_clear(&nic_data->wol_virtues);
146 fibril_rwlock_write_unlock(&nic_data->wv_lock);
148 /* Ensure stopping period of NIC_POLL_SOFTWARE_PERIODIC */
149 nic_sw_period_stop(nic_data);
152 nic_data->state = state;
154 nic_ev_device_state(nic_data->client_session, state);
156 fibril_rwlock_write_unlock(&nic_data->main_lock);
158 return EOK;
162 * Default implementation of the send_frame method.
163 * Send messages to the network.
165 * @param fun
166 * @param data Frame data
167 * @param size Frame size in bytes
169 * @return EOK If the message was sent
170 * @return EBUSY If the device is not in state when the frame can be sent.
172 errno_t nic_send_frame_impl(ddf_fun_t *fun, void *data, size_t size)
174 nic_t *nic_data = nic_get_from_ddf_fun(fun);
176 fibril_rwlock_read_lock(&nic_data->main_lock);
177 if (nic_data->state != NIC_STATE_ACTIVE || nic_data->tx_busy) {
178 fibril_rwlock_read_unlock(&nic_data->main_lock);
179 return EBUSY;
182 nic_data->send_frame(nic_data, data, size);
183 fibril_rwlock_read_unlock(&nic_data->main_lock);
184 return EOK;
188 * Default implementation of the connect_client method.
189 * Creates callback connection to the client.
191 * @param fun
193 * @return EOK On success, or an error code.
195 errno_t nic_callback_create_impl(ddf_fun_t *fun)
197 nic_t *nic = nic_get_from_ddf_fun(fun);
198 fibril_rwlock_write_lock(&nic->main_lock);
200 nic->client_session = async_callback_receive(EXCHANGE_SERIALIZE);
201 if (nic->client_session == NULL) {
202 fibril_rwlock_write_unlock(&nic->main_lock);
203 return ENOMEM;
206 fibril_rwlock_write_unlock(&nic->main_lock);
207 return EOK;
211 * Default implementation of the get_address method.
212 * Retrieves the NIC's physical address.
214 * @param fun
215 * @param address Pointer to the structure where the address will be stored.
217 * @return EOK If the services were bound
218 * @return ELIMIT If the buffer is too short
220 errno_t nic_get_address_impl(ddf_fun_t *fun, nic_address_t *address)
222 assert(address);
223 nic_t *nic_data = nic_get_from_ddf_fun(fun);
224 fibril_rwlock_read_lock(&nic_data->main_lock);
225 memcpy(address, &nic_data->mac, sizeof (nic_address_t));
226 fibril_rwlock_read_unlock(&nic_data->main_lock);
227 return EOK;
231 * Default implementation of the get_stats method. Copies the statistics from
232 * the drivers data to supplied buffer.
234 * @param fun
235 * @param[out] stats The buffer for statistics
237 * @return EOK (cannot fail)
239 errno_t nic_get_stats_impl(ddf_fun_t *fun, nic_device_stats_t *stats)
241 nic_t *nic_data = nic_get_from_ddf_fun(fun);
242 assert (stats != NULL);
243 fibril_rwlock_read_lock(&nic_data->stats_lock);
244 memcpy(stats, &nic_data->stats, sizeof (nic_device_stats_t));
245 fibril_rwlock_read_unlock(&nic_data->stats_lock);
246 return EOK;
250 * Default implementation of unicast_get_mode method.
252 * @param fun
253 * @param[out] mode Current operation mode
254 * @param[in] max_count Max number of addresses that can be written into the
255 * buffer (addr_list).
256 * @param[out] addr_list Buffer for addresses
257 * @param[out] addr_count Number of addresses written into the list
259 * @return EOK
261 errno_t nic_unicast_get_mode_impl(ddf_fun_t *fun, nic_unicast_mode_t *mode,
262 size_t max_count, nic_address_t *addr_list, size_t *addr_count)
264 nic_t *nic_data = nic_get_from_ddf_fun(fun);
265 fibril_rwlock_read_lock(&nic_data->rxc_lock);
266 nic_rxc_unicast_get_mode(&nic_data->rx_control, mode, max_count,
267 addr_list, addr_count);
268 fibril_rwlock_read_unlock(&nic_data->rxc_lock);
269 return EOK;
273 * Default implementation of unicast_set_mode method.
275 * @param fun
276 * @param[in] mode New operation mode
277 * @param[in] addr_list List of unicast addresses
278 * @param[in] addr_count Number of addresses in the list
280 * @return EOK
281 * @return EINVAL
282 * @return ENOTSUP
283 * @return ENOMEM
285 errno_t nic_unicast_set_mode_impl(ddf_fun_t *fun,
286 nic_unicast_mode_t mode, const nic_address_t *addr_list, size_t addr_count)
288 assert((addr_count == 0 && addr_list == NULL) ||
289 (addr_count != 0 && addr_list != NULL));
290 size_t i;
291 for (i = 0; i < addr_count; ++i) {
292 if (addr_list[i].address[0] & 1)
293 return EINVAL;
296 nic_t *nic_data = nic_get_from_ddf_fun(fun);
297 fibril_rwlock_write_lock(&nic_data->rxc_lock);
298 errno_t rc = ENOTSUP;
299 if (nic_data->on_unicast_mode_change) {
300 rc = nic_data->on_unicast_mode_change(nic_data,
301 mode, addr_list, addr_count);
303 if (rc == EOK) {
304 rc = nic_rxc_unicast_set_mode(&nic_data->rx_control, mode,
305 addr_list, addr_count);
307 * After changing the mode the addr db gets cleared, therefore we have
308 * to reinsert also the physical address of NIC.
310 nic_rxc_set_addr(&nic_data->rx_control, NULL, &nic_data->mac);
312 fibril_rwlock_write_unlock(&nic_data->rxc_lock);
313 return rc;
318 * Default implementation of multicast_get_mode method.
320 * @param fun
321 * @param[out] mode Current operation mode
322 * @param[in] max_count Max number of addresses that can be written into the
323 * buffer (addr_list).
324 * @param[out] addr_list Buffer for addresses
325 * @param[out] addr_count Number of addresses written into the list
327 * @return EOK
329 errno_t nic_multicast_get_mode_impl(ddf_fun_t *fun, nic_multicast_mode_t *mode,
330 size_t max_count, nic_address_t *addr_list, size_t *addr_count)
332 nic_t *nic_data = nic_get_from_ddf_fun(fun);
333 fibril_rwlock_read_lock(&nic_data->rxc_lock);
334 nic_rxc_multicast_get_mode(&nic_data->rx_control, mode, max_count,
335 addr_list, addr_count);
336 fibril_rwlock_read_unlock(&nic_data->rxc_lock);
337 return EOK;
341 * Default implementation of multicast_set_mode method.
343 * @param fun
344 * @param[in] mode New operation mode
345 * @param[in] addr_list List of multicast addresses
346 * @param[in] addr_count Number of addresses in the list
348 * @return EOK
349 * @return EINVAL
350 * @return ENOTSUP
351 * @return ENOMEM
353 errno_t nic_multicast_set_mode_impl(ddf_fun_t *fun, nic_multicast_mode_t mode,
354 const nic_address_t *addr_list, size_t addr_count)
356 assert((addr_count == 0 && addr_list == NULL) ||
357 (addr_count != 0 && addr_list != NULL));
358 size_t i;
359 for (i = 0; i < addr_count; ++i) {
360 if (!(addr_list[i].address[0] & 1))
361 return EINVAL;
364 nic_t *nic_data = nic_get_from_ddf_fun(fun);
365 fibril_rwlock_write_lock(&nic_data->rxc_lock);
366 errno_t rc = ENOTSUP;
367 if (nic_data->on_multicast_mode_change) {
368 rc = nic_data->on_multicast_mode_change(nic_data, mode, addr_list, addr_count);
370 if (rc == EOK) {
371 rc = nic_rxc_multicast_set_mode(&nic_data->rx_control, mode,
372 addr_list, addr_count);
374 fibril_rwlock_write_unlock(&nic_data->rxc_lock);
375 return rc;
379 * Default implementation of broadcast_get_mode method.
381 * @param fun
382 * @param[out] mode Current operation mode
384 * @return EOK
386 errno_t nic_broadcast_get_mode_impl(ddf_fun_t *fun, nic_broadcast_mode_t *mode)
388 nic_t *nic_data = nic_get_from_ddf_fun(fun);
389 fibril_rwlock_read_lock(&nic_data->rxc_lock);
390 nic_rxc_broadcast_get_mode(&nic_data->rx_control, mode);
391 fibril_rwlock_read_unlock(&nic_data->rxc_lock);
392 return EOK;
396 * Default implementation of broadcast_set_mode method.
398 * @param fun
399 * @param[in] mode New operation mode
401 * @return EOK
402 * @return EINVAL
403 * @return ENOTSUP
404 * @return ENOMEM
406 errno_t nic_broadcast_set_mode_impl(ddf_fun_t *fun, nic_broadcast_mode_t mode)
408 nic_t *nic_data = nic_get_from_ddf_fun(fun);
409 fibril_rwlock_write_lock(&nic_data->rxc_lock);
410 errno_t rc = ENOTSUP;
411 if (nic_data->on_broadcast_mode_change) {
412 rc = nic_data->on_broadcast_mode_change(nic_data, mode);
414 if (rc == EOK) {
415 rc = nic_rxc_broadcast_set_mode(&nic_data->rx_control, mode);
417 fibril_rwlock_write_unlock(&nic_data->rxc_lock);
418 return rc;
422 * Default implementation of blocked_sources_get method.
424 * @param fun
425 * @param[in] max_count Max number of addresses that can be written into the
426 * buffer (addr_list).
427 * @param[out] addr_list Buffer for addresses
428 * @param[out] addr_count Number of addresses written into the list
430 * @return EOK
432 errno_t nic_blocked_sources_get_impl(ddf_fun_t *fun,
433 size_t max_count, nic_address_t *addr_list, size_t *addr_count)
435 nic_t *nic_data = nic_get_from_ddf_fun(fun);
436 fibril_rwlock_read_lock(&nic_data->rxc_lock);
437 nic_rxc_blocked_sources_get(&nic_data->rx_control,
438 max_count, addr_list, addr_count);
439 fibril_rwlock_read_unlock(&nic_data->rxc_lock);
440 return EOK;
444 * Default implementation of blocked_sources_set method.
446 * @param fun
447 * @param[in] addr_list List of blocked addresses
448 * @param[in] addr_count Number of addresses in the list
450 * @return EOK
451 * @return EINVAL
452 * @return ENOTSUP
453 * @return ENOMEM
455 errno_t nic_blocked_sources_set_impl(ddf_fun_t *fun,
456 const nic_address_t *addr_list, size_t addr_count)
458 nic_t *nic_data = nic_get_from_ddf_fun(fun);
459 fibril_rwlock_write_lock(&nic_data->rxc_lock);
460 if (nic_data->on_blocked_sources_change) {
461 nic_data->on_blocked_sources_change(nic_data, addr_list, addr_count);
463 errno_t rc = nic_rxc_blocked_sources_set(&nic_data->rx_control,
464 addr_list, addr_count);
465 fibril_rwlock_write_unlock(&nic_data->rxc_lock);
466 return rc;
470 * Default implementation of vlan_get_mask method.
472 * @param fun
473 * @param[out] mask Current VLAN mask
475 * @return EOK
476 * @return ENOENT If the mask is not set
478 errno_t nic_vlan_get_mask_impl(ddf_fun_t *fun, nic_vlan_mask_t *mask)
480 nic_t *nic_data = nic_get_from_ddf_fun(fun);
481 fibril_rwlock_read_lock(&nic_data->rxc_lock);
482 errno_t rc = nic_rxc_vlan_get_mask(&nic_data->rx_control, mask);
483 fibril_rwlock_read_unlock(&nic_data->rxc_lock);
484 return rc;
488 * Default implementation of vlan_set_mask method.
490 * @param fun
491 * @param[in] mask The new VLAN mask
493 * @return EOK
494 * @return ENOMEM
496 errno_t nic_vlan_set_mask_impl(ddf_fun_t *fun, const nic_vlan_mask_t *mask)
498 nic_t *nic_data = nic_get_from_ddf_fun(fun);
499 fibril_rwlock_write_lock(&nic_data->rxc_lock);
500 errno_t rc = nic_rxc_vlan_set_mask(&nic_data->rx_control, mask);
501 if (rc == EOK && nic_data->on_vlan_mask_change) {
502 nic_data->on_vlan_mask_change(nic_data, mask);
504 fibril_rwlock_write_unlock(&nic_data->rxc_lock);
505 return rc;
509 * Default implementation of the wol_virtue_add method.
510 * Create a new WOL virtue.
512 * @param[in] fun
513 * @param[in] type Type of the virtue
514 * @param[in] data Data required for this virtue (depends on type)
515 * @param[in] length Length of the data
516 * @param[out] filter Identifier of the new virtue
518 * @return EOK If the operation was successfully completed
519 * @return EINVAL If virtue type is not supported or the data are invalid
520 * @return ELIMIT If the driver does not allow to create more virtues
521 * @return ENOMEM If there was not enough memory to complete the operation
523 errno_t nic_wol_virtue_add_impl(ddf_fun_t *fun, nic_wv_type_t type,
524 const void *data, size_t length, nic_wv_id_t *new_id)
526 nic_t *nic_data = nic_get_from_ddf_fun(fun);
527 if (nic_data->on_wol_virtue_add == NULL ||
528 nic_data->on_wol_virtue_remove == NULL) {
529 return ENOTSUP;
531 if (type == NIC_WV_NONE || type >= NIC_WV_MAX) {
532 return EINVAL;
534 if (nic_wol_virtues_verify(type, data, length) != EOK) {
535 return EINVAL;
537 nic_wol_virtue_t *virtue = malloc(sizeof (nic_wol_virtue_t));
538 if (virtue == NULL) {
539 return ENOMEM;
541 memset(virtue, 0, sizeof(nic_wol_virtue_t));
542 if (length != 0) {
543 virtue->data = malloc(length);
544 if (virtue->data == NULL) {
545 free(virtue);
546 return ENOMEM;
548 memcpy((void *) virtue->data, data, length);
550 virtue->type = type;
551 virtue->length = length;
553 fibril_rwlock_write_lock(&nic_data->wv_lock);
554 /* Check if we haven't reached the maximum */
555 if (nic_data->wol_virtues.caps_max[type] < 0) {
556 fibril_rwlock_write_unlock(&nic_data->wv_lock);
557 return EINVAL;
559 if ((int) nic_data->wol_virtues.lists_sizes[type] >=
560 nic_data->wol_virtues.caps_max[type]) {
561 fibril_rwlock_write_unlock(&nic_data->wv_lock);
562 return ELIMIT;
564 /* Call the user-defined add callback */
565 errno_t rc = nic_data->on_wol_virtue_add(nic_data, virtue);
566 if (rc != EOK) {
567 free(virtue->data);
568 free(virtue);
569 fibril_rwlock_write_unlock(&nic_data->wv_lock);
570 return rc;
572 rc = nic_wol_virtues_add(&nic_data->wol_virtues, virtue);
573 if (rc != EOK) {
574 /* If the adding fails, call user-defined remove callback */
575 nic_data->on_wol_virtue_remove(nic_data, virtue);
576 fibril_rwlock_write_unlock(&nic_data->wv_lock);
577 free(virtue->data);
578 free(virtue);
579 return rc;
580 } else {
581 *new_id = virtue->id;
582 fibril_rwlock_write_unlock(&nic_data->wv_lock);
584 return EOK;
588 * Default implementation of the wol_virtue_remove method.
589 * Destroys the WOL virtue.
591 * @param[in] fun
592 * @param[in] id WOL virtue identification
594 * @return EOK If the operation was successfully completed
595 * @return ENOTSUP If the function is not supported by the driver or device
596 * @return ENOENT If the virtue identifier is not valid.
598 errno_t nic_wol_virtue_remove_impl(ddf_fun_t *fun, nic_wv_id_t id)
600 nic_t *nic_data = nic_get_from_ddf_fun(fun);
601 if (nic_data->on_wol_virtue_add == NULL ||
602 nic_data->on_wol_virtue_remove == NULL) {
603 return ENOTSUP;
605 fibril_rwlock_write_lock(&nic_data->wv_lock);
606 nic_wol_virtue_t *virtue =
607 nic_wol_virtues_remove(&nic_data->wol_virtues, id);
608 if (virtue == NULL) {
609 fibril_rwlock_write_unlock(&nic_data->wv_lock);
610 return ENOENT;
612 /* The event handler is called after the filter was removed */
613 nic_data->on_wol_virtue_remove(nic_data, virtue);
614 fibril_rwlock_write_unlock(&nic_data->wv_lock);
615 free(virtue->data);
616 free(virtue);
617 return EOK;
621 * Default implementation of the wol_virtue_probe method.
622 * Queries the type and data of the virtue.
624 * @param[in] fun
625 * @param[in] id Virtue identifier
626 * @param[out] type Type of the virtue. Can be NULL.
627 * @param[out] data Data used when the virtue was created. Can be NULL.
628 * @param[out] length Length of the data. Can be NULL.
630 * @return EOK If the operation was successfully completed
631 * @return ENOENT If the virtue identifier is not valid.
632 * @return ENOMEM If there was not enough memory to complete the operation
634 errno_t nic_wol_virtue_probe_impl(ddf_fun_t *fun, nic_wv_id_t id,
635 nic_wv_type_t *type, size_t max_length, void *data, size_t *length)
637 nic_t *nic_data = nic_get_from_ddf_fun(fun);
638 fibril_rwlock_read_lock(&nic_data->wv_lock);
639 const nic_wol_virtue_t *virtue =
640 nic_wol_virtues_find(&nic_data->wol_virtues, id);
641 if (virtue == NULL) {
642 *type = NIC_WV_NONE;
643 *length = 0;
644 fibril_rwlock_read_unlock(&nic_data->wv_lock);
645 return ENOENT;
646 } else {
647 *type = virtue->type;
648 if (max_length > virtue->length) {
649 max_length = virtue->length;
651 memcpy(data, virtue->data, max_length);
652 *length = virtue->length;
653 fibril_rwlock_read_unlock(&nic_data->wv_lock);
654 return EOK;
659 * Default implementation of the wol_virtue_list method.
660 * List filters of the specified type. If NIC_WV_NONE is the type, it lists all
661 * filters.
663 * @param[in] fun
664 * @param[in] type Type of the virtues
665 * @param[out] virtues Vector of virtue ID's.
666 * @param[out] count Length of the data. Can be NULL.
668 * @return EOK If the operation was successfully completed
669 * @return ENOENT If the filter identification is not valid.
670 * @return ENOMEM If there was not enough memory to complete the operation
672 errno_t nic_wol_virtue_list_impl(ddf_fun_t *fun, nic_wv_type_t type,
673 size_t max_count, nic_wv_id_t *id_list, size_t *id_count)
675 nic_t *nic_data = nic_get_from_ddf_fun(fun);
676 fibril_rwlock_read_lock(&nic_data->wv_lock);
677 errno_t rc = nic_wol_virtues_list(&nic_data->wol_virtues, type,
678 max_count, id_list, id_count);
679 fibril_rwlock_read_unlock(&nic_data->wv_lock);
680 return rc;
684 * Default implementation of the wol_virtue_get_caps method.
685 * Queries for the current capabilities for some type of filter.
687 * @param[in] fun
688 * @param[in] type Type of the virtues
689 * @param[out] count Number of virtues of this type that can be currently set
691 * @return EOK If the operation was successfully completed
693 errno_t nic_wol_virtue_get_caps_impl(ddf_fun_t *fun, nic_wv_type_t type, int *count)
695 nic_t *nic_data = nic_get_from_ddf_fun(fun);
696 fibril_rwlock_read_lock(&nic_data->wv_lock);
697 *count = nic_data->wol_virtues.caps_max[type] -
698 (int) nic_data->wol_virtues.lists_sizes[type];
699 fibril_rwlock_read_unlock(&nic_data->wv_lock);
700 return EOK;
704 * Default implementation of the poll_get_mode method.
705 * Queries the current interrupt/poll mode of the NIC
707 * @param[in] fun
708 * @param[out] mode Current poll mode
709 * @param[out] period Period used in periodic polling. Can be NULL.
711 * @return EOK If the operation was successfully completed
712 * @return ENOTSUP This function is not supported.
713 * @return EPARTY Error in communication protocol
715 errno_t nic_poll_get_mode_impl(ddf_fun_t *fun,
716 nic_poll_mode_t *mode, struct timespec *period)
718 nic_t *nic_data = nic_get_from_ddf_fun(fun);
719 fibril_rwlock_read_lock(&nic_data->main_lock);
720 *mode = nic_data->poll_mode;
721 memcpy(period, &nic_data->poll_period, sizeof(struct timespec));
722 fibril_rwlock_read_unlock(&nic_data->main_lock);
723 return EOK;
727 * Default implementation of the poll_set_mode_impl method.
728 * Sets the interrupt/poll mode of the NIC.
730 * @param[in] fun
731 * @param[in] mode The new poll mode
732 * @param[in] period Period used in periodic polling. Can be NULL.
734 * @return EOK If the operation was successfully completed
735 * @return ENOTSUP This operation is not supported.
736 * @return EPARTY Error in communication protocol
738 errno_t nic_poll_set_mode_impl(ddf_fun_t *fun,
739 nic_poll_mode_t mode, const struct timespec *period)
741 nic_t *nic_data = nic_get_from_ddf_fun(fun);
743 * If the driver does not implement the poll mode change handler it cannot
744 * switch off interrupts and this is not supported.
746 if (nic_data->on_poll_mode_change == NULL)
747 return ENOTSUP;
749 if ((mode == NIC_POLL_ON_DEMAND) && nic_data->on_poll_request == NULL)
750 return ENOTSUP;
752 if (mode == NIC_POLL_PERIODIC || mode == NIC_POLL_SOFTWARE_PERIODIC) {
753 if (period == NULL)
754 return EINVAL;
755 if (period->tv_sec == 0 && period->tv_nsec == 0)
756 return EINVAL;
757 if (period->tv_sec < 0 || period->tv_nsec < 0)
758 return EINVAL;
760 fibril_rwlock_write_lock(&nic_data->main_lock);
761 errno_t rc = nic_data->on_poll_mode_change(nic_data, mode, period);
762 assert(rc == EOK || rc == ENOTSUP || rc == EINVAL);
763 if (rc == ENOTSUP && (nic_data->on_poll_request != NULL) &&
764 (mode == NIC_POLL_PERIODIC || mode == NIC_POLL_SOFTWARE_PERIODIC)) {
766 rc = nic_data->on_poll_mode_change(nic_data, NIC_POLL_ON_DEMAND, NULL);
767 assert(rc == EOK || rc == ENOTSUP);
768 if (rc == EOK)
769 nic_sw_period_start(nic_data);
771 if (rc == EOK) {
772 nic_data->poll_mode = mode;
773 if (period)
774 nic_data->poll_period = *period;
776 fibril_rwlock_write_unlock(&nic_data->main_lock);
777 return rc;
781 * Default implementation of the poll_now method.
782 * Wrapper for the actual poll implementation.
784 * @param[in] fun
786 * @return EOK If the NIC was polled
787 * @return ENOTSUP If the function is not supported
788 * @return EINVAL If the NIC is not in state where it allows on demand polling
790 errno_t nic_poll_now_impl(ddf_fun_t *fun)
792 nic_t *nic_data = nic_get_from_ddf_fun(fun);
793 fibril_rwlock_read_lock(&nic_data->main_lock);
794 if (nic_data->poll_mode != NIC_POLL_ON_DEMAND) {
795 fibril_rwlock_read_unlock(&nic_data->main_lock);
796 return EINVAL;
798 if (nic_data->on_poll_request != NULL) {
799 nic_data->on_poll_request(nic_data);
800 fibril_rwlock_read_unlock(&nic_data->main_lock);
801 return EOK;
802 } else {
803 fibril_rwlock_read_unlock(&nic_data->main_lock);
804 return ENOTSUP;
809 * Default handler for unknown methods (outside of the NIC interface).
810 * Logs a warning message and returns ENOTSUP to the caller.
812 * @param fun The DDF function where the method should be called.
813 * @param call IPC call data
816 void nic_default_handler_impl(ddf_fun_t *fun, ipc_call_t *call)
818 async_answer_0(call, ENOTSUP);
822 * Default (empty) OPEN function implementation.
824 * @param fun The DDF function
826 * @return EOK always.
828 errno_t nic_open_impl(ddf_fun_t *fun)
830 return EOK;
834 * Default (empty) OPEN function implementation.
836 * @param fun The DDF function
838 void nic_close_impl(ddf_fun_t *fun)
842 /** @}