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

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

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 24.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/**
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 */
54errno_t 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 */
74errno_t 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 errno_t 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 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 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 */
170errno_t 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 */
193errno_t 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 */
218errno_t 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 */
237errno_t 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 */
259errno_t 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 */
283errno_t 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 errno_t 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 */
326errno_t 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 */
350errno_t 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 errno_t 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 */
383errno_t 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 */
403errno_t 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 errno_t 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 */
429errno_t 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 */
452errno_t 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 errno_t 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 */
475errno_t 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 errno_t 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 */
493errno_t 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 errno_t 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 */
520errno_t 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 errno_t 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 */
595errno_t 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 */
631errno_t 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 */
669errno_t 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 errno_t 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 */
690errno_t 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 */
712errno_t 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 */
735errno_t 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 errno_t 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 */
785errno_t 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 */
823errno_t 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.