Ignore:
File:
1 edited

Legend:

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

    ra405563 r1313ee9  
    4242#include <errno.h>
    4343#include <bool.h>
    44 #include <fibril_sync.h>
     44#include <fibril_synch.h>
    4545#include <stdlib.h>
    4646#include <string.h>
     
    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 (!ipc_data_write_receive(&callid, &name_size)) {
     398        int rc = async_data_string_receive(&driver->name, DEVMAP_NAME_MAXLEN);
     399        if (rc != EOK) {
    216400                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 (ipc_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;
     401                ipc_answer_0(iid, rc);
     402                return NULL;
     403        }
    251404       
    252405        /* Initialize mutex for list of devices owned by this driver */
     
    262415         */
    263416        ipc_call_t call;
    264         callid = async_get_call(&call);
     417        ipc_callid_t callid = async_get_call(&call);
    265418       
    266419        if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) {
     
    270423                free(driver);
    271424                ipc_answer_0(iid, ENOTSUP);
    272                 return;
     425                return NULL;
    273426        }
    274427       
     
    293446        ipc_answer_0(iid, EOK);
    294447       
    295         *odriver = driver;
     448        return driver;
    296449}
    297450
     
    355508        }
    356509       
    357         /* Get device name */
    358         ipc_callid_t callid;
    359         size_t size;
    360         if (!ipc_data_write_receive(&callid, &size)) {
     510        /* Get fqdn */
     511        char *fqdn;
     512        int rc = async_data_string_receive(&fqdn, DEVMAP_NAME_MAXLEN);
     513        if (rc != EOK) {
    361514                free(device);
    362                 ipc_answer_0(iid, EREFUSED);
    363                 return;
    364         }
    365        
    366         if (size > DEVMAP_NAME_MAXLEN) {
     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);
    367522                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) {
     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);
    377535                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;
     536                ipc_answer_0(iid, ENOMEM);
     537                return;
     538        }
    385539       
    386540        list_initialize(&(device->devices));
    387541        list_initialize(&(device->driver_devices));
    388542       
    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);
     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);
    394547                fibril_mutex_unlock(&devices_list_mutex);
     548                free(device->namespace);
    395549                free(device->name);
    396550                free(device);
     
    402556        device->handle = devmap_create_handle();
    403557       
     558        devmap_namespace_addref(namespace, device);
    404559        device->driver = driver;
    405560       
     
    437592static void devmap_forward(ipc_callid_t callid, ipc_call_t *call)
    438593{
     594        fibril_mutex_lock(&devices_list_mutex);
     595       
    439596        /*
    440597         * Get handle from request
     
    450607        ipc_forward_fast(callid, dev->driver->phone, dev->handle,
    451608            IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
     609       
     610        fibril_mutex_unlock(&devices_list_mutex);
    452611}
    453612
     
    458617 *
    459618 */
    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 (!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';
     619static 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);
    500639       
    501640        fibril_mutex_lock(&devices_list_mutex);
    502641        const devmap_device_t *dev;
     642       
    503643recheck:
    504 
     644       
    505645        /*
    506646         * Find device name in the list of known devices.
    507647         */
    508         dev = devmap_device_find_name(name);
     648        dev = devmap_device_find_name(ns_name, name);
    509649       
    510650        /*
     
    520660               
    521661                ipc_answer_0(iid, ENOENT);
     662                free(ns_name);
    522663                free(name);
    523664                fibril_mutex_unlock(&devices_list_mutex);
     
    527668       
    528669        ipc_answer_1(iid, EOK, dev->handle);
     670        free(ns_name);
    529671        free(name);
    530672}
    531673
    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));
     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 */
     680static 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       
     694recheck:
    538695       
    539696        /*
    540          * Device not found.
     697         * Find namespace name in the list of known namespaces.
    541698         */
    542         if (device == NULL) {
     699        namespace = devmap_namespace_find_name(name);
     700       
     701        /*
     702         * Namespace was not found.
     703         */
     704        if (namespace == NULL) {
     705                if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
     706                        /* Blocking lookup */
     707                        fibril_condvar_wait(&devices_list_cv,
     708                            &devices_list_mutex);
     709                        goto recheck;
     710                }
     711               
    543712                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 
    565 static void devmap_get_count(ipc_callid_t iid, ipc_call_t *icall)
     713                free(name);
     714                fibril_mutex_unlock(&devices_list_mutex);
     715                return;
     716        }
     717        fibril_mutex_unlock(&devices_list_mutex);
     718       
     719        ipc_answer_1(iid, EOK, namespace->handle);
     720        free(name);
     721}
     722
     723static void devmap_handle_probe(ipc_callid_t iid, ipc_call_t *icall)
    566724{
    567725        fibril_mutex_lock(&devices_list_mutex);
    568         ipc_answer_1(iid, EOK, list_count(&devices_list));
     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       
    569737        fibril_mutex_unlock(&devices_list_mutex);
    570738}
    571739
    572 static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
     740static void devmap_get_namespace_count(ipc_callid_t iid, ipc_call_t *icall)
    573741{
    574742        fibril_mutex_lock(&devices_list_mutex);
    575        
     743        ipc_answer_1(iid, EOK, list_count(&namespaces_list));
     744        fibril_mutex_unlock(&devices_list_mutex);
     745}
     746
     747static 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
     760static void devmap_get_namespaces(ipc_callid_t iid, ipc_call_t *icall)
     761{
    576762        ipc_callid_t callid;
    577763        size_t size;
    578         if (!ipc_data_read_receive(&callid, &size)) {
     764        if (!async_data_read_receive(&callid, &size)) {
    579765                ipc_answer_0(callid, EREFUSED);
    580766                ipc_answer_0(iid, EREFUSED);
     
    584770        if ((size % sizeof(dev_desc_t)) != 0) {
    585771                ipc_answer_0(callid, EINVAL);
     772                ipc_answer_0(iid, EINVAL);
     773                return;
     774        }
     775       
     776        fibril_mutex_lock(&devices_list_mutex);
     777       
     778        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       
     785        dev_desc_t *desc = (dev_desc_t *) malloc(size);
     786        if (desc == NULL) {
     787                ipc_answer_0(callid, ENOMEM);
     788                ipc_answer_0(iid, ENOMEM);
     789                return;
     790        }
     791       
     792        link_t *item = namespaces_list.next;
     793        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
     812static 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);
    586821                ipc_answer_0(iid, EREFUSED);
    587822                return;
    588823        }
    589824       
     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       
    590841        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       
    591848        dev_desc_t *desc = (dev_desc_t *) malloc(size);
    592849        if (desc == NULL) {
     
    596853        }
    597854       
     855        link_t *item = devices_list.next;
    598856        size_t pos = 0;
    599         link_t *item = devices_list.next;
    600        
    601         while ((item != &devices_list) && (pos < count)) {
     857        while (item != &devices_list) {
    602858                devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
    603859               
    604                 desc[pos].handle = device->handle;
    605                 str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
    606                 pos++;
     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               
    607866                item = item->next;
    608867        }
    609868       
    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         }
     869        ipcarg_t retval = async_data_read_finalize(callid, desc, size);
    616870       
    617871        free(desc);
    618        
    619872        fibril_mutex_unlock(&devices_list_mutex);
    620873       
    621         ipc_answer_1(iid, EOK, pos);
     874        ipc_answer_0(iid, retval);
    622875}
    623876
     
    642895        }
    643896       
    644         /* Create NULL device entry */
     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       
    645907        devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
    646908        if (device == NULL) {
     
    650912        }
    651913       
    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) {
     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);
    657919                fibril_mutex_unlock(&null_devices_mutex);
    658                 free(device);
    659920                ipc_answer_0(iid, ENOMEM);
    660921                return;
     
    663924        list_initialize(&(device->devices));
    664925        list_initialize(&(device->driver_devices));
    665        
    666         fibril_mutex_lock(&devices_list_mutex);
    667926       
    668927        /* Get unique device handle */
    669928        device->handle = devmap_create_handle();
    670929        device->driver = NULL;
     930       
     931        devmap_namespace_addref(namespace, device);
     932        device->name = dev_name;
    671933       
    672934        /* Insert device into list of all devices
     
    692954        }
    693955       
     956        fibril_mutex_lock(&devices_list_mutex);
    694957        devmap_device_unregister_core(null_devices[i]);
     958        fibril_mutex_unlock(&devices_list_mutex);
     959       
    695960        null_devices[i] = NULL;
    696961       
     
    725990        ipc_answer_0(iid, EOK);
    726991       
    727         devmap_driver_t *driver = NULL;
    728         devmap_driver_register(&driver);
    729        
    730         if (NULL == driver)
     992        devmap_driver_t *driver = devmap_driver_register();
     993        if (driver == NULL)
    731994                return;
    732995       
     
    7551018                        break;
    7561019                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);
     1020                        devmap_device_get_handle(callid, &call);
     1021                        break;
     1022                case DEVMAP_NAMESPACE_GET_HANDLE:
     1023                        devmap_namespace_get_handle(callid, &call);
    7611024                        break;
    7621025                default:
     
    7931056                        continue;
    7941057                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:
     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:
    8011067                        devmap_null_create(callid, &call);
    8021068                        break;
    803                 case DEVMAP_DEVICE_NULL_DESTROY:
     1069                case DEVMAP_NULL_DESTROY:
    8041070                        devmap_null_destroy(callid, &call);
    8051071                        break;
    806                 case DEVMAP_DEVICE_GET_COUNT:
    807                         devmap_get_count(callid, &call);
    808                         break;
    809                 case DEVMAP_DEVICE_GET_DEVICES:
     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:
    8101082                        devmap_get_devices(callid, &call);
    8111083                        break;
     
    8671139}
    8681140
    869 /** 
     1141/**
    8701142 * @}
    8711143 */
Note: See TracChangeset for help on using the changeset viewer.