source: mainline/uspace/lib/drv/generic/remote_nic.c@ 26c03dbd

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 26c03dbd was 7f80313, checked in by Jan Vesely <jano.vesely@…>, 12 years ago

libdrv: Make interface structures constant.

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