source: mainline/uspace/srv/devmap/devmap.c@ fc02cc41

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

get back fine-grained locking (which was removed in commit 4458), but this time with proper fibril synchronization

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