Subversion Repositories HelenOS

Rev

Rev 2594 | Rev 2622 | 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_fast(iid, EREFUSED, 0, 0);
  193.         return;
  194.     }
  195.  
  196.     if (NULL ==
  197.         (driver = (devmap_driver_t *)malloc(sizeof(devmap_driver_t)))) {
  198.         ipc_answer_fast(iid, ENOMEM, 0, 0);
  199.         return;
  200.     }
  201.  
  202.     /*
  203.      * Get driver name
  204.      */
  205.     if (!ipc_data_receive(&callid, &call, NULL, &name_size)) {
  206.         printf("Unexpected request: %u.\n", IPC_GET_METHOD(call));
  207.         free(driver);
  208.         ipc_answer_fast(callid, EREFUSED, 0, 0);
  209.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  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_fast(callid, EINVAL, 0, 0);
  218.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  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_fast(callid, ENOMEM, 0, 0);
  229.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  230.         return;
  231.     }  
  232.  
  233.     /*
  234.      * Send confirmation to sender and get data into buffer.
  235.      */
  236.     if (EOK != ipc_data_deliver(callid, &call, driver->name, name_size)) {
  237.         printf("Cannot read driver name.\n");
  238.         free(driver->name);
  239.         free(driver);
  240.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  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_fast(callid, ENOTSUP, 0, 0);
  265.        
  266.         free(driver->name);
  267.         free(driver);
  268.         ipc_answer_fast(iid, ENOTSUP, 0, 0);
  269.         return;
  270.     }
  271.  
  272.     driver->phone = IPC_GET_ARG3(call);
  273.    
  274.     ipc_answer_fast(callid, EOK, 0, 0);
  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_fast(iid, EOK, 0, 0);
  291.     printf("Driver registered.\n");
  292.  
  293.     *odriver = driver;
  294.     return;
  295. }
  296.  
  297. /** Unregister device driver, unregister all its devices and free driver structure.
  298.  *
  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.     ipc_call_t call;
  354.     size_t size;
  355.     devmap_device_t *device;
  356.  
  357.     if (NULL == driver) {
  358.         printf("Invalid driver registration.\n");
  359.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  360.         return;
  361.     }
  362.    
  363.     /* Create new device entry */
  364.     if (NULL ==
  365.         (device = (devmap_device_t *)malloc(sizeof(devmap_device_t)))) {
  366.         printf("Cannot allocate new device.\n");
  367.         ipc_answer_fast(iid, ENOMEM, 0, 0);
  368.         return;
  369.     }
  370.    
  371.     /* Get device name */
  372.     if (!ipc_data_receive(&callid, &call, NULL, &size)) {
  373.         free(device);
  374.         printf("Cannot read device name.\n");
  375.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  376.         return;
  377.     }
  378.  
  379.     if (size > DEVMAP_NAME_MAXLEN) {
  380.         printf("Too long device name: %u.\n", size);
  381.         free(device);
  382.         ipc_answer_fast(callid, EINVAL, 0, 0);
  383.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  384.         return;
  385.     }
  386.  
  387.         /* +1 for terminating \0 */
  388.     device->name = (char *)malloc(size + 1);
  389.  
  390.     if (NULL == device->name) {
  391.         printf("Cannot read device name.\n");
  392.         free(device);
  393.         ipc_answer_fast(callid, ENOMEM, 0, 0);
  394.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  395.         return;
  396.     }
  397.    
  398.     ipc_data_deliver(callid, &call, device->name, size);
  399.     device->name[size] = 0;
  400.  
  401.     list_initialize(&(device->devices));
  402.     list_initialize(&(device->driver_devices));
  403.  
  404.     futex_down(&devices_list_futex);   
  405.  
  406.     /* Check that device with such name is not already registered */
  407.     if (NULL != devmap_device_find_name(device->name)) {
  408.         printf("Device '%s' already registered.\n", device->name);
  409.         futex_up(&devices_list_futex); 
  410.         free(device->name);
  411.         free(device);
  412.         ipc_answer_fast(iid, EEXISTS, 0, 0);
  413.         return;
  414.     }
  415.  
  416.     /* Get unique device handle */
  417.     device->handle = devmap_create_handle();
  418.  
  419.     device->driver = driver;
  420.    
  421.     /* Insert device into list of all devices  */
  422.     list_append(&(device->devices), &devices_list);
  423.  
  424.     /* Insert device into list of devices that belog to one driver */
  425.     futex_down(&(device->driver->devices_futex));  
  426.    
  427.     list_append(&(device->driver_devices), &(device->driver->devices));
  428.    
  429.     futex_up(&(device->driver->devices_futex));
  430.     futex_up(&devices_list_futex); 
  431.  
  432.     printf("Device '%s' registered.\n", device->name); 
  433.     ipc_answer_fast(iid, EOK, device->handle, 0);
  434.  
  435.     return;
  436. }
  437.  
  438. /**
  439.  *
  440.  */
  441. static int devmap_device_unregister(ipc_callid_t iid, ipc_call_t *icall,
  442.     devmap_driver_t *driver)
  443. {
  444.     /* TODO */
  445.  
  446.     return EOK;
  447. }
  448.  
  449. /** Connect client to the device.
  450.  * Find device driver owning requested device and forward
  451.  * the message to it.
  452.  *
  453.  *
  454.  */
  455. static void devmap_forward(ipc_callid_t callid, ipc_call_t *call)
  456. {
  457.     devmap_device_t *dev;
  458.     int handle;
  459.  
  460.     /*
  461.      * Get handle from request
  462.      */
  463.     handle = IPC_GET_ARG1(*call);
  464.     dev = devmap_device_find_handle(handle);
  465.  
  466.     if (NULL == dev) {
  467.         printf("DevMap: No registered device with handle %d.\n",
  468.             handle);
  469.         ipc_answer_fast(callid, ENOENT, 0, 0);
  470.         return;
  471.     }
  472.  
  473.     /* FIXME: is this correct method how to pass argument on forwarding ?*/
  474.     ipc_forward_fast(callid, dev->driver->phone, (ipcarg_t)(dev->handle),
  475.         0);
  476.     return;
  477. }
  478.  
  479. /** Find handle for device instance identified by name.
  480.  * In answer will be send EOK and device handle in arg1 or a error
  481.  * code from errno.h.
  482.  */
  483. static void devmap_get_handle(ipc_callid_t iid, ipc_call_t *icall)
  484. {
  485.     char *name = NULL;
  486.     size_t name_size;
  487.     const devmap_device_t *dev;
  488.     ipc_callid_t callid;
  489.     ipc_call_t call;
  490.     ipcarg_t retval;
  491.    
  492.    
  493.     /*
  494.      * Wait for incoming message with device name (but do not
  495.      * read the name itself until the buffer is allocated).
  496.      */
  497.     if (!ipc_data_receive(&callid, &call, NULL, &name_size)) {
  498.         ipc_answer_fast(callid, EREFUSED, 0, 0);
  499.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  500.         return;
  501.     }
  502.  
  503.     if (name_size > DEVMAP_NAME_MAXLEN) {
  504.         ipc_answer_fast(callid, EINVAL, 0, 0);
  505.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  506.         return;
  507.     }
  508.  
  509.     /*
  510.      * Allocate buffer for device name.
  511.      */
  512.     if (NULL == (name = (char *)malloc(name_size))) {
  513.         ipc_answer_fast(callid, ENOMEM, 0, 0);
  514.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  515.         return;
  516.     }  
  517.  
  518.     /*
  519.      * Send confirmation to sender and get data into buffer.
  520.      */
  521.     if (EOK != (retval = ipc_data_deliver(callid, &call, name,
  522.         name_size))) {
  523.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  524.         return;
  525.     }
  526.  
  527.     /*
  528.      * Find device name in linked list of known devices.
  529.      */
  530.     dev = devmap_device_find_name(name);
  531.  
  532.     /*
  533.      * Device was not found.
  534.      */
  535.     if (NULL == dev) {
  536.         printf("DevMap: device %s has not been registered.\n", name);
  537.         ipc_answer_fast(iid, ENOENT, 0, 0);
  538.         return;
  539.     }
  540.  
  541.     printf("DevMap: device %s has handler %d.\n", name, dev->handle);
  542.        
  543.     ipc_answer_fast(iid, EOK, dev->handle, 0);
  544.  
  545.     return;
  546. }
  547.  
  548. /** Find name of device identified by id and send it to caller.
  549.  *
  550.  */
  551. static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall)
  552. {
  553.     const devmap_device_t *device;
  554.     size_t name_size;
  555.  
  556.     device = devmap_device_find_handle(IPC_GET_ARG1(*icall));
  557.  
  558.     /*
  559.      * Device not found.
  560.      */
  561.     if (NULL == device) {
  562.         ipc_answer_fast(iid, ENOENT, 0, 0);
  563.         return;
  564.     }  
  565.  
  566.     ipc_answer_fast(iid, EOK, 0, 0);
  567.  
  568.     name_size = strlen(device->name);
  569.  
  570.  
  571. /*  FIXME:
  572.     we have no channel from DevMap to client ->
  573.     sending must be initiated by client
  574.  
  575.     int rc = ipc_data_send(phone, device->name, name_size);
  576.     if (rc != EOK) {
  577.         async_wait_for(req, NULL);
  578.         return rc;
  579.     }
  580. */ 
  581.     /* TODO: send name in response */
  582.  
  583.     return;
  584. }
  585.  
  586. /** Handle connection with device driver.
  587.  *
  588.  */
  589. static void
  590. devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
  591. {
  592.     ipc_callid_t callid;
  593.     ipc_call_t call;
  594.     bool cont = true;
  595.     devmap_driver_t *driver = NULL;
  596.  
  597.     ipc_answer_fast(iid, EOK, 0, 0);
  598.  
  599.     devmap_driver_register(&driver);
  600.  
  601.     if (NULL == driver) {
  602.         printf("DevMap: driver registration failed.\n");
  603.         return;
  604.     }
  605.    
  606.     while (cont) {
  607.         callid = async_get_call(&call);
  608.  
  609.         switch (IPC_GET_METHOD(call)) {
  610.         case IPC_M_PHONE_HUNGUP:
  611.             printf("DevMap: connection hung up.\n");
  612.             cont = false;
  613.             continue; /* Exit thread */
  614.         case DEVMAP_DRIVER_UNREGISTER:
  615.             printf("DevMap: unregister driver.\n");
  616.             if (NULL == driver) {
  617.                 printf("DevMap: driver was not registered!\n");
  618.                 ipc_answer_fast(callid, ENOENT, 0, 0);
  619.             } else {
  620.                 ipc_answer_fast(callid, EOK, 0, 0);
  621.             }
  622.             break;
  623.         case DEVMAP_DEVICE_REGISTER:
  624.             /* Register one instance of device */
  625.             devmap_device_register(callid, &call, driver);
  626.             break;
  627.         case DEVMAP_DEVICE_UNREGISTER:
  628.             /* Remove instance of device identified by handler */
  629.             devmap_device_unregister(callid, &call, driver);
  630.             break;
  631.         case DEVMAP_DEVICE_GET_HANDLE:
  632.             devmap_get_handle(callid, &call);
  633.             break;
  634.         case DEVMAP_DEVICE_GET_NAME:
  635.             devmap_get_handle(callid, &call);
  636.             break;
  637.         default:
  638.             if (!(callid & IPC_CALLID_NOTIFICATION)) {
  639.                 ipc_answer_fast(callid, ENOENT, 0, 0);
  640.             }
  641.         }
  642.     }
  643.    
  644.     if (NULL != driver) {
  645.             /*
  646.              * Unregister the device driver and all its devices.
  647.              */
  648.         devmap_driver_unregister(driver);
  649.         driver = NULL;
  650.     }
  651.    
  652. }
  653.  
  654. /** Handle connection with device client.
  655.  *
  656.  */
  657. static void
  658. devmap_connection_client(ipc_callid_t iid, ipc_call_t *icall)
  659. {
  660.     ipc_callid_t callid;
  661.     ipc_call_t call;
  662.     bool cont = true;
  663.  
  664.     ipc_answer_fast(iid, EOK, 0, 0); /* Accept connection */
  665.  
  666.     while (cont) {
  667.         callid = async_get_call(&call);
  668.  
  669.         switch (IPC_GET_METHOD(call)) {
  670.         case IPC_M_PHONE_HUNGUP:
  671.             printf("DevMap: connection hung up.\n");
  672.             cont = false;
  673.             continue; /* Exit thread */
  674.  
  675.         case DEVMAP_DEVICE_CONNECT_ME_TO:
  676.             /* Connect client to selected device */
  677.             printf("DevMap: connect to device %d.\n",
  678.                 IPC_GET_ARG1(call));
  679.             devmap_forward(callid, &call);
  680.             break;
  681.  
  682.         case DEVMAP_DEVICE_GET_HANDLE:
  683.             devmap_get_handle(callid, &call);
  684.  
  685.             break;
  686.         case DEVMAP_DEVICE_GET_NAME:
  687.             /* TODO */
  688.             devmap_get_name(callid, &call);
  689.             break;
  690.         default:
  691.             if (!(callid & IPC_CALLID_NOTIFICATION)) {
  692.                 ipc_answer_fast(callid, ENOENT, 0, 0);
  693.             }
  694.         }
  695.     }
  696. }
  697.  
  698. /** Function for handling connections to devmap
  699.  *
  700.  */
  701. static void
  702. devmap_connection(ipc_callid_t iid, ipc_call_t *icall)
  703. {
  704.  
  705.     printf("DevMap: new connection.\n");
  706.  
  707.         /* Select interface */
  708.     switch ((ipcarg_t)(IPC_GET_ARG1(*icall))) {
  709.     case DEVMAP_DRIVER:
  710.         devmap_connection_driver(iid, icall);
  711.         break;
  712.     case DEVMAP_CLIENT:
  713.         devmap_connection_client(iid, icall);
  714.         break;
  715.     default:
  716.         ipc_answer_fast(iid, ENOENT, 0, 0); /* No such interface */
  717.         printf("DevMap: Unknown interface %u.\n",
  718.             (ipcarg_t)(IPC_GET_ARG1(*icall)));
  719.     }
  720.  
  721.     /* Cleanup */
  722.    
  723.     printf("DevMap: connection closed.\n");
  724.     return;
  725. }
  726.  
  727. /**
  728.  *
  729.  */
  730. int main(int argc, char *argv[])
  731. {
  732.     ipcarg_t phonead;
  733.  
  734.     printf("DevMap: HelenOS device mapper.\n");
  735.  
  736.     if (devmap_init() != 0) {
  737.         printf("Error while initializing DevMap service.\n");
  738.         return -1;
  739.     }
  740.  
  741.         /* Set a handler of incomming connections */
  742.     async_set_client_connection(devmap_connection);
  743.  
  744.     /* Register device mapper at naming service */
  745.     if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAP, 0, &phonead) != 0)
  746.         return -1;
  747.    
  748.     async_manager();
  749.     /* Never reached */
  750.     return 0;
  751. }
  752.  
  753. /**
  754.  * @}
  755.  */
  756.  
  757.