source: mainline/uspace/lib/drv/generic/remote_nic.c@ 7fc260ff

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

cherrypick general networking improvements from lp:~helenos-nicf/helenos/nicf (after sanitization)
remove obsolete networking drivers
this renders the networking non-functional for the time being

  • Property mode set to 100644
File size: 31.9 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 libdrv
30 * @{
31 */
32/**
33 * @file
34 * @brief Driver-side RPC skeletons for DDF NIC interface
35 */
36
37#include <assert.h>
38#include <async.h>
39#include <errno.h>
40#include <ipc/services.h>
41#include <adt/measured_strings.h>
42#include <sys/time.h>
43#include "ops/nic.h"
44
45static void remote_nic_send_message(ddf_fun_t *dev, void *iface,
46 ipc_callid_t callid, ipc_call_t *call)
47{
48 nic_iface_t *nic_iface = (nic_iface_t *) iface;
49 assert(nic_iface->send_message);
50
51 packet_id_t packet_id = (packet_id_t) IPC_GET_ARG2(*call);
52
53 int rc = nic_iface->send_message(dev, packet_id);
54 async_answer_0(callid, rc);
55}
56
57static void remote_nic_connect_to_nil(ddf_fun_t *dev, void *iface,
58 ipc_callid_t callid, ipc_call_t *call)
59{
60 nic_iface_t *nic_iface = (nic_iface_t *) iface;
61 assert(nic_iface->connect_to_nil);
62
63 services_t nil_service = (services_t) IPC_GET_ARG2(*call);
64 nic_device_id_t device_id = (nic_device_id_t) IPC_GET_ARG3(*call);
65
66 int rc = nic_iface->connect_to_nil(dev, nil_service, device_id);
67 async_answer_0(callid, rc);
68}
69
70static void remote_nic_get_state(ddf_fun_t *dev, void *iface,
71 ipc_callid_t callid, ipc_call_t *call)
72{
73 nic_iface_t *nic_iface = (nic_iface_t *) iface;
74 assert(nic_iface->get_state);
75
76 nic_device_state_t state = NIC_STATE_MAX;
77
78 int rc = nic_iface->get_state(dev, &state);
79 async_answer_1(callid, rc, state);
80}
81
82static void remote_nic_set_state(ddf_fun_t *dev, void *iface,
83 ipc_callid_t callid, ipc_call_t *call)
84{
85 nic_iface_t *nic_iface = (nic_iface_t *) iface;
86 assert(nic_iface->set_state);
87
88 nic_device_state_t state = (nic_device_state_t) IPC_GET_ARG2(*call);
89
90 int rc = nic_iface->set_state(dev, state);
91 async_answer_0(callid, rc);
92}
93
94static void remote_nic_get_address(ddf_fun_t *dev, void *iface,
95 ipc_callid_t callid, ipc_call_t *call)
96{
97 nic_iface_t *nic_iface = (nic_iface_t *) iface;
98 assert(nic_iface->get_address);
99
100 nic_address_t address;
101 bzero(&address, sizeof(nic_address_t));
102
103 int rc = nic_iface->get_address(dev, &address);
104 if (rc == EOK) {
105 size_t max_len;
106 ipc_callid_t data_callid;
107
108 /* All errors will be translated into EPARTY anyway */
109 if (!async_data_read_receive(&data_callid, &max_len)) {
110 async_answer_0(data_callid, EINVAL);
111 async_answer_0(callid, EINVAL);
112 return;
113 }
114
115 if (max_len != sizeof(nic_address_t)) {
116 async_answer_0(data_callid, ELIMIT);
117 async_answer_0(callid, ELIMIT);
118 return;
119 }
120
121 async_data_read_finalize(data_callid, &address,
122 sizeof(nic_address_t));
123 }
124
125 async_answer_0(callid, rc);
126}
127
128static void remote_nic_set_address(ddf_fun_t *dev, void *iface,
129 ipc_callid_t callid, ipc_call_t *call)
130{
131 nic_iface_t *nic_iface = (nic_iface_t *) iface;
132
133 size_t length;
134 ipc_callid_t data_callid;
135 if (!async_data_write_receive(&data_callid, &length)) {
136 async_answer_0(data_callid, EINVAL);
137 async_answer_0(callid, EINVAL);
138 return;
139 }
140
141 if (length > sizeof(nic_address_t)) {
142 async_answer_0(data_callid, ELIMIT);
143 async_answer_0(callid, ELIMIT);
144 return;
145 }
146
147 nic_address_t address;
148 if (async_data_write_finalize(data_callid, &address, length) != EOK) {
149 async_answer_0(callid, EINVAL);
150 return;
151 }
152
153 if (nic_iface->set_address != NULL) {
154 int rc = nic_iface->set_address(dev, &address);
155 async_answer_0(callid, rc);
156 } else
157 async_answer_0(callid, ENOTSUP);
158}
159
160static void remote_nic_get_stats(ddf_fun_t *dev, void *iface,
161 ipc_callid_t callid, ipc_call_t *call)
162{
163 nic_iface_t *nic_iface = (nic_iface_t *) iface;
164 if (nic_iface->get_stats == NULL) {
165 async_answer_0(callid, ENOTSUP);
166 return;
167 }
168
169 nic_device_stats_t stats;
170 bzero(&stats, sizeof(nic_device_stats_t));
171
172 int rc = nic_iface->get_stats(dev, &stats);
173 if (rc == EOK) {
174 ipc_callid_t data_callid;
175 size_t max_len;
176 if (!async_data_read_receive(&data_callid, &max_len)) {
177 async_answer_0(data_callid, EINVAL);
178 async_answer_0(callid, EINVAL);
179 return;
180 }
181
182 if (max_len < sizeof(nic_device_stats_t)) {
183 async_answer_0(data_callid, ELIMIT);
184 async_answer_0(callid, ELIMIT);
185 return;
186 }
187
188 async_data_read_finalize(data_callid, &stats,
189 sizeof(nic_device_stats_t));
190 }
191
192 async_answer_0(callid, rc);
193}
194
195static void remote_nic_get_device_info(ddf_fun_t *dev, void *iface,
196 ipc_callid_t callid, ipc_call_t *call)
197{
198 nic_iface_t *nic_iface = (nic_iface_t *) iface;
199 if (nic_iface->get_device_info == NULL) {
200 async_answer_0(callid, ENOTSUP);
201 return;
202 }
203
204 nic_device_info_t info;
205 bzero(&info, sizeof(nic_device_info_t));
206
207 int rc = nic_iface->get_device_info(dev, &info);
208 if (rc == EOK) {
209 ipc_callid_t data_callid;
210 size_t max_len;
211 if (!async_data_read_receive(&data_callid, &max_len)) {
212 async_answer_0(data_callid, EINVAL);
213 async_answer_0(callid, EINVAL);
214 return;
215 }
216
217 if (max_len < sizeof (nic_device_info_t)) {
218 async_answer_0(data_callid, ELIMIT);
219 async_answer_0(callid, ELIMIT);
220 return;
221 }
222
223 async_data_read_finalize(data_callid, &info,
224 sizeof(nic_device_info_t));
225 }
226
227 async_answer_0(callid, rc);
228}
229
230static void remote_nic_get_cable_state(ddf_fun_t *dev, void *iface,
231 ipc_callid_t callid, ipc_call_t *call)
232{
233 nic_iface_t *nic_iface = (nic_iface_t *) iface;
234 if (nic_iface->get_cable_state == NULL) {
235 async_answer_0(callid, ENOTSUP);
236 return;
237 }
238
239 nic_cable_state_t cs = NIC_CS_UNKNOWN;
240
241 int rc = nic_iface->get_cable_state(dev, &cs);
242 async_answer_1(callid, rc, (sysarg_t) cs);
243}
244
245static void remote_nic_get_operation_mode(ddf_fun_t *dev, void *iface,
246 ipc_callid_t callid, ipc_call_t *call)
247{
248 nic_iface_t *nic_iface = (nic_iface_t *) iface;
249 if (nic_iface->get_operation_mode == NULL) {
250 async_answer_0(callid, ENOTSUP);
251 return;
252 }
253
254 int speed = 0;
255 nic_channel_mode_t duplex = NIC_CM_UNKNOWN;
256 nic_role_t role = NIC_ROLE_UNKNOWN;
257
258 int rc = nic_iface->get_operation_mode(dev, &speed, &duplex, &role);
259 async_answer_3(callid, rc, (sysarg_t) speed, (sysarg_t) duplex,
260 (sysarg_t) role);
261}
262
263static void remote_nic_set_operation_mode(ddf_fun_t *dev, void *iface,
264 ipc_callid_t callid, ipc_call_t *call)
265{
266 nic_iface_t *nic_iface = (nic_iface_t *) iface;
267 if (nic_iface->set_operation_mode == NULL) {
268 async_answer_0(callid, ENOTSUP);
269 return;
270 }
271
272 int speed = (int) IPC_GET_ARG2(*call);
273 nic_channel_mode_t duplex = (nic_channel_mode_t) IPC_GET_ARG3(*call);
274 nic_role_t role = (nic_role_t) IPC_GET_ARG4(*call);
275
276 int rc = nic_iface->set_operation_mode(dev, speed, duplex, role);
277 async_answer_0(callid, rc);
278}
279
280static void remote_nic_autoneg_enable(ddf_fun_t *dev, void *iface,
281 ipc_callid_t callid, ipc_call_t *call)
282{
283 nic_iface_t *nic_iface = (nic_iface_t *) iface;
284 if (nic_iface->autoneg_enable == NULL) {
285 async_answer_0(callid, ENOTSUP);
286 return;
287 }
288
289 uint32_t advertisement = (uint32_t) IPC_GET_ARG2(*call);
290
291 int rc = nic_iface->autoneg_enable(dev, advertisement);
292 async_answer_0(callid, rc);
293}
294
295static void remote_nic_autoneg_disable(ddf_fun_t *dev, void *iface,
296 ipc_callid_t callid, ipc_call_t *call)
297{
298 nic_iface_t *nic_iface = (nic_iface_t *) iface;
299 if (nic_iface->autoneg_disable == NULL) {
300 async_answer_0(callid, ENOTSUP);
301 return;
302 }
303
304 int rc = nic_iface->autoneg_disable(dev);
305 async_answer_0(callid, rc);
306}
307
308static void remote_nic_autoneg_probe(ddf_fun_t *dev, void *iface,
309 ipc_callid_t callid, ipc_call_t *call)
310{
311 nic_iface_t *nic_iface = (nic_iface_t *) iface;
312 if (nic_iface->autoneg_probe == NULL) {
313 async_answer_0(callid, ENOTSUP);
314 return;
315 }
316
317 uint32_t our_adv = 0;
318 uint32_t their_adv = 0;
319 nic_result_t result = NIC_RESULT_NOT_AVAILABLE;
320 nic_result_t their_result = NIC_RESULT_NOT_AVAILABLE;
321
322 int rc = nic_iface->autoneg_probe(dev, &our_adv, &their_adv, &result,
323 &their_result);
324 async_answer_4(callid, rc, our_adv, their_adv, (sysarg_t) result,
325 (sysarg_t) their_result);
326}
327
328static void remote_nic_autoneg_restart(ddf_fun_t *dev, void *iface,
329 ipc_callid_t callid, ipc_call_t *call)
330{
331 nic_iface_t *nic_iface = (nic_iface_t *) iface;
332 if (nic_iface->autoneg_restart == NULL) {
333 async_answer_0(callid, ENOTSUP);
334 return;
335 }
336
337 int rc = nic_iface->autoneg_restart(dev);
338 async_answer_0(callid, rc);
339}
340
341static void remote_nic_get_pause(ddf_fun_t *dev, void *iface,
342 ipc_callid_t callid, ipc_call_t *call)
343{
344 nic_iface_t *nic_iface = (nic_iface_t *) iface;
345 if (nic_iface->get_pause == NULL) {
346 async_answer_0(callid, ENOTSUP);
347 return;
348 }
349
350 nic_result_t we_send;
351 nic_result_t we_receive;
352 uint16_t pause;
353
354 int rc = nic_iface->get_pause(dev, &we_send, &we_receive, &pause);
355 async_answer_3(callid, rc, we_send, we_receive, pause);
356}
357
358static void remote_nic_set_pause(ddf_fun_t *dev, void *iface,
359 ipc_callid_t callid, ipc_call_t *call)
360{
361 nic_iface_t *nic_iface = (nic_iface_t *) iface;
362 if (nic_iface->set_pause == NULL) {
363 async_answer_0(callid, ENOTSUP);
364 return;
365 }
366
367 int allow_send = (int) IPC_GET_ARG2(*call);
368 int allow_receive = (int) IPC_GET_ARG3(*call);
369 uint16_t pause = (uint16_t) IPC_GET_ARG4(*call);
370
371 int rc = nic_iface->set_pause(dev, allow_send, allow_receive,
372 pause);
373 async_answer_0(callid, rc);
374}
375
376static void remote_nic_unicast_get_mode(ddf_fun_t *dev, void *iface,
377 ipc_callid_t callid, ipc_call_t *call)
378{
379 nic_iface_t *nic_iface = (nic_iface_t *) iface;
380 if (nic_iface->unicast_get_mode == NULL) {
381 async_answer_0(callid, ENOTSUP);
382 return;
383 }
384
385 size_t max_count = IPC_GET_ARG2(*call);
386 nic_address_t *address_list = NULL;
387
388 if (max_count != 0) {
389 address_list = malloc(max_count * sizeof (nic_address_t));
390 if (!address_list) {
391 async_answer_0(callid, ENOMEM);
392 return;
393 }
394 }
395
396 bzero(address_list, max_count * sizeof(nic_address_t));
397 nic_unicast_mode_t mode = NIC_UNICAST_DEFAULT;
398 size_t address_count = 0;
399
400 int rc = nic_iface->unicast_get_mode(dev, &mode, max_count, address_list,
401 &address_count);
402
403 if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
404 free(address_list);
405 async_answer_2(callid, rc, mode, address_count);
406 return;
407 }
408
409 ipc_callid_t data_callid;
410 size_t max_len;
411 if (!async_data_read_receive(&data_callid, &max_len)) {
412 async_answer_0(data_callid, EINVAL);
413 async_answer_2(callid, rc, mode, address_count);
414 free(address_list);
415 return;
416 }
417
418 if (max_len > address_count * sizeof(nic_address_t))
419 max_len = address_count * sizeof(nic_address_t);
420
421 if (max_len > max_count * sizeof(nic_address_t))
422 max_len = max_count * sizeof(nic_address_t);
423
424 async_data_read_finalize(data_callid, address_list, max_len);
425 async_answer_0(data_callid, EINVAL);
426
427 free(address_list);
428 async_answer_2(callid, rc, mode, address_count);
429}
430
431static void remote_nic_unicast_set_mode(ddf_fun_t *dev, void *iface,
432 ipc_callid_t callid, ipc_call_t *call)
433{
434 nic_iface_t *nic_iface = (nic_iface_t *) iface;
435
436 size_t length;
437 nic_unicast_mode_t mode = IPC_GET_ARG2(*call);
438 size_t address_count = IPC_GET_ARG3(*call);
439 nic_address_t *address_list = NULL;
440
441 if (address_count) {
442 ipc_callid_t data_callid;
443 if (!async_data_write_receive(&data_callid, &length)) {
444 async_answer_0(data_callid, EINVAL);
445 async_answer_0(callid, EINVAL);
446 return;
447 }
448
449 if (length != address_count * sizeof(nic_address_t)) {
450 async_answer_0(data_callid, ELIMIT);
451 async_answer_0(callid, ELIMIT);
452 return;
453 }
454
455 address_list = malloc(length);
456 if (address_list == NULL) {
457 async_answer_0(data_callid, ENOMEM);
458 async_answer_0(callid, ENOMEM);
459 return;
460 }
461
462 if (async_data_write_finalize(data_callid, address_list,
463 length) != EOK) {
464 async_answer_0(callid, EINVAL);
465 free(address_list);
466 return;
467 }
468 }
469
470 if (nic_iface->unicast_set_mode != NULL) {
471 int rc = nic_iface->unicast_set_mode(dev, mode, address_list,
472 address_count);
473 async_answer_0(callid, rc);
474 } else
475 async_answer_0(callid, ENOTSUP);
476
477 free(address_list);
478}
479
480static void remote_nic_multicast_get_mode(ddf_fun_t *dev, void *iface,
481 ipc_callid_t callid, ipc_call_t *call)
482{
483 nic_iface_t *nic_iface = (nic_iface_t *) iface;
484 if (nic_iface->multicast_get_mode == NULL) {
485 async_answer_0(callid, ENOTSUP);
486 return;
487 }
488
489 size_t max_count = IPC_GET_ARG2(*call);
490 nic_address_t *address_list = NULL;
491
492 if (max_count != 0) {
493 address_list = malloc(max_count * sizeof(nic_address_t));
494 if (!address_list) {
495 async_answer_0(callid, ENOMEM);
496 return;
497 }
498 }
499
500 bzero(address_list, max_count * sizeof(nic_address_t));
501 nic_multicast_mode_t mode = NIC_MULTICAST_BLOCKED;
502 size_t address_count = 0;
503
504 int rc = nic_iface->multicast_get_mode(dev, &mode, max_count, address_list,
505 &address_count);
506
507
508 if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
509 free(address_list);
510 async_answer_2(callid, rc, mode, address_count);
511 return;
512 }
513
514 ipc_callid_t data_callid;
515 size_t max_len;
516 if (!async_data_read_receive(&data_callid, &max_len)) {
517 async_answer_0(data_callid, EINVAL);
518 async_answer_2(callid, rc, mode, address_count);
519 free(address_list);
520 return;
521 }
522
523 if (max_len > address_count * sizeof(nic_address_t))
524 max_len = address_count * sizeof(nic_address_t);
525
526 if (max_len > max_count * sizeof(nic_address_t))
527 max_len = max_count * sizeof(nic_address_t);
528
529 async_data_read_finalize(data_callid, address_list, max_len);
530
531 free(address_list);
532 async_answer_2(callid, rc, mode, address_count);
533}
534
535static void remote_nic_multicast_set_mode(ddf_fun_t *dev, void *iface,
536 ipc_callid_t callid, ipc_call_t *call)
537{
538 nic_iface_t *nic_iface = (nic_iface_t *) iface;
539
540 nic_multicast_mode_t mode = IPC_GET_ARG2(*call);
541 size_t address_count = IPC_GET_ARG3(*call);
542 nic_address_t *address_list = NULL;
543
544 if (address_count) {
545 ipc_callid_t data_callid;
546 size_t length;
547 if (!async_data_write_receive(&data_callid, &length)) {
548 async_answer_0(data_callid, EINVAL);
549 async_answer_0(callid, EINVAL);
550 return;
551 }
552
553 if (length != address_count * sizeof (nic_address_t)) {
554 async_answer_0(data_callid, ELIMIT);
555 async_answer_0(callid, ELIMIT);
556 return;
557 }
558
559 address_list = malloc(length);
560 if (address_list == NULL) {
561 async_answer_0(data_callid, ENOMEM);
562 async_answer_0(callid, ENOMEM);
563 return;
564 }
565
566 if (async_data_write_finalize(data_callid, address_list,
567 length) != EOK) {
568 async_answer_0(callid, EINVAL);
569 free(address_list);
570 return;
571 }
572 }
573
574 if (nic_iface->multicast_set_mode != NULL) {
575 int rc = nic_iface->multicast_set_mode(dev, mode, address_list,
576 address_count);
577 async_answer_0(callid, rc);
578 } else
579 async_answer_0(callid, ENOTSUP);
580
581 free(address_list);
582}
583
584static void remote_nic_broadcast_get_mode(ddf_fun_t *dev, void *iface,
585 ipc_callid_t callid, ipc_call_t *call)
586{
587 nic_iface_t *nic_iface = (nic_iface_t *) iface;
588 if (nic_iface->broadcast_get_mode == NULL) {
589 async_answer_0(callid, ENOTSUP);
590 return;
591 }
592
593 nic_broadcast_mode_t mode = NIC_BROADCAST_ACCEPTED;
594
595 int rc = nic_iface->broadcast_get_mode(dev, &mode);
596 async_answer_1(callid, rc, mode);
597}
598
599static void remote_nic_broadcast_set_mode(ddf_fun_t *dev, void *iface,
600 ipc_callid_t callid, ipc_call_t *call)
601{
602 nic_iface_t *nic_iface = (nic_iface_t *) iface;
603 if (nic_iface->broadcast_set_mode == NULL) {
604 async_answer_0(callid, ENOTSUP);
605 return;
606 }
607
608 nic_broadcast_mode_t mode = IPC_GET_ARG2(*call);
609
610 int rc = nic_iface->broadcast_set_mode(dev, mode);
611 async_answer_0(callid, rc);
612}
613
614static void remote_nic_defective_get_mode(ddf_fun_t *dev, void *iface,
615 ipc_callid_t callid, ipc_call_t *call)
616{
617 nic_iface_t *nic_iface = (nic_iface_t *) iface;
618 if (nic_iface->defective_get_mode == NULL) {
619 async_answer_0(callid, ENOTSUP);
620 return;
621 }
622
623 uint32_t mode = 0;
624
625 int rc = nic_iface->defective_get_mode(dev, &mode);
626 async_answer_1(callid, rc, mode);
627}
628
629static void remote_nic_defective_set_mode(ddf_fun_t *dev, void *iface,
630 ipc_callid_t callid, ipc_call_t *call)
631{
632 nic_iface_t *nic_iface = (nic_iface_t *) iface;
633 if (nic_iface->defective_set_mode == NULL) {
634 async_answer_0(callid, ENOTSUP);
635 return;
636 }
637
638 uint32_t mode = IPC_GET_ARG2(*call);
639
640 int rc = nic_iface->defective_set_mode(dev, mode);
641 async_answer_0(callid, rc);
642}
643
644static void remote_nic_blocked_sources_get(ddf_fun_t *dev, void *iface,
645 ipc_callid_t callid, ipc_call_t *call)
646{
647 nic_iface_t *nic_iface = (nic_iface_t *) iface;
648 if (nic_iface->blocked_sources_get == NULL) {
649 async_answer_0(callid, ENOTSUP);
650 return;
651 }
652
653 size_t max_count = IPC_GET_ARG2(*call);
654 nic_address_t *address_list = NULL;
655
656 if (max_count != 0) {
657 address_list = malloc(max_count * sizeof(nic_address_t));
658 if (!address_list) {
659 async_answer_0(callid, ENOMEM);
660 return;
661 }
662 }
663
664 bzero(address_list, max_count * sizeof(nic_address_t));
665 size_t address_count = 0;
666
667 int rc = nic_iface->blocked_sources_get(dev, max_count, address_list,
668 &address_count);
669
670 if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
671 async_answer_1(callid, rc, address_count);
672 free(address_list);
673 return;
674 }
675
676 ipc_callid_t data_callid;
677 size_t max_len;
678 if (!async_data_read_receive(&data_callid, &max_len)) {
679 async_answer_0(data_callid, EINVAL);
680 async_answer_1(callid, rc, address_count);
681 free(address_list);
682 return;
683 }
684
685 if (max_len > address_count * sizeof(nic_address_t))
686 max_len = address_count * sizeof(nic_address_t);
687
688 if (max_len > max_count * sizeof(nic_address_t))
689 max_len = max_count * sizeof(nic_address_t);
690
691 async_data_read_finalize(data_callid, address_list, max_len);
692 async_answer_0(data_callid, EINVAL);
693
694 free(address_list);
695 async_answer_1(callid, rc, address_count);
696}
697
698static void remote_nic_blocked_sources_set(ddf_fun_t *dev, void *iface,
699 ipc_callid_t callid, ipc_call_t *call)
700{
701 nic_iface_t *nic_iface = (nic_iface_t *) iface;
702
703 size_t length;
704 size_t address_count = IPC_GET_ARG2(*call);
705 nic_address_t *address_list = NULL;
706
707 if (address_count) {
708 ipc_callid_t data_callid;
709 if (!async_data_write_receive(&data_callid, &length)) {
710 async_answer_0(data_callid, EINVAL);
711 async_answer_0(callid, EINVAL);
712 return;
713 }
714
715 if (length != address_count * sizeof(nic_address_t)) {
716 async_answer_0(data_callid, ELIMIT);
717 async_answer_0(callid, ELIMIT);
718 return;
719 }
720
721 address_list = malloc(length);
722 if (address_list == NULL) {
723 async_answer_0(data_callid, ENOMEM);
724 async_answer_0(callid, ENOMEM);
725 return;
726 }
727
728 if (async_data_write_finalize(data_callid, address_list,
729 length) != EOK) {
730 async_answer_0(callid, EINVAL);
731 free(address_list);
732 return;
733 }
734 }
735
736 if (nic_iface->blocked_sources_set != NULL) {
737 int rc = nic_iface->blocked_sources_set(dev, address_list,
738 address_count);
739 async_answer_0(callid, rc);
740 } else
741 async_answer_0(callid, ENOTSUP);
742
743 free(address_list);
744}
745
746static void remote_nic_vlan_get_mask(ddf_fun_t *dev, void *iface,
747 ipc_callid_t callid, ipc_call_t *call)
748{
749 nic_iface_t *nic_iface = (nic_iface_t *) iface;
750 if (nic_iface->vlan_get_mask == NULL) {
751 async_answer_0(callid, ENOTSUP);
752 return;
753 }
754
755 nic_vlan_mask_t vlan_mask;
756 bzero(&vlan_mask, sizeof(nic_vlan_mask_t));
757
758 int rc = nic_iface->vlan_get_mask(dev, &vlan_mask);
759 if (rc == EOK) {
760 ipc_callid_t data_callid;
761 size_t max_len;
762 if (!async_data_read_receive(&data_callid, &max_len)) {
763 async_answer_0(data_callid, EINVAL);
764 async_answer_0(callid, EINVAL);
765 return;
766 }
767
768 if (max_len != sizeof(nic_vlan_mask_t)) {
769 async_answer_0(data_callid, EINVAL);
770 async_answer_0(callid, EINVAL);
771 return;
772 }
773
774 async_data_read_finalize(data_callid, &vlan_mask, max_len);
775 }
776
777 async_answer_0(callid, rc);
778}
779
780static void remote_nic_vlan_set_mask(ddf_fun_t *dev, void *iface,
781 ipc_callid_t callid, ipc_call_t *call)
782{
783 nic_iface_t *nic_iface = (nic_iface_t *) iface;
784
785 nic_vlan_mask_t vlan_mask;
786 nic_vlan_mask_t *vlan_mask_pointer = NULL;
787 bool vlan_mask_set = (bool) IPC_GET_ARG2(*call);
788
789 if (vlan_mask_set) {
790 ipc_callid_t data_callid;
791 size_t length;
792 if (!async_data_write_receive(&data_callid, &length)) {
793 async_answer_0(data_callid, EINVAL);
794 async_answer_0(callid, EINVAL);
795 return;
796 }
797
798 if (length != sizeof(nic_vlan_mask_t)) {
799 async_answer_0(data_callid, ELIMIT);
800 async_answer_0(callid, ELIMIT);
801 return;
802 }
803
804 if (async_data_write_finalize(data_callid, &vlan_mask,
805 length) != EOK) {
806 async_answer_0(callid, EINVAL);
807 return;
808 }
809
810 vlan_mask_pointer = &vlan_mask;
811 }
812
813 if (nic_iface->vlan_set_mask != NULL) {
814 int rc = nic_iface->vlan_set_mask(dev, vlan_mask_pointer);
815 async_answer_0(callid, rc);
816 } else
817 async_answer_0(callid, ENOTSUP);
818}
819
820static void remote_nic_vlan_set_tag(ddf_fun_t *dev, void *iface,
821 ipc_callid_t callid, ipc_call_t *call)
822{
823 nic_iface_t *nic_iface = (nic_iface_t *) iface;
824
825 if (nic_iface->vlan_set_tag == NULL) {
826 async_answer_0(callid, ENOTSUP);
827 return;
828 }
829
830 uint16_t tag = (uint16_t) IPC_GET_ARG2(*call);
831 int add = (int) IPC_GET_ARG3(*call);
832 int strip = (int) IPC_GET_ARG4(*call);
833
834 int rc = nic_iface->vlan_set_tag(dev, tag, add, strip);
835 async_answer_0(callid, rc);
836}
837
838static void remote_nic_wol_virtue_add(ddf_fun_t *dev, void *iface,
839 ipc_callid_t callid, ipc_call_t *call)
840{
841 nic_iface_t *nic_iface = (nic_iface_t *) iface;
842
843 int send_data = (int) IPC_GET_ARG3(*call);
844 ipc_callid_t data_callid;
845
846 if (nic_iface->wol_virtue_add == NULL) {
847 if (send_data) {
848 async_data_write_receive(&data_callid, NULL);
849 async_answer_0(data_callid, ENOTSUP);
850 }
851
852 async_answer_0(callid, ENOTSUP);
853 }
854
855 size_t length = 0;
856 void *data = NULL;
857
858 if (send_data) {
859 if (!async_data_write_receive(&data_callid, &length)) {
860 async_answer_0(data_callid, EINVAL);
861 async_answer_0(callid, EINVAL);
862 return;
863 }
864
865 data = malloc(length);
866 if (data == NULL) {
867 async_answer_0(data_callid, ENOMEM);
868 async_answer_0(callid, ENOMEM);
869 return;
870 }
871
872 if (async_data_write_finalize(data_callid, data,
873 length) != EOK) {
874 async_answer_0(callid, EINVAL);
875 free(data);
876 return;
877 }
878 }
879
880 nic_wv_id_t id = 0;
881 nic_wv_type_t type = (nic_wv_type_t) IPC_GET_ARG2(*call);
882
883 int rc = nic_iface->wol_virtue_add(dev, type, data, length, &id);
884 async_answer_1(callid, rc, (sysarg_t) id);
885 free(data);
886}
887
888static void remote_nic_wol_virtue_remove(ddf_fun_t *dev, void *iface,
889 ipc_callid_t callid, ipc_call_t *call)
890{
891 nic_iface_t *nic_iface = (nic_iface_t *) iface;
892
893 if (nic_iface->wol_virtue_remove == NULL) {
894 async_answer_0(callid, ENOTSUP);
895 return;
896 }
897
898 nic_wv_id_t id = (nic_wv_id_t) IPC_GET_ARG2(*call);
899
900 int rc = nic_iface->wol_virtue_remove(dev, id);
901 async_answer_0(callid, rc);
902}
903
904static void remote_nic_wol_virtue_probe(ddf_fun_t *dev, void *iface,
905 ipc_callid_t callid, ipc_call_t *call)
906{
907 nic_iface_t *nic_iface = (nic_iface_t *) iface;
908
909 if (nic_iface->wol_virtue_probe == NULL) {
910 async_answer_0(callid, ENOTSUP);
911 return;
912 }
913
914 nic_wv_id_t id = (nic_wv_id_t) IPC_GET_ARG2(*call);
915 size_t max_length = IPC_GET_ARG3(*call);
916 nic_wv_type_t type = NIC_WV_NONE;
917 size_t length = 0;
918 ipc_callid_t data_callid;
919 void *data = NULL;
920
921 if (max_length != 0) {
922 data = malloc(max_length);
923 if (data == NULL) {
924 async_answer_0(callid, ENOMEM);
925 return;
926 }
927 }
928
929 bzero(data, max_length);
930
931 int rc = nic_iface->wol_virtue_probe(dev, id, &type, max_length,
932 data, &length);
933
934 if ((max_length != 0) && (length != 0)) {
935 size_t req_length;
936 if (!async_data_read_receive(&data_callid, &req_length)) {
937 async_answer_0(data_callid, EINVAL);
938 async_answer_0(callid, EINVAL);
939 free(data);
940 return;
941 }
942
943 if (req_length > length)
944 req_length = length;
945
946 if (req_length > max_length)
947 req_length = max_length;
948
949 async_data_read_finalize(data_callid, data, req_length);
950 }
951
952 async_answer_2(callid, rc, (sysarg_t) type, (sysarg_t) length);
953 free(data);
954}
955
956static void remote_nic_wol_virtue_list(ddf_fun_t *dev, void *iface,
957 ipc_callid_t callid, ipc_call_t *call)
958{
959 nic_iface_t *nic_iface = (nic_iface_t *) iface;
960 if (nic_iface->wol_virtue_list == NULL) {
961 async_answer_0(callid, ENOTSUP);
962 return;
963 }
964
965 nic_wv_type_t type = (nic_wv_type_t) IPC_GET_ARG2(*call);
966 size_t max_count = IPC_GET_ARG3(*call);
967 size_t count = 0;
968 nic_wv_id_t *id_list = NULL;
969 ipc_callid_t data_callid;
970
971 if (max_count != 0) {
972 id_list = malloc(max_count * sizeof(nic_wv_id_t));
973 if (id_list == NULL) {
974 async_answer_0(callid, ENOMEM);
975 return;
976 }
977 }
978
979 bzero(id_list, max_count * sizeof (nic_wv_id_t));
980
981 int rc = nic_iface->wol_virtue_list(dev, type, max_count, id_list,
982 &count);
983
984 if ((max_count != 0) && (count != 0)) {
985 size_t req_length;
986 if (!async_data_read_receive(&data_callid, &req_length)) {
987 async_answer_0(data_callid, EINVAL);
988 async_answer_0(callid, EINVAL);
989 free(id_list);
990 return;
991 }
992
993 if (req_length > count * sizeof(nic_wv_id_t))
994 req_length = count * sizeof(nic_wv_id_t);
995
996 if (req_length > max_count * sizeof(nic_wv_id_t))
997 req_length = max_count * sizeof(nic_wv_id_t);
998
999 rc = async_data_read_finalize(data_callid, id_list, req_length);
1000 }
1001
1002 async_answer_1(callid, rc, (sysarg_t) count);
1003 free(id_list);
1004}
1005
1006static void remote_nic_wol_virtue_get_caps(ddf_fun_t *dev, void *iface,
1007 ipc_callid_t callid, ipc_call_t *call)
1008{
1009 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1010 if (nic_iface->wol_virtue_get_caps == NULL) {
1011 async_answer_0(callid, ENOTSUP);
1012 return;
1013 }
1014
1015 int count = -1;
1016 nic_wv_type_t type = (nic_wv_type_t) IPC_GET_ARG2(*call);
1017
1018 int rc = nic_iface->wol_virtue_get_caps(dev, type, &count);
1019 async_answer_1(callid, rc, (sysarg_t) count);
1020}
1021
1022static void remote_nic_wol_load_info(ddf_fun_t *dev, void *iface,
1023 ipc_callid_t callid, ipc_call_t *call)
1024{
1025 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1026 if (nic_iface->wol_load_info == NULL) {
1027 async_answer_0(callid, ENOTSUP);
1028 return;
1029 }
1030
1031 size_t max_length = (size_t) IPC_GET_ARG2(*call);
1032 size_t frame_length = 0;
1033 nic_wv_type_t type = NIC_WV_NONE;
1034 uint8_t *data = NULL;
1035
1036 if (max_length != 0) {
1037 data = malloc(max_length);
1038 if (data == NULL) {
1039 async_answer_0(callid, ENOMEM);
1040 return;
1041 }
1042 }
1043
1044 bzero(data, max_length);
1045
1046 int rc = nic_iface->wol_load_info(dev, &type, max_length, data,
1047 &frame_length);
1048 if (rc == EOK) {
1049 ipc_callid_t data_callid;
1050 size_t req_length;
1051 if (!async_data_read_receive(&data_callid, &req_length)) {
1052 async_answer_0(data_callid, EINVAL);
1053 async_answer_0(callid, EINVAL);
1054 free(data);
1055 return;
1056 }
1057
1058 req_length = req_length > max_length ? max_length : req_length;
1059 req_length = req_length > frame_length ? frame_length : req_length;
1060 async_data_read_finalize(data_callid, data, req_length);
1061 }
1062
1063 async_answer_2(callid, rc, (sysarg_t) type, (sysarg_t) frame_length);
1064 free(data);
1065}
1066
1067static void remote_nic_offload_probe(ddf_fun_t *dev, void *iface,
1068 ipc_callid_t callid, ipc_call_t *call)
1069{
1070 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1071 if (nic_iface->offload_probe == NULL) {
1072 async_answer_0(callid, ENOTSUP);
1073 return;
1074 }
1075
1076 uint32_t supported = 0;
1077 uint32_t active = 0;
1078
1079 int rc = nic_iface->offload_probe(dev, &supported, &active);
1080 async_answer_2(callid, rc, supported, active);
1081}
1082
1083static void remote_nic_offload_set(ddf_fun_t *dev, void *iface,
1084 ipc_callid_t callid, ipc_call_t *call)
1085{
1086 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1087 if (nic_iface->offload_set == NULL) {
1088 async_answer_0(callid, ENOTSUP);
1089 return;
1090 }
1091
1092 uint32_t mask = (uint32_t) IPC_GET_ARG2(*call);
1093 uint32_t active = (uint32_t) IPC_GET_ARG3(*call);
1094
1095 int rc = nic_iface->offload_set(dev, mask, active);
1096 async_answer_0(callid, rc);
1097}
1098
1099static void remote_nic_poll_get_mode(ddf_fun_t *dev, void *iface,
1100 ipc_callid_t callid, ipc_call_t *call)
1101{
1102 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1103 if (nic_iface->poll_get_mode == NULL) {
1104 async_answer_0(callid, ENOTSUP);
1105 return;
1106 }
1107
1108 nic_poll_mode_t mode = NIC_POLL_IMMEDIATE;
1109 int request_data = IPC_GET_ARG2(*call);
1110 struct timeval period = {
1111 .tv_sec = 0,
1112 .tv_usec = 0
1113 };
1114
1115 int rc = nic_iface->poll_get_mode(dev, &mode, &period);
1116 if ((rc == EOK) && (request_data)) {
1117 size_t max_len;
1118 ipc_callid_t data_callid;
1119
1120 if (!async_data_read_receive(&data_callid, &max_len)) {
1121 async_answer_0(data_callid, EINVAL);
1122 async_answer_0(callid, EINVAL);
1123 return;
1124 }
1125
1126 if (max_len != sizeof(struct timeval)) {
1127 async_answer_0(data_callid, ELIMIT);
1128 async_answer_0(callid, ELIMIT);
1129 return;
1130 }
1131
1132 async_data_read_finalize(data_callid, &period,
1133 sizeof(struct timeval));
1134 }
1135
1136 async_answer_1(callid, rc, (sysarg_t) mode);
1137}
1138
1139static void remote_nic_poll_set_mode(ddf_fun_t *dev, void *iface,
1140 ipc_callid_t callid, ipc_call_t *call)
1141{
1142 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1143
1144 nic_poll_mode_t mode = IPC_GET_ARG2(*call);
1145 int has_period = IPC_GET_ARG3(*call);
1146 struct timeval period_buf;
1147 struct timeval *period = NULL;
1148 size_t length;
1149
1150 if (has_period) {
1151 ipc_callid_t data_callid;
1152 if (!async_data_write_receive(&data_callid, &length)) {
1153 async_answer_0(data_callid, EINVAL);
1154 async_answer_0(callid, EINVAL);
1155 return;
1156 }
1157
1158 if (length != sizeof(struct timeval)) {
1159 async_answer_0(data_callid, ELIMIT);
1160 async_answer_0(callid, ELIMIT);
1161 return;
1162 }
1163
1164 period = &period_buf;
1165 if (async_data_write_finalize(data_callid, period,
1166 length) != EOK) {
1167 async_answer_0(callid, EINVAL);
1168 return;
1169 }
1170 }
1171
1172 if (nic_iface->poll_set_mode != NULL) {
1173 int rc = nic_iface->poll_set_mode(dev, mode, period);
1174 async_answer_0(callid, rc);
1175 } else
1176 async_answer_0(callid, ENOTSUP);
1177}
1178
1179static void remote_nic_poll_now(ddf_fun_t *dev, void *iface,
1180 ipc_callid_t callid, ipc_call_t *call)
1181{
1182 nic_iface_t *nic_iface = (nic_iface_t *) iface;
1183 if (nic_iface->poll_now == NULL) {
1184 async_answer_0(callid, ENOTSUP);
1185 return;
1186 }
1187
1188 int rc = nic_iface->poll_now(dev);
1189 async_answer_0(callid, rc);
1190}
1191
1192/** Remote NIC interface operations.
1193 *
1194 */
1195static remote_iface_func_ptr_t remote_nic_iface_ops[] = {
1196 &remote_nic_send_message,
1197 &remote_nic_connect_to_nil,
1198 &remote_nic_get_state,
1199 &remote_nic_set_state,
1200 &remote_nic_get_address,
1201 &remote_nic_set_address,
1202 &remote_nic_get_stats,
1203 &remote_nic_get_device_info,
1204 &remote_nic_get_cable_state,
1205 &remote_nic_get_operation_mode,
1206 &remote_nic_set_operation_mode,
1207 &remote_nic_autoneg_enable,
1208 &remote_nic_autoneg_disable,
1209 &remote_nic_autoneg_probe,
1210 &remote_nic_autoneg_restart,
1211 &remote_nic_get_pause,
1212 &remote_nic_set_pause,
1213 &remote_nic_unicast_get_mode,
1214 &remote_nic_unicast_set_mode,
1215 &remote_nic_multicast_get_mode,
1216 &remote_nic_multicast_set_mode,
1217 &remote_nic_broadcast_get_mode,
1218 &remote_nic_broadcast_set_mode,
1219 &remote_nic_defective_get_mode,
1220 &remote_nic_defective_set_mode,
1221 &remote_nic_blocked_sources_get,
1222 &remote_nic_blocked_sources_set,
1223 &remote_nic_vlan_get_mask,
1224 &remote_nic_vlan_set_mask,
1225 &remote_nic_vlan_set_tag,
1226 &remote_nic_wol_virtue_add,
1227 &remote_nic_wol_virtue_remove,
1228 &remote_nic_wol_virtue_probe,
1229 &remote_nic_wol_virtue_list,
1230 &remote_nic_wol_virtue_get_caps,
1231 &remote_nic_wol_load_info,
1232 &remote_nic_offload_probe,
1233 &remote_nic_offload_set,
1234 &remote_nic_poll_get_mode,
1235 &remote_nic_poll_set_mode,
1236 &remote_nic_poll_now
1237};
1238
1239/** Remote NIC interface structure.
1240 *
1241 * Interface for processing request from remote
1242 * clients addressed to the NIC interface.
1243 *
1244 */
1245remote_iface_t remote_nic_iface = {
1246 .method_count = sizeof(remote_nic_iface_ops) /
1247 sizeof(remote_iface_func_ptr_t),
1248 .methods = remote_nic_iface_ops
1249};
1250
1251/**
1252 * @}
1253 */
Note: See TracBrowser for help on using the repository browser.