Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/drv/generic/driver.c

    r80a96d2 r45059d6b  
    6363
    6464/** Devices */
    65 LIST_INITIALIZE(devices);
    66 FIBRIL_MUTEX_INITIALIZE(devices_mutex);
    67 
    68 /** Functions */
    6965LIST_INITIALIZE(functions);
    7066FIBRIL_MUTEX_INITIALIZE(functions_mutex);
     
    8682static ddf_dev_t *create_device(void);
    8783static void delete_device(ddf_dev_t *);
    88 static void dev_add_ref(ddf_dev_t *);
    89 static void dev_del_ref(ddf_dev_t *);
    90 static void fun_add_ref(ddf_fun_t *);
    91 static void fun_del_ref(ddf_fun_t *);
    9284static remote_handler_t *function_get_default_handler(ddf_fun_t *);
    9385static void *function_get_ops(ddf_fun_t *, dev_inferface_idx_t);
     
    235227}
    236228
    237 static ddf_dev_t *driver_get_device(devman_handle_t handle)
    238 {
    239         ddf_dev_t *dev = NULL;
    240        
    241         assert(fibril_mutex_is_locked(&devices_mutex));
    242        
    243         list_foreach(devices, link) {
    244                 dev = list_get_instance(link, ddf_dev_t, link);
    245                 if (dev->handle == handle)
    246                         return dev;
    247         }
     229static ddf_fun_t *driver_get_function(list_t *functions, devman_handle_t handle)
     230{
     231        ddf_fun_t *fun = NULL;
     232       
     233        fibril_mutex_lock(&functions_mutex);
     234       
     235        list_foreach(*functions, link) {
     236                fun = list_get_instance(link, ddf_fun_t, link);
     237                if (fun->handle == handle) {
     238                        fibril_mutex_unlock(&functions_mutex);
     239                        return fun;
     240                }
     241        }
     242       
     243        fibril_mutex_unlock(&functions_mutex);
    248244       
    249245        return NULL;
    250246}
    251247
    252 static ddf_fun_t *driver_get_function(devman_handle_t handle)
    253 {
    254         ddf_fun_t *fun = NULL;
    255        
    256         assert(fibril_mutex_is_locked(&functions_mutex));
    257        
    258         list_foreach(functions, link) {
    259                 fun = list_get_instance(link, ddf_fun_t, link);
    260                 if (fun->handle == handle)
    261                         return fun;
    262         }
    263        
    264         return NULL;
    265 }
    266 
    267 static void driver_dev_add(ipc_callid_t iid, ipc_call_t *icall)
     248static void driver_add_device(ipc_callid_t iid, ipc_call_t *icall)
    268249{
    269250        char *dev_name = NULL;
     
    274255       
    275256        ddf_dev_t *dev = create_device();
    276 
    277         /* Add one reference that will be dropped by driver_dev_remove() */
    278         dev_add_ref(dev);
    279257        dev->handle = dev_handle;
    280258
     
    289267       
    290268        res = driver->driver_ops->add_device(dev);
    291        
    292         if (res != EOK) {
    293                 dev_del_ref(dev);
    294                 async_answer_0(iid, res);
    295                 return;
    296         }
    297        
    298         fibril_mutex_lock(&devices_mutex);
    299         list_append(&dev->link, &devices);
    300         fibril_mutex_unlock(&devices_mutex);
     269        if (res != EOK)
     270                delete_device(dev);
    301271       
    302272        async_answer_0(iid, res);
    303 }
    304 
    305 static void driver_dev_remove(ipc_callid_t iid, ipc_call_t *icall)
    306 {
    307         devman_handle_t devh;
    308         ddf_dev_t *dev;
    309         int rc;
    310        
    311         devh = IPC_GET_ARG1(*icall);
    312        
    313         fibril_mutex_lock(&devices_mutex);
    314         dev = driver_get_device(devh);
    315         if (dev != NULL)
    316                 dev_add_ref(dev);
    317         fibril_mutex_unlock(&devices_mutex);
    318        
    319         if (dev == NULL) {
    320                 async_answer_0(iid, ENOENT);
    321                 return;
    322         }
    323        
    324         if (driver->driver_ops->dev_remove != NULL)
    325                 rc = driver->driver_ops->dev_remove(dev);
    326         else
    327                 rc = ENOTSUP;
    328        
    329         if (rc == EOK)
    330                 dev_del_ref(dev);
    331        
    332         async_answer_0(iid, (sysarg_t) rc);
    333 }
    334 
    335 static void driver_dev_gone(ipc_callid_t iid, ipc_call_t *icall)
    336 {
    337         devman_handle_t devh;
    338         ddf_dev_t *dev;
    339         int rc;
    340        
    341         devh = IPC_GET_ARG1(*icall);
    342        
    343         fibril_mutex_lock(&devices_mutex);
    344         dev = driver_get_device(devh);
    345         if (dev != NULL)
    346                 dev_add_ref(dev);
    347         fibril_mutex_unlock(&devices_mutex);
    348        
    349         if (dev == NULL) {
    350                 async_answer_0(iid, ENOENT);
    351                 return;
    352         }
    353        
    354         if (driver->driver_ops->dev_gone != NULL)
    355                 rc = driver->driver_ops->dev_gone(dev);
    356         else
    357                 rc = ENOTSUP;
    358        
    359         if (rc == EOK)
    360                 dev_del_ref(dev);
    361        
    362         async_answer_0(iid, (sysarg_t) rc);
    363 }
    364 
    365 static void driver_fun_online(ipc_callid_t iid, ipc_call_t *icall)
    366 {
    367         devman_handle_t funh;
    368         ddf_fun_t *fun;
    369         int rc;
    370        
    371         funh = IPC_GET_ARG1(*icall);
    372        
    373         /*
    374          * Look the function up. Bump reference count so that
    375          * the function continues to exist until we return
    376          * from the driver.
    377          */
    378         fibril_mutex_lock(&functions_mutex);
    379        
    380         fun = driver_get_function(funh);
    381         if (fun != NULL)
    382                 fun_add_ref(fun);
    383        
    384         fibril_mutex_unlock(&functions_mutex);
    385        
    386         if (fun == NULL) {
    387                 async_answer_0(iid, ENOENT);
    388                 return;
    389         }
    390        
    391         /* Call driver entry point */
    392         if (driver->driver_ops->fun_online != NULL)
    393                 rc = driver->driver_ops->fun_online(fun);
    394         else
    395                 rc = ENOTSUP;
    396        
    397         fun_del_ref(fun);
    398        
    399         async_answer_0(iid, (sysarg_t) rc);
    400 }
    401 
    402 static void driver_fun_offline(ipc_callid_t iid, ipc_call_t *icall)
    403 {
    404         devman_handle_t funh;
    405         ddf_fun_t *fun;
    406         int rc;
    407        
    408         funh = IPC_GET_ARG1(*icall);
    409        
    410         /*
    411          * Look the function up. Bump reference count so that
    412          * the function continues to exist until we return
    413          * from the driver.
    414          */
    415         fibril_mutex_lock(&functions_mutex);
    416        
    417         fun = driver_get_function(funh);
    418         if (fun != NULL)
    419                 fun_add_ref(fun);
    420        
    421         fibril_mutex_unlock(&functions_mutex);
    422        
    423         if (fun == NULL) {
    424                 async_answer_0(iid, ENOENT);
    425                 return;
    426         }
    427        
    428         /* Call driver entry point */
    429         if (driver->driver_ops->fun_offline != NULL)
    430                 rc = driver->driver_ops->fun_offline(fun);
    431         else
    432                 rc = ENOTSUP;
    433        
    434         async_answer_0(iid, (sysarg_t) rc);
    435273}
    436274
     
    448286               
    449287                switch (IPC_GET_IMETHOD(call)) {
    450                 case DRIVER_DEV_ADD:
    451                         driver_dev_add(callid, &call);
    452                         break;
    453                 case DRIVER_DEV_REMOVE:
    454                         driver_dev_remove(callid, &call);
    455                         break;
    456                 case DRIVER_DEV_GONE:
    457                         driver_dev_gone(callid, &call);
    458                         break;
    459                 case DRIVER_FUN_ONLINE:
    460                         driver_fun_online(callid, &call);
    461                         break;
    462                 case DRIVER_FUN_OFFLINE:
    463                         driver_fun_offline(callid, &call);
     288                case DRIVER_ADD_DEVICE:
     289                        driver_add_device(callid, &call);
    464290                        break;
    465291                default:
    466                         async_answer_0(callid, ENOTSUP);
     292                        async_answer_0(callid, ENOENT);
    467293                }
    468294        }
     
    482308         */
    483309        devman_handle_t handle = IPC_GET_ARG2(*icall);
    484 
    485         fibril_mutex_lock(&functions_mutex);
    486         ddf_fun_t *fun = driver_get_function(handle);
    487         fibril_mutex_unlock(&functions_mutex);
    488         /* XXX Need a lock on fun */
     310        ddf_fun_t *fun = driver_get_function(&functions, handle);
    489311       
    490312        if (fun == NULL) {
     
    644466        ddf_dev_t *dev;
    645467
    646         dev = calloc(1, sizeof(ddf_dev_t));
     468        dev = malloc(sizeof(ddf_dev_t));
    647469        if (dev == NULL)
    648470                return NULL;
    649471
     472        memset(dev, 0, sizeof(ddf_dev_t));
    650473        return dev;
    651474}
     
    675498static void delete_device(ddf_dev_t *dev)
    676499{
    677         if (dev->driver_data != NULL)
    678                 free(dev->driver_data);
    679500        free(dev);
    680501}
    681502
    682 /** Delete function structure.
     503/** Delete device structure.
    683504 *
    684505 * @param dev           The device structure.
     
    687508{
    688509        clean_match_ids(&fun->match_ids);
    689         if (fun->driver_data != NULL)
    690                 free(fun->driver_data);
    691510        if (fun->name != NULL)
    692511                free(fun->name);
     
    694513}
    695514
    696 /** Increase device reference count. */
    697 static void dev_add_ref(ddf_dev_t *dev)
    698 {
    699         atomic_inc(&dev->refcnt);
    700 }
    701 
    702 /** Decrease device reference count.
    703  *
    704  * Free the device structure if the reference count drops to zero.
    705  */
    706 static void dev_del_ref(ddf_dev_t *dev)
    707 {
    708         if (atomic_predec(&dev->refcnt) == 0)
    709                 delete_device(dev);
    710 }
    711 
    712 /** Increase function reference count.
    713  *
    714  * This also increases reference count on the device. The device structure
    715  * will thus not be deallocated while there are some associated function
    716  * structures.
    717  */
    718 static void fun_add_ref(ddf_fun_t *fun)
    719 {
    720         dev_add_ref(fun->dev);
    721         atomic_inc(&fun->refcnt);
    722 }
    723 
    724 /** Decrease function reference count.
    725  *
    726  * Free the function structure if the reference count drops to zero.
    727  */
    728 static void fun_del_ref(ddf_fun_t *fun)
    729 {
    730         ddf_dev_t *dev = fun->dev;
    731 
    732         if (atomic_predec(&fun->refcnt) == 0)
    733                 delete_function(fun);
    734 
    735         dev_del_ref(dev);
    736 }
    737 
    738 /** Allocate driver-specific device data. */
    739 extern void *ddf_dev_data_alloc(ddf_dev_t *dev, size_t size)
    740 {
    741         void *data;
    742 
    743         assert(dev->driver_data == NULL);
    744 
    745         data = calloc(1, size);
    746         if (data == NULL)
    747                 return NULL;
    748 
    749         dev->driver_data = data;
    750         return data;
    751 }
    752 
    753515/** Create a DDF function node.
    754516 *
     
    782544                return NULL;
    783545
    784         /* Add one reference that will be dropped by ddf_fun_destroy() */
     546        fun->bound = false;
    785547        fun->dev = dev;
    786         fun_add_ref(fun);
    787 
    788         fun->bound = false;
    789548        fun->ftype = ftype;
    790549
     
    798557}
    799558
    800 /** Allocate driver-specific function data. */
    801 extern void *ddf_fun_data_alloc(ddf_fun_t *fun, size_t size)
    802 {
    803         void *data;
    804 
    805         assert(fun->bound == false);
    806         assert(fun->driver_data == NULL);
    807 
    808         data = calloc(1, size);
    809         if (data == NULL)
    810                 return NULL;
    811 
    812         fun->driver_data = data;
    813         return data;
    814 }
    815 
    816559/** Destroy DDF function node.
    817560 *
     
    824567{
    825568        assert(fun->bound == false);
    826 
    827         /*
    828          * Drop the reference added by ddf_fun_create(). This will deallocate
    829          * the function as soon as all other references are dropped (i.e.
    830          * as soon control leaves all driver entry points called in context
    831          * of this function.
    832          */
    833         fun_del_ref(fun);
     569        delete_function(fun);
    834570}
    835571
     
    878614 * the function invisible to the system.
    879615 *
    880  * @param fun           Function to unbind
     616 * @param fun           Function to bind
    881617 * @return              EOK on success or negative error code
    882618 */
     
    887623        assert(fun->bound == true);
    888624       
     625        add_to_functions_list(fun);
    889626        res = devman_remove_function(fun->handle);
    890627        if (res != EOK)
     
    894631       
    895632        fun->bound = false;
    896         return EOK;
    897 }
    898 
    899 /** Online function.
    900  *
    901  * @param fun           Function to online
    902  * @return              EOK on success or negative error code
    903  */
    904 int ddf_fun_online(ddf_fun_t *fun)
    905 {
    906         int res;
    907        
    908         assert(fun->bound == true);
    909        
    910         res = devman_drv_fun_online(fun->handle);
    911         if (res != EOK)
    912                 return res;
    913        
    914         return EOK;
    915 }
    916 
    917 /** Offline function.
    918  *
    919  * @param fun           Function to offline
    920  * @return              EOK on success or negative error code
    921  */
    922 int ddf_fun_offline(ddf_fun_t *fun)
    923 {
    924         int res;
    925        
    926         assert(fun->bound == true);
    927        
    928         res = devman_drv_fun_offline(fun->handle);
    929         if (res != EOK)
    930                 return res;
    931        
    932633        return EOK;
    933634}
Note: See TracChangeset for help on using the changeset viewer.