Changeset cb41a5e in mainline for uspace/srv/devmap/devmap.c


Ignore:
Timestamp:
2009-05-21T07:03:38Z (16 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a095d20
Parents:
2246de6
Message:

improve devmap interface
remove spared device

File:
1 edited

Legend:

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

    r2246de6 rcb41a5e  
    4949#define NAME  "devmap"
    5050
     51/** Representation of device driver.
     52 *
     53 * Each driver is responsible for a set of devices.
     54 *
     55 */
     56typedef struct {
     57        /** Pointers to previous and next drivers in linked list */
     58        link_t drivers;
     59        /** Pointer to the linked list of devices controlled by this driver */
     60        link_t devices;
     61        /** Phone asociated with this driver */
     62        ipcarg_t phone;
     63        /** Device driver name */
     64        char *name;
     65        /** Futex for list of devices owned by this driver */
     66        atomic_t devices_futex;
     67} devmap_driver_t;
     68
     69/** Info about registered device
     70 *
     71 */
     72typedef struct {
     73        /** Pointer to the previous and next device in the list of all devices */
     74        link_t devices;
     75        /** Pointer to the previous and next device in the list of devices
     76            owned by one driver */
     77        link_t driver_devices;
     78        /** Unique device identifier  */
     79        dev_handle_t handle;
     80        /** Device name */
     81        char *name;
     82        /** Device driver handling this device */
     83        devmap_driver_t *driver;
     84} devmap_device_t;
     85
    5186/** Pending lookup structure. */
    5287typedef struct {
     
    71106static atomic_t create_handle_futex = FUTEX_INITIALIZER;
    72107
    73 static int devmap_create_handle(void)
    74 {
    75         static int last_handle = 0;
    76         int handle;
    77        
     108static dev_handle_t last_handle = 0;
     109
     110static dev_handle_t devmap_create_handle(void)
     111{
    78112        /* TODO: allow reusing old handles after their unregistration
    79113         * and implement some version of LRU algorithm
     
    82116        /* FIXME: overflow */
    83117        futex_down(&create_handle_futex);
    84        
    85         last_handle += 1;
    86         handle = last_handle;
    87        
     118        last_handle++;
    88119        futex_up(&create_handle_futex);
    89120       
    90         return handle;
    91 }
    92 
    93 
    94 /** Initialize device mapper.
    95  *
    96  *
    97  */
    98 static int devmap_init()
    99 {
    100         /* TODO: */
    101        
    102         return EOK;
     121        return last_handle;
    103122}
    104123
     
    130149 *
    131150 */
    132 static devmap_device_t *devmap_device_find_handle(int handle)
     151static devmap_device_t *devmap_device_find_handle(dev_handle_t handle)
    133152{
    134153        futex_down(&devices_list_futex);
     
    298317        futex_down(&drivers_list_futex);
    299318       
    300         ipc_hangup(driver->phone);
    301        
    302         /* remove it from list of drivers */
     319        if (driver->phone != 0)
     320                ipc_hangup(driver->phone);
     321       
     322        /* Remove it from list of drivers */
    303323        list_remove(&(driver->drivers));
    304324       
    305         /* unregister all its devices */
    306        
     325        /* Unregister all its devices */
    307326        futex_down(&devices_list_futex);
    308327        futex_down(&(driver->devices_futex));
     
    319338       
    320339        /* free name and driver */
    321         if (NULL != driver->name)
     340        if (driver->name != NULL)
    322341                free(driver->name);
    323342       
     
    455474         * Get handle from request
    456475         */
    457         int handle = IPC_GET_ARG2(*call);
     476        dev_handle_t handle = IPC_GET_ARG2(*call);
    458477        devmap_device_t *dev = devmap_device_find_handle(handle);
    459478       
    460         if (NULL == dev) {
     479        if ((dev == NULL) || (dev->driver == NULL) || (dev->driver->phone == 0)) {
    461480                ipc_answer_0(callid, ENOENT);
    462481                return;
    463482        }
    464483       
    465         ipc_forward_fast(callid, dev->driver->phone, (ipcarg_t)(dev->handle),
     484        ipc_forward_fast(callid, dev->driver->phone, dev->handle,
    466485            IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
    467486}
     
    496515         * Allocate buffer for device name.
    497516         */
    498         char *name = (char *) malloc(size);
     517        char *name = (char *) malloc(size + 1);
    499518        if (name == NULL) {
    500519                ipc_answer_0(callid, ENOMEM);
     
    550569 *
    551570 */
    552 static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall) 
     571static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall)
    553572{
    554573        const devmap_device_t *device = devmap_device_find_handle(IPC_GET_ARG1(*icall));
     
    578597       
    579598        /* TODO: send name in response */
     599}
     600
     601static void devmap_get_count(ipc_callid_t iid, ipc_call_t *icall)
     602{
     603        futex_down(&devices_list_futex);
     604        ipc_answer_1(iid, EOK, list_count(&devices_list));
     605        futex_up(&devices_list_futex);
     606}
     607
     608static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
     609{
     610        futex_down(&devices_list_futex);
     611       
     612        ipc_callid_t callid;
     613        size_t size;
     614        if (!ipc_data_read_receive(&callid, &size)) {
     615                ipc_answer_0(callid, EREFUSED);
     616                ipc_answer_0(iid, EREFUSED);
     617                return;
     618        }
     619       
     620        if ((size % sizeof(dev_desc_t)) != 0) {
     621                ipc_answer_0(callid, EINVAL);
     622                ipc_answer_0(iid, EREFUSED);
     623                return;
     624        }
     625       
     626        count_t count = size / sizeof(dev_desc_t);
     627        dev_desc_t *desc = (dev_desc_t *) malloc(size);
     628        if (desc == NULL) {
     629                ipc_answer_0(callid, ENOMEM);
     630                ipc_answer_0(iid, EREFUSED);
     631                return;
     632        }
     633       
     634        count_t pos = 0;
     635        link_t *item = devices_list.next;
     636       
     637        while ((item != &devices_list) && (pos < count)) {
     638                devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
     639               
     640                desc[pos].handle = device->handle;
     641                str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
     642                pos++;
     643                item = item->next;
     644        }
     645       
     646        ipcarg_t retval = ipc_data_read_finalize(callid, desc, pos * sizeof(dev_desc_t));
     647        if (retval != EOK) {
     648                ipc_answer_0(iid, EREFUSED);
     649                free(desc);
     650                return;
     651        }
     652       
     653        free(desc);
     654       
     655        futex_up(&devices_list_futex);
     656       
     657        ipc_answer_1(iid, EOK, pos);
     658}
     659
     660/** Initialize device mapper.
     661 *
     662 *
     663 */
     664static bool devmap_init()
     665{
     666        /* Create NULL device entry */
     667        devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
     668        if (device == NULL)
     669                return false;
     670       
     671        device->name = str_dup("null");
     672        if (device->name == NULL) {
     673                free(device);
     674                return false;
     675        }
     676       
     677        list_initialize(&(device->devices));
     678        list_initialize(&(device->driver_devices));
     679       
     680        futex_down(&devices_list_futex);
     681       
     682        /* Get unique device handle */
     683        device->handle = devmap_create_handle();
     684        device->driver = NULL;
     685       
     686        /* Insert device into list of all devices  */
     687        list_append(&device->devices, &devices_list);
     688       
     689        futex_up(&devices_list_futex);
     690       
     691        return true;
    580692}
    581693
     
    622734                        break;
    623735                case DEVMAP_DEVICE_GET_NAME:
    624                         devmap_get_handle(callid, &call);
     736                        devmap_get_name(callid, &call);
    625737                        break;
    626738                default:
     
    661773                        break;
    662774                case DEVMAP_DEVICE_GET_NAME:
    663                         /* TODO */
    664775                        devmap_get_name(callid, &call);
     776                        break;
     777                case DEVMAP_DEVICE_GET_COUNT:
     778                        devmap_get_count(callid, &call);
     779                        break;
     780                case DEVMAP_DEVICE_GET_DEVICES:
     781                        devmap_get_devices(callid, &call);
    665782                        break;
    666783                default:
     
    701818        printf(NAME ": HelenOS Device Mapper\n");
    702819       
    703         if (devmap_init() != 0) {
     820        if (!devmap_init()) {
    704821                printf(NAME ": Error while initializing service\n");
    705822                return -1;
Note: See TracChangeset for help on using the changeset viewer.