Ignore:
File:
1 edited

Legend:

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

    r1313ee9 r0da4e41  
    4242#include <errno.h>
    4343#include <bool.h>
    44 #include <fibril_synch.h>
     44#include <fibril_sync.h>
    4545#include <stdlib.h>
    4646#include <string.h>
     
    6868} devmap_driver_t;
    6969
    70 /** Info about registered namespaces
    71  *
    72  */
    73 typedef struct {
    74         /** Pointer to the previous and next device in the list of all namespaces */
    75         link_t namespaces;
    76         /** Unique namespace identifier */
    77         dev_handle_t handle;
    78         /** Namespace name */
    79         char *name;
    80         /** Reference count */
    81         size_t refcnt;
    82 } devmap_namespace_t;
    83 
    8470/** Info about registered device
    8571 *
     
    9177            owned by one driver */
    9278        link_t driver_devices;
    93         /** Unique device identifier */
     79        /** Unique device identifier  */
    9480        dev_handle_t handle;
    95         /** Device namespace */
    96         devmap_namespace_t *namespace;
    9781        /** Device name */
    9882        char *name;
     
    10286
    10387LIST_INITIALIZE(devices_list);
    104 LIST_INITIALIZE(namespaces_list);
    10588LIST_INITIALIZE(drivers_list);
    10689
     
    134117}
    135118
    136 /** Convert fully qualified device name to namespace and device name.
    137  *
    138  * A fully qualified device name can be either a plain device name
    139  * (then the namespace is considered to be an empty string) or consist
    140  * of two components separated by a slash. No more than one slash
    141  * is allowed.
    142  *
    143  */
    144 static bool devmap_fqdn_split(const char *fqdn, char **ns_name, char **name)
    145 {
    146         size_t cnt = 0;
    147         size_t slash_offset = 0;
    148         size_t slash_after = 0;
    149        
    150         size_t offset = 0;
    151         size_t offset_prev = 0;
    152         wchar_t c;
    153        
    154         while ((c = str_decode(fqdn, &offset, STR_NO_LIMIT)) != 0) {
    155                 if (c == '/') {
    156                         cnt++;
    157                         slash_offset = offset_prev;
    158                         slash_after = offset;
    159                 }
    160                 offset_prev = offset;
    161         }
    162        
    163         /* More than one slash */
    164         if (cnt > 1)
    165                 return false;
    166        
    167         /* No slash -> namespace is empty */
    168         if (cnt == 0) {
    169                 *ns_name = str_dup("");
    170                 if (*ns_name == NULL)
    171                         return false;
    172                
    173                 *name = str_dup(fqdn);
    174                 if ((*name == NULL) || (str_cmp(*name, "") == 0)) {
    175                         free(*ns_name);
    176                         return false;
    177                 }
    178                
    179                 return true;
    180         }
    181        
    182         /* Exactly one slash */
    183         *ns_name = str_ndup(fqdn, slash_offset);
    184         if (*ns_name == NULL)
    185                 return false;
    186        
    187         *name = str_dup(fqdn + slash_after);
    188         if ((*name == NULL) || (str_cmp(*name, "") == 0)) {
    189                 free(*ns_name);
    190                 return false;
    191         }
    192        
    193         return true;
    194 }
    195 
    196 /** Find namespace with given name.
    197  *
    198  * The devices_list_mutex should be already held when
    199  * calling this function.
    200  *
    201  */
    202 static devmap_namespace_t *devmap_namespace_find_name(const char *name)
    203 {
    204         link_t *item = namespaces_list.next;
    205        
    206         while (item != &namespaces_list) {
    207                 devmap_namespace_t *namespace = list_get_instance(item, devmap_namespace_t, namespaces);
    208                 if (str_cmp(namespace->name, name) == 0)
    209                         return namespace;
     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;
    210131                item = item->next;
    211132        }
    212133       
    213         return NULL;
    214 }
    215 
    216 /** Find namespace with given handle.
    217  *
    218  * The devices_list_mutex should be already held when
    219  * calling this function.
     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.
    220142 *
    221143 * @todo: use hash table
    222144 *
    223145 */
    224 static devmap_namespace_t *devmap_namespace_find_handle(dev_handle_t handle)
    225 {
    226         link_t *item = namespaces_list.next;
    227        
    228         while (item != &namespaces_list) {
    229                 devmap_namespace_t *namespace = list_get_instance(item, devmap_namespace_t, namespaces);
    230                 if (namespace->handle == handle)
    231                         return namespace;
    232                
     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);
     155                if (device->handle == handle)
     156                        break;
    233157                item = item->next;
    234158        }
    235159       
    236         return NULL;
    237 }
    238 
    239 /** Find device with given name.
    240  *
    241  * The devices_list_mutex should be already held when
    242  * calling this function.
    243  *
    244  */
    245 static devmap_device_t *devmap_device_find_name(const char *ns_name,
    246     const char *name)
    247 {
    248         link_t *item = devices_list.next;
    249        
    250         while (item != &devices_list) {
    251                 devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
    252                 if ((str_cmp(device->namespace->name, ns_name) == 0) && (str_cmp(device->name, name) == 0))
    253                         return device;
    254                 item = item->next;
    255         }
    256        
    257         return NULL;
    258 }
    259 
    260 /** Find device with given handle.
    261  *
    262  * The devices_list_mutex should be already held when
    263  * calling this function.
    264  *
    265  * @todo: use hash table
    266  *
    267  */
    268 static devmap_device_t *devmap_device_find_handle(dev_handle_t handle)
    269 {
    270         link_t *item = devices_list.next;
    271        
    272         while (item != &devices_list) {
    273                 devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
    274                 if (device->handle == handle)
    275                         return device;
    276                
    277                 item = item->next;
    278         }
    279        
    280         return NULL;
    281 }
    282 
    283 /** Create a namespace (if not already present)
    284  *
    285  * The devices_list_mutex should be already held when
    286  * calling this function.
    287  *
    288  */
    289 static devmap_namespace_t *devmap_namespace_create(const char *ns_name)
    290 {
    291         devmap_namespace_t *namespace = devmap_namespace_find_name(ns_name);
    292         if (namespace != NULL)
    293                 return namespace;
    294        
    295         namespace = (devmap_namespace_t *) malloc(sizeof(devmap_namespace_t));
    296         if (namespace == NULL)
     160        if (item == &devices_list) {
     161                fibril_mutex_unlock(&devices_list_mutex);
    297162                return NULL;
    298        
    299         namespace->name = str_dup(ns_name);
    300         if (namespace->name == NULL) {
    301                 free(namespace);
    302                 return NULL;
    303         }
    304        
    305         namespace->handle = devmap_create_handle();
    306         namespace->refcnt = 0;
    307        
    308         /*
    309          * Insert new namespace into list of registered namespaces
    310          */
    311         list_append(&(namespace->namespaces), &namespaces_list);
    312        
    313         return namespace;
    314 }
    315 
    316 /** Destroy a namespace (if it is no longer needed)
    317  *
    318  * The devices_list_mutex should be already held when
    319  * calling this function.
    320  *
    321  */
    322 static void devmap_namespace_destroy(devmap_namespace_t *namespace)
    323 {
    324         if (namespace->refcnt == 0) {
    325                 list_remove(&(namespace->namespaces));
    326                
    327                 free(namespace->name);
    328                 free(namespace);
    329         }
    330 }
    331 
    332 /** Increase namespace reference count by including device
    333  *
    334  * The devices_list_mutex should be already held when
    335  * calling this function.
    336  *
    337  */
    338 static void devmap_namespace_addref(devmap_namespace_t *namespace,
    339     devmap_device_t *device)
    340 {
    341         device->namespace = namespace;
    342         namespace->refcnt++;
    343 }
    344 
    345 /** Decrease namespace reference count
    346  *
    347  * The devices_list_mutex should be already held when
    348  * calling this function.
    349  *
    350  */
    351 static void devmap_namespace_delref(devmap_namespace_t *namespace)
    352 {
    353         namespace->refcnt--;
    354         devmap_namespace_destroy(namespace);
    355 }
    356 
    357 /** Unregister device and free it
    358  *
    359  * The devices_list_mutex should be already held when
    360  * calling this function.
    361  *
    362  */
    363 static void devmap_device_unregister_core(devmap_device_t *device)
    364 {
    365         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{
    366178        list_remove(&(device->devices));
    367179        list_remove(&(device->driver_devices));
    368180       
    369         free(device->namespace);
    370181        free(device->name);
    371182        free(device);
     183       
     184        return EOK;
    372185}
    373186
     
    376189 * drivers.
    377190 */
    378 static devmap_driver_t *devmap_driver_register(void)
    379 {
     191static void devmap_driver_register(devmap_driver_t **odriver)
     192{
     193        *odriver = NULL;
     194       
    380195        ipc_call_t icall;
    381196        ipc_callid_t iid = async_get_call(&icall);
     
    383198        if (IPC_GET_METHOD(icall) != DEVMAP_DRIVER_REGISTER) {
    384199                ipc_answer_0(iid, EREFUSED);
    385                 return NULL;
     200                return;
    386201        }
    387202       
     
    390205        if (driver == NULL) {
    391206                ipc_answer_0(iid, ENOMEM);
    392                 return NULL;
     207                return;
    393208        }
    394209       
     
    396211         * Get driver name
    397212         */
    398         int rc = async_data_string_receive(&driver->name, DEVMAP_NAME_MAXLEN);
    399         if (rc != EOK) {
     213        ipc_callid_t callid;
     214        size_t name_size;
     215        if (!async_data_write_receive(&callid, &name_size)) {
    400216                free(driver);
    401                 ipc_answer_0(iid, rc);
    402                 return NULL;
    403         }
     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 (async_data_write_finalize(callid, driver->name, name_size) != EOK) {
     244                free(driver->name);
     245                free(driver);
     246                ipc_answer_0(iid, EREFUSED);
     247                return;
     248        }
     249       
     250        driver->name[name_size] = 0;
    404251       
    405252        /* Initialize mutex for list of devices owned by this driver */
     
    415262         */
    416263        ipc_call_t call;
    417         ipc_callid_t callid = async_get_call(&call);
     264        callid = async_get_call(&call);
    418265       
    419266        if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) {
     
    423270                free(driver);
    424271                ipc_answer_0(iid, ENOTSUP);
    425                 return NULL;
     272                return;
    426273        }
    427274       
     
    446293        ipc_answer_0(iid, EOK);
    447294       
    448         return driver;
     295        *odriver = driver;
    449296}
    450297
     
    508355        }
    509356       
    510         /* Get fqdn */
    511         char *fqdn;
    512         int rc = async_data_string_receive(&fqdn, DEVMAP_NAME_MAXLEN);
    513         if (rc != EOK) {
     357        /* Get device name */
     358        ipc_callid_t callid;
     359        size_t size;
     360        if (!async_data_write_receive(&callid, &size)) {
    514361                free(device);
    515                 ipc_answer_0(iid, rc);
    516                 return;
    517         }
    518        
    519         char *ns_name;
    520         if (!devmap_fqdn_split(fqdn, &ns_name, &device->name)) {
    521                 free(fqdn);
     362                ipc_answer_0(iid, EREFUSED);
     363                return;
     364        }
     365       
     366        if (size > DEVMAP_NAME_MAXLEN) {
    522367                free(device);
    523                 ipc_answer_0(iid, EINVAL);
    524                 return;
    525         }
    526        
    527         free(fqdn);
    528        
    529         fibril_mutex_lock(&devices_list_mutex);
    530        
    531         devmap_namespace_t *namespace = devmap_namespace_create(ns_name);
    532         free(ns_name);
    533         if (!namespace) {
    534                 fibril_mutex_unlock(&devices_list_mutex);
     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) {
    535377                free(device);
    536                 ipc_answer_0(iid, ENOMEM);
    537                 return;
    538         }
     378                ipc_answer_0(callid, ENOMEM);
     379                ipc_answer_0(iid, EREFUSED);
     380                return;
     381        }
     382       
     383        async_data_write_finalize(callid, device->name, size);
     384        device->name[size] = 0;
    539385       
    540386        list_initialize(&(device->devices));
    541387        list_initialize(&(device->driver_devices));
    542388       
    543         /* Check that device is not already registered */
    544         if (devmap_device_find_name(namespace->name, device->name) != NULL) {
    545                 printf(NAME ": Device '%s/%s' already registered\n", device->namespace, device->name);
    546                 devmap_namespace_destroy(namespace);
     389        fibril_mutex_lock(&devices_list_mutex);
     390       
     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);
    547394                fibril_mutex_unlock(&devices_list_mutex);
    548                 free(device->namespace);
    549395                free(device->name);
    550396                free(device);
     
    556402        device->handle = devmap_create_handle();
    557403       
    558         devmap_namespace_addref(namespace, device);
    559404        device->driver = driver;
    560405       
     
    592437static void devmap_forward(ipc_callid_t callid, ipc_call_t *call)
    593438{
    594         fibril_mutex_lock(&devices_list_mutex);
    595        
    596439        /*
    597440         * Get handle from request
     
    607450        ipc_forward_fast(callid, dev->driver->phone, dev->handle,
    608451            IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
    609        
    610         fibril_mutex_unlock(&devices_list_mutex);
    611452}
    612453
     
    617458 *
    618459 */
    619 static void devmap_device_get_handle(ipc_callid_t iid, ipc_call_t *icall)
    620 {
    621         char *fqdn;
    622        
    623         /* Get fqdn */
    624         int rc = async_data_string_receive(&fqdn, DEVMAP_NAME_MAXLEN);
    625         if (rc != EOK) {
    626                 ipc_answer_0(iid, rc);
    627                 return;
    628         }
    629        
    630         char *ns_name;
    631         char *name;
    632         if (!devmap_fqdn_split(fqdn, &ns_name, &name)) {
    633                 free(fqdn);
    634                 ipc_answer_0(iid, EINVAL);
    635                 return;
    636         }
    637        
    638         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 (!async_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 = async_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';
    639500       
    640501        fibril_mutex_lock(&devices_list_mutex);
    641502        const devmap_device_t *dev;
    642        
    643503recheck:
    644        
     504
    645505        /*
    646506         * Find device name in the list of known devices.
    647507         */
    648         dev = devmap_device_find_name(ns_name, name);
     508        dev = devmap_device_find_name(name);
    649509       
    650510        /*
     
    652512         */
    653513        if (dev == NULL) {
    654                 if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
    655                         /* Blocking lookup */
    656                         fibril_condvar_wait(&devices_list_cv,
    657                             &devices_list_mutex);
    658                         goto recheck;
    659                 }
    660                
    661                 ipc_answer_0(iid, ENOENT);
    662                 free(ns_name);
    663                 free(name);
    664                 fibril_mutex_unlock(&devices_list_mutex);
    665                 return;
    666         }
    667         fibril_mutex_unlock(&devices_list_mutex);
    668        
    669         ipc_answer_1(iid, EOK, dev->handle);
    670         free(ns_name);
    671         free(name);
    672 }
    673 
    674 /** Find handle for namespace identified by name.
    675  *
    676  * In answer will be send EOK and device handle in arg1 or a error
    677  * code from errno.h.
    678  *
    679  */
    680 static void devmap_namespace_get_handle(ipc_callid_t iid, ipc_call_t *icall)
    681 {
    682         char *name;
    683        
    684         /* Get device name */
    685         int rc = async_data_string_receive(&name, DEVMAP_NAME_MAXLEN);
    686         if (rc != EOK) {
    687                 ipc_answer_0(iid, rc);
    688                 return;
    689         }
    690        
    691         fibril_mutex_lock(&devices_list_mutex);
    692         const devmap_namespace_t *namespace;
    693        
    694 recheck:
    695        
    696         /*
    697          * Find namespace name in the list of known namespaces.
    698          */
    699         namespace = devmap_namespace_find_name(name);
    700        
    701         /*
    702          * Namespace was not found.
    703          */
    704         if (namespace == NULL) {
    705514                if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
    706515                        /* Blocking lookup */
     
    717526        fibril_mutex_unlock(&devices_list_mutex);
    718527       
    719         ipc_answer_1(iid, EOK, namespace->handle);
     528        ipc_answer_1(iid, EOK, dev->handle);
    720529        free(name);
    721530}
    722531
    723 static void devmap_handle_probe(ipc_callid_t iid, ipc_call_t *icall)
     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 = async_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)
    724566{
    725567        fibril_mutex_lock(&devices_list_mutex);
    726        
    727         devmap_namespace_t *namespace = devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
    728         if (namespace == NULL) {
    729                 devmap_device_t *dev = devmap_device_find_handle(IPC_GET_ARG1(*icall));
    730                 if (dev == NULL)
    731                         ipc_answer_1(iid, EOK, DEV_HANDLE_NONE);
    732                 else
    733                         ipc_answer_1(iid, EOK, DEV_HANDLE_DEVICE);
    734         } else
    735                 ipc_answer_1(iid, EOK, DEV_HANDLE_NAMESPACE);
    736        
     568        ipc_answer_1(iid, EOK, list_count(&devices_list));
    737569        fibril_mutex_unlock(&devices_list_mutex);
    738570}
    739571
    740 static void devmap_get_namespace_count(ipc_callid_t iid, ipc_call_t *icall)
     572static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
    741573{
    742574        fibril_mutex_lock(&devices_list_mutex);
    743         ipc_answer_1(iid, EOK, list_count(&namespaces_list));
    744         fibril_mutex_unlock(&devices_list_mutex);
    745 }
    746 
    747 static void devmap_get_device_count(ipc_callid_t iid, ipc_call_t *icall)
    748 {
    749         fibril_mutex_lock(&devices_list_mutex);
    750        
    751         devmap_namespace_t *namespace = devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
    752         if (namespace == NULL)
    753                 ipc_answer_0(iid, EEXISTS);
    754         else
    755                 ipc_answer_1(iid, EOK, namespace->refcnt);
    756        
    757         fibril_mutex_unlock(&devices_list_mutex);
    758 }
    759 
    760 static void devmap_get_namespaces(ipc_callid_t iid, ipc_call_t *icall)
    761 {
     575       
    762576        ipc_callid_t callid;
    763577        size_t size;
     
    770584        if ((size % sizeof(dev_desc_t)) != 0) {
    771585                ipc_answer_0(callid, EINVAL);
    772                 ipc_answer_0(iid, EINVAL);
    773                 return;
    774         }
    775        
    776         fibril_mutex_lock(&devices_list_mutex);
     586                ipc_answer_0(iid, EREFUSED);
     587                return;
     588        }
    777589       
    778590        size_t count = size / sizeof(dev_desc_t);
    779         if (count != list_count(&namespaces_list)) {
    780                 ipc_answer_0(callid, EOVERFLOW);
    781                 ipc_answer_0(iid, EOVERFLOW);
    782                 return;
    783         }
    784        
    785591        dev_desc_t *desc = (dev_desc_t *) malloc(size);
    786592        if (desc == NULL) {
    787593                ipc_answer_0(callid, ENOMEM);
    788                 ipc_answer_0(iid, ENOMEM);
    789                 return;
    790         }
    791        
    792         link_t *item = namespaces_list.next;
     594                ipc_answer_0(iid, EREFUSED);
     595                return;
     596        }
     597       
    793598        size_t pos = 0;
    794         while (item != &namespaces_list) {
    795                 devmap_namespace_t *namespace = list_get_instance(item, devmap_namespace_t, namespaces);
    796                
    797                 desc[pos].handle = namespace->handle;
    798                 str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, namespace->name);
    799                 pos++;
    800                
    801                 item = item->next;
    802         }
    803        
    804         ipcarg_t retval = async_data_read_finalize(callid, desc, size);
    805        
    806         free(desc);
    807         fibril_mutex_unlock(&devices_list_mutex);
    808        
    809         ipc_answer_0(iid, retval);
    810 }
    811 
    812 static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
    813 {
    814         /* FIXME: Use faster algorithm which can make better use
    815            of namespaces */
    816        
    817         ipc_callid_t callid;
    818         size_t size;
    819         if (!async_data_read_receive(&callid, &size)) {
    820                 ipc_answer_0(callid, EREFUSED);
    821                 ipc_answer_0(iid, EREFUSED);
    822                 return;
    823         }
    824        
    825         if ((size % sizeof(dev_desc_t)) != 0) {
    826                 ipc_answer_0(callid, EINVAL);
    827                 ipc_answer_0(iid, EINVAL);
    828                 return;
    829         }
    830        
    831         fibril_mutex_lock(&devices_list_mutex);
    832        
    833         devmap_namespace_t *namespace = devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
    834         if (namespace == NULL) {
    835                 fibril_mutex_unlock(&devices_list_mutex);
    836                 ipc_answer_0(callid, ENOENT);
    837                 ipc_answer_0(iid, ENOENT);
    838                 return;
    839         }
    840        
    841         size_t count = size / sizeof(dev_desc_t);
    842         if (count != namespace->refcnt) {
    843                 ipc_answer_0(callid, EOVERFLOW);
    844                 ipc_answer_0(iid, EOVERFLOW);
    845                 return;
    846         }
    847        
    848         dev_desc_t *desc = (dev_desc_t *) malloc(size);
    849         if (desc == NULL) {
    850                 ipc_answer_0(callid, ENOMEM);
    851                 ipc_answer_0(iid, EREFUSED);
    852                 return;
    853         }
    854        
    855599        link_t *item = devices_list.next;
    856         size_t pos = 0;
    857         while (item != &devices_list) {
     600       
     601        while ((item != &devices_list) && (pos < count)) {
    858602                devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
    859603               
    860                 if (device->namespace == namespace) {
    861                         desc[pos].handle = device->handle;
    862                         str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
    863                         pos++;
    864                 }
    865                
     604                desc[pos].handle = device->handle;
     605                str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
     606                pos++;
    866607                item = item->next;
    867608        }
    868609       
    869         ipcarg_t retval = async_data_read_finalize(callid, desc, size);
     610        ipcarg_t retval = async_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        }
    870616       
    871617        free(desc);
     618       
    872619        fibril_mutex_unlock(&devices_list_mutex);
    873620       
    874         ipc_answer_0(iid, retval);
     621        ipc_answer_1(iid, EOK, pos);
    875622}
    876623
     
    895642        }
    896643       
    897         char null[DEVMAP_NAME_MAXLEN];
    898         snprintf(null, DEVMAP_NAME_MAXLEN, "%u", i);
    899        
    900         char *dev_name = str_dup(null);
    901         if (dev_name == NULL) {
    902                 fibril_mutex_unlock(&null_devices_mutex);
    903                 ipc_answer_0(iid, ENOMEM);
    904                 return;
    905         }
    906        
     644        /* Create NULL device entry */
    907645        devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
    908646        if (device == NULL) {
     
    912650        }
    913651       
    914         fibril_mutex_lock(&devices_list_mutex);
    915        
    916         devmap_namespace_t *namespace = devmap_namespace_create("null");
    917         if (!namespace) {
    918                 fibril_mutex_lock(&devices_list_mutex);
     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) {
    919657                fibril_mutex_unlock(&null_devices_mutex);
     658                free(device);
    920659                ipc_answer_0(iid, ENOMEM);
    921660                return;
     
    924663        list_initialize(&(device->devices));
    925664        list_initialize(&(device->driver_devices));
     665       
     666        fibril_mutex_lock(&devices_list_mutex);
    926667       
    927668        /* Get unique device handle */
    928669        device->handle = devmap_create_handle();
    929670        device->driver = NULL;
    930        
    931         devmap_namespace_addref(namespace, device);
    932         device->name = dev_name;
    933671       
    934672        /* Insert device into list of all devices
     
    954692        }
    955693       
    956         fibril_mutex_lock(&devices_list_mutex);
    957694        devmap_device_unregister_core(null_devices[i]);
    958         fibril_mutex_unlock(&devices_list_mutex);
    959        
    960695        null_devices[i] = NULL;
    961696       
     
    990725        ipc_answer_0(iid, EOK);
    991726       
    992         devmap_driver_t *driver = devmap_driver_register();
    993         if (driver == NULL)
     727        devmap_driver_t *driver = NULL;
     728        devmap_driver_register(&driver);
     729       
     730        if (NULL == driver)
    994731                return;
    995732       
     
    1018755                        break;
    1019756                case DEVMAP_DEVICE_GET_HANDLE:
    1020                         devmap_device_get_handle(callid, &call);
    1021                         break;
    1022                 case DEVMAP_NAMESPACE_GET_HANDLE:
    1023                         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);
    1024761                        break;
    1025762                default:
     
    1056793                        continue;
    1057794                case DEVMAP_DEVICE_GET_HANDLE:
    1058                         devmap_device_get_handle(callid, &call);
    1059                         break;
    1060                 case DEVMAP_NAMESPACE_GET_HANDLE:
    1061                         devmap_namespace_get_handle(callid, &call);
    1062                         break;
    1063                 case DEVMAP_HANDLE_PROBE:
    1064                         devmap_handle_probe(callid, &call);
    1065                         break;
    1066                 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:
    1067801                        devmap_null_create(callid, &call);
    1068802                        break;
    1069                 case DEVMAP_NULL_DESTROY:
     803                case DEVMAP_DEVICE_NULL_DESTROY:
    1070804                        devmap_null_destroy(callid, &call);
    1071805                        break;
    1072                 case DEVMAP_GET_NAMESPACE_COUNT:
    1073                         devmap_get_namespace_count(callid, &call);
    1074                         break;
    1075                 case DEVMAP_GET_DEVICE_COUNT:
    1076                         devmap_get_device_count(callid, &call);
    1077                         break;
    1078                 case DEVMAP_GET_NAMESPACES:
    1079                         devmap_get_namespaces(callid, &call);
    1080                         break;
    1081                 case DEVMAP_GET_DEVICES:
     806                case DEVMAP_DEVICE_GET_COUNT:
     807                        devmap_get_count(callid, &call);
     808                        break;
     809                case DEVMAP_DEVICE_GET_DEVICES:
    1082810                        devmap_get_devices(callid, &call);
    1083811                        break;
     
    1139867}
    1140868
    1141 /**
     869/** 
    1142870 * @}
    1143871 */
Note: See TracChangeset for help on using the changeset viewer.