source: mainline/uspace/srv/devman/client_conn.c@ ca48672

Last change on this file since ca48672 was 8300c72, checked in by Jiri Svoboda <jiri@…>, 4 months ago

Quiesce devices before proceeding with shutdown.

Only implemented for e1k, uhci and xhci.

  • Property mode set to 100644
File size: 19.2 KB
Line 
1/*
2 * Copyright (c) 2025 Jiri Svoboda
3 * Copyright (c) 2010 Lenka Trochtova
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/**
31 * @addtogroup devman
32 * @{
33 */
34
35/** @file
36 */
37
38#include <inttypes.h>
39#include <assert.h>
40#include <ns.h>
41#include <async.h>
42#include <stdio.h>
43#include <errno.h>
44#include <str_error.h>
45#include <stdbool.h>
46#include <fibril_synch.h>
47#include <stdlib.h>
48#include <str.h>
49#include <ctype.h>
50#include <ipc/devman.h>
51
52#include "client_conn.h"
53#include "dev.h"
54#include "devman.h"
55#include "driver.h"
56#include "fun.h"
57#include "loc.h"
58#include "main.h"
59
60/** Find handle for the device instance identified by the device's path in the
61 * device tree.
62 */
63static void devman_function_get_handle(ipc_call_t *icall)
64{
65 char *pathname;
66 devman_handle_t handle;
67
68 errno_t rc = async_data_write_accept((void **) &pathname, true, 0, 0, 0, 0);
69 if (rc != EOK) {
70 async_answer_0(icall, rc);
71 return;
72 }
73
74 fun_node_t *fun = find_fun_node_by_path(&device_tree, pathname);
75
76 free(pathname);
77
78 if (fun == NULL) {
79 async_answer_0(icall, ENOENT);
80 return;
81 }
82
83 fibril_rwlock_read_lock(&device_tree.rwlock);
84
85 /* Check function state */
86 if (fun->state == FUN_REMOVED) {
87 fibril_rwlock_read_unlock(&device_tree.rwlock);
88 async_answer_0(icall, ENOENT);
89 return;
90 }
91 handle = fun->handle;
92
93 fibril_rwlock_read_unlock(&device_tree.rwlock);
94
95 /* Delete reference created above by find_fun_node_by_path() */
96 fun_del_ref(fun);
97
98 async_answer_1(icall, EOK, handle);
99}
100
101/** Get device match ID. */
102static void devman_fun_get_match_id(ipc_call_t *icall)
103{
104 devman_handle_t handle = ipc_get_arg1(icall);
105 size_t index = ipc_get_arg2(icall);
106 void *buffer = NULL;
107
108 fun_node_t *fun = find_fun_node(&device_tree, handle);
109 if (fun == NULL) {
110 async_answer_0(icall, ENOMEM);
111 return;
112 }
113
114 ipc_call_t data;
115 size_t data_len;
116 if (!async_data_read_receive(&data, &data_len)) {
117 async_answer_0(icall, EINVAL);
118 fun_del_ref(fun);
119 return;
120 }
121
122 buffer = malloc(data_len);
123 if (buffer == NULL) {
124 async_answer_0(&data, ENOMEM);
125 async_answer_0(icall, ENOMEM);
126 fun_del_ref(fun);
127 return;
128 }
129
130 fibril_rwlock_read_lock(&device_tree.rwlock);
131
132 /* Check function state */
133 if (fun->state == FUN_REMOVED)
134 goto error;
135
136 link_t *link = list_nth(&fun->match_ids.ids, index);
137 if (link == NULL)
138 goto error;
139
140 match_id_t *mid = list_get_instance(link, match_id_t, link);
141
142 size_t sent_length = str_size(mid->id);
143 if (sent_length > data_len) {
144 sent_length = data_len;
145 }
146
147 async_data_read_finalize(&data, mid->id, sent_length);
148 async_answer_1(icall, EOK, mid->score);
149
150 fibril_rwlock_read_unlock(&device_tree.rwlock);
151 fun_del_ref(fun);
152 free(buffer);
153
154 return;
155error:
156 fibril_rwlock_read_unlock(&device_tree.rwlock);
157 free(buffer);
158
159 async_answer_0(&data, ENOENT);
160 async_answer_0(icall, ENOENT);
161 fun_del_ref(fun);
162}
163
164/** Get device name. */
165static void devman_fun_get_name(ipc_call_t *icall)
166{
167 devman_handle_t handle = ipc_get_arg1(icall);
168
169 fun_node_t *fun = find_fun_node(&device_tree, handle);
170 if (fun == NULL) {
171 async_answer_0(icall, ENOMEM);
172 return;
173 }
174
175 ipc_call_t data;
176 size_t data_len;
177 if (!async_data_read_receive(&data, &data_len)) {
178 async_answer_0(icall, EINVAL);
179 fun_del_ref(fun);
180 return;
181 }
182
183 void *buffer = malloc(data_len);
184 if (buffer == NULL) {
185 async_answer_0(&data, ENOMEM);
186 async_answer_0(icall, ENOMEM);
187 fun_del_ref(fun);
188 return;
189 }
190
191 fibril_rwlock_read_lock(&device_tree.rwlock);
192
193 /* Check function state */
194 if (fun->state == FUN_REMOVED) {
195 fibril_rwlock_read_unlock(&device_tree.rwlock);
196 free(buffer);
197
198 async_answer_0(&data, ENOENT);
199 async_answer_0(icall, ENOENT);
200 fun_del_ref(fun);
201 return;
202 }
203
204 size_t sent_length = str_size(fun->name);
205 if (sent_length > data_len) {
206 sent_length = data_len;
207 }
208
209 async_data_read_finalize(&data, fun->name, sent_length);
210 async_answer_0(icall, EOK);
211
212 fibril_rwlock_read_unlock(&device_tree.rwlock);
213 fun_del_ref(fun);
214 free(buffer);
215}
216
217/** Get function driver name. */
218static void devman_fun_get_driver_name(ipc_call_t *icall)
219{
220 devman_handle_t handle = ipc_get_arg1(icall);
221
222 fun_node_t *fun = find_fun_node(&device_tree, handle);
223 if (fun == NULL) {
224 async_answer_0(icall, ENOMEM);
225 return;
226 }
227
228 ipc_call_t data;
229 size_t data_len;
230 if (!async_data_read_receive(&data, &data_len)) {
231 async_answer_0(icall, EINVAL);
232 fun_del_ref(fun);
233 return;
234 }
235
236 void *buffer = malloc(data_len);
237 if (buffer == NULL) {
238 async_answer_0(&data, ENOMEM);
239 async_answer_0(icall, ENOMEM);
240 fun_del_ref(fun);
241 return;
242 }
243
244 fibril_rwlock_read_lock(&device_tree.rwlock);
245
246 /* Check function state */
247 if (fun->state == FUN_REMOVED) {
248 fibril_rwlock_read_unlock(&device_tree.rwlock);
249 free(buffer);
250
251 async_answer_0(&data, ENOENT);
252 async_answer_0(icall, ENOENT);
253 fun_del_ref(fun);
254 return;
255 }
256
257 /* Check whether function has a driver */
258 if (fun->child == NULL || fun->child->drv == NULL) {
259 fibril_rwlock_read_unlock(&device_tree.rwlock);
260 free(buffer);
261
262 async_answer_0(&data, EINVAL);
263 async_answer_0(icall, EINVAL);
264 fun_del_ref(fun);
265 return;
266 }
267
268 size_t sent_length = str_size(fun->child->drv->name);
269 if (sent_length > data_len) {
270 sent_length = data_len;
271 }
272
273 async_data_read_finalize(&data, fun->child->drv->name,
274 sent_length);
275 async_answer_0(icall, EOK);
276
277 fibril_rwlock_read_unlock(&device_tree.rwlock);
278 fun_del_ref(fun);
279 free(buffer);
280}
281
282/** Get device path. */
283static void devman_fun_get_path(ipc_call_t *icall)
284{
285 devman_handle_t handle = ipc_get_arg1(icall);
286
287 fun_node_t *fun = find_fun_node(&device_tree, handle);
288 if (fun == NULL) {
289 async_answer_0(icall, ENOMEM);
290 return;
291 }
292
293 ipc_call_t data;
294 size_t data_len;
295 if (!async_data_read_receive(&data, &data_len)) {
296 async_answer_0(icall, EINVAL);
297 fun_del_ref(fun);
298 return;
299 }
300
301 void *buffer = malloc(data_len);
302 if (buffer == NULL) {
303 async_answer_0(&data, ENOMEM);
304 async_answer_0(icall, ENOMEM);
305 fun_del_ref(fun);
306 return;
307 }
308
309 fibril_rwlock_read_lock(&device_tree.rwlock);
310
311 /* Check function state */
312 if (fun->state == FUN_REMOVED) {
313 fibril_rwlock_read_unlock(&device_tree.rwlock);
314 free(buffer);
315
316 async_answer_0(&data, ENOENT);
317 async_answer_0(icall, ENOENT);
318 fun_del_ref(fun);
319 return;
320 }
321
322 size_t sent_length = str_size(fun->pathname);
323 if (sent_length > data_len) {
324 sent_length = data_len;
325 }
326
327 async_data_read_finalize(&data, fun->pathname, sent_length);
328 async_answer_0(icall, EOK);
329
330 fibril_rwlock_read_unlock(&device_tree.rwlock);
331 fun_del_ref(fun);
332 free(buffer);
333}
334
335/** Get handle for parent function of a device. */
336static void devman_dev_get_parent(ipc_call_t *icall)
337{
338 dev_node_t *dev;
339
340 fibril_rwlock_read_lock(&device_tree.rwlock);
341
342 dev = find_dev_node_no_lock(&device_tree, ipc_get_arg1(icall));
343 if (dev == NULL || dev->state == DEVICE_REMOVED) {
344 fibril_rwlock_read_unlock(&device_tree.rwlock);
345 async_answer_0(icall, ENOENT);
346 return;
347 }
348
349 if (dev->pfun == NULL) {
350 fibril_rwlock_read_unlock(&device_tree.rwlock);
351 async_answer_0(icall, ENOENT);
352 return;
353 }
354
355 async_answer_1(icall, EOK, dev->pfun->handle);
356
357 fibril_rwlock_read_unlock(&device_tree.rwlock);
358}
359
360static void devman_dev_get_functions(ipc_call_t *icall)
361{
362 ipc_call_t call;
363 size_t size;
364 size_t act_size;
365 errno_t rc;
366
367 if (!async_data_read_receive(&call, &size)) {
368 async_answer_0(&call, EREFUSED);
369 async_answer_0(icall, EREFUSED);
370 return;
371 }
372
373 fibril_rwlock_read_lock(&device_tree.rwlock);
374
375 dev_node_t *dev = find_dev_node_no_lock(&device_tree,
376 ipc_get_arg1(icall));
377 if (dev == NULL || dev->state == DEVICE_REMOVED) {
378 fibril_rwlock_read_unlock(&device_tree.rwlock);
379 async_answer_0(&call, ENOENT);
380 async_answer_0(icall, ENOENT);
381 return;
382 }
383
384 devman_handle_t *hdl_buf = (devman_handle_t *) malloc(size);
385 if (hdl_buf == NULL) {
386 fibril_rwlock_read_unlock(&device_tree.rwlock);
387 async_answer_0(&call, ENOMEM);
388 async_answer_0(icall, ENOMEM);
389 return;
390 }
391
392 rc = dev_get_functions(&device_tree, dev, hdl_buf, size, &act_size);
393 if (rc != EOK) {
394 fibril_rwlock_read_unlock(&device_tree.rwlock);
395 async_answer_0(&call, rc);
396 async_answer_0(icall, rc);
397 return;
398 }
399
400 fibril_rwlock_read_unlock(&device_tree.rwlock);
401
402 errno_t retval = async_data_read_finalize(&call, hdl_buf, size);
403 free(hdl_buf);
404
405 async_answer_1(icall, retval, act_size);
406}
407
408/** Get handle for child device of a function. */
409static void devman_fun_get_child(ipc_call_t *icall)
410{
411 fun_node_t *fun;
412
413 fibril_rwlock_read_lock(&device_tree.rwlock);
414
415 fun = find_fun_node_no_lock(&device_tree, ipc_get_arg1(icall));
416 if (fun == NULL || fun->state == FUN_REMOVED) {
417 fibril_rwlock_read_unlock(&device_tree.rwlock);
418 async_answer_0(icall, ENOENT);
419 return;
420 }
421
422 if (fun->child == NULL) {
423 fibril_rwlock_read_unlock(&device_tree.rwlock);
424 async_answer_0(icall, ENOENT);
425 return;
426 }
427
428 async_answer_1(icall, EOK, fun->child->handle);
429
430 fibril_rwlock_read_unlock(&device_tree.rwlock);
431}
432
433/** Online function.
434 *
435 * Send a request to online a function to the responsible driver.
436 * The driver may offline other functions if necessary (i.e. if the state
437 * of this function is linked to state of another function somehow).
438 */
439static void devman_fun_online(ipc_call_t *icall)
440{
441 fun_node_t *fun;
442 errno_t rc;
443
444 fun = find_fun_node(&device_tree, ipc_get_arg1(icall));
445 if (fun == NULL) {
446 async_answer_0(icall, ENOENT);
447 return;
448 }
449
450 rc = driver_fun_online(&device_tree, fun);
451 fun_del_ref(fun);
452
453 async_answer_0(icall, rc);
454}
455
456/** Offline function.
457 *
458 * Send a request to offline a function to the responsible driver. As
459 * a result the subtree rooted at that function should be cleanly
460 * detatched. The driver may offline other functions if necessary
461 * (i.e. if the state of this function is linked to state of another
462 * function somehow).
463 */
464static void devman_fun_offline(ipc_call_t *icall)
465{
466 fun_node_t *fun;
467 errno_t rc;
468
469 fun = find_fun_node(&device_tree, ipc_get_arg1(icall));
470 if (fun == NULL) {
471 async_answer_0(icall, ENOENT);
472 return;
473 }
474
475 rc = driver_fun_offline(&device_tree, fun);
476 fun_del_ref(fun);
477
478 async_answer_0(icall, rc);
479}
480
481/** Quiesce function.
482 *
483 * Send a request to quiesce a function to the responsible driver.
484 */
485static void devman_fun_quiesce(ipc_call_t *icall)
486{
487 fun_node_t *fun;
488 dev_node_t *child;
489 errno_t rc;
490
491 fun = find_fun_node(&device_tree, ipc_get_arg1(icall));
492 if (fun == NULL) {
493 async_answer_0(icall, ENOENT);
494 return;
495 }
496
497 fibril_rwlock_read_lock(&device_tree.rwlock);
498
499 /* Check function state */
500 if (fun->state == FUN_REMOVED) {
501 fibril_rwlock_read_unlock(&device_tree.rwlock);
502 async_answer_0(icall, ENOENT);
503 return;
504 }
505
506 child = fun->child;
507 dev_add_ref(child);
508 fibril_rwlock_read_unlock(&device_tree.rwlock);
509
510 rc = driver_dev_quiesce(&device_tree, child);
511 fun_del_ref(fun);
512
513 async_answer_0(icall, rc);
514}
515
516/** Find handle for the function instance identified by its service ID. */
517static void devman_fun_sid_to_handle(ipc_call_t *icall)
518{
519 fun_node_t *fun;
520
521 fun = find_loc_tree_function(&device_tree, ipc_get_arg1(icall));
522
523 if (fun == NULL) {
524 async_answer_0(icall, ENOENT);
525 return;
526 }
527
528 fibril_rwlock_read_lock(&device_tree.rwlock);
529
530 /* Check function state */
531 if (fun->state == FUN_REMOVED) {
532 fibril_rwlock_read_unlock(&device_tree.rwlock);
533 async_answer_0(icall, ENOENT);
534 return;
535 }
536
537 async_answer_1(icall, EOK, fun->handle);
538 fibril_rwlock_read_unlock(&device_tree.rwlock);
539 fun_del_ref(fun);
540}
541
542/** Get list of all registered drivers. */
543static void devman_get_drivers(ipc_call_t *icall)
544{
545 ipc_call_t call;
546 size_t size;
547 size_t act_size;
548 errno_t rc;
549
550 if (!async_data_read_receive(&call, &size)) {
551 async_answer_0(icall, EREFUSED);
552 return;
553 }
554
555 devman_handle_t *hdl_buf = (devman_handle_t *) malloc(size);
556 if (hdl_buf == NULL) {
557 async_answer_0(&call, ENOMEM);
558 async_answer_0(icall, ENOMEM);
559 return;
560 }
561
562 rc = driver_get_list(&drivers_list, hdl_buf, size, &act_size);
563 if (rc != EOK) {
564 async_answer_0(&call, rc);
565 async_answer_0(icall, rc);
566 return;
567 }
568
569 errno_t retval = async_data_read_finalize(&call, hdl_buf, size);
570 free(hdl_buf);
571
572 async_answer_1(icall, retval, act_size);
573}
574
575static void devman_driver_get_devices(ipc_call_t *icall)
576{
577 ipc_call_t call;
578 size_t size;
579 size_t act_size;
580 errno_t rc;
581
582 if (!async_data_read_receive(&call, &size)) {
583 async_answer_0(icall, EREFUSED);
584 return;
585 }
586
587 driver_t *drv = driver_find(&drivers_list, ipc_get_arg1(icall));
588 if (drv == NULL) {
589 async_answer_0(&call, ENOENT);
590 async_answer_0(icall, ENOENT);
591 return;
592 }
593
594 devman_handle_t *hdl_buf = (devman_handle_t *) malloc(size);
595 if (hdl_buf == NULL) {
596 async_answer_0(&call, ENOMEM);
597 async_answer_0(icall, ENOMEM);
598 return;
599 }
600
601 rc = driver_get_devices(drv, hdl_buf, size, &act_size);
602 if (rc != EOK) {
603 fibril_rwlock_read_unlock(&device_tree.rwlock);
604 async_answer_0(&call, rc);
605 async_answer_0(icall, rc);
606 return;
607 }
608
609 errno_t retval = async_data_read_finalize(&call, hdl_buf, size);
610 free(hdl_buf);
611
612 async_answer_1(icall, retval, act_size);
613}
614
615/** Find driver by name. */
616static void devman_driver_get_handle(ipc_call_t *icall)
617{
618 char *drvname;
619
620 errno_t rc = async_data_write_accept((void **) &drvname, true, 0, 0, 0, 0);
621 if (rc != EOK) {
622 async_answer_0(icall, rc);
623 return;
624 }
625
626 driver_t *driver = driver_find_by_name(&drivers_list, drvname);
627
628 free(drvname);
629
630 if (driver == NULL) {
631 async_answer_0(icall, ENOENT);
632 return;
633 }
634
635 async_answer_1(icall, EOK, driver->handle);
636}
637
638/** Get driver match ID. */
639static void devman_driver_get_match_id(ipc_call_t *icall)
640{
641 devman_handle_t handle = ipc_get_arg1(icall);
642 size_t index = ipc_get_arg2(icall);
643
644 driver_t *drv = driver_find(&drivers_list, handle);
645 if (drv == NULL) {
646 async_answer_0(icall, ENOMEM);
647 return;
648 }
649
650 ipc_call_t data;
651 size_t data_len;
652 if (!async_data_read_receive(&data, &data_len)) {
653 async_answer_0(icall, EINVAL);
654 return;
655 }
656
657 void *buffer = malloc(data_len);
658 if (buffer == NULL) {
659 async_answer_0(&data, ENOMEM);
660 async_answer_0(icall, ENOMEM);
661 return;
662 }
663
664 fibril_mutex_lock(&drv->driver_mutex);
665 link_t *link = list_nth(&drv->match_ids.ids, index);
666 if (link == NULL) {
667 fibril_mutex_unlock(&drv->driver_mutex);
668 free(buffer);
669 async_answer_0(&data, ENOMEM);
670 async_answer_0(icall, ENOMEM);
671 return;
672 }
673
674 match_id_t *mid = list_get_instance(link, match_id_t, link);
675
676 size_t sent_length = str_size(mid->id);
677 if (sent_length > data_len) {
678 sent_length = data_len;
679 }
680
681 async_data_read_finalize(&data, mid->id, sent_length);
682 async_answer_1(icall, EOK, mid->score);
683
684 fibril_mutex_unlock(&drv->driver_mutex);
685
686 free(buffer);
687}
688
689/** Get driver name. */
690static void devman_driver_get_name(ipc_call_t *icall)
691{
692 devman_handle_t handle = ipc_get_arg1(icall);
693
694 driver_t *drv = driver_find(&drivers_list, handle);
695 if (drv == NULL) {
696 async_answer_0(icall, ENOMEM);
697 return;
698 }
699
700 ipc_call_t data;
701 size_t data_len;
702 if (!async_data_read_receive(&data, &data_len)) {
703 async_answer_0(icall, EINVAL);
704 return;
705 }
706
707 void *buffer = malloc(data_len);
708 if (buffer == NULL) {
709 async_answer_0(&data, ENOMEM);
710 async_answer_0(icall, ENOMEM);
711 return;
712 }
713
714 fibril_mutex_lock(&drv->driver_mutex);
715
716 size_t sent_length = str_size(drv->name);
717 if (sent_length > data_len) {
718 sent_length = data_len;
719 }
720
721 async_data_read_finalize(&data, drv->name, sent_length);
722 async_answer_0(icall, EOK);
723
724 fibril_mutex_unlock(&drv->driver_mutex);
725
726 free(buffer);
727}
728
729/** Get driver state. */
730static void devman_driver_get_state(ipc_call_t *icall)
731{
732 driver_t *drv;
733
734 drv = driver_find(&drivers_list, ipc_get_arg1(icall));
735 if (drv == NULL) {
736 async_answer_0(icall, ENOENT);
737 return;
738 }
739
740 async_answer_1(icall, EOK, (sysarg_t) drv->state);
741}
742
743/** Forcibly load a driver. */
744static void devman_driver_load(ipc_call_t *icall)
745{
746 driver_t *drv;
747 errno_t rc;
748
749 drv = driver_find(&drivers_list, ipc_get_arg1(icall));
750 if (drv == NULL) {
751 async_answer_0(icall, ENOENT);
752 return;
753 }
754
755 fibril_mutex_lock(&drv->driver_mutex);
756 rc = start_driver(drv) ? EOK : EIO;
757 fibril_mutex_unlock(&drv->driver_mutex);
758
759 async_answer_0(icall, rc);
760}
761
762/** Unload a driver by user request. */
763static void devman_driver_unload(ipc_call_t *icall)
764{
765 driver_t *drv;
766 errno_t rc;
767
768 drv = driver_find(&drivers_list, ipc_get_arg1(icall));
769 if (drv == NULL) {
770 async_answer_0(icall, ENOENT);
771 return;
772 }
773
774 fibril_mutex_lock(&drv->driver_mutex);
775 rc = stop_driver(drv);
776 fibril_mutex_unlock(&drv->driver_mutex);
777
778 async_answer_0(icall, rc);
779}
780
781/** Function for handling connections from a client to the device manager. */
782void devman_connection_client(ipc_call_t *icall, void *arg)
783{
784 /* Accept connection. */
785 async_accept_0(icall);
786
787 while (true) {
788 ipc_call_t call;
789 async_get_call(&call);
790
791 if (!ipc_get_imethod(&call)) {
792 async_answer_0(&call, EOK);
793 break;
794 }
795
796 switch (ipc_get_imethod(&call)) {
797 case DEVMAN_DEVICE_GET_HANDLE:
798 devman_function_get_handle(&call);
799 break;
800 case DEVMAN_DEV_GET_PARENT:
801 devman_dev_get_parent(&call);
802 break;
803 case DEVMAN_DEV_GET_FUNCTIONS:
804 devman_dev_get_functions(&call);
805 break;
806 case DEVMAN_FUN_GET_CHILD:
807 devman_fun_get_child(&call);
808 break;
809 case DEVMAN_FUN_GET_MATCH_ID:
810 devman_fun_get_match_id(&call);
811 break;
812 case DEVMAN_FUN_GET_NAME:
813 devman_fun_get_name(&call);
814 break;
815 case DEVMAN_FUN_GET_DRIVER_NAME:
816 devman_fun_get_driver_name(&call);
817 break;
818 case DEVMAN_FUN_GET_PATH:
819 devman_fun_get_path(&call);
820 break;
821 case DEVMAN_FUN_ONLINE:
822 devman_fun_online(&call);
823 break;
824 case DEVMAN_FUN_OFFLINE:
825 devman_fun_offline(&call);
826 break;
827 case DEVMAN_FUN_QUIESCE:
828 devman_fun_quiesce(&call);
829 break;
830 case DEVMAN_FUN_SID_TO_HANDLE:
831 devman_fun_sid_to_handle(&call);
832 break;
833 case DEVMAN_GET_DRIVERS:
834 devman_get_drivers(&call);
835 break;
836 case DEVMAN_DRIVER_GET_DEVICES:
837 devman_driver_get_devices(&call);
838 break;
839 case DEVMAN_DRIVER_GET_HANDLE:
840 devman_driver_get_handle(&call);
841 break;
842 case DEVMAN_DRIVER_GET_MATCH_ID:
843 devman_driver_get_match_id(&call);
844 break;
845 case DEVMAN_DRIVER_GET_NAME:
846 devman_driver_get_name(&call);
847 break;
848 case DEVMAN_DRIVER_GET_STATE:
849 devman_driver_get_state(&call);
850 break;
851 case DEVMAN_DRIVER_LOAD:
852 devman_driver_load(&call);
853 break;
854 case DEVMAN_DRIVER_UNLOAD:
855 devman_driver_unload(&call);
856 break;
857 default:
858 async_answer_0(&call, ENOENT);
859 }
860 }
861}
862
863/** @}
864 */
Note: See TracBrowser for help on using the repository browser.