Subversion Repositories HelenOS

Rev

Rev 2678 | 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_finalize(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_finalize(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_finalize(callid, name,
  517.         name_size))) {
  518.         ipc_answer_0(iid, EREFUSED);
  519.         return;
  520.     }
  521.  
  522.     /*
  523.      * Find device name in linked list of known devices.
  524.      */
  525.     dev = devmap_device_find_name(name);
  526.  
  527.     /*
  528.      * Device was not found.
  529.      */
  530.     if (NULL == dev) {
  531.         printf("DEVMAP: device %s has not been registered.\n", name);
  532.         ipc_answer_0(iid, ENOENT);
  533.         return;
  534.     }
  535.  
  536.     printf("DEVMAP: device %s has handler %d.\n", name, dev->handle);
  537.        
  538.     ipc_answer_1(iid, EOK, dev->handle);
  539.  
  540.     return;
  541. }
  542.  
  543. /** Find name of device identified by id and send it to caller.
  544.  *
  545.  */
  546. static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall)
  547. {
  548.     const devmap_device_t *device;
  549.     size_t name_size;
  550.  
  551.     device = devmap_device_find_handle(IPC_GET_ARG1(*icall));
  552.  
  553.     /*
  554.      * Device not found.
  555.      */
  556.     if (NULL == device) {
  557.         ipc_answer_0(iid, ENOENT);
  558.         return;
  559.     }  
  560.  
  561.     ipc_answer_0(iid, EOK);
  562.  
  563.     name_size = strlen(device->name);
  564.  
  565.  
  566. /*  FIXME:
  567.     we have no channel from DEVMAP to client ->
  568.     sending must be initiated by client
  569.  
  570.     int rc = ipc_data_write_send(phone, device->name, name_size);
  571.     if (rc != EOK) {
  572.         async_wait_for(req, NULL);
  573.         return rc;
  574.     }
  575. */ 
  576.     /* TODO: send name in response */
  577.  
  578.     return;
  579. }
  580.  
  581. /** Handle connection with device driver.
  582.  *
  583.  */
  584. static void
  585. devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
  586. {
  587.     ipc_callid_t callid;
  588.     ipc_call_t call;
  589.     bool cont = true;
  590.     devmap_driver_t *driver = NULL;
  591.  
  592.     ipc_answer_0(iid, EOK);
  593.  
  594.     devmap_driver_register(&driver);
  595.  
  596.     if (NULL == driver) {
  597.         printf("DEVMAP: driver registration failed.\n");
  598.         return;
  599.     }
  600.    
  601.     while (cont) {
  602.         callid = async_get_call(&call);
  603.  
  604.         switch (IPC_GET_METHOD(call)) {
  605.         case IPC_M_PHONE_HUNGUP:
  606.             printf("DEVMAP: connection hung up.\n");
  607.             cont = false;
  608.             continue; /* Exit thread */
  609.         case DEVMAP_DRIVER_UNREGISTER:
  610.             printf("DEVMAP: unregister driver.\n");
  611.             if (NULL == driver) {
  612.                 printf("DEVMAP: driver was not registered!\n");
  613.                 ipc_answer_0(callid, ENOENT);
  614.             } else {
  615.                 ipc_answer_0(callid, EOK);
  616.             }
  617.             break;
  618.         case DEVMAP_DEVICE_REGISTER:
  619.             /* Register one instance of device */
  620.             devmap_device_register(callid, &call, driver);
  621.             break;
  622.         case DEVMAP_DEVICE_UNREGISTER:
  623.             /* Remove instance of device identified by handler */
  624.             devmap_device_unregister(callid, &call, driver);
  625.             break;
  626.         case DEVMAP_DEVICE_GET_HANDLE:
  627.             devmap_get_handle(callid, &call);
  628.             break;
  629.         case DEVMAP_DEVICE_GET_NAME:
  630.             devmap_get_handle(callid, &call);
  631.             break;
  632.         default:
  633.             if (!(callid & IPC_CALLID_NOTIFICATION)) {
  634.                 ipc_answer_0(callid, ENOENT);
  635.             }
  636.         }
  637.     }
  638.    
  639.     if (NULL != driver) {
  640.         /*
  641.          * Unregister the device driver and all its devices.
  642.          */
  643.         devmap_driver_unregister(driver);
  644.         driver = NULL;
  645.     }
  646.    
  647. }
  648.  
  649. /** Handle connection with device client.
  650.  *
  651.  */
  652. static void
  653. devmap_connection_client(ipc_callid_t iid, ipc_call_t *icall)
  654. {
  655.     ipc_callid_t callid;
  656.     ipc_call_t call;
  657.     bool cont = true;
  658.  
  659.     ipc_answer_0(iid, EOK); /* Accept connection */
  660.  
  661.     while (cont) {
  662.         callid = async_get_call(&call);
  663.  
  664.         switch (IPC_GET_METHOD(call)) {
  665.         case IPC_M_PHONE_HUNGUP:
  666.             printf("DEVMAP: connection hung up.\n");
  667.             cont = false;
  668.             continue; /* Exit thread */
  669.  
  670.         case DEVMAP_DEVICE_GET_HANDLE:
  671.             devmap_get_handle(callid, &call);
  672.  
  673.             break;
  674.         case DEVMAP_DEVICE_GET_NAME:
  675.             /* TODO */
  676.             devmap_get_name(callid, &call);
  677.             break;
  678.         default:
  679.             if (!(callid & IPC_CALLID_NOTIFICATION)) {
  680.                 ipc_answer_0(callid, ENOENT);
  681.             }
  682.         }
  683.     }
  684. }
  685.  
  686. /** Function for handling connections to devmap
  687.  *
  688.  */
  689. static void
  690. devmap_connection(ipc_callid_t iid, ipc_call_t *icall)
  691. {
  692.  
  693.     printf("DEVMAP: new connection.\n");
  694.  
  695.         /* Select interface */
  696.     switch ((ipcarg_t)(IPC_GET_ARG1(*icall))) {
  697.     case DEVMAP_DRIVER:
  698.         devmap_connection_driver(iid, icall);
  699.         break;
  700.     case DEVMAP_CLIENT:
  701.         devmap_connection_client(iid, icall);
  702.         break;
  703.     case DEVMAP_CONNECT_TO_DEVICE:
  704.             /* Connect client to selected device */
  705.         printf("DEVMAP: connect to device %d.\n",
  706.             IPC_GET_ARG2(*icall));
  707.         devmap_forward(iid, icall);
  708.         break;
  709.     default:
  710.         ipc_answer_0(iid, ENOENT); /* No such interface */
  711.         printf("DEVMAP: Unknown interface %u.\n",
  712.             (ipcarg_t)(IPC_GET_ARG1(*icall)));
  713.     }
  714.  
  715.     /* Cleanup */
  716.    
  717.     printf("DEVMAP: connection closed.\n");
  718.     return;
  719. }
  720.  
  721. /**
  722.  *
  723.  */
  724. int main(int argc, char *argv[])
  725. {
  726.     ipcarg_t phonead;
  727.  
  728.     printf("DEVMAP: HelenOS device mapper.\n");
  729.  
  730.     if (devmap_init() != 0) {
  731.         printf("Error while initializing DEVMAP service.\n");
  732.         return -1;
  733.     }
  734.  
  735.         /* Set a handler of incomming connections */
  736.     async_set_client_connection(devmap_connection);
  737.  
  738.     /* Register device mapper at naming service */
  739.     if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAP, 0, 0, &phonead) != 0)
  740.         return -1;
  741.    
  742.     async_manager();
  743.     /* Never reached */
  744.     return 0;
  745. }
  746.  
  747. /**
  748.  * @}
  749.  */
  750.  
  751.