Subversion Repositories HelenOS

Rev

Rev 2555 | Rev 2598 | 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. /** Unregister device and free it. Its assumed that driver's device list
  158.  * is already locked.
  159.  *
  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. /** Read info about new driver and add it into linked list of registered drivers.
  175.  */
  176. static void devmap_driver_register(devmap_driver_t **odriver)
  177. {
  178.     size_t name_size;
  179.     ipc_callid_t callid;
  180.     ipc_call_t call;
  181.     devmap_driver_t *driver;
  182.     ipc_callid_t iid;
  183.     ipc_call_t icall;
  184.  
  185.     *odriver = NULL;
  186.    
  187.     iid = async_get_call(&icall);
  188.  
  189.     if (IPC_GET_METHOD(icall) != DEVMAP_DRIVER_REGISTER) {
  190.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  191.         return;
  192.     }
  193.  
  194.     if (NULL == (driver = (devmap_driver_t *)malloc(sizeof(devmap_driver_t)))) {
  195.         ipc_answer_fast(iid, ENOMEM, 0, 0);
  196.         return;
  197.     }
  198.  
  199.     /*
  200.      * Get driver name
  201.      */
  202.     if (!ipc_data_receive(&callid, &call, NULL, &name_size)) {
  203.         printf("Unexpected request: %u.\n", IPC_GET_METHOD(call));
  204.         free(driver);
  205.         ipc_answer_fast(callid, EREFUSED, 0, 0);
  206.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  207.         return;
  208.     }
  209.  
  210.     if (name_size > DEVMAP_NAME_MAXLEN) {
  211.         printf("Too logn name: %u: maximum is %u.\n", name_size, DEVMAP_NAME_MAXLEN);
  212.         free(driver);
  213.         ipc_answer_fast(callid, EINVAL, 0, 0);
  214.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  215.         return;
  216.     }
  217.  
  218.     /*
  219.      * Allocate buffer for device name.
  220.      */
  221.     if (NULL == (driver->name = (char *)malloc(name_size + 1))) {
  222.         printf("Cannot allocate space for driver name.\n");
  223.         free(driver);
  224.         ipc_answer_fast(callid, ENOMEM, 0, 0);
  225.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  226.         return;
  227.     }  
  228.  
  229.     /*
  230.      * Send confirmation to sender and get data into buffer.
  231.      */
  232.     if (EOK != ipc_data_deliver(callid, &call, driver->name, name_size)) {
  233.         printf("Cannot read driver name.\n");
  234.         free(driver->name);
  235.         free(driver);
  236.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  237.         return;
  238.     }
  239.  
  240.     driver->name[name_size] = 0;
  241.  
  242.     printf("Read driver name: '%s'.\n", driver->name);
  243.  
  244.     /* Initialize futex for list of devices owned by this driver */
  245.     futex_initialize(&(driver->devices_futex) ,1);
  246.  
  247.     /*
  248.      * Initialize list of asociated devices
  249.      */
  250.     list_initialize(&(driver->devices));
  251.  
  252.     /*
  253.      * Create connection to the driver
  254.      */
  255.     callid = async_get_call(&call);
  256.  
  257.     if (IPC_M_CONNECT_TO_ME != IPC_GET_METHOD(call)) {
  258.         printf("DevMap: Unexpected method: %u.\n", \
  259.             IPC_GET_METHOD(call));
  260.         ipc_answer_fast(callid, ENOTSUP, 0, 0);
  261.        
  262.         free(driver->name);
  263.         free(driver);
  264.         ipc_answer_fast(iid, ENOTSUP, 0, 0);
  265.         return;
  266.     }
  267.  
  268.     driver->phone = IPC_GET_ARG3(call);
  269.    
  270.     ipc_answer_fast(callid, EOK, 0, 0);
  271.    
  272.     list_initialize(&(driver->drivers));
  273.  
  274.     futex_down(&drivers_list_futex);   
  275.    
  276.     /* TODO: check that no driver with name equals to driver->name is registered */
  277.  
  278.     /*
  279.      * Insert new driver into list of registered drivers
  280.      */
  281.     list_append(&(driver->drivers), &drivers_list);
  282.     futex_up(&drivers_list_futex); 
  283.    
  284.     ipc_answer_fast(iid, EOK, 0, 0);
  285.     printf("Driver registered.\n");
  286.  
  287.     *odriver = driver;
  288.     return;
  289. }
  290.  
  291. /** Unregister device driver, unregister all its devices and free driver structure.
  292.  *
  293.  */
  294. static int devmap_driver_unregister(devmap_driver_t *driver)
  295. {
  296.     devmap_device_t *device;
  297.  
  298.     if (NULL == driver) {
  299.         printf("Error: driver == NULL.\n");
  300.         return EEXISTS;
  301.     }
  302.  
  303.     printf("Unregister driver '%s'.\n", driver->name);
  304.     futex_down(&drivers_list_futex);   
  305.  
  306.     ipc_hangup(driver->phone);
  307.    
  308.     /* remove it from list of drivers */
  309.     list_remove(&(driver->drivers));
  310.  
  311.     /* unregister all its devices */
  312.    
  313.     futex_down(&devices_list_futex);   
  314.     futex_down(&(driver->devices_futex));
  315.  
  316.     while (!list_empty(&(driver->devices))) {
  317.         device = list_get_instance(driver->devices.next, devmap_device_t, driver_devices);
  318.         printf("Unregister device '%s'.\n", device->name);
  319.         devmap_device_unregister_core(device);
  320.     }
  321.    
  322.     futex_up(&(driver->devices_futex));
  323.     futex_up(&devices_list_futex); 
  324.     futex_up(&drivers_list_futex); 
  325.  
  326.     /* free name and driver */
  327.     if (NULL != driver->name) {
  328.         free(driver->name);
  329.     }
  330.  
  331.     free(driver);
  332.  
  333.     printf("Driver unregistered.\n");
  334.  
  335.     return EOK;
  336. }
  337.  
  338.  
  339. /** Register instance of device
  340.  *
  341.  */
  342. static void devmap_device_register(ipc_callid_t iid, ipc_call_t *icall,
  343.         devmap_driver_t *driver)
  344. {
  345.     ipc_callid_t callid;
  346.     ipc_call_t call;
  347.     size_t size;
  348.     devmap_device_t *device;
  349.  
  350.     if (NULL == driver) {
  351.         printf("Invalid driver registration.\n");
  352.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  353.         return;
  354.     }
  355.    
  356.     /* Create new device entry */
  357.     if (NULL == (device = (devmap_device_t *)malloc(sizeof(devmap_device_t)))) {
  358.         printf("Cannot allocate new device.\n");
  359.         ipc_answer_fast(iid, ENOMEM, 0, 0);
  360.         return;
  361.     }
  362.    
  363.     /* Get device name */
  364.     if (!ipc_data_receive(&callid, &call, NULL, &size)) {
  365.         free(device);
  366.         printf("Cannot read device name.\n");
  367.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  368.         return;
  369.     }
  370.  
  371.     if (size > DEVMAP_NAME_MAXLEN) {
  372.         printf("Too long device name: %u.\n", size);
  373.         free(device);
  374.         ipc_answer_fast(callid, EINVAL, 0, 0);
  375.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  376.         return;
  377.     }
  378.  
  379.         /* +1 for terminating \0 */
  380.     device->name = (char *)malloc(size + 1);
  381.  
  382.     if (NULL == device->name) {
  383.         printf("Cannot read device name.\n");
  384.         free(device);
  385.         ipc_answer_fast(callid, ENOMEM, 0, 0);
  386.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  387.         return;
  388.     }
  389.    
  390.     ipc_data_deliver(callid, &call, device->name, size);
  391.     device->name[size] = 0;
  392.  
  393.     list_initialize(&(device->devices));
  394.     list_initialize(&(device->driver_devices));
  395.  
  396.     futex_down(&devices_list_futex);   
  397.  
  398.     /* Check that device with such name is not already registered */
  399.     if (NULL != devmap_device_find_name(device->name)) {
  400.         printf("Device '%s' already registered.\n", device->name);
  401.         futex_up(&devices_list_futex); 
  402.         free(device->name);
  403.         free(device);
  404.         ipc_answer_fast(iid, EEXISTS, 0, 0);
  405.         return;
  406.     }
  407.  
  408.     /* Get unique device handle */
  409.     device->handle = devmap_create_handle();
  410.  
  411.     device->driver = driver;
  412.    
  413.     /* Insert device into list of all devices  */
  414.     list_append(&(device->devices), &devices_list);
  415.  
  416.     /* Insert device into list of devices that belog to one driver */
  417.     futex_down(&(device->driver->devices_futex));  
  418.    
  419.     list_append(&(device->driver_devices), &(device->driver->devices));
  420.    
  421.     futex_up(&(device->driver->devices_futex));
  422.     futex_up(&devices_list_futex); 
  423.  
  424.     printf("Device '%s' registered.\n", device->name); 
  425.     ipc_answer_fast(iid, EOK, device->handle, 0);
  426.  
  427.     return;
  428. }
  429.  
  430. /**
  431.  *
  432.  */
  433. static int devmap_device_unregister(ipc_callid_t iid, ipc_call_t *icall,
  434.     devmap_driver_t *driver)
  435. {
  436.     /* TODO */
  437.  
  438.     return EOK;
  439. }
  440.  
  441. /** Connect client to the device.
  442.  * Find device driver owning requested device and forward
  443.  * the message to it.
  444.  *
  445.  *
  446.  */
  447. static void devmap_forward(ipc_callid_t callid, ipc_call_t *call)
  448. {
  449.     devmap_device_t *dev;
  450.     int handle;
  451.  
  452.     /*
  453.      * Get handle from request
  454.      */
  455.     handle = IPC_GET_ARG1(*call);
  456.     dev = devmap_device_find_handle(handle);
  457.  
  458.     if (NULL == dev) {
  459.         printf("DevMap: No registered device with handle %d.\n", handle);
  460.         ipc_answer_fast(callid, ENOENT, 0, 0);
  461.         return;
  462.     }
  463.  
  464.         /* FIXME: is this correct method how to pass argument on forwarding ?*/
  465.     ipc_forward_fast(callid, dev->driver->phone, (ipcarg_t)(dev->handle), 0);
  466.     return;
  467. }
  468.  
  469. /** Find handle for device instance identified by name.
  470.  * In answer will be send EOK and device handle in arg1 or a error
  471.  * code from errno.h.
  472.  */
  473. static void devmap_get_handle(ipc_callid_t iid, ipc_call_t *icall)
  474. {
  475.     char *name = NULL;
  476.     size_t name_size;
  477.     const devmap_device_t *dev;
  478.     ipc_callid_t callid;
  479.     ipc_call_t call;
  480.     ipcarg_t retval;
  481.    
  482.    
  483.     /*
  484.      * Wait for incoming message with device name (but do not
  485.      * read the name itself until the buffer is allocated).
  486.      */
  487.     if (!ipc_data_receive(&callid, &call, NULL, &name_size)) {
  488.         ipc_answer_fast(callid, EREFUSED, 0, 0);
  489.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  490.         return;
  491.     }
  492.  
  493.     if (name_size > DEVMAP_NAME_MAXLEN) {
  494.         ipc_answer_fast(callid, EINVAL, 0, 0);
  495.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  496.         return;
  497.     }
  498.  
  499.     /*
  500.      * Allocate buffer for device name.
  501.      */
  502.     if (NULL == (name = (char *)malloc(name_size))) {
  503.         ipc_answer_fast(callid, ENOMEM, 0, 0);
  504.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  505.         return;
  506.     }  
  507.  
  508.     /*
  509.      * Send confirmation to sender and get data into buffer.
  510.      */
  511.     if (EOK != (retval = ipc_data_deliver(callid, &call, name, name_size))) {
  512.         ipc_answer_fast(iid, EREFUSED, 0, 0);
  513.         return;
  514.     }
  515.  
  516.     /*
  517.      * Find device name in linked list of known devices.
  518.      */
  519.     dev = devmap_device_find_name(name);
  520.  
  521.     /*
  522.      * Device was not found.
  523.      */
  524.     if (NULL == dev) {
  525.         printf("DevMap: device %s has not been registered.\n", name);
  526.         ipc_answer_fast(iid, ENOENT, 0, 0);
  527.         return;
  528.     }
  529.  
  530.     printf("DevMap: device %s has handler %d.\n", name, dev->handle);
  531.        
  532.     ipc_answer_fast(iid, EOK, dev->handle, 0);
  533.  
  534.     return;
  535. }
  536.  
  537. /** Find name of device identified by id and send it to caller.
  538.  *
  539.  */
  540. static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall)
  541. {
  542.     const devmap_device_t *device;
  543.     size_t name_size;
  544.  
  545.     device = devmap_device_find_handle(IPC_GET_ARG1(*icall));
  546.  
  547.     /*
  548.      * Device not found.
  549.      */
  550.     if (NULL == device) {
  551.         ipc_answer_fast(iid, ENOENT, 0, 0);
  552.         return;
  553.     }  
  554.  
  555.     ipc_answer_fast(iid, EOK, 0, 0);
  556.  
  557.     name_size = strlen(device->name);
  558.  
  559.  
  560. /*  FIXME:
  561.     we have no channel from DevMap to client ->
  562.     sending must be initiated by client
  563.  
  564.     int rc = ipc_data_send(phone, device->name, name_size);
  565.     if (rc != EOK) {
  566.         async_wait_for(req, NULL);
  567.         return rc;
  568.     }
  569. */ 
  570.     /* TODO: send name in response */
  571.  
  572.     return;
  573. }
  574.  
  575. /** Handle connection with device driver.
  576.  *
  577.  */
  578. static void
  579. devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
  580. {
  581.     ipc_callid_t callid;
  582.     ipc_call_t call;
  583.     bool cont = true;
  584.     devmap_driver_t *driver = NULL;
  585.  
  586.     ipc_answer_fast(iid, EOK, 0, 0);
  587.  
  588.     devmap_driver_register(&driver);
  589.  
  590.     if (NULL == driver) {
  591.         printf("DevMap: driver registration failed.\n");
  592.         return;
  593.     }
  594.    
  595.     while (cont) {
  596.         callid = async_get_call(&call);
  597.  
  598.         switch (IPC_GET_METHOD(call)) {
  599.         case IPC_M_PHONE_HUNGUP:
  600.             printf("DevMap: connection hung up.\n");
  601.             cont = false;
  602.             continue; /* Exit thread */
  603.         case DEVMAP_DRIVER_UNREGISTER:
  604.             printf("DevMap: unregister driver.\n");
  605.             if (NULL == driver) {
  606.                 printf("DevMap: driver was not registered!\n");
  607.                 ipc_answer_fast(callid, ENOENT, 0, 0);
  608.             } else {
  609.                 ipc_answer_fast(callid, EOK, 0, 0);
  610.             }
  611.             break;
  612.         case DEVMAP_DEVICE_REGISTER:
  613.             /* Register one instance of device */
  614.             devmap_device_register(callid, &call, driver);
  615.             break;
  616.         case DEVMAP_DEVICE_UNREGISTER:
  617.             /* Remove instance of device identified by handler */
  618.             devmap_device_unregister(callid, &call, driver);
  619.             break;
  620.         case DEVMAP_DEVICE_GET_HANDLE:
  621.             devmap_get_handle(callid, &call);
  622.             break;
  623.         case DEVMAP_DEVICE_GET_NAME:
  624.             devmap_get_handle(callid, &call);
  625.             break;
  626.         default:
  627.             if (!(callid & IPC_CALLID_NOTIFICATION)) {
  628.                 ipc_answer_fast(callid, ENOENT, 0, 0);
  629.             }
  630.         }
  631.     }
  632.    
  633.     if (NULL != driver) {
  634.             /*
  635.              * Unregister the device driver and all its devices.
  636.              */
  637.         devmap_driver_unregister(driver);
  638.         driver = NULL;
  639.     }
  640.    
  641. }
  642.  
  643. /** Handle connection with device client.
  644.  *
  645.  */
  646. static void
  647. devmap_connection_client(ipc_callid_t iid, ipc_call_t *icall)
  648. {
  649.     ipc_callid_t callid;
  650.     ipc_call_t call;
  651.     bool cont = true;
  652.  
  653.     ipc_answer_fast(iid, EOK, 0, 0); /* Accept connection */
  654.  
  655.     while (cont) {
  656.         callid = async_get_call(&call);
  657.  
  658.         switch (IPC_GET_METHOD(call)) {
  659.         case IPC_M_PHONE_HUNGUP:
  660.             printf("DevMap: connection hung up.\n");
  661.             cont = false;
  662.             continue; /* Exit thread */
  663.  
  664.         case DEVMAP_DEVICE_CONNECT_ME_TO:
  665.             /* Connect client to selected device */
  666.             printf("DevMap: connect to device %d.\n", IPC_GET_ARG1(call));
  667.             devmap_forward(callid, &call);
  668.             break;
  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_fast(callid, ENOENT, 0, 0);
  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.         default:
  704.             ipc_answer_fast(iid, ENOENT, 0, 0); /* No such interface */
  705.             printf("DevMap: Unknown interface %u.\n", \
  706.                 (ipcarg_t)(IPC_GET_ARG1(*icall)));
  707.     }
  708.  
  709.     /* Cleanup */
  710.    
  711.     printf("DevMap: connection closed.\n");
  712.     return;
  713. }
  714.  
  715. /**
  716.  *
  717.  */
  718. int main(int argc, char *argv[])
  719. {
  720.     ipcarg_t phonead;
  721.  
  722.     printf("DevMap: HelenOS device mapper.\n");
  723.  
  724.     if (devmap_init() != 0) {
  725.         printf("Error while initializing DevMap service.\n");
  726.         return -1;
  727.     }
  728.  
  729.         /* Set a handler of incomming connections */
  730.     async_set_client_connection(devmap_connection);
  731.  
  732.         /* Register device mapper at naming service */
  733.     if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAP, 0, &phonead) != 0)
  734.         return -1;
  735.    
  736.     async_manager();
  737.     /* Never reached */
  738.     return 0;
  739. }
  740.  
  741. /**
  742.  * @}
  743.  */
  744.  
  745.