Ignore:
File:
1 edited

Legend:

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

    r0da4e41 r19f857a  
    4242#include <errno.h>
    4343#include <bool.h>
    44 #include <fibril_sync.h>
     44#include <fibril_synch.h>
    4545#include <stdlib.h>
    46 #include <string.h>
     46#include <str.h>
    4747#include <ipc/devmap.h>
    4848
     
    6868} devmap_driver_t;
    6969
     70/** Info about registered namespaces
     71 *
     72 */
     73typedef 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
    7084/** Info about registered device
    7185 *
     
    7791            owned by one driver */
    7892        link_t driver_devices;
    79         /** Unique device identifier  */
     93        /** Unique device identifier */
    8094        dev_handle_t handle;
     95        /** Device namespace */
     96        devmap_namespace_t *namespace;
    8197        /** Device name */
    8298        char *name;
     
    86102
    87103LIST_INITIALIZE(devices_list);
     104LIST_INITIALIZE(namespaces_list);
    88105LIST_INITIALIZE(drivers_list);
    89106
     
    117134}
    118135
     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 */
     144static 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 */
     202static 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;
     210                item = item->next;
     211        }
     212       
     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.
     220 *
     221 * @todo: use hash table
     222 *
     223 */
     224static 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               
     233                item = item->next;
     234        }
     235       
     236        return NULL;
     237}
     238
    119239/** Find device with given name.
    120240 *
    121  */
    122 static devmap_device_t *devmap_device_find_name(const char *name)
     241 * The devices_list_mutex should be already held when
     242 * calling this function.
     243 *
     244 */
     245static devmap_device_t *devmap_device_find_name(const char *ns_name,
     246    const char *name)
    123247{
    124248        link_t *item = devices_list.next;
    125         devmap_device_t *device = NULL;
    126249       
    127250        while (item != &devices_list) {
    128                 device = list_get_instance(item, devmap_device_t, devices);
    129                 if (str_cmp(device->name, name) == 0)
    130                         break;
     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;
    131254                item = item->next;
    132255        }
    133256       
    134         if (item == &devices_list)
     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 */
     268static 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 */
     289static 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)
    135297                return NULL;
    136298       
    137         device = list_get_instance(item, devmap_device_t, devices);
    138         return device;
    139 }
    140 
    141 /** Find device with given handle.
    142  *
    143  * @todo: use hash table
    144  *
    145  */
    146 static 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;
    157                 item = item->next;
    158         }
    159        
    160         if (item == &devices_list) {
    161                 fibril_mutex_unlock(&devices_list_mutex);
     299        namespace->name = str_dup(ns_name);
     300        if (namespace->name == NULL) {
     301                free(namespace);
    162302                return NULL;
    163303        }
    164304       
    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  */
    176 static int devmap_device_unregister_core(devmap_device_t *device)
    177 {
     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 */
     322static 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 */
     338static 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 */
     351static 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 */
     363static void devmap_device_unregister_core(devmap_device_t *device)
     364{
     365        devmap_namespace_delref(device->namespace);
    178366        list_remove(&(device->devices));
    179367        list_remove(&(device->driver_devices));
    180368       
     369        free(device->namespace);
    181370        free(device->name);
    182371        free(device);
    183        
    184         return EOK;
    185372}
    186373
     
    189376 * drivers.
    190377 */
    191 static void devmap_driver_register(devmap_driver_t **odriver)
    192 {
    193         *odriver = NULL;
    194        
     378static devmap_driver_t *devmap_driver_register(void)
     379{
    195380        ipc_call_t icall;
    196381        ipc_callid_t iid = async_get_call(&icall);
     
    198383        if (IPC_GET_METHOD(icall) != DEVMAP_DRIVER_REGISTER) {
    199384                ipc_answer_0(iid, EREFUSED);
    200                 return;
     385                return NULL;
    201386        }
    202387       
     
    205390        if (driver == NULL) {
    206391                ipc_answer_0(iid, ENOMEM);
    207                 return;
     392                return NULL;
    208393        }
    209394       
     
    211396         * Get driver name
    212397         */
    213         ipc_callid_t callid;
    214         size_t name_size;
    215         if (!async_data_write_receive(&callid, &name_size)) {
     398        int rc = async_data_write_accept((void **) &driver->name, true, 0,
     399            DEVMAP_NAME_MAXLEN, 0, NULL);
     400        if (rc != EOK) {
    216401                free(driver);
    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;
     402                ipc_answer_0(iid, rc);
     403                return NULL;
     404        }
    251405       
    252406        /* Initialize mutex for list of devices owned by this driver */
     
    262416         */
    263417        ipc_call_t call;
    264         callid = async_get_call(&call);
     418        ipc_callid_t callid = async_get_call(&call);
    265419       
    266420        if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) {
     
    270424                free(driver);
    271425                ipc_answer_0(iid, ENOTSUP);
    272                 return;
     426                return NULL;
    273427        }
    274428       
     
    293447        ipc_answer_0(iid, EOK);
    294448       
    295         *odriver = driver;
     449        return driver;
    296450}
    297451
     
    355509        }
    356510       
    357         /* Get device name */
    358         ipc_callid_t callid;
    359         size_t size;
    360         if (!async_data_write_receive(&callid, &size)) {
     511        /* Get fqdn */
     512        char *fqdn;
     513        int rc = async_data_write_accept((void **) &fqdn, true, 0,
     514            DEVMAP_NAME_MAXLEN, 0, NULL);
     515        if (rc != EOK) {
    361516                free(device);
    362                 ipc_answer_0(iid, EREFUSED);
    363                 return;
    364         }
    365        
    366         if (size > DEVMAP_NAME_MAXLEN) {
     517                ipc_answer_0(iid, rc);
     518                return;
     519        }
     520       
     521        char *ns_name;
     522        if (!devmap_fqdn_split(fqdn, &ns_name, &device->name)) {
     523                free(fqdn);
    367524                free(device);
    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) {
     525                ipc_answer_0(iid, EINVAL);
     526                return;
     527        }
     528       
     529        free(fqdn);
     530       
     531        fibril_mutex_lock(&devices_list_mutex);
     532       
     533        devmap_namespace_t *namespace = devmap_namespace_create(ns_name);
     534        free(ns_name);
     535        if (!namespace) {
     536                fibril_mutex_unlock(&devices_list_mutex);
    377537                free(device);
    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;
     538                ipc_answer_0(iid, ENOMEM);
     539                return;
     540        }
    385541       
    386542        list_initialize(&(device->devices));
    387543        list_initialize(&(device->driver_devices));
    388544       
    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);
     545        /* Check that device is not already registered */
     546        if (devmap_device_find_name(namespace->name, device->name) != NULL) {
     547                printf(NAME ": Device '%s/%s' already registered\n", device->namespace, device->name);
     548                devmap_namespace_destroy(namespace);
    394549                fibril_mutex_unlock(&devices_list_mutex);
     550                free(device->namespace);
    395551                free(device->name);
    396552                free(device);
     
    402558        device->handle = devmap_create_handle();
    403559       
     560        devmap_namespace_addref(namespace, device);
    404561        device->driver = driver;
    405562       
     
    437594static void devmap_forward(ipc_callid_t callid, ipc_call_t *call)
    438595{
     596        fibril_mutex_lock(&devices_list_mutex);
     597       
    439598        /*
    440599         * Get handle from request
     
    450609        ipc_forward_fast(callid, dev->driver->phone, dev->handle,
    451610            IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
     611       
     612        fibril_mutex_unlock(&devices_list_mutex);
    452613}
    453614
     
    458619 *
    459620 */
    460 static 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';
     621static void devmap_device_get_handle(ipc_callid_t iid, ipc_call_t *icall)
     622{
     623        char *fqdn;
     624       
     625        /* Get fqdn */
     626        int rc = async_data_write_accept((void **) &fqdn, true, 0,
     627            DEVMAP_NAME_MAXLEN, 0, NULL);
     628        if (rc != EOK) {
     629                ipc_answer_0(iid, rc);
     630                return;
     631        }
     632       
     633        char *ns_name;
     634        char *name;
     635        if (!devmap_fqdn_split(fqdn, &ns_name, &name)) {
     636                free(fqdn);
     637                ipc_answer_0(iid, EINVAL);
     638                return;
     639        }
     640       
     641        free(fqdn);
    500642       
    501643        fibril_mutex_lock(&devices_list_mutex);
    502644        const devmap_device_t *dev;
     645       
    503646recheck:
    504 
     647       
    505648        /*
    506649         * Find device name in the list of known devices.
    507650         */
    508         dev = devmap_device_find_name(name);
     651        dev = devmap_device_find_name(ns_name, name);
    509652       
    510653        /*
     
    520663               
    521664                ipc_answer_0(iid, ENOENT);
     665                free(ns_name);
    522666                free(name);
    523667                fibril_mutex_unlock(&devices_list_mutex);
     
    527671       
    528672        ipc_answer_1(iid, EOK, dev->handle);
     673        free(ns_name);
    529674        free(name);
    530675}
    531676
    532 /** Find name of device identified by id and send it to caller.
    533  *
    534  */
    535 static 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));
     677/** Find handle for namespace identified by name.
     678 *
     679 * In answer will be send EOK and device handle in arg1 or a error
     680 * code from errno.h.
     681 *
     682 */
     683static void devmap_namespace_get_handle(ipc_callid_t iid, ipc_call_t *icall)
     684{
     685        char *name;
     686       
     687        /* Get device name */
     688        int rc = async_data_write_accept((void **) &name, true, 0,
     689            DEVMAP_NAME_MAXLEN, 0, NULL);
     690        if (rc != EOK) {
     691                ipc_answer_0(iid, rc);
     692                return;
     693        }
     694       
     695        fibril_mutex_lock(&devices_list_mutex);
     696        const devmap_namespace_t *namespace;
     697       
     698recheck:
    538699       
    539700        /*
    540          * Device not found.
     701         * Find namespace name in the list of known namespaces.
    541702         */
    542         if (device == NULL) {
     703        namespace = devmap_namespace_find_name(name);
     704       
     705        /*
     706         * Namespace was not found.
     707         */
     708        if (namespace == NULL) {
     709                if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
     710                        /* Blocking lookup */
     711                        fibril_condvar_wait(&devices_list_cv,
     712                            &devices_list_mutex);
     713                        goto recheck;
     714                }
     715               
    543716                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 
    565 static void devmap_get_count(ipc_callid_t iid, ipc_call_t *icall)
     717                free(name);
     718                fibril_mutex_unlock(&devices_list_mutex);
     719                return;
     720        }
     721        fibril_mutex_unlock(&devices_list_mutex);
     722       
     723        ipc_answer_1(iid, EOK, namespace->handle);
     724        free(name);
     725}
     726
     727static void devmap_handle_probe(ipc_callid_t iid, ipc_call_t *icall)
    566728{
    567729        fibril_mutex_lock(&devices_list_mutex);
    568         ipc_answer_1(iid, EOK, list_count(&devices_list));
     730       
     731        devmap_namespace_t *namespace = devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
     732        if (namespace == NULL) {
     733                devmap_device_t *dev = devmap_device_find_handle(IPC_GET_ARG1(*icall));
     734                if (dev == NULL)
     735                        ipc_answer_1(iid, EOK, DEV_HANDLE_NONE);
     736                else
     737                        ipc_answer_1(iid, EOK, DEV_HANDLE_DEVICE);
     738        } else
     739                ipc_answer_1(iid, EOK, DEV_HANDLE_NAMESPACE);
     740       
    569741        fibril_mutex_unlock(&devices_list_mutex);
    570742}
    571743
    572 static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
     744static void devmap_get_namespace_count(ipc_callid_t iid, ipc_call_t *icall)
    573745{
    574746        fibril_mutex_lock(&devices_list_mutex);
    575        
     747        ipc_answer_1(iid, EOK, list_count(&namespaces_list));
     748        fibril_mutex_unlock(&devices_list_mutex);
     749}
     750
     751static void devmap_get_device_count(ipc_callid_t iid, ipc_call_t *icall)
     752{
     753        fibril_mutex_lock(&devices_list_mutex);
     754       
     755        devmap_namespace_t *namespace = devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
     756        if (namespace == NULL)
     757                ipc_answer_0(iid, EEXISTS);
     758        else
     759                ipc_answer_1(iid, EOK, namespace->refcnt);
     760       
     761        fibril_mutex_unlock(&devices_list_mutex);
     762}
     763
     764static void devmap_get_namespaces(ipc_callid_t iid, ipc_call_t *icall)
     765{
    576766        ipc_callid_t callid;
    577767        size_t size;
     
    584774        if ((size % sizeof(dev_desc_t)) != 0) {
    585775                ipc_answer_0(callid, EINVAL);
     776                ipc_answer_0(iid, EINVAL);
     777                return;
     778        }
     779       
     780        fibril_mutex_lock(&devices_list_mutex);
     781       
     782        size_t count = size / sizeof(dev_desc_t);
     783        if (count != list_count(&namespaces_list)) {
     784                ipc_answer_0(callid, EOVERFLOW);
     785                ipc_answer_0(iid, EOVERFLOW);
     786                return;
     787        }
     788       
     789        dev_desc_t *desc = (dev_desc_t *) malloc(size);
     790        if (desc == NULL) {
     791                ipc_answer_0(callid, ENOMEM);
     792                ipc_answer_0(iid, ENOMEM);
     793                return;
     794        }
     795       
     796        link_t *item = namespaces_list.next;
     797        size_t pos = 0;
     798        while (item != &namespaces_list) {
     799                devmap_namespace_t *namespace = list_get_instance(item, devmap_namespace_t, namespaces);
     800               
     801                desc[pos].handle = namespace->handle;
     802                str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, namespace->name);
     803                pos++;
     804               
     805                item = item->next;
     806        }
     807       
     808        ipcarg_t retval = async_data_read_finalize(callid, desc, size);
     809       
     810        free(desc);
     811        fibril_mutex_unlock(&devices_list_mutex);
     812       
     813        ipc_answer_0(iid, retval);
     814}
     815
     816static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
     817{
     818        /* FIXME: Use faster algorithm which can make better use
     819           of namespaces */
     820       
     821        ipc_callid_t callid;
     822        size_t size;
     823        if (!async_data_read_receive(&callid, &size)) {
     824                ipc_answer_0(callid, EREFUSED);
    586825                ipc_answer_0(iid, EREFUSED);
    587826                return;
    588827        }
    589828       
     829        if ((size % sizeof(dev_desc_t)) != 0) {
     830                ipc_answer_0(callid, EINVAL);
     831                ipc_answer_0(iid, EINVAL);
     832                return;
     833        }
     834       
     835        fibril_mutex_lock(&devices_list_mutex);
     836       
     837        devmap_namespace_t *namespace = devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
     838        if (namespace == NULL) {
     839                fibril_mutex_unlock(&devices_list_mutex);
     840                ipc_answer_0(callid, ENOENT);
     841                ipc_answer_0(iid, ENOENT);
     842                return;
     843        }
     844       
    590845        size_t count = size / sizeof(dev_desc_t);
     846        if (count != namespace->refcnt) {
     847                ipc_answer_0(callid, EOVERFLOW);
     848                ipc_answer_0(iid, EOVERFLOW);
     849                return;
     850        }
     851       
    591852        dev_desc_t *desc = (dev_desc_t *) malloc(size);
    592853        if (desc == NULL) {
     
    596857        }
    597858       
     859        link_t *item = devices_list.next;
    598860        size_t pos = 0;
    599         link_t *item = devices_list.next;
    600        
    601         while ((item != &devices_list) && (pos < count)) {
     861        while (item != &devices_list) {
    602862                devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
    603863               
    604                 desc[pos].handle = device->handle;
    605                 str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
    606                 pos++;
     864                if (device->namespace == namespace) {
     865                        desc[pos].handle = device->handle;
     866                        str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
     867                        pos++;
     868                }
     869               
    607870                item = item->next;
    608871        }
    609872       
    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         }
     873        ipcarg_t retval = async_data_read_finalize(callid, desc, size);
    616874       
    617875        free(desc);
    618        
    619876        fibril_mutex_unlock(&devices_list_mutex);
    620877       
    621         ipc_answer_1(iid, EOK, pos);
     878        ipc_answer_0(iid, retval);
    622879}
    623880
     
    642899        }
    643900       
    644         /* Create NULL device entry */
     901        char null[DEVMAP_NAME_MAXLEN];
     902        snprintf(null, DEVMAP_NAME_MAXLEN, "%u", i);
     903       
     904        char *dev_name = str_dup(null);
     905        if (dev_name == NULL) {
     906                fibril_mutex_unlock(&null_devices_mutex);
     907                ipc_answer_0(iid, ENOMEM);
     908                return;
     909        }
     910       
    645911        devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
    646912        if (device == NULL) {
     
    650916        }
    651917       
    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) {
     918        fibril_mutex_lock(&devices_list_mutex);
     919       
     920        devmap_namespace_t *namespace = devmap_namespace_create("null");
     921        if (!namespace) {
     922                fibril_mutex_lock(&devices_list_mutex);
    657923                fibril_mutex_unlock(&null_devices_mutex);
    658                 free(device);
    659924                ipc_answer_0(iid, ENOMEM);
    660925                return;
     
    663928        list_initialize(&(device->devices));
    664929        list_initialize(&(device->driver_devices));
    665        
    666         fibril_mutex_lock(&devices_list_mutex);
    667930       
    668931        /* Get unique device handle */
    669932        device->handle = devmap_create_handle();
    670933        device->driver = NULL;
     934       
     935        devmap_namespace_addref(namespace, device);
     936        device->name = dev_name;
    671937       
    672938        /* Insert device into list of all devices
     
    692958        }
    693959       
     960        fibril_mutex_lock(&devices_list_mutex);
    694961        devmap_device_unregister_core(null_devices[i]);
     962        fibril_mutex_unlock(&devices_list_mutex);
     963       
    695964        null_devices[i] = NULL;
    696965       
     
    725994        ipc_answer_0(iid, EOK);
    726995       
    727         devmap_driver_t *driver = NULL;
    728         devmap_driver_register(&driver);
    729        
    730         if (NULL == driver)
     996        devmap_driver_t *driver = devmap_driver_register();
     997        if (driver == NULL)
    731998                return;
    732999       
     
    7551022                        break;
    7561023                case DEVMAP_DEVICE_GET_HANDLE:
    757                         devmap_get_handle(callid, &call);
    758                         break;
    759                 case DEVMAP_DEVICE_GET_NAME:
    760                         devmap_get_name(callid, &call);
     1024                        devmap_device_get_handle(callid, &call);
     1025                        break;
     1026                case DEVMAP_NAMESPACE_GET_HANDLE:
     1027                        devmap_namespace_get_handle(callid, &call);
    7611028                        break;
    7621029                default:
     
    7931060                        continue;
    7941061                case DEVMAP_DEVICE_GET_HANDLE:
    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:
     1062                        devmap_device_get_handle(callid, &call);
     1063                        break;
     1064                case DEVMAP_NAMESPACE_GET_HANDLE:
     1065                        devmap_namespace_get_handle(callid, &call);
     1066                        break;
     1067                case DEVMAP_HANDLE_PROBE:
     1068                        devmap_handle_probe(callid, &call);
     1069                        break;
     1070                case DEVMAP_NULL_CREATE:
    8011071                        devmap_null_create(callid, &call);
    8021072                        break;
    803                 case DEVMAP_DEVICE_NULL_DESTROY:
     1073                case DEVMAP_NULL_DESTROY:
    8041074                        devmap_null_destroy(callid, &call);
    8051075                        break;
    806                 case DEVMAP_DEVICE_GET_COUNT:
    807                         devmap_get_count(callid, &call);
    808                         break;
    809                 case DEVMAP_DEVICE_GET_DEVICES:
     1076                case DEVMAP_GET_NAMESPACE_COUNT:
     1077                        devmap_get_namespace_count(callid, &call);
     1078                        break;
     1079                case DEVMAP_GET_DEVICE_COUNT:
     1080                        devmap_get_device_count(callid, &call);
     1081                        break;
     1082                case DEVMAP_GET_NAMESPACES:
     1083                        devmap_get_namespaces(callid, &call);
     1084                        break;
     1085                case DEVMAP_GET_DEVICES:
    8101086                        devmap_get_devices(callid, &call);
    8111087                        break;
     
    8671143}
    8681144
    869 /** 
     1145/**
    8701146 * @}
    8711147 */
Note: See TracChangeset for help on using the changeset viewer.