Subversion Repositories HelenOS

Rev

Rev 2660 | Rev 3080 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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 <futex.h>
  45. #include <stdlib.h>
  46. #include <string.h>
  47.  
  48. #include "devmap.h"
  49.  
  50.  
  51. LIST_INITIALIZE(devices_list);
  52. LIST_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.  
  61. static atomic_t devices_list_futex = FUTEX_INITIALIZER;
  62. static atomic_t drivers_list_futex = FUTEX_INITIALIZER;
  63. static atomic_t create_handle_futex = FUTEX_INITIALIZER;
  64.  
  65.  
  66. static 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.  
  84.  
  85. /** Initialize device mapper.
  86.  *
  87.  *
  88.  */
  89. static int devmap_init()
  90. {
  91.     /* TODO: */
  92.  
  93.     return EOK;
  94. }
  95.  
  96. /** Find device with given name.
  97.  *
  98.  */
  99. static devmap_device_t *devmap_device_find_name(const char *name)
  100. {
  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) {
  116.         printf("DEVMAP: no device named %s.\n", name);
  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.  */
  127. static 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.  
  157. /**
  158.  * Unregister device and free it. It's assumed that driver's device list is
  159.  * already locked.
  160.  */
  161. static 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.  
  174. /**
  175.  * Read info about new driver and add it into linked list of registered
  176.  * drivers.
  177.  */
  178. static void devmap_driver_register(devmap_driver_t **odriver)
  179. {
  180.     size_t name_size;
  181.     ipc_callid_t callid;
  182.     ipc_call_t call;
  183.     devmap_driver_t *driver;
  184.     ipc_callid_t iid;
  185.     ipc_call_t icall;
  186.  
  187.     *odriver = NULL;
  188.    
  189.     iid = async_get_call(&icall);
  190.  
  191.     if (IPC_GET_METHOD(icall) != DEVMAP_DRIVER_REGISTER) {
  192.         ipc_answer_0(iid, EREFUSED);
  193.         return;
  194.     }
  195.  
  196.     if (NULL ==
  197.         (driver = (devmap_driver_t *)malloc(sizeof(devmap_driver_t)))) {
  198.         ipc_answer_0(iid, ENOMEM);
  199.         return;
  200.     }
  201.  
  202.     /*
  203.      * Get driver name
  204.      */
  205.     if (!ipc_data_write_receive(&callid, &name_size)) {
  206.         printf("Unexpected request.\n");
  207.         free(driver);
  208.         ipc_answer_0(callid, EREFUSED);
  209.         ipc_answer_0(iid, EREFUSED);
  210.         return;
  211.     }
  212.  
  213.     if (name_size > DEVMAP_NAME_MAXLEN) {
  214.         printf("Too logn name: %u: maximum is %u.\n", name_size,
  215.             DEVMAP_NAME_MAXLEN);
  216.         free(driver);
  217.         ipc_answer_0(callid, EINVAL);
  218.         ipc_answer_0(iid, EREFUSED);
  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);
  228.         ipc_answer_0(callid, ENOMEM);
  229.         ipc_answer_0(iid, EREFUSED);
  230.         return;
  231.     }  
  232.  
  233.     /*
  234.      * Send confirmation to sender and get data into buffer.
  235.      */
  236.     if (EOK != ipc_data_write_deliver(callid, driver->name, name_size)) {
  237.         printf("Cannot read driver name.\n");
  238.         free(driver->name);
  239.         free(driver);
  240.         ipc_answer_0(iid, EREFUSED);
  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 */
  249.     futex_initialize(&(driver->devices_futex), 1);
  250.  
  251.     /*
  252.      * Initialize list of asociated devices
  253.      */
  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)) {
  262.         printf("DEVMAP: Unexpected method: %u.\n",
  263.             IPC_GET_METHOD(call));
  264.         ipc_answer_0(callid, ENOTSUP);
  265.        
  266.         free(driver->name);
  267.         free(driver);
  268.         ipc_answer_0(iid, ENOTSUP);
  269.         return;
  270.     }
  271.  
  272.     driver->phone = IPC_GET_ARG5(call);
  273.    
  274.     ipc_answer_0(callid, EOK);
  275.    
  276.     list_initialize(&(driver->drivers));
  277.  
  278.     futex_down(&drivers_list_futex);   
  279.    
  280.     /* TODO:
  281.      * check that no driver with name equal to driver->name is registered
  282.      */
  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.    
  290.     ipc_answer_0(iid, EOK);
  291.     printf("Driver registered.\n");
  292.  
  293.     *odriver = driver;
  294.     return;
  295. }
  296.  
  297. /** Unregister device driver, unregister all its devices and free driver
  298.  * structure.
  299.  */
  300. static int devmap_driver_unregister(devmap_driver_t *driver)
  301. {
  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))) {
  323.         device = list_get_instance(driver->devices.next,
  324.             devmap_device_t, driver_devices);
  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.  
  342.     return EOK;
  343. }
  344.  
  345.  
  346. /** Register instance of device
  347.  *
  348.  */
  349. static void devmap_device_register(ipc_callid_t iid, ipc_call_t *icall,
  350.     devmap_driver_t *driver)
  351. {
  352.     ipc_callid_t callid;
  353.     size_t size;
  354.     devmap_device_t *device;
  355.  
  356.     if (NULL == driver) {
  357.         printf("Invalid driver registration.\n");
  358.         ipc_answer_0(iid, EREFUSED);
  359.         return;
  360.     }
  361.    
  362.     /* Create new device entry */
  363.     if (NULL ==
  364.         (device = (devmap_device_t *)malloc(sizeof(devmap_device_t)))) {
  365.         printf("Cannot allocate new device.\n");
  366.         ipc_answer_0(iid, ENOMEM);
  367.         return;
  368.     }
  369.    
  370.     /* Get device name */
  371.     if (!ipc_data_write_receive(&callid, &size)) {
  372.         free(device);
  373.         printf("Cannot read device name.\n");
  374.         ipc_answer_0(iid, EREFUSED);
  375.         return;
  376.     }
  377.  
  378.     if (size > DEVMAP_NAME_MAXLEN) {
  379.         printf("Too long device name: %u.\n", size);
  380.         free(device);
  381.         ipc_answer_0(callid, EINVAL);
  382.         ipc_answer_0(iid, EREFUSED);
  383.         return;
  384.     }
  385.  
  386.         /* +1 for terminating \0 */
  387.     device->name = (char *)malloc(size + 1);
  388.  
  389.     if (NULL == device->name) {
  390.         printf("Cannot read device name.\n");
  391.         free(device);
  392.         ipc_answer_0(callid, ENOMEM);
  393.         ipc_answer_0(iid, EREFUSED);
  394.         return;
  395.     }
  396.    
  397.     ipc_data_write_deliver(callid, device->name, size);
  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);
  411.         ipc_answer_0(iid, EEXISTS);
  412.         return;
  413.     }
  414.  
  415.     /* Get unique device handle */
  416.     device->handle = devmap_create_handle();
  417.  
  418.     device->driver = driver;
  419.    
  420.     /* Insert device into list of all devices  */
  421.     list_append(&device->devices, &devices_list);
  422.  
  423.     /* Insert device into list of devices that belog to one driver */
  424.     futex_down(&device->driver->devices_futex);
  425.    
  426.     list_append(&device->driver_devices, &device->driver->devices);
  427.    
  428.     futex_up(&device->driver->devices_futex);  
  429.     futex_up(&devices_list_futex); 
  430.  
  431.     printf("Device '%s' registered.\n", device->name); 
  432.     ipc_answer_1(iid, EOK, device->handle);
  433.  
  434.     return;
  435. }
  436.  
  437. /**
  438.  *
  439.  */
  440. static int devmap_device_unregister(ipc_callid_t iid, ipc_call_t *icall,
  441.     devmap_driver_t *driver)
  442. {
  443.     /* TODO */
  444.  
  445.     return EOK;
  446. }
  447.  
  448. /** Connect client to the device.
  449.  * Find device driver owning requested device and forward
  450.  * the message to it.
  451.  */
  452. static void devmap_forward(ipc_callid_t callid, ipc_call_t *call)
  453. {
  454.     devmap_device_t *dev;
  455.     int handle;
  456.  
  457.     /*
  458.      * Get handle from request
  459.      */
  460.     handle = IPC_GET_ARG2(*call);
  461.     dev = devmap_device_find_handle(handle);
  462.  
  463.     if (NULL == dev) {
  464.         printf("DEVMAP: No registered device with handle %d.\n",
  465.             handle);
  466.         ipc_answer_0(callid, ENOENT);
  467.         return;
  468.     }
  469.  
  470.     ipc_forward_fast(callid, dev->driver->phone, (ipcarg_t)(dev->handle),
  471.         IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
  472.     return;
  473. }
  474.  
  475. /** Find handle for device instance identified by name.
  476.  * In answer will be send EOK and device handle in arg1 or a error
  477.  * code from errno.h.
  478.  */
  479. static void devmap_get_handle(ipc_callid_t iid, ipc_call_t *icall)
  480. {
  481.     char *name = NULL;
  482.     size_t name_size;
  483.     const devmap_device_t *dev;
  484.     ipc_callid_t callid;
  485.     ipcarg_t retval;
  486.    
  487.    
  488.     /*
  489.      * Wait for incoming message with device name (but do not
  490.      * read the name itself until the buffer is allocated).
  491.      */
  492.     if (!ipc_data_write_receive(&callid, &name_size)) {
  493.         ipc_answer_0(callid, EREFUSED);
  494.         ipc_answer_0(iid, EREFUSED);
  495.         return;
  496.     }
  497.  
  498.     if (name_size > DEVMAP_NAME_MAXLEN) {
  499.         ipc_answer_0(callid, EINVAL);
  500.         ipc_answer_0(iid, EREFUSED);
  501.         return;
  502.     }
  503.  
  504.     /*
  505.      * Allocate buffer for device name.
  506.      */
  507.     if (NULL == (name = (char *)malloc(name_size))) {
  508.         ipc_answer_0(callid, ENOMEM);
  509.         ipc_answer_0(iid, EREFUSED);
  510.         return;
  511.     }  
  512.  
  513.     /*
  514.      * Send confirmation to sender and get data into buffer.
  515.      */
  516.     if (EOK != (retval = ipc_data_write_deliver(callid, name, name_size))) {
  517.         ipc_answer_0(iid, EREFUSED);
  518.         return;
  519.     }
  520.  
  521.     /*
  522.      * Find device name in linked list of known devices.
  523.      */
  524.     dev = devmap_device_find_name(name);
  525.  
  526.     /*
  527.      * Device was not found.
  528.      */
  529.     if (NULL == dev) {
  530.         printf("DEVMAP: device %s has not been registered.\n", name);
  531.         ipc_answer_0(iid, ENOENT);
  532.         return;
  533.     }
  534.  
  535.     printf("DEVMAP: device %s has handler %d.\n", name, dev->handle);
  536.        
  537.     ipc_answer_1(iid, EOK, dev->handle);
  538.  
  539.     return;
  540. }
  541.  
  542. /** Find name of device identified by id and send it to caller.
  543.  *
  544.  */
  545. static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall)
  546. {
  547.     const devmap_device_t *device;
  548.     size_t name_size;
  549.  
  550.     device = devmap_device_find_handle(IPC_GET_ARG1(*icall));
  551.  
  552.     /*
  553.      * Device not found.
  554.      */
  555.     if (NULL == device) {
  556.         ipc_answer_0(iid, ENOENT);
  557.         return;
  558.     }  
  559.  
  560.     ipc_answer_0(iid, EOK);
  561.  
  562.     name_size = strlen(device->name);
  563.  
  564.  
  565. /*  FIXME:
  566.     we have no channel from DEVMAP to client ->
  567.     sending must be initiated by client
  568.  
  569.     int rc = ipc_data_write_send(phone, device->name, name_size);
  570.     if (rc != EOK) {
  571.         async_wait_for(req, NULL);
  572.         return rc;
  573.     }
  574. */ 
  575.     /* TODO: send name in response */
  576.  
  577.     return;
  578. }
  579.  
  580. /** Handle connection with device driver.
  581.  *
  582.  */
  583. static void
  584. devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
  585. {
  586.     ipc_callid_t callid;
  587.     ipc_call_t call;
  588.     bool cont = true;
  589.     devmap_driver_t *driver = NULL;
  590.  
  591.     ipc_answer_0(iid, EOK);
  592.  
  593.     devmap_driver_register(&driver);
  594.  
  595.     if (NULL == driver) {
  596.         printf("DEVMAP: driver registration failed.\n");
  597.         return;
  598.     }
  599.    
  600.     while (cont) {
  601.         callid = async_get_call(&call);
  602.  
  603.         switch (IPC_GET_METHOD(call)) {
  604.         case IPC_M_PHONE_HUNGUP:
  605.             printf("DEVMAP: connection hung up.\n");
  606.             cont = false;
  607.             continue; /* Exit thread */
  608.         case DEVMAP_DRIVER_UNREGISTER:
  609.             printf("DEVMAP: unregister driver.\n");
  610.             if (NULL == driver) {
  611.                 printf("DEVMAP: driver was not registered!\n");
  612.                 ipc_answer_0(callid, ENOENT);
  613.             } else {
  614.                 ipc_answer_0(callid, EOK);
  615.             }
  616.             break;
  617.         case DEVMAP_DEVICE_REGISTER:
  618.             /* Register one instance of device */
  619.             devmap_device_register(callid, &call, driver);
  620.             break;
  621.         case DEVMAP_DEVICE_UNREGISTER:
  622.             /* Remove instance of device identified by handler */
  623.             devmap_device_unregister(callid, &call, driver);
  624.             break;
  625.         case DEVMAP_DEVICE_GET_HANDLE:
  626.             devmap_get_handle(callid, &call);
  627.             break;
  628.         case DEVMAP_DEVICE_GET_NAME:
  629.             devmap_get_handle(callid, &call);
  630.             break;
  631.         default:
  632.             if (!(callid & IPC_CALLID_NOTIFICATION)) {
  633.                 ipc_answer_0(callid, ENOENT);
  634.             }
  635.         }
  636.     }
  637.    
  638.     if (NULL != driver) {
  639.         /*
  640.          * Unregister the device driver and all its devices.
  641.          */
  642.         devmap_driver_unregister(driver);
  643.         driver = NULL;
  644.     }
  645.    
  646. }
  647.  
  648. /** Handle connection with device client.
  649.  *
  650.  */
  651. static void
  652. devmap_connection_client(ipc_callid_t iid, ipc_call_t *icall)
  653. {
  654.     ipc_callid_t callid;
  655.     ipc_call_t call;
  656.     bool cont = true;
  657.  
  658.     ipc_answer_0(iid, EOK); /* Accept connection */
  659.  
  660.     while (cont) {
  661.         callid = async_get_call(&call);
  662.  
  663.         switch (IPC_GET_METHOD(call)) {
  664.         case IPC_M_PHONE_HUNGUP:
  665.             printf("DEVMAP: connection hung up.\n");
  666.             cont = false;
  667.             continue; /* Exit thread */
  668.  
  669.         case DEVMAP_DEVICE_GET_HANDLE:
  670.             devmap_get_handle(callid, &call);
  671.  
  672.             break;
  673.         case DEVMAP_DEVICE_GET_NAME:
  674.             /* TODO */
  675.             devmap_get_name(callid, &call);
  676.             break;
  677.         default:
  678.             if (!(callid & IPC_CALLID_NOTIFICATION)) {
  679.                 ipc_answer_0(callid, ENOENT);
  680.             }
  681.         }
  682.     }
  683. }
  684.  
  685. /** Function for handling connections to devmap
  686.  *
  687.  */
  688. static void
  689. devmap_connection(ipc_callid_t iid, ipc_call_t *icall)
  690. {
  691.  
  692.     printf("DEVMAP: new connection.\n");
  693.  
  694.         /* Select interface */
  695.     switch ((ipcarg_t)(IPC_GET_ARG1(*icall))) {
  696.     case DEVMAP_DRIVER:
  697.         devmap_connection_driver(iid, icall);
  698.         break;
  699.     case DEVMAP_CLIENT:
  700.         devmap_connection_client(iid, icall);
  701.         break;
  702.     case DEVMAP_CONNECT_TO_DEVICE:
  703.             /* Connect client to selected device */
  704.         printf("DEVMAP: connect to device %d.\n",
  705.             IPC_GET_ARG2(*icall));
  706.         devmap_forward(iid, icall);
  707.         break;
  708.     default:
  709.         ipc_answer_0(iid, ENOENT); /* No such interface */
  710.         printf("DEVMAP: Unknown interface %u.\n",
  711.             (ipcarg_t)(IPC_GET_ARG1(*icall)));
  712.     }
  713.  
  714.     /* Cleanup */
  715.    
  716.     printf("DEVMAP: connection closed.\n");
  717.     return;
  718. }
  719.  
  720. /**
  721.  *
  722.  */
  723. int main(int argc, char *argv[])
  724. {
  725.     ipcarg_t phonead;
  726.  
  727.     printf("DEVMAP: HelenOS device mapper.\n");
  728.  
  729.     if (devmap_init() != 0) {
  730.         printf("Error while initializing DEVMAP service.\n");
  731.         return -1;
  732.     }
  733.  
  734.         /* Set a handler of incomming connections */
  735.     async_set_client_connection(devmap_connection);
  736.  
  737.     /* Register device mapper at naming service */
  738.     if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAP, 0, 0, &phonead) != 0)
  739.         return -1;
  740.    
  741.     async_manager();
  742.     /* Never reached */
  743.     return 0;
  744. }
  745.  
  746. /**
  747.  * @}
  748.  */
  749.  
  750.