Changeset 1a5b252 in mainline for uspace/lib/drv/generic/driver.c


Ignore:
Timestamp:
2011-08-21T11:54:15Z (13 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
8cc4ddb
Parents:
e64df9a
Message:

DDF support for function offlining and onlining. This allows
(anticipated) hot removal — support needs to be added in individual
drivers, currently there is support in test1 and partially in rootvirt.
Surprise removal is not supported. TODO: synchronization.

File:
1 edited

Legend:

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

    re64df9a r1a5b252  
    6363
    6464/** Devices */
     65LIST_INITIALIZE(devices);
     66FIBRIL_MUTEX_INITIALIZE(devices_mutex);
     67
     68/** Functions */
    6569LIST_INITIALIZE(functions);
    6670FIBRIL_MUTEX_INITIALIZE(functions_mutex);
     
    227231}
    228232
    229 static ddf_fun_t *driver_get_function(list_t *functions, devman_handle_t handle)
     233static ddf_dev_t *driver_get_device(devman_handle_t handle)
     234{
     235        ddf_dev_t *dev = NULL;
     236       
     237        assert(fibril_mutex_is_locked(&devices_mutex));
     238       
     239        list_foreach(devices, link) {
     240                dev = list_get_instance(link, ddf_dev_t, link);
     241                if (dev->handle == handle)
     242                        return dev;
     243        }
     244       
     245        return NULL;
     246}
     247
     248static ddf_fun_t *driver_get_function(devman_handle_t handle)
    230249{
    231250        ddf_fun_t *fun = NULL;
    232251       
    233         fibril_mutex_lock(&functions_mutex);
    234        
    235         list_foreach(*functions, link) {
     252        assert(fibril_mutex_is_locked(&functions_mutex));
     253       
     254        list_foreach(functions, link) {
    236255                fun = list_get_instance(link, ddf_fun_t, link);
    237                 if (fun->handle == handle) {
    238                         fibril_mutex_unlock(&functions_mutex);
     256                if (fun->handle == handle)
    239257                        return fun;
    240                 }
    241         }
    242        
    243         fibril_mutex_unlock(&functions_mutex);
     258        }
    244259       
    245260        return NULL;
     
    270285                delete_device(dev);
    271286       
     287        fibril_mutex_lock(&devices_mutex);
     288        list_append(&dev->link, &devices);
     289        fibril_mutex_unlock(&devices_mutex);
     290       
    272291        async_answer_0(iid, res);
     292}
     293
     294static void driver_dev_remove(ipc_callid_t iid, ipc_call_t *icall)
     295{
     296        devman_handle_t devh;
     297        ddf_dev_t *dev;
     298        int rc;
     299       
     300        printf("libdrv: driver_dev_offline()\n");
     301        devh = IPC_GET_ARG1(*icall);
     302       
     303        fibril_mutex_lock(&devices_mutex);
     304        dev = driver_get_device(devh);
     305        fibril_mutex_unlock(&devices_mutex);
     306        /* XXX need lock on dev */
     307       
     308        if (dev == NULL) {
     309                async_answer_0(iid, ENOENT);
     310                return;
     311        }
     312       
     313        if (driver->driver_ops->dev_remove != NULL)
     314                rc = driver->driver_ops->dev_remove(dev);
     315        else
     316                rc = ENOTSUP;
     317       
     318        async_answer_0(iid, (sysarg_t) rc);
     319}
     320
     321static void driver_fun_online(ipc_callid_t iid, ipc_call_t *icall)
     322{
     323        devman_handle_t funh;
     324        ddf_fun_t *fun;
     325        int rc;
     326       
     327        funh = IPC_GET_ARG1(*icall);
     328        fibril_mutex_lock(&functions_mutex);
     329        fun = driver_get_function(funh);
     330        fibril_mutex_unlock(&functions_mutex);
     331        /* XXX Need lock on fun */
     332       
     333        if (fun == NULL) {
     334                async_answer_0(iid, ENOENT);
     335                return;
     336        }
     337       
     338        if (driver->driver_ops->fun_online != NULL)
     339                rc = driver->driver_ops->fun_online(fun);
     340        else
     341                rc = ENOTSUP;
     342       
     343        async_answer_0(iid, (sysarg_t) rc);
     344}
     345
     346static void driver_fun_offline(ipc_callid_t iid, ipc_call_t *icall)
     347{
     348        devman_handle_t funh;
     349        ddf_fun_t *fun;
     350        int rc;
     351       
     352        funh = IPC_GET_ARG1(*icall);
     353        fibril_mutex_lock(&functions_mutex);
     354        fun = driver_get_function(funh);
     355        fibril_mutex_unlock(&functions_mutex);
     356        /* XXX Need lock on fun */
     357       
     358        if (fun == NULL) {
     359                async_answer_0(iid, ENOENT);
     360                return;
     361        }
     362       
     363        if (driver->driver_ops->fun_offline != NULL)
     364                rc = driver->driver_ops->fun_offline(fun);
     365        else
     366                rc = ENOTSUP;
     367       
     368        async_answer_0(iid, (sysarg_t) rc);
    273369}
    274370
     
    286382               
    287383                switch (IPC_GET_IMETHOD(call)) {
    288                 case DRIVER_ADD_DEVICE:
     384                case DRIVER_DEV_ADD:
    289385                        driver_add_device(callid, &call);
    290386                        break;
     387                case DRIVER_DEV_REMOVE:
     388                        driver_dev_remove(callid, &call);
     389                        break;
     390                case DRIVER_FUN_ONLINE:
     391                        driver_fun_online(callid, &call);
     392                        break;
     393                case DRIVER_FUN_OFFLINE:
     394                        driver_fun_offline(callid, &call);
     395                        break;
    291396                default:
    292                         async_answer_0(callid, ENOENT);
     397                        async_answer_0(callid, ENOTSUP);
    293398                }
    294399        }
     
    308413         */
    309414        devman_handle_t handle = IPC_GET_ARG2(*icall);
    310         ddf_fun_t *fun = driver_get_function(&functions, handle);
     415
     416        fibril_mutex_lock(&functions_mutex);
     417        ddf_fun_t *fun = driver_get_function(handle);
     418        fibril_mutex_unlock(&functions_mutex);
     419        /* XXX Need a lock on fun */
    311420       
    312421        if (fun == NULL) {
     
    614723 * the function invisible to the system.
    615724 *
    616  * @param fun           Function to bind
     725 * @param fun           Function to unbind
    617726 * @return              EOK on success or negative error code
    618727 */
     
    623732        assert(fun->bound == true);
    624733       
    625         add_to_functions_list(fun);
    626734        res = devman_remove_function(fun->handle);
    627735        if (res != EOK)
     
    631739       
    632740        fun->bound = false;
     741        return EOK;
     742}
     743
     744/** Online function.
     745 *
     746 * @param fun           Function to online
     747 * @return              EOK on success or negative error code
     748 */
     749int ddf_fun_online(ddf_fun_t *fun)
     750{
     751        int res;
     752       
     753        assert(fun->bound == true);
     754       
     755        res = devman_drv_fun_online(fun->handle);
     756        if (res != EOK)
     757                return res;
     758       
     759        return EOK;
     760}
     761
     762/** Offline function.
     763 *
     764 * @param fun           Function to offline
     765 * @return              EOK on success or negative error code
     766 */
     767int ddf_fun_offline(ddf_fun_t *fun)
     768{
     769        int res;
     770       
     771        assert(fun->bound == true);
     772       
     773        res = devman_drv_fun_offline(fun->handle);
     774        if (res != EOK)
     775                return res;
     776       
    633777        return EOK;
    634778}
Note: See TracChangeset for help on using the changeset viewer.