Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/devmap/devmap.c

    r63e0bdd ra405563  
    4242#include <errno.h>
    4343#include <bool.h>
    44 #include <fibril_synch.h>
     44#include <fibril_sync.h>
    4545#include <stdlib.h>
    46 #include <str.h>
     46#include <string.h>
    4747#include <ipc/devmap.h>
    48 #include <assert.h>
    4948
    5049#define NAME          "devmap"
     
    6261        link_t devices;
    6362        /** Phone asociated with this driver */
    64         sysarg_t phone;
     63        ipcarg_t phone;
    6564        /** Device driver name */
    6665        char *name;
     
    6867        fibril_mutex_t devices_mutex;
    6968} devmap_driver_t;
    70 
    71 /** Info about registered namespaces
    72  *
    73  */
    74 typedef struct {
    75         /** Pointer to the previous and next device in the list of all namespaces */
    76         link_t namespaces;
    77         /** Unique namespace identifier */
    78         devmap_handle_t handle;
    79         /** Namespace name */
    80         char *name;
    81         /** Reference count */
    82         size_t refcnt;
    83 } devmap_namespace_t;
    8469
    8570/** Info about registered device
     
    9277            owned by one driver */
    9378        link_t driver_devices;
    94         /** Unique device identifier */
    95         devmap_handle_t handle;
    96         /** Device namespace */
    97         devmap_namespace_t *namespace;
     79        /** Unique device identifier  */
     80        dev_handle_t handle;
    9881        /** Device name */
    9982        char *name;
    10083        /** Device driver handling this device */
    10184        devmap_driver_t *driver;
    102         /** Use this interface when forwarding to driver. */
    103         sysarg_t forward_interface;
    10485} devmap_device_t;
    10586
    10687LIST_INITIALIZE(devices_list);
    107 LIST_INITIALIZE(namespaces_list);
    10888LIST_INITIALIZE(drivers_list);
    10989
     
    121101static FIBRIL_MUTEX_INITIALIZE(null_devices_mutex);
    122102
    123 static devmap_handle_t last_handle = 0;
     103static dev_handle_t last_handle = 0;
    124104static devmap_device_t *null_devices[NULL_DEVICES];
    125105
    126 /*
    127  * Dummy list for null devices. This is necessary so that null devices can
    128  * be used just as any other devices, e.g. in devmap_device_unregister_core().
    129  */
    130 static LIST_INITIALIZE(dummy_null_driver_devices);
    131 
    132 static devmap_handle_t devmap_create_handle(void)
     106static dev_handle_t devmap_create_handle(void)
    133107{
    134108        /* TODO: allow reusing old handles after their unregistration
     
    143117}
    144118
    145 /** Convert fully qualified device name to namespace and device name.
    146  *
    147  * A fully qualified device name can be either a plain device name
    148  * (then the namespace is considered to be an empty string) or consist
    149  * of two components separated by a slash. No more than one slash
    150  * is allowed.
    151  *
    152  */
    153 static bool devmap_fqdn_split(const char *fqdn, char **ns_name, char **name)
    154 {
    155         size_t cnt = 0;
    156         size_t slash_offset = 0;
    157         size_t slash_after = 0;
    158        
    159         size_t offset = 0;
    160         size_t offset_prev = 0;
    161         wchar_t c;
    162        
    163         while ((c = str_decode(fqdn, &offset, STR_NO_LIMIT)) != 0) {
    164                 if (c == '/') {
    165                         cnt++;
    166                         slash_offset = offset_prev;
    167                         slash_after = offset;
    168                 }
    169                 offset_prev = offset;
    170         }
    171        
    172         /* More than one slash */
    173         if (cnt > 1)
    174                 return false;
    175        
    176         /* No slash -> namespace is empty */
    177         if (cnt == 0) {
    178                 *ns_name = str_dup("");
    179                 if (*ns_name == NULL)
    180                         return false;
    181                
    182                 *name = str_dup(fqdn);
    183                 if (*name == NULL) {
    184                         free(*ns_name);
    185                         return false;
    186                 }
    187                
    188                 if (str_cmp(*name, "") == 0) {
    189                         free(*name);
    190                         free(*ns_name);
    191                         return false;
    192                 }
    193                
    194                 return true;
    195         }
    196        
    197         /* Exactly one slash */
    198         *ns_name = str_ndup(fqdn, slash_offset);
    199         if (*ns_name == NULL)
    200                 return false;
    201        
    202         *name = str_dup(fqdn + slash_after);
    203         if (*name == NULL) {
    204                 free(*ns_name);
    205                 return false;
    206         }
    207        
    208         if (str_cmp(*name, "") == 0) {
    209                 free(*name);
    210                 free(*ns_name);
    211                 return false;
    212         }
    213        
    214         return true;
    215 }
    216 
    217 /** Find namespace with given name. */
    218 static devmap_namespace_t *devmap_namespace_find_name(const char *name)
    219 {
    220         link_t *item;
    221        
    222         assert(fibril_mutex_is_locked(&devices_list_mutex));
    223        
    224         for (item = namespaces_list.next; item != &namespaces_list; item = item->next) {
    225                 devmap_namespace_t *namespace =
    226                     list_get_instance(item, devmap_namespace_t, namespaces);
    227                 if (str_cmp(namespace->name, name) == 0)
    228                         return namespace;
    229         }
    230        
    231         return NULL;
    232 }
    233 
    234 /** Find namespace with given handle.
     119/** Find device with given name.
     120 *
     121 */
     122static devmap_device_t *devmap_device_find_name(const char *name)
     123{
     124        link_t *item = devices_list.next;
     125        devmap_device_t *device = NULL;
     126       
     127        while (item != &devices_list) {
     128                device = list_get_instance(item, devmap_device_t, devices);
     129                if (str_cmp(device->name, name) == 0)
     130                        break;
     131                item = item->next;
     132        }
     133       
     134        if (item == &devices_list)
     135                return NULL;
     136       
     137        device = list_get_instance(item, devmap_device_t, devices);
     138        return device;
     139}
     140
     141/** Find device with given handle.
    235142 *
    236143 * @todo: use hash table
    237144 *
    238145 */
    239 static devmap_namespace_t *devmap_namespace_find_handle(devmap_handle_t handle)
    240 {
    241         link_t *item;
    242        
    243         assert(fibril_mutex_is_locked(&devices_list_mutex));
    244        
    245         for (item = namespaces_list.next; item != &namespaces_list; item = item->next) {
    246                 devmap_namespace_t *namespace =
    247                     list_get_instance(item, devmap_namespace_t, namespaces);
    248                 if (namespace->handle == handle)
    249                         return namespace;
    250         }
    251        
    252         return NULL;
    253 }
    254 
    255 /** Find device with given name. */
    256 static devmap_device_t *devmap_device_find_name(const char *ns_name,
    257     const char *name)
    258 {
    259         link_t *item;
    260        
    261         assert(fibril_mutex_is_locked(&devices_list_mutex));
    262        
    263         for (item = devices_list.next; item != &devices_list; item = item->next) {
    264                 devmap_device_t *device =
    265                     list_get_instance(item, devmap_device_t, devices);
    266                 if ((str_cmp(device->namespace->name, ns_name) == 0)
    267                     && (str_cmp(device->name, name) == 0))
    268                         return device;
    269         }
    270        
    271         return NULL;
    272 }
    273 
    274 /** Find device with given handle.
    275  *
    276  * @todo: use hash table
    277  *
    278  */
    279 static devmap_device_t *devmap_device_find_handle(devmap_handle_t handle)
    280 {
    281         link_t *item;
    282        
    283         assert(fibril_mutex_is_locked(&devices_list_mutex));
    284        
    285         for (item = devices_list.next; item != &devices_list; item = item->next) {
    286                 devmap_device_t *device =
    287                     list_get_instance(item, devmap_device_t, devices);
     146static devmap_device_t *devmap_device_find_handle(dev_handle_t handle)
     147{
     148        fibril_mutex_lock(&devices_list_mutex);
     149       
     150        link_t *item = (&devices_list)->next;
     151        devmap_device_t *device = NULL;
     152       
     153        while (item != &devices_list) {
     154                device = list_get_instance(item, devmap_device_t, devices);
    288155                if (device->handle == handle)
    289                         return device;
    290         }
    291        
    292         return NULL;
    293 }
    294 
    295 /** Create a namespace (if not already present). */
    296 static devmap_namespace_t *devmap_namespace_create(const char *ns_name)
    297 {
    298         devmap_namespace_t *namespace;
    299        
    300         assert(fibril_mutex_is_locked(&devices_list_mutex));
    301        
    302         namespace = devmap_namespace_find_name(ns_name);
    303         if (namespace != NULL)
    304                 return namespace;
    305        
    306         namespace = (devmap_namespace_t *) malloc(sizeof(devmap_namespace_t));
    307         if (namespace == NULL)
     156                        break;
     157                item = item->next;
     158        }
     159       
     160        if (item == &devices_list) {
     161                fibril_mutex_unlock(&devices_list_mutex);
    308162                return NULL;
    309        
    310         namespace->name = str_dup(ns_name);
    311         if (namespace->name == NULL) {
    312                 free(namespace);
    313                 return NULL;
    314         }
    315        
    316         namespace->handle = devmap_create_handle();
    317         namespace->refcnt = 0;
    318        
    319         /*
    320          * Insert new namespace into list of registered namespaces
    321          */
    322         list_append(&(namespace->namespaces), &namespaces_list);
    323        
    324         return namespace;
    325 }
    326 
    327 /** Destroy a namespace (if it is no longer needed). */
    328 static void devmap_namespace_destroy(devmap_namespace_t *namespace)
    329 {
    330         assert(fibril_mutex_is_locked(&devices_list_mutex));
    331 
    332         if (namespace->refcnt == 0) {
    333                 list_remove(&(namespace->namespaces));
    334                
    335                 free(namespace->name);
    336                 free(namespace);
    337         }
    338 }
    339 
    340 /** Increase namespace reference count by including device. */
    341 static void devmap_namespace_addref(devmap_namespace_t *namespace,
    342     devmap_device_t *device)
    343 {
    344         assert(fibril_mutex_is_locked(&devices_list_mutex));
    345 
    346         device->namespace = namespace;
    347         namespace->refcnt++;
    348 }
    349 
    350 /** Decrease namespace reference count. */
    351 static void devmap_namespace_delref(devmap_namespace_t *namespace)
    352 {
    353         assert(fibril_mutex_is_locked(&devices_list_mutex));
    354 
    355         namespace->refcnt--;
    356         devmap_namespace_destroy(namespace);
    357 }
    358 
    359 /** Unregister device and free it. */
    360 static void devmap_device_unregister_core(devmap_device_t *device)
    361 {
    362         assert(fibril_mutex_is_locked(&devices_list_mutex));
    363 
    364         devmap_namespace_delref(device->namespace);
     163        }
     164       
     165        device = list_get_instance(item, devmap_device_t, devices);
     166       
     167        fibril_mutex_unlock(&devices_list_mutex);
     168       
     169        return device;
     170}
     171
     172/**
     173 * Unregister device and free it. It's assumed that driver's device list is
     174 * already locked.
     175 */
     176static int devmap_device_unregister_core(devmap_device_t *device)
     177{
    365178        list_remove(&(device->devices));
    366179        list_remove(&(device->driver_devices));
     
    368181        free(device->name);
    369182        free(device);
     183       
     184        return EOK;
    370185}
    371186
     
    374189 * drivers.
    375190 */
    376 static devmap_driver_t *devmap_driver_register(void)
    377 {
     191static void devmap_driver_register(devmap_driver_t **odriver)
     192{
     193        *odriver = NULL;
     194       
    378195        ipc_call_t icall;
    379196        ipc_callid_t iid = async_get_call(&icall);
    380197       
    381         if (IPC_GET_IMETHOD(icall) != DEVMAP_DRIVER_REGISTER) {
    382                 async_answer_0(iid, EREFUSED);
    383                 return NULL;
    384         }
    385        
    386         devmap_driver_t *driver =
    387             (devmap_driver_t *) malloc(sizeof(devmap_driver_t));
     198        if (IPC_GET_METHOD(icall) != DEVMAP_DRIVER_REGISTER) {
     199                ipc_answer_0(iid, EREFUSED);
     200                return;
     201        }
     202       
     203        devmap_driver_t *driver = (devmap_driver_t *) malloc(sizeof(devmap_driver_t));
     204       
    388205        if (driver == NULL) {
    389                 async_answer_0(iid, ENOMEM);
    390                 return NULL;
     206                ipc_answer_0(iid, ENOMEM);
     207                return;
    391208        }
    392209       
     
    394211         * Get driver name
    395212         */
    396         int rc = async_data_write_accept((void **) &driver->name, true, 0,
    397             DEVMAP_NAME_MAXLEN, 0, NULL);
    398         if (rc != EOK) {
     213        ipc_callid_t callid;
     214        size_t name_size;
     215        if (!ipc_data_write_receive(&callid, &name_size)) {
    399216                free(driver);
    400                 async_answer_0(iid, rc);
    401                 return NULL;
    402         }
    403        
    404         /*
    405          * Create connection to the driver
    406          */
    407         ipc_call_t call;
    408         ipc_callid_t callid = async_get_call(&call);
    409        
    410         if (IPC_GET_IMETHOD(call) != IPC_M_CONNECT_TO_ME) {
     217                ipc_answer_0(callid, EREFUSED);
     218                ipc_answer_0(iid, EREFUSED);
     219                return;
     220        }
     221       
     222        if (name_size > DEVMAP_NAME_MAXLEN) {
     223                free(driver);
     224                ipc_answer_0(callid, EINVAL);
     225                ipc_answer_0(iid, EREFUSED);
     226                return;
     227        }
     228       
     229        /*
     230         * Allocate buffer for device name.
     231         */
     232        driver->name = (char *) malloc(name_size + 1);
     233        if (driver->name == NULL) {
     234                free(driver);
     235                ipc_answer_0(callid, ENOMEM);
     236                ipc_answer_0(iid, EREFUSED);
     237                return;
     238        }
     239       
     240        /*
     241         * Send confirmation to sender and get data into buffer.
     242         */
     243        if (ipc_data_write_finalize(callid, driver->name, name_size) != EOK) {
    411244                free(driver->name);
    412245                free(driver);
    413                 async_answer_0(callid, ENOTSUP);
    414                 async_answer_0(iid, ENOTSUP);
    415                 return NULL;
     246                ipc_answer_0(iid, EREFUSED);
     247                return;
     248        }
     249       
     250        driver->name[name_size] = 0;
     251       
     252        /* Initialize mutex for list of devices owned by this driver */
     253        fibril_mutex_initialize(&driver->devices_mutex);
     254       
     255        /*
     256         * Initialize list of asociated devices
     257         */
     258        list_initialize(&driver->devices);
     259       
     260        /*
     261         * Create connection to the driver
     262         */
     263        ipc_call_t call;
     264        callid = async_get_call(&call);
     265       
     266        if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) {
     267                ipc_answer_0(callid, ENOTSUP);
     268               
     269                free(driver->name);
     270                free(driver);
     271                ipc_answer_0(iid, ENOTSUP);
     272                return;
    416273        }
    417274       
    418275        driver->phone = IPC_GET_ARG5(call);
    419         async_answer_0(callid, EOK);
    420        
    421         /*
    422          * Initialize mutex for list of devices
    423          * owned by this driver
    424          */
    425         fibril_mutex_initialize(&driver->devices_mutex);
    426        
    427         /*
    428          * Initialize list of asociated devices
    429          */
    430         list_initialize(&driver->devices);
    431 
    432         link_initialize(&driver->drivers);
     276       
     277        ipc_answer_0(callid, EOK);
     278       
     279        list_initialize(&(driver->drivers));
    433280       
    434281        fibril_mutex_lock(&drivers_list_mutex);
    435282       
    436283        /* TODO:
    437          * Check that no driver with name equal to
    438          * driver->name is registered
     284         * check that no driver with name equal to driver->name is registered
    439285         */
    440286       
     
    445291        fibril_mutex_unlock(&drivers_list_mutex);
    446292       
    447         async_answer_0(iid, EOK);
    448        
    449         return driver;
     293        ipc_answer_0(iid, EOK);
     294       
     295        *odriver = driver;
    450296}
    451297
     
    463309       
    464310        if (driver->phone != 0)
    465                 async_hangup(driver->phone);
     311                ipc_hangup(driver->phone);
    466312       
    467313        /* Remove it from list of drivers */
     
    482328        fibril_mutex_unlock(&drivers_list_mutex);
    483329       
    484         /* Free name and driver */
     330        /* free name and driver */
    485331        if (driver->name != NULL)
    486332                free(driver->name);
     
    498344{
    499345        if (driver == NULL) {
    500                 async_answer_0(iid, EREFUSED);
     346                ipc_answer_0(iid, EREFUSED);
    501347                return;
    502348        }
    503349       
    504350        /* Create new device entry */
    505         devmap_device_t *device =
    506             (devmap_device_t *) malloc(sizeof(devmap_device_t));
     351        devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
    507352        if (device == NULL) {
    508                 async_answer_0(iid, ENOMEM);
    509                 return;
    510         }
    511        
    512         /* Set the interface, if any. */
    513         device->forward_interface = IPC_GET_ARG1(*icall);
    514 
    515         /* Get fqdn */
    516         char *fqdn;
    517         int rc = async_data_write_accept((void **) &fqdn, true, 0,
    518             DEVMAP_NAME_MAXLEN, 0, NULL);
    519         if (rc != EOK) {
     353                ipc_answer_0(iid, ENOMEM);
     354                return;
     355        }
     356       
     357        /* Get device name */
     358        ipc_callid_t callid;
     359        size_t size;
     360        if (!ipc_data_write_receive(&callid, &size)) {
    520361                free(device);
    521                 async_answer_0(iid, rc);
    522                 return;
    523         }
    524        
    525         char *ns_name;
    526         if (!devmap_fqdn_split(fqdn, &ns_name, &device->name)) {
    527                 free(fqdn);
     362                ipc_answer_0(iid, EREFUSED);
     363                return;
     364        }
     365       
     366        if (size > DEVMAP_NAME_MAXLEN) {
    528367                free(device);
    529                 async_answer_0(iid, EINVAL);
    530                 return;
    531         }
    532        
    533         free(fqdn);
     368                ipc_answer_0(callid, EINVAL);
     369                ipc_answer_0(iid, EREFUSED);
     370                return;
     371        }
     372       
     373        /* +1 for terminating \0 */
     374        device->name = (char *) malloc(size + 1);
     375       
     376        if (device->name == NULL) {
     377                free(device);
     378                ipc_answer_0(callid, ENOMEM);
     379                ipc_answer_0(iid, EREFUSED);
     380                return;
     381        }
     382       
     383        ipc_data_write_finalize(callid, device->name, size);
     384        device->name[size] = 0;
     385       
     386        list_initialize(&(device->devices));
     387        list_initialize(&(device->driver_devices));
    534388       
    535389        fibril_mutex_lock(&devices_list_mutex);
    536390       
    537         devmap_namespace_t *namespace = devmap_namespace_create(ns_name);
    538         free(ns_name);
    539         if (namespace == NULL) {
     391        /* Check that device with such name is not already registered */
     392        if (NULL != devmap_device_find_name(device->name)) {
     393                printf(NAME ": Device '%s' already registered\n", device->name);
    540394                fibril_mutex_unlock(&devices_list_mutex);
    541395                free(device->name);
    542396                free(device);
    543                 async_answer_0(iid, ENOMEM);
    544                 return;
    545         }
    546        
    547         link_initialize(&device->devices);
    548         link_initialize(&device->driver_devices);
    549        
    550         /* Check that device is not already registered */
    551         if (devmap_device_find_name(namespace->name, device->name) != NULL) {
    552                 printf("%s: Device '%s/%s' already registered\n", NAME,
    553                     device->namespace->name, device->name);
    554                 devmap_namespace_destroy(namespace);
    555                 fibril_mutex_unlock(&devices_list_mutex);
    556                 free(device->name);
    557                 free(device);
    558                 async_answer_0(iid, EEXISTS);
     397                ipc_answer_0(iid, EEXISTS);
    559398                return;
    560399        }
     
    562401        /* Get unique device handle */
    563402        device->handle = devmap_create_handle();
    564 
    565         devmap_namespace_addref(namespace, device);
     403       
    566404        device->driver = driver;
    567405       
     
    578416        fibril_mutex_unlock(&devices_list_mutex);
    579417       
    580         async_answer_1(iid, EOK, device->handle);
     418        ipc_answer_1(iid, EOK, device->handle);
    581419}
    582420
     
    599437static void devmap_forward(ipc_callid_t callid, ipc_call_t *call)
    600438{
    601         fibril_mutex_lock(&devices_list_mutex);
    602        
    603439        /*
    604440         * Get handle from request
    605441         */
    606         devmap_handle_t handle = IPC_GET_ARG2(*call);
     442        dev_handle_t handle = IPC_GET_ARG2(*call);
    607443        devmap_device_t *dev = devmap_device_find_handle(handle);
    608444       
    609445        if ((dev == NULL) || (dev->driver == NULL) || (dev->driver->phone == 0)) {
    610                 fibril_mutex_unlock(&devices_list_mutex);
    611                 async_answer_0(callid, ENOENT);
    612                 return;
    613         }
    614        
    615         if (dev->forward_interface == 0) {
    616                 async_forward_fast(callid, dev->driver->phone,
    617                     dev->handle, 0, 0,
    618                     IPC_FF_NONE);
    619         } else {
    620                 async_forward_fast(callid, dev->driver->phone,
    621                     dev->forward_interface, dev->handle, 0,
    622                     IPC_FF_NONE);
    623         }
    624        
    625         fibril_mutex_unlock(&devices_list_mutex);
     446                ipc_answer_0(callid, ENOENT);
     447                return;
     448        }
     449       
     450        ipc_forward_fast(callid, dev->driver->phone, dev->handle,
     451            IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
    626452}
    627453
     
    632458 *
    633459 */
    634 static void devmap_device_get_handle(ipc_callid_t iid, ipc_call_t *icall)
    635 {
    636         char *fqdn;
    637        
    638         /* Get fqdn */
    639         int rc = async_data_write_accept((void **) &fqdn, true, 0,
    640             DEVMAP_NAME_MAXLEN, 0, NULL);
    641         if (rc != EOK) {
    642                 async_answer_0(iid, rc);
    643                 return;
    644         }
    645        
    646         char *ns_name;
    647         char *name;
    648         if (!devmap_fqdn_split(fqdn, &ns_name, &name)) {
    649                 free(fqdn);
    650                 async_answer_0(iid, EINVAL);
    651                 return;
    652         }
    653        
    654         free(fqdn);
     460static void devmap_get_handle(ipc_callid_t iid, ipc_call_t *icall)
     461{
     462        /*
     463         * Wait for incoming message with device name (but do not
     464         * read the name itself until the buffer is allocated).
     465         */
     466        ipc_callid_t callid;
     467        size_t size;
     468        if (!ipc_data_write_receive(&callid, &size)) {
     469                ipc_answer_0(callid, EREFUSED);
     470                ipc_answer_0(iid, EREFUSED);
     471                return;
     472        }
     473       
     474        if ((size < 1) || (size > DEVMAP_NAME_MAXLEN)) {
     475                ipc_answer_0(callid, EINVAL);
     476                ipc_answer_0(iid, EREFUSED);
     477                return;
     478        }
     479       
     480        /*
     481         * Allocate buffer for device name.
     482         */
     483        char *name = (char *) malloc(size + 1);
     484        if (name == NULL) {
     485                ipc_answer_0(callid, ENOMEM);
     486                ipc_answer_0(iid, EREFUSED);
     487                return;
     488        }
     489       
     490        /*
     491         * Send confirmation to sender and get data into buffer.
     492         */
     493        ipcarg_t retval = ipc_data_write_finalize(callid, name, size);
     494        if (retval != EOK) {
     495                ipc_answer_0(iid, EREFUSED);
     496                free(name);
     497                return;
     498        }
     499        name[size] = '\0';
    655500       
    656501        fibril_mutex_lock(&devices_list_mutex);
    657502        const devmap_device_t *dev;
    658        
    659503recheck:
    660        
     504
    661505        /*
    662506         * Find device name in the list of known devices.
    663507         */
    664         dev = devmap_device_find_name(ns_name, name);
     508        dev = devmap_device_find_name(name);
    665509       
    666510        /*
     
    675519                }
    676520               
    677                 async_answer_0(iid, ENOENT);
    678                 free(ns_name);
     521                ipc_answer_0(iid, ENOENT);
    679522                free(name);
    680523                fibril_mutex_unlock(&devices_list_mutex);
    681524                return;
    682525        }
    683        
    684         async_answer_1(iid, EOK, dev->handle);
    685        
    686526        fibril_mutex_unlock(&devices_list_mutex);
    687         free(ns_name);
     527       
     528        ipc_answer_1(iid, EOK, dev->handle);
    688529        free(name);
    689530}
    690531
    691 /** Find handle for namespace identified by name.
    692  *
    693  * In answer will be send EOK and device handle in arg1 or a error
    694  * code from errno.h.
    695  *
    696  */
    697 static void devmap_namespace_get_handle(ipc_callid_t iid, ipc_call_t *icall)
    698 {
    699         char *name;
    700        
    701         /* Get device name */
    702         int rc = async_data_write_accept((void **) &name, true, 0,
    703             DEVMAP_NAME_MAXLEN, 0, NULL);
    704         if (rc != EOK) {
    705                 async_answer_0(iid, rc);
    706                 return;
    707         }
    708        
     532/** Find name of device identified by id and send it to caller.
     533 *
     534 */
     535static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall)
     536{
     537        const devmap_device_t *device = devmap_device_find_handle(IPC_GET_ARG1(*icall));
     538       
     539        /*
     540         * Device not found.
     541         */
     542        if (device == NULL) {
     543                ipc_answer_0(iid, ENOENT);
     544                return;
     545        }
     546       
     547        ipc_answer_0(iid, EOK);
     548       
     549        /* FIXME:
     550         * We have no channel from DEVMAP to client, therefore
     551         * sending must be initiated by client.
     552         *
     553         * size_t name_size = str_size(device->name);
     554         *
     555         * int rc = ipc_data_write_send(phone, device->name, name_size);
     556         * if (rc != EOK) {
     557         *     async_wait_for(req, NULL);
     558         *     return rc;
     559         * }
     560         */
     561       
     562        /* TODO: send name in response */
     563}
     564
     565static void devmap_get_count(ipc_callid_t iid, ipc_call_t *icall)
     566{
    709567        fibril_mutex_lock(&devices_list_mutex);
    710         const devmap_namespace_t *namespace;
    711        
    712 recheck:
    713        
    714         /*
    715          * Find namespace name in the list of known namespaces.
    716          */
    717         namespace = devmap_namespace_find_name(name);
    718        
    719         /*
    720          * Namespace was not found.
    721          */
    722         if (namespace == NULL) {
    723                 if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
    724                         /* Blocking lookup */
    725                         fibril_condvar_wait(&devices_list_cv,
    726                             &devices_list_mutex);
    727                         goto recheck;
    728                 }
    729                
    730                 async_answer_0(iid, ENOENT);
    731                 free(name);
    732                 fibril_mutex_unlock(&devices_list_mutex);
    733                 return;
    734         }
    735        
    736         async_answer_1(iid, EOK, namespace->handle);
    737        
     568        ipc_answer_1(iid, EOK, list_count(&devices_list));
    738569        fibril_mutex_unlock(&devices_list_mutex);
    739         free(name);
    740 }
    741 
    742 static void devmap_handle_probe(ipc_callid_t iid, ipc_call_t *icall)
     570}
     571
     572static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
    743573{
    744574        fibril_mutex_lock(&devices_list_mutex);
    745575       
    746         devmap_namespace_t *namespace =
    747             devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
    748         if (namespace == NULL) {
    749                 devmap_device_t *dev =
    750                     devmap_device_find_handle(IPC_GET_ARG1(*icall));
    751                 if (dev == NULL)
    752                         async_answer_1(iid, EOK, DEV_HANDLE_NONE);
    753                 else
    754                         async_answer_1(iid, EOK, DEV_HANDLE_DEVICE);
    755         } else
    756                 async_answer_1(iid, EOK, DEV_HANDLE_NAMESPACE);
    757        
    758         fibril_mutex_unlock(&devices_list_mutex);
    759 }
    760 
    761 static void devmap_get_namespace_count(ipc_callid_t iid, ipc_call_t *icall)
    762 {
    763         fibril_mutex_lock(&devices_list_mutex);
    764         async_answer_1(iid, EOK, list_count(&namespaces_list));
    765         fibril_mutex_unlock(&devices_list_mutex);
    766 }
    767 
    768 static void devmap_get_device_count(ipc_callid_t iid, ipc_call_t *icall)
    769 {
    770         fibril_mutex_lock(&devices_list_mutex);
    771        
    772         devmap_namespace_t *namespace =
    773             devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
    774         if (namespace == NULL)
    775                 async_answer_0(iid, EEXISTS);
    776         else
    777                 async_answer_1(iid, EOK, namespace->refcnt);
    778        
    779         fibril_mutex_unlock(&devices_list_mutex);
    780 }
    781 
    782 static void devmap_get_namespaces(ipc_callid_t iid, ipc_call_t *icall)
    783 {
    784576        ipc_callid_t callid;
    785577        size_t size;
    786         if (!async_data_read_receive(&callid, &size)) {
    787                 async_answer_0(callid, EREFUSED);
    788                 async_answer_0(iid, EREFUSED);
     578        if (!ipc_data_read_receive(&callid, &size)) {
     579                ipc_answer_0(callid, EREFUSED);
     580                ipc_answer_0(iid, EREFUSED);
    789581                return;
    790582        }
    791583       
    792584        if ((size % sizeof(dev_desc_t)) != 0) {
    793                 async_answer_0(callid, EINVAL);
    794                 async_answer_0(iid, EINVAL);
    795                 return;
    796         }
    797        
    798         fibril_mutex_lock(&devices_list_mutex);
     585                ipc_answer_0(callid, EINVAL);
     586                ipc_answer_0(iid, EREFUSED);
     587                return;
     588        }
    799589       
    800590        size_t count = size / sizeof(dev_desc_t);
    801         if (count != list_count(&namespaces_list)) {
    802                 fibril_mutex_unlock(&devices_list_mutex);
    803                 async_answer_0(callid, EOVERFLOW);
    804                 async_answer_0(iid, EOVERFLOW);
    805                 return;
    806         }
    807        
    808591        dev_desc_t *desc = (dev_desc_t *) malloc(size);
    809592        if (desc == NULL) {
    810                 fibril_mutex_unlock(&devices_list_mutex);
    811                 async_answer_0(callid, ENOMEM);
    812                 async_answer_0(iid, ENOMEM);
    813                 return;
    814         }
    815        
    816         link_t *item;
     593                ipc_answer_0(callid, ENOMEM);
     594                ipc_answer_0(iid, EREFUSED);
     595                return;
     596        }
     597       
    817598        size_t pos = 0;
    818         for (item = namespaces_list.next; item != &namespaces_list;
    819             item = item->next) {
    820                 devmap_namespace_t *namespace =
    821                     list_get_instance(item, devmap_namespace_t, namespaces);
     599        link_t *item = devices_list.next;
     600       
     601        while ((item != &devices_list) && (pos < count)) {
     602                devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
    822603               
    823                 desc[pos].handle = namespace->handle;
    824                 str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, namespace->name);
     604                desc[pos].handle = device->handle;
     605                str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
    825606                pos++;
    826         }
    827        
    828         sysarg_t retval = async_data_read_finalize(callid, desc, size);
     607                item = item->next;
     608        }
     609       
     610        ipcarg_t retval = ipc_data_read_finalize(callid, desc, pos * sizeof(dev_desc_t));
     611        if (retval != EOK) {
     612                ipc_answer_0(iid, EREFUSED);
     613                free(desc);
     614                return;
     615        }
    829616       
    830617        free(desc);
     618       
    831619        fibril_mutex_unlock(&devices_list_mutex);
    832620       
    833         async_answer_0(iid, retval);
    834 }
    835 
    836 static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
    837 {
    838         /* FIXME: Use faster algorithm which can make better use
    839            of namespaces */
    840        
    841         ipc_callid_t callid;
    842         size_t size;
    843         if (!async_data_read_receive(&callid, &size)) {
    844                 async_answer_0(callid, EREFUSED);
    845                 async_answer_0(iid, EREFUSED);
    846                 return;
    847         }
    848        
    849         if ((size % sizeof(dev_desc_t)) != 0) {
    850                 async_answer_0(callid, EINVAL);
    851                 async_answer_0(iid, EINVAL);
    852                 return;
    853         }
    854        
    855         fibril_mutex_lock(&devices_list_mutex);
    856        
    857         devmap_namespace_t *namespace =
    858             devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
    859         if (namespace == NULL) {
    860                 fibril_mutex_unlock(&devices_list_mutex);
    861                 async_answer_0(callid, ENOENT);
    862                 async_answer_0(iid, ENOENT);
    863                 return;
    864         }
    865        
    866         size_t count = size / sizeof(dev_desc_t);
    867         if (count != namespace->refcnt) {
    868                 fibril_mutex_unlock(&devices_list_mutex);
    869                 async_answer_0(callid, EOVERFLOW);
    870                 async_answer_0(iid, EOVERFLOW);
    871                 return;
    872         }
    873        
    874         dev_desc_t *desc = (dev_desc_t *) malloc(size);
    875         if (desc == NULL) {
    876                 fibril_mutex_unlock(&devices_list_mutex);
    877                 async_answer_0(callid, ENOMEM);
    878                 async_answer_0(iid, EREFUSED);
    879                 return;
    880         }
    881        
    882         link_t *item;
    883         size_t pos = 0;
    884         for (item = devices_list.next; item != &devices_list; item = item->next) {
    885                 devmap_device_t *device =
    886                     list_get_instance(item, devmap_device_t, devices);
    887                
    888                 if (device->namespace == namespace) {
    889                         desc[pos].handle = device->handle;
    890                         str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
    891                         pos++;
    892                 }
    893         }
    894        
    895         sysarg_t retval = async_data_read_finalize(callid, desc, size);
    896        
    897         free(desc);
    898         fibril_mutex_unlock(&devices_list_mutex);
    899        
    900         async_answer_0(iid, retval);
     621        ipc_answer_1(iid, EOK, pos);
    901622}
    902623
     
    917638        if (!fnd) {
    918639                fibril_mutex_unlock(&null_devices_mutex);
    919                 async_answer_0(iid, ENOMEM);
    920                 return;
    921         }
    922        
    923         char null[DEVMAP_NAME_MAXLEN];
    924         snprintf(null, DEVMAP_NAME_MAXLEN, "%u", i);
    925        
    926         char *dev_name = str_dup(null);
    927         if (dev_name == NULL) {
    928                 fibril_mutex_unlock(&null_devices_mutex);
    929                 async_answer_0(iid, ENOMEM);
    930                 return;
    931         }
    932        
    933         devmap_device_t *device =
    934             (devmap_device_t *) malloc(sizeof(devmap_device_t));
     640                ipc_answer_0(iid, ENOMEM);
     641                return;
     642        }
     643       
     644        /* Create NULL device entry */
     645        devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
    935646        if (device == NULL) {
    936647                fibril_mutex_unlock(&null_devices_mutex);
    937                 async_answer_0(iid, ENOMEM);
    938                 return;
    939         }
     648                ipc_answer_0(iid, ENOMEM);
     649                return;
     650        }
     651       
     652        char null[DEVMAP_NAME_MAXLEN];
     653        snprintf(null, DEVMAP_NAME_MAXLEN, "null%u", i);
     654       
     655        device->name = str_dup(null);
     656        if (device->name == NULL) {
     657                fibril_mutex_unlock(&null_devices_mutex);
     658                free(device);
     659                ipc_answer_0(iid, ENOMEM);
     660                return;
     661        }
     662       
     663        list_initialize(&(device->devices));
     664        list_initialize(&(device->driver_devices));
    940665       
    941666        fibril_mutex_lock(&devices_list_mutex);
    942        
    943         devmap_namespace_t *namespace = devmap_namespace_create("null");
    944         if (namespace == NULL) {
    945                 fibril_mutex_lock(&devices_list_mutex);
    946                 fibril_mutex_unlock(&null_devices_mutex);
    947                 async_answer_0(iid, ENOMEM);
    948                 return;
    949         }
    950        
    951         link_initialize(&device->devices);
    952         link_initialize(&device->driver_devices);
    953667       
    954668        /* Get unique device handle */
     
    956670        device->driver = NULL;
    957671       
    958         devmap_namespace_addref(namespace, device);
    959         device->name = dev_name;
    960        
    961         /*
    962          * Insert device into list of all devices and into null devices array.
    963          * Insert device into a dummy list of null driver's devices so that it
    964          * can be safely removed later.
    965          */
     672        /* Insert device into list of all devices
     673           and into null devices array */
    966674        list_append(&device->devices, &devices_list);
    967         list_append(&device->driver_devices, &dummy_null_driver_devices);
    968675        null_devices[i] = device;
    969676       
     
    971678        fibril_mutex_unlock(&null_devices_mutex);
    972679       
    973         async_answer_1(iid, EOK, (sysarg_t) i);
     680        ipc_answer_1(iid, EOK, (ipcarg_t) i);
    974681}
    975682
    976683static void devmap_null_destroy(ipc_callid_t iid, ipc_call_t *icall)
    977684{
    978         sysarg_t i = IPC_GET_ARG1(*icall);
    979         if (i >= NULL_DEVICES) {
    980                 async_answer_0(iid, ELIMIT);
    981                 return;
    982         }
    983        
    984685        fibril_mutex_lock(&null_devices_mutex);
    985686       
     687        ipcarg_t i = IPC_GET_ARG1(*icall);
     688       
    986689        if (null_devices[i] == NULL) {
    987                 fibril_mutex_unlock(&null_devices_mutex);
    988                 async_answer_0(iid, ENOENT);
    989                 return;
    990         }
    991        
    992         fibril_mutex_lock(&devices_list_mutex);
     690                ipc_answer_0(iid, ENOENT);
     691                return;
     692        }
     693       
    993694        devmap_device_unregister_core(null_devices[i]);
    994         fibril_mutex_unlock(&devices_list_mutex);
    995        
    996695        null_devices[i] = NULL;
    997696       
    998697        fibril_mutex_unlock(&null_devices_mutex);
    999         async_answer_0(iid, EOK);
     698       
     699        ipc_answer_0(iid, EOK);
    1000700}
    1001701
     
    1023723{
    1024724        /* Accept connection */
    1025         async_answer_0(iid, EOK);
    1026        
    1027         devmap_driver_t *driver = devmap_driver_register();
    1028         if (driver == NULL)
     725        ipc_answer_0(iid, EOK);
     726       
     727        devmap_driver_t *driver = NULL;
     728        devmap_driver_register(&driver);
     729       
     730        if (NULL == driver)
    1029731                return;
    1030732       
     
    1034736                ipc_callid_t callid = async_get_call(&call);
    1035737               
    1036                 switch (IPC_GET_IMETHOD(call)) {
     738                switch (IPC_GET_METHOD(call)) {
    1037739                case IPC_M_PHONE_HUNGUP:
    1038740                        cont = false;
     
    1040742                case DEVMAP_DRIVER_UNREGISTER:
    1041743                        if (NULL == driver)
    1042                                 async_answer_0(callid, ENOENT);
     744                                ipc_answer_0(callid, ENOENT);
    1043745                        else
    1044                                 async_answer_0(callid, EOK);
     746                                ipc_answer_0(callid, EOK);
    1045747                        break;
    1046748                case DEVMAP_DEVICE_REGISTER:
     
    1053755                        break;
    1054756                case DEVMAP_DEVICE_GET_HANDLE:
    1055                         devmap_device_get_handle(callid, &call);
    1056                         break;
    1057                 case DEVMAP_NAMESPACE_GET_HANDLE:
    1058                         devmap_namespace_get_handle(callid, &call);
     757                        devmap_get_handle(callid, &call);
     758                        break;
     759                case DEVMAP_DEVICE_GET_NAME:
     760                        devmap_get_name(callid, &call);
    1059761                        break;
    1060762                default:
    1061                         async_answer_0(callid, ENOENT);
     763                        if (!(callid & IPC_CALLID_NOTIFICATION))
     764                                ipc_answer_0(callid, ENOENT);
    1062765                }
    1063766        }
     
    1078781{
    1079782        /* Accept connection */
    1080         async_answer_0(iid, EOK);
     783        ipc_answer_0(iid, EOK);
    1081784       
    1082785        bool cont = true;
     
    1085788                ipc_callid_t callid = async_get_call(&call);
    1086789               
    1087                 switch (IPC_GET_IMETHOD(call)) {
     790                switch (IPC_GET_METHOD(call)) {
    1088791                case IPC_M_PHONE_HUNGUP:
    1089792                        cont = false;
    1090793                        continue;
    1091794                case DEVMAP_DEVICE_GET_HANDLE:
    1092                         devmap_device_get_handle(callid, &call);
    1093                         break;
    1094                 case DEVMAP_NAMESPACE_GET_HANDLE:
    1095                         devmap_namespace_get_handle(callid, &call);
    1096                         break;
    1097                 case DEVMAP_HANDLE_PROBE:
    1098                         devmap_handle_probe(callid, &call);
    1099                         break;
    1100                 case DEVMAP_NULL_CREATE:
     795                        devmap_get_handle(callid, &call);
     796                        break;
     797                case DEVMAP_DEVICE_GET_NAME:
     798                        devmap_get_name(callid, &call);
     799                        break;
     800                case DEVMAP_DEVICE_NULL_CREATE:
    1101801                        devmap_null_create(callid, &call);
    1102802                        break;
    1103                 case DEVMAP_NULL_DESTROY:
     803                case DEVMAP_DEVICE_NULL_DESTROY:
    1104804                        devmap_null_destroy(callid, &call);
    1105805                        break;
    1106                 case DEVMAP_GET_NAMESPACE_COUNT:
    1107                         devmap_get_namespace_count(callid, &call);
    1108                         break;
    1109                 case DEVMAP_GET_DEVICE_COUNT:
    1110                         devmap_get_device_count(callid, &call);
    1111                         break;
    1112                 case DEVMAP_GET_NAMESPACES:
    1113                         devmap_get_namespaces(callid, &call);
    1114                         break;
    1115                 case DEVMAP_GET_DEVICES:
     806                case DEVMAP_DEVICE_GET_COUNT:
     807                        devmap_get_count(callid, &call);
     808                        break;
     809                case DEVMAP_DEVICE_GET_DEVICES:
    1116810                        devmap_get_devices(callid, &call);
    1117811                        break;
    1118812                default:
    1119                         async_answer_0(callid, ENOENT);
     813                        if (!(callid & IPC_CALLID_NOTIFICATION))
     814                                ipc_answer_0(callid, ENOENT);
    1120815                }
    1121816        }
     
    1128823{
    1129824        /* Select interface */
    1130         switch ((sysarg_t) (IPC_GET_ARG1(*icall))) {
     825        switch ((ipcarg_t) (IPC_GET_ARG1(*icall))) {
    1131826        case DEVMAP_DRIVER:
    1132827                devmap_connection_driver(iid, icall);
     
    1141836        default:
    1142837                /* No such interface */
    1143                 async_answer_0(iid, ENOENT);
     838                ipc_answer_0(iid, ENOENT);
    1144839        }
    1145840}
     
    1150845int main(int argc, char *argv[])
    1151846{
    1152         printf("%s: HelenOS Device Mapper\n", NAME);
     847        printf(NAME ": HelenOS Device Mapper\n");
    1153848       
    1154849        if (!devmap_init()) {
    1155                 printf("%s: Error while initializing service\n", NAME);
     850                printf(NAME ": Error while initializing service\n");
    1156851                return -1;
    1157852        }
     
    1161856       
    1162857        /* Register device mapper at naming service */
    1163         if (service_register(SERVICE_DEVMAP) != EOK)
     858        ipcarg_t phonead;
     859        if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAP, 0, 0, &phonead) != 0)
    1164860                return -1;
    1165861       
    1166         printf("%s: Accepting connections\n", NAME);
     862        printf(NAME ": Accepting connections\n");
    1167863        async_manager();
    1168864       
     
    1171867}
    1172868
    1173 /**
     869/** 
    1174870 * @}
    1175871 */
Note: See TracChangeset for help on using the changeset viewer.