source: mainline/uspace/srv/devmap/devmap.c@ 0cc4313

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 0cc4313 was b74959bd, checked in by Jakub Jermar <jakub@…>, 18 years ago

Modify ipc_answer_*() to make use of all six syscall arguments. The recommended
means of answering calls is via the ipc_answer_m() macros (where m denotes the
number of return arguments) that automatically decide between the fast register
version or the slow universal version of ipc_answer().

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