source: mainline/uspace/srv/devmap/devmap.c@ 1e4cada

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

rename fibril_sync.[ch] to fibril_synch.[ch]

  • Property mode set to 100644
File size: 19.5 KB
Line 
1/*
2 * Copyright (c) 2007 Josef Cejka
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/**
30 * @defgroup devmap Device mapper.
31 * @brief HelenOS device mapper.
32 * @{
33 */
34
35/** @file
36 */
37
38#include <ipc/services.h>
39#include <ipc/ns.h>
40#include <async.h>
41#include <stdio.h>
42#include <errno.h>
43#include <bool.h>
44#include <fibril_synch.h>
45#include <stdlib.h>
46#include <string.h>
47#include <ipc/devmap.h>
48
49#define NAME "devmap"
50#define NULL_DEVICES 256
51
52/** Representation of device driver.
53 *
54 * Each driver is responsible for a set of devices.
55 *
56 */
57typedef struct {
58 /** Pointers to previous and next drivers in linked list */
59 link_t drivers;
60 /** Pointer to the linked list of devices controlled by this driver */
61 link_t devices;
62 /** Phone asociated with this driver */
63 ipcarg_t phone;
64 /** Device driver name */
65 char *name;
66 /** Fibril mutex for list of devices owned by this driver */
67 fibril_mutex_t devices_mutex;
68} devmap_driver_t;
69
70/** Info about registered device
71 *
72 */
73typedef struct {
74 /** Pointer to the previous and next device in the list of all devices */
75 link_t devices;
76 /** Pointer to the previous and next device in the list of devices
77 owned by one driver */
78 link_t driver_devices;
79 /** Unique device identifier */
80 dev_handle_t handle;
81 /** Device name */
82 char *name;
83 /** Device driver handling this device */
84 devmap_driver_t *driver;
85} devmap_device_t;
86
87LIST_INITIALIZE(devices_list);
88LIST_INITIALIZE(drivers_list);
89
90/* Locking order:
91 * drivers_list_mutex
92 * devices_list_mutex
93 * (devmap_driver_t *)->devices_mutex
94 * create_handle_mutex
95 **/
96
97static FIBRIL_MUTEX_INITIALIZE(devices_list_mutex);
98static FIBRIL_CONDVAR_INITIALIZE(devices_list_cv);
99static FIBRIL_MUTEX_INITIALIZE(drivers_list_mutex);
100static FIBRIL_MUTEX_INITIALIZE(create_handle_mutex);
101static FIBRIL_MUTEX_INITIALIZE(null_devices_mutex);
102
103static dev_handle_t last_handle = 0;
104static devmap_device_t *null_devices[NULL_DEVICES];
105
106static dev_handle_t devmap_create_handle(void)
107{
108 /* TODO: allow reusing old handles after their unregistration
109 * and implement some version of LRU algorithm, avoid overflow
110 */
111
112 fibril_mutex_lock(&create_handle_mutex);
113 last_handle++;
114 fibril_mutex_unlock(&create_handle_mutex);
115
116 return last_handle;
117}
118
119/** Find device with given name.
120 *
121 */
122static devmap_device_t *devmap_device_find_name(const char *name)
123{
124 link_t *item = devices_list.next;
125 devmap_device_t *device = NULL;
126
127 while (item != &devices_list) {
128 device = list_get_instance(item, devmap_device_t, devices);
129 if (str_cmp(device->name, name) == 0)
130 break;
131 item = item->next;
132 }
133
134 if (item == &devices_list)
135 return NULL;
136
137 device = list_get_instance(item, devmap_device_t, devices);
138 return device;
139}
140
141/** Find device with given handle.
142 *
143 * @todo: use hash table
144 *
145 */
146static devmap_device_t *devmap_device_find_handle(dev_handle_t handle)
147{
148 fibril_mutex_lock(&devices_list_mutex);
149
150 link_t *item = (&devices_list)->next;
151 devmap_device_t *device = NULL;
152
153 while (item != &devices_list) {
154 device = list_get_instance(item, devmap_device_t, devices);
155 if (device->handle == handle)
156 break;
157 item = item->next;
158 }
159
160 if (item == &devices_list) {
161 fibril_mutex_unlock(&devices_list_mutex);
162 return NULL;
163 }
164
165 device = list_get_instance(item, devmap_device_t, devices);
166
167 fibril_mutex_unlock(&devices_list_mutex);
168
169 return device;
170}
171
172/**
173 * Unregister device and free it. It's assumed that driver's device list is
174 * already locked.
175 */
176static int devmap_device_unregister_core(devmap_device_t *device)
177{
178 list_remove(&(device->devices));
179 list_remove(&(device->driver_devices));
180
181 free(device->name);
182 free(device);
183
184 return EOK;
185}
186
187/**
188 * Read info about new driver and add it into linked list of registered
189 * drivers.
190 */
191static void devmap_driver_register(devmap_driver_t **odriver)
192{
193 *odriver = NULL;
194
195 ipc_call_t icall;
196 ipc_callid_t iid = async_get_call(&icall);
197
198 if (IPC_GET_METHOD(icall) != DEVMAP_DRIVER_REGISTER) {
199 ipc_answer_0(iid, EREFUSED);
200 return;
201 }
202
203 devmap_driver_t *driver = (devmap_driver_t *) malloc(sizeof(devmap_driver_t));
204
205 if (driver == NULL) {
206 ipc_answer_0(iid, ENOMEM);
207 return;
208 }
209
210 /*
211 * Get driver name
212 */
213 ipc_callid_t callid;
214 size_t name_size;
215 if (!async_data_write_receive(&callid, &name_size)) {
216 free(driver);
217 ipc_answer_0(callid, EREFUSED);
218 ipc_answer_0(iid, EREFUSED);
219 return;
220 }
221
222 if (name_size > DEVMAP_NAME_MAXLEN) {
223 free(driver);
224 ipc_answer_0(callid, EINVAL);
225 ipc_answer_0(iid, EREFUSED);
226 return;
227 }
228
229 /*
230 * Allocate buffer for device name.
231 */
232 driver->name = (char *) malloc(name_size + 1);
233 if (driver->name == NULL) {
234 free(driver);
235 ipc_answer_0(callid, ENOMEM);
236 ipc_answer_0(iid, EREFUSED);
237 return;
238 }
239
240 /*
241 * Send confirmation to sender and get data into buffer.
242 */
243 if (async_data_write_finalize(callid, driver->name, name_size) != EOK) {
244 free(driver->name);
245 free(driver);
246 ipc_answer_0(iid, EREFUSED);
247 return;
248 }
249
250 driver->name[name_size] = 0;
251
252 /* Initialize mutex for list of devices owned by this driver */
253 fibril_mutex_initialize(&driver->devices_mutex);
254
255 /*
256 * Initialize list of asociated devices
257 */
258 list_initialize(&driver->devices);
259
260 /*
261 * Create connection to the driver
262 */
263 ipc_call_t call;
264 callid = async_get_call(&call);
265
266 if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) {
267 ipc_answer_0(callid, ENOTSUP);
268
269 free(driver->name);
270 free(driver);
271 ipc_answer_0(iid, ENOTSUP);
272 return;
273 }
274
275 driver->phone = IPC_GET_ARG5(call);
276
277 ipc_answer_0(callid, EOK);
278
279 list_initialize(&(driver->drivers));
280
281 fibril_mutex_lock(&drivers_list_mutex);
282
283 /* TODO:
284 * check that no driver with name equal to driver->name is registered
285 */
286
287 /*
288 * Insert new driver into list of registered drivers
289 */
290 list_append(&(driver->drivers), &drivers_list);
291 fibril_mutex_unlock(&drivers_list_mutex);
292
293 ipc_answer_0(iid, EOK);
294
295 *odriver = driver;
296}
297
298/**
299 * Unregister device driver, unregister all its devices and free driver
300 * structure.
301 *
302 */
303static int devmap_driver_unregister(devmap_driver_t *driver)
304{
305 if (driver == NULL)
306 return EEXISTS;
307
308 fibril_mutex_lock(&drivers_list_mutex);
309
310 if (driver->phone != 0)
311 ipc_hangup(driver->phone);
312
313 /* Remove it from list of drivers */
314 list_remove(&(driver->drivers));
315
316 /* Unregister all its devices */
317 fibril_mutex_lock(&devices_list_mutex);
318 fibril_mutex_lock(&driver->devices_mutex);
319
320 while (!list_empty(&(driver->devices))) {
321 devmap_device_t *device = list_get_instance(driver->devices.next,
322 devmap_device_t, driver_devices);
323 devmap_device_unregister_core(device);
324 }
325
326 fibril_mutex_unlock(&driver->devices_mutex);
327 fibril_mutex_unlock(&devices_list_mutex);
328 fibril_mutex_unlock(&drivers_list_mutex);
329
330 /* free name and driver */
331 if (driver->name != NULL)
332 free(driver->name);
333
334 free(driver);
335
336 return EOK;
337}
338
339/** Register instance of device
340 *
341 */
342static void devmap_device_register(ipc_callid_t iid, ipc_call_t *icall,
343 devmap_driver_t *driver)
344{
345 if (driver == NULL) {
346 ipc_answer_0(iid, EREFUSED);
347 return;
348 }
349
350 /* Create new device entry */
351 devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
352 if (device == NULL) {
353 ipc_answer_0(iid, ENOMEM);
354 return;
355 }
356
357 /* Get device name */
358 ipc_callid_t callid;
359 size_t size;
360 if (!async_data_write_receive(&callid, &size)) {
361 free(device);
362 ipc_answer_0(iid, EREFUSED);
363 return;
364 }
365
366 if (size > DEVMAP_NAME_MAXLEN) {
367 free(device);
368 ipc_answer_0(callid, EINVAL);
369 ipc_answer_0(iid, EREFUSED);
370 return;
371 }
372
373 /* +1 for terminating \0 */
374 device->name = (char *) malloc(size + 1);
375
376 if (device->name == NULL) {
377 free(device);
378 ipc_answer_0(callid, ENOMEM);
379 ipc_answer_0(iid, EREFUSED);
380 return;
381 }
382
383 async_data_write_finalize(callid, device->name, size);
384 device->name[size] = 0;
385
386 list_initialize(&(device->devices));
387 list_initialize(&(device->driver_devices));
388
389 fibril_mutex_lock(&devices_list_mutex);
390
391 /* Check that device with such name is not already registered */
392 if (NULL != devmap_device_find_name(device->name)) {
393 printf(NAME ": Device '%s' already registered\n", device->name);
394 fibril_mutex_unlock(&devices_list_mutex);
395 free(device->name);
396 free(device);
397 ipc_answer_0(iid, EEXISTS);
398 return;
399 }
400
401 /* Get unique device handle */
402 device->handle = devmap_create_handle();
403
404 device->driver = driver;
405
406 /* Insert device into list of all devices */
407 list_append(&device->devices, &devices_list);
408
409 /* Insert device into list of devices that belog to one driver */
410 fibril_mutex_lock(&device->driver->devices_mutex);
411
412 list_append(&device->driver_devices, &device->driver->devices);
413
414 fibril_mutex_unlock(&device->driver->devices_mutex);
415 fibril_condvar_broadcast(&devices_list_cv);
416 fibril_mutex_unlock(&devices_list_mutex);
417
418 ipc_answer_1(iid, EOK, device->handle);
419}
420
421/**
422 *
423 */
424static int devmap_device_unregister(ipc_callid_t iid, ipc_call_t *icall,
425 devmap_driver_t *driver)
426{
427 /* TODO */
428 return EOK;
429}
430
431/** Connect client to the device.
432 *
433 * Find device driver owning requested device and forward
434 * the message to it.
435 *
436 */
437static void devmap_forward(ipc_callid_t callid, ipc_call_t *call)
438{
439 /*
440 * Get handle from request
441 */
442 dev_handle_t handle = IPC_GET_ARG2(*call);
443 devmap_device_t *dev = devmap_device_find_handle(handle);
444
445 if ((dev == NULL) || (dev->driver == NULL) || (dev->driver->phone == 0)) {
446 ipc_answer_0(callid, ENOENT);
447 return;
448 }
449
450 ipc_forward_fast(callid, dev->driver->phone, dev->handle,
451 IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
452}
453
454/** Find handle for device instance identified by name.
455 *
456 * In answer will be send EOK and device handle in arg1 or a error
457 * code from errno.h.
458 *
459 */
460static void devmap_get_handle(ipc_callid_t iid, ipc_call_t *icall)
461{
462 /*
463 * Wait for incoming message with device name (but do not
464 * read the name itself until the buffer is allocated).
465 */
466 ipc_callid_t callid;
467 size_t size;
468 if (!async_data_write_receive(&callid, &size)) {
469 ipc_answer_0(callid, EREFUSED);
470 ipc_answer_0(iid, EREFUSED);
471 return;
472 }
473
474 if ((size < 1) || (size > DEVMAP_NAME_MAXLEN)) {
475 ipc_answer_0(callid, EINVAL);
476 ipc_answer_0(iid, EREFUSED);
477 return;
478 }
479
480 /*
481 * Allocate buffer for device name.
482 */
483 char *name = (char *) malloc(size + 1);
484 if (name == NULL) {
485 ipc_answer_0(callid, ENOMEM);
486 ipc_answer_0(iid, EREFUSED);
487 return;
488 }
489
490 /*
491 * Send confirmation to sender and get data into buffer.
492 */
493 ipcarg_t retval = async_data_write_finalize(callid, name, size);
494 if (retval != EOK) {
495 ipc_answer_0(iid, EREFUSED);
496 free(name);
497 return;
498 }
499 name[size] = '\0';
500
501 fibril_mutex_lock(&devices_list_mutex);
502 const devmap_device_t *dev;
503recheck:
504
505 /*
506 * Find device name in the list of known devices.
507 */
508 dev = devmap_device_find_name(name);
509
510 /*
511 * Device was not found.
512 */
513 if (dev == NULL) {
514 if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
515 /* Blocking lookup */
516 fibril_condvar_wait(&devices_list_cv,
517 &devices_list_mutex);
518 goto recheck;
519 }
520
521 ipc_answer_0(iid, ENOENT);
522 free(name);
523 fibril_mutex_unlock(&devices_list_mutex);
524 return;
525 }
526 fibril_mutex_unlock(&devices_list_mutex);
527
528 ipc_answer_1(iid, EOK, dev->handle);
529 free(name);
530}
531
532/** Find name of device identified by id and send it to caller.
533 *
534 */
535static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall)
536{
537 const devmap_device_t *device = devmap_device_find_handle(IPC_GET_ARG1(*icall));
538
539 /*
540 * Device not found.
541 */
542 if (device == NULL) {
543 ipc_answer_0(iid, ENOENT);
544 return;
545 }
546
547 ipc_answer_0(iid, EOK);
548
549 /* FIXME:
550 * We have no channel from DEVMAP to client, therefore
551 * sending must be initiated by client.
552 *
553 * size_t name_size = str_size(device->name);
554 *
555 * int rc = async_data_write_send(phone, device->name, name_size);
556 * if (rc != EOK) {
557 * async_wait_for(req, NULL);
558 * return rc;
559 * }
560 */
561
562 /* TODO: send name in response */
563}
564
565static void devmap_get_count(ipc_callid_t iid, ipc_call_t *icall)
566{
567 fibril_mutex_lock(&devices_list_mutex);
568 ipc_answer_1(iid, EOK, list_count(&devices_list));
569 fibril_mutex_unlock(&devices_list_mutex);
570}
571
572static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
573{
574 fibril_mutex_lock(&devices_list_mutex);
575
576 ipc_callid_t callid;
577 size_t size;
578 if (!async_data_read_receive(&callid, &size)) {
579 ipc_answer_0(callid, EREFUSED);
580 ipc_answer_0(iid, EREFUSED);
581 return;
582 }
583
584 if ((size % sizeof(dev_desc_t)) != 0) {
585 ipc_answer_0(callid, EINVAL);
586 ipc_answer_0(iid, EREFUSED);
587 return;
588 }
589
590 size_t count = size / sizeof(dev_desc_t);
591 dev_desc_t *desc = (dev_desc_t *) malloc(size);
592 if (desc == NULL) {
593 ipc_answer_0(callid, ENOMEM);
594 ipc_answer_0(iid, EREFUSED);
595 return;
596 }
597
598 size_t pos = 0;
599 link_t *item = devices_list.next;
600
601 while ((item != &devices_list) && (pos < count)) {
602 devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
603
604 desc[pos].handle = device->handle;
605 str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
606 pos++;
607 item = item->next;
608 }
609
610 ipcarg_t retval = async_data_read_finalize(callid, desc, pos * sizeof(dev_desc_t));
611 if (retval != EOK) {
612 ipc_answer_0(iid, EREFUSED);
613 free(desc);
614 return;
615 }
616
617 free(desc);
618
619 fibril_mutex_unlock(&devices_list_mutex);
620
621 ipc_answer_1(iid, EOK, pos);
622}
623
624static void devmap_null_create(ipc_callid_t iid, ipc_call_t *icall)
625{
626 fibril_mutex_lock(&null_devices_mutex);
627
628 unsigned int i;
629 bool fnd = false;
630
631 for (i = 0; i < NULL_DEVICES; i++) {
632 if (null_devices[i] == NULL) {
633 fnd = true;
634 break;
635 }
636 }
637
638 if (!fnd) {
639 fibril_mutex_unlock(&null_devices_mutex);
640 ipc_answer_0(iid, ENOMEM);
641 return;
642 }
643
644 /* Create NULL device entry */
645 devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
646 if (device == NULL) {
647 fibril_mutex_unlock(&null_devices_mutex);
648 ipc_answer_0(iid, ENOMEM);
649 return;
650 }
651
652 char null[DEVMAP_NAME_MAXLEN];
653 snprintf(null, DEVMAP_NAME_MAXLEN, "null%u", i);
654
655 device->name = str_dup(null);
656 if (device->name == NULL) {
657 fibril_mutex_unlock(&null_devices_mutex);
658 free(device);
659 ipc_answer_0(iid, ENOMEM);
660 return;
661 }
662
663 list_initialize(&(device->devices));
664 list_initialize(&(device->driver_devices));
665
666 fibril_mutex_lock(&devices_list_mutex);
667
668 /* Get unique device handle */
669 device->handle = devmap_create_handle();
670 device->driver = NULL;
671
672 /* Insert device into list of all devices
673 and into null devices array */
674 list_append(&device->devices, &devices_list);
675 null_devices[i] = device;
676
677 fibril_mutex_unlock(&devices_list_mutex);
678 fibril_mutex_unlock(&null_devices_mutex);
679
680 ipc_answer_1(iid, EOK, (ipcarg_t) i);
681}
682
683static void devmap_null_destroy(ipc_callid_t iid, ipc_call_t *icall)
684{
685 fibril_mutex_lock(&null_devices_mutex);
686
687 ipcarg_t i = IPC_GET_ARG1(*icall);
688
689 if (null_devices[i] == NULL) {
690 ipc_answer_0(iid, ENOENT);
691 return;
692 }
693
694 devmap_device_unregister_core(null_devices[i]);
695 null_devices[i] = NULL;
696
697 fibril_mutex_unlock(&null_devices_mutex);
698
699 ipc_answer_0(iid, EOK);
700}
701
702/** Initialize device mapper.
703 *
704 *
705 */
706static bool devmap_init(void)
707{
708 fibril_mutex_lock(&null_devices_mutex);
709
710 unsigned int i;
711 for (i = 0; i < NULL_DEVICES; i++)
712 null_devices[i] = NULL;
713
714 fibril_mutex_unlock(&null_devices_mutex);
715
716 return true;
717}
718
719/** Handle connection with device driver.
720 *
721 */
722static void devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
723{
724 /* Accept connection */
725 ipc_answer_0(iid, EOK);
726
727 devmap_driver_t *driver = NULL;
728 devmap_driver_register(&driver);
729
730 if (NULL == driver)
731 return;
732
733 bool cont = true;
734 while (cont) {
735 ipc_call_t call;
736 ipc_callid_t callid = async_get_call(&call);
737
738 switch (IPC_GET_METHOD(call)) {
739 case IPC_M_PHONE_HUNGUP:
740 cont = false;
741 continue;
742 case DEVMAP_DRIVER_UNREGISTER:
743 if (NULL == driver)
744 ipc_answer_0(callid, ENOENT);
745 else
746 ipc_answer_0(callid, EOK);
747 break;
748 case DEVMAP_DEVICE_REGISTER:
749 /* Register one instance of device */
750 devmap_device_register(callid, &call, driver);
751 break;
752 case DEVMAP_DEVICE_UNREGISTER:
753 /* Remove instance of device identified by handler */
754 devmap_device_unregister(callid, &call, driver);
755 break;
756 case DEVMAP_DEVICE_GET_HANDLE:
757 devmap_get_handle(callid, &call);
758 break;
759 case DEVMAP_DEVICE_GET_NAME:
760 devmap_get_name(callid, &call);
761 break;
762 default:
763 if (!(callid & IPC_CALLID_NOTIFICATION))
764 ipc_answer_0(callid, ENOENT);
765 }
766 }
767
768 if (driver != NULL) {
769 /*
770 * Unregister the device driver and all its devices.
771 */
772 devmap_driver_unregister(driver);
773 driver = NULL;
774 }
775}
776
777/** Handle connection with device client.
778 *
779 */
780static void devmap_connection_client(ipc_callid_t iid, ipc_call_t *icall)
781{
782 /* Accept connection */
783 ipc_answer_0(iid, EOK);
784
785 bool cont = true;
786 while (cont) {
787 ipc_call_t call;
788 ipc_callid_t callid = async_get_call(&call);
789
790 switch (IPC_GET_METHOD(call)) {
791 case IPC_M_PHONE_HUNGUP:
792 cont = false;
793 continue;
794 case DEVMAP_DEVICE_GET_HANDLE:
795 devmap_get_handle(callid, &call);
796 break;
797 case DEVMAP_DEVICE_GET_NAME:
798 devmap_get_name(callid, &call);
799 break;
800 case DEVMAP_DEVICE_NULL_CREATE:
801 devmap_null_create(callid, &call);
802 break;
803 case DEVMAP_DEVICE_NULL_DESTROY:
804 devmap_null_destroy(callid, &call);
805 break;
806 case DEVMAP_DEVICE_GET_COUNT:
807 devmap_get_count(callid, &call);
808 break;
809 case DEVMAP_DEVICE_GET_DEVICES:
810 devmap_get_devices(callid, &call);
811 break;
812 default:
813 if (!(callid & IPC_CALLID_NOTIFICATION))
814 ipc_answer_0(callid, ENOENT);
815 }
816 }
817}
818
819/** Function for handling connections to devmap
820 *
821 */
822static void devmap_connection(ipc_callid_t iid, ipc_call_t *icall)
823{
824 /* Select interface */
825 switch ((ipcarg_t) (IPC_GET_ARG1(*icall))) {
826 case DEVMAP_DRIVER:
827 devmap_connection_driver(iid, icall);
828 break;
829 case DEVMAP_CLIENT:
830 devmap_connection_client(iid, icall);
831 break;
832 case DEVMAP_CONNECT_TO_DEVICE:
833 /* Connect client to selected device */
834 devmap_forward(iid, icall);
835 break;
836 default:
837 /* No such interface */
838 ipc_answer_0(iid, ENOENT);
839 }
840}
841
842/**
843 *
844 */
845int main(int argc, char *argv[])
846{
847 printf(NAME ": HelenOS Device Mapper\n");
848
849 if (!devmap_init()) {
850 printf(NAME ": Error while initializing service\n");
851 return -1;
852 }
853
854 /* Set a handler of incomming connections */
855 async_set_client_connection(devmap_connection);
856
857 /* Register device mapper at naming service */
858 ipcarg_t phonead;
859 if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAP, 0, 0, &phonead) != 0)
860 return -1;
861
862 printf(NAME ": Accepting connections\n");
863 async_manager();
864
865 /* Never reached */
866 return 0;
867}
868
869/**
870 * @}
871 */
Note: See TracBrowser for help on using the repository browser.