Ignore:
File:
1 edited

Legend:

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

    ra996ae31 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);
     
    8076
    8177static irq_code_t default_pseudocode = {
    82         0,
    83         NULL,
    8478        sizeof(default_cmds) / sizeof(irq_cmd_t),
    8579        default_cmds
     
    8882static ddf_dev_t *create_device(void);
    8983static void delete_device(ddf_dev_t *);
    90 static void dev_add_ref(ddf_dev_t *);
    91 static void dev_del_ref(ddf_dev_t *);
    92 static void fun_add_ref(ddf_fun_t *);
    93 static void fun_del_ref(ddf_fun_t *);
    9484static remote_handler_t *function_get_default_handler(ddf_fun_t *);
    9585static void *function_get_ops(ddf_fun_t *, dev_inferface_idx_t);
     
    200190                pseudocode = &default_pseudocode;
    201191       
    202         int res = irq_register(irq, dev->handle, ctx->id, pseudocode);
     192        int res = register_irq(irq, dev->handle, ctx->id, pseudocode);
    203193        if (res != EOK) {
    204194                remove_interrupt_context(&interrupt_contexts, ctx);
     
    213203        interrupt_context_t *ctx = find_interrupt_context(&interrupt_contexts,
    214204            dev, irq);
    215         int res = irq_unregister(irq, dev->handle);
     205        int res = unregister_irq(irq, dev->handle);
    216206       
    217207        if (ctx != NULL) {
     
    237227}
    238228
    239 static ddf_dev_t *driver_get_device(devman_handle_t handle)
    240 {
    241         ddf_dev_t *dev = NULL;
    242        
    243         assert(fibril_mutex_is_locked(&devices_mutex));
    244        
    245         list_foreach(devices, link) {
    246                 dev = list_get_instance(link, ddf_dev_t, link);
    247                 if (dev->handle == handle)
    248                         return dev;
    249         }
     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);
    250244       
    251245        return NULL;
    252246}
    253247
    254 static ddf_fun_t *driver_get_function(devman_handle_t handle)
    255 {
    256         ddf_fun_t *fun = NULL;
    257        
    258         assert(fibril_mutex_is_locked(&functions_mutex));
    259        
    260         list_foreach(functions, link) {
    261                 fun = list_get_instance(link, ddf_fun_t, link);
    262                 if (fun->handle == handle)
    263                         return fun;
    264         }
    265        
    266         return NULL;
    267 }
    268 
    269 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)
    270249{
    271250        char *dev_name = NULL;
     
    273252       
    274253        devman_handle_t dev_handle = IPC_GET_ARG1(*icall);
    275         devman_handle_t parent_fun_handle = IPC_GET_ARG2(*icall);
     254        devman_handle_t parent_fun_handle = IPC_GET_ARG2(*icall);
    276255       
    277256        ddf_dev_t *dev = create_device();
    278 
    279         /* Add one reference that will be dropped by driver_dev_remove() */
    280         dev_add_ref(dev);
    281257        dev->handle = dev_handle;
    282258
     
    290266        (void) parent_fun_handle;
    291267       
    292         res = driver->driver_ops->dev_add(dev);
    293        
    294         if (res != EOK) {
    295                 dev_del_ref(dev);
    296                 async_answer_0(iid, res);
    297                 return;
    298         }
    299        
    300         fibril_mutex_lock(&devices_mutex);
    301         list_append(&dev->link, &devices);
    302         fibril_mutex_unlock(&devices_mutex);
     268        res = driver->driver_ops->add_device(dev);
     269        if (res != EOK)
     270                delete_device(dev);
    303271       
    304272        async_answer_0(iid, res);
    305 }
    306 
    307 static void driver_dev_added(ipc_callid_t iid, ipc_call_t *icall)
    308 {
    309         fibril_mutex_lock(&devices_mutex);
    310         ddf_dev_t *dev = driver_get_device(IPC_GET_ARG1(*icall));
    311         fibril_mutex_unlock(&devices_mutex);
    312        
    313         if (dev != NULL && driver->driver_ops->device_added != NULL)
    314                 driver->driver_ops->device_added(dev);
    315 }
    316 
    317 static void driver_dev_remove(ipc_callid_t iid, ipc_call_t *icall)
    318 {
    319         devman_handle_t devh;
    320         ddf_dev_t *dev;
    321         int rc;
    322        
    323         devh = IPC_GET_ARG1(*icall);
    324        
    325         fibril_mutex_lock(&devices_mutex);
    326         dev = driver_get_device(devh);
    327         if (dev != NULL)
    328                 dev_add_ref(dev);
    329         fibril_mutex_unlock(&devices_mutex);
    330        
    331         if (dev == NULL) {
    332                 async_answer_0(iid, ENOENT);
    333                 return;
    334         }
    335        
    336         if (driver->driver_ops->dev_remove != NULL)
    337                 rc = driver->driver_ops->dev_remove(dev);
    338         else
    339                 rc = ENOTSUP;
    340        
    341         if (rc == EOK)
    342                 dev_del_ref(dev);
    343        
    344         async_answer_0(iid, (sysarg_t) rc);
    345 }
    346 
    347 static void driver_dev_gone(ipc_callid_t iid, ipc_call_t *icall)
    348 {
    349         devman_handle_t devh;
    350         ddf_dev_t *dev;
    351         int rc;
    352        
    353         devh = IPC_GET_ARG1(*icall);
    354        
    355         fibril_mutex_lock(&devices_mutex);
    356         dev = driver_get_device(devh);
    357         if (dev != NULL)
    358                 dev_add_ref(dev);
    359         fibril_mutex_unlock(&devices_mutex);
    360        
    361         if (dev == NULL) {
    362                 async_answer_0(iid, ENOENT);
    363                 return;
    364         }
    365        
    366         if (driver->driver_ops->dev_gone != NULL)
    367                 rc = driver->driver_ops->dev_gone(dev);
    368         else
    369                 rc = ENOTSUP;
    370        
    371         if (rc == EOK)
    372                 dev_del_ref(dev);
    373        
    374         async_answer_0(iid, (sysarg_t) rc);
    375 }
    376 
    377 static void driver_fun_online(ipc_callid_t iid, ipc_call_t *icall)
    378 {
    379         devman_handle_t funh;
    380         ddf_fun_t *fun;
    381         int rc;
    382        
    383         funh = IPC_GET_ARG1(*icall);
    384        
    385         /*
    386          * Look the function up. Bump reference count so that
    387          * the function continues to exist until we return
    388          * from the driver.
    389          */
    390         fibril_mutex_lock(&functions_mutex);
    391        
    392         fun = driver_get_function(funh);
    393         if (fun != NULL)
    394                 fun_add_ref(fun);
    395        
    396         fibril_mutex_unlock(&functions_mutex);
    397        
    398         if (fun == NULL) {
    399                 async_answer_0(iid, ENOENT);
    400                 return;
    401         }
    402        
    403         /* Call driver entry point */
    404         if (driver->driver_ops->fun_online != NULL)
    405                 rc = driver->driver_ops->fun_online(fun);
    406         else
    407                 rc = ENOTSUP;
    408        
    409         fun_del_ref(fun);
    410        
    411         async_answer_0(iid, (sysarg_t) rc);
    412 }
    413 
    414 static void driver_fun_offline(ipc_callid_t iid, ipc_call_t *icall)
    415 {
    416         devman_handle_t funh;
    417         ddf_fun_t *fun;
    418         int rc;
    419        
    420         funh = IPC_GET_ARG1(*icall);
    421        
    422         /*
    423          * Look the function up. Bump reference count so that
    424          * the function continues to exist until we return
    425          * from the driver.
    426          */
    427         fibril_mutex_lock(&functions_mutex);
    428        
    429         fun = driver_get_function(funh);
    430         if (fun != NULL)
    431                 fun_add_ref(fun);
    432        
    433         fibril_mutex_unlock(&functions_mutex);
    434        
    435         if (fun == NULL) {
    436                 async_answer_0(iid, ENOENT);
    437                 return;
    438         }
    439        
    440         /* Call driver entry point */
    441         if (driver->driver_ops->fun_offline != NULL)
    442                 rc = driver->driver_ops->fun_offline(fun);
    443         else
    444                 rc = ENOTSUP;
    445        
    446         async_answer_0(iid, (sysarg_t) rc);
    447273}
    448274
     
    460286               
    461287                switch (IPC_GET_IMETHOD(call)) {
    462                 case DRIVER_DEV_ADD:
    463                         driver_dev_add(callid, &call);
    464                         break;
    465                 case DRIVER_DEV_ADDED:
    466                         async_answer_0(callid, EOK);
    467                         driver_dev_added(callid, &call);
    468                         break;
    469                 case DRIVER_DEV_REMOVE:
    470                         driver_dev_remove(callid, &call);
    471                         break;
    472                 case DRIVER_DEV_GONE:
    473                         driver_dev_gone(callid, &call);
    474                         break;
    475                 case DRIVER_FUN_ONLINE:
    476                         driver_fun_online(callid, &call);
    477                         break;
    478                 case DRIVER_FUN_OFFLINE:
    479                         driver_fun_offline(callid, &call);
     288                case DRIVER_ADD_DEVICE:
     289                        driver_add_device(callid, &call);
    480290                        break;
    481291                default:
    482                         async_answer_0(callid, ENOTSUP);
     292                        async_answer_0(callid, ENOENT);
    483293                }
    484294        }
     
    498308         */
    499309        devman_handle_t handle = IPC_GET_ARG2(*icall);
    500 
    501         fibril_mutex_lock(&functions_mutex);
    502         ddf_fun_t *fun = driver_get_function(handle);
    503         fibril_mutex_unlock(&functions_mutex);
    504         /* XXX Need a lock on fun */
     310        ddf_fun_t *fun = driver_get_function(&functions, handle);
    505311       
    506312        if (fun == NULL) {
     
    660466        ddf_dev_t *dev;
    661467
    662         dev = calloc(1, sizeof(ddf_dev_t));
     468        dev = malloc(sizeof(ddf_dev_t));
    663469        if (dev == NULL)
    664470                return NULL;
    665471
     472        memset(dev, 0, sizeof(ddf_dev_t));
    666473        return dev;
    667474}
     
    691498static void delete_device(ddf_dev_t *dev)
    692499{
    693         if (dev->driver_data != NULL)
    694                 free(dev->driver_data);
    695500        free(dev);
    696501}
    697502
    698 /** Delete function structure.
     503/** Delete device structure.
    699504 *
    700505 * @param dev           The device structure.
     
    703508{
    704509        clean_match_ids(&fun->match_ids);
    705         if (fun->driver_data != NULL)
    706                 free(fun->driver_data);
    707510        if (fun->name != NULL)
    708511                free(fun->name);
     
    710513}
    711514
    712 /** Increase device reference count. */
    713 static void dev_add_ref(ddf_dev_t *dev)
    714 {
    715         atomic_inc(&dev->refcnt);
    716 }
    717 
    718 /** Decrease device reference count.
    719  *
    720  * Free the device structure if the reference count drops to zero.
    721  */
    722 static void dev_del_ref(ddf_dev_t *dev)
    723 {
    724         if (atomic_predec(&dev->refcnt) == 0)
    725                 delete_device(dev);
    726 }
    727 
    728 /** Increase function reference count.
    729  *
    730  * This also increases reference count on the device. The device structure
    731  * will thus not be deallocated while there are some associated function
    732  * structures.
    733  */
    734 static void fun_add_ref(ddf_fun_t *fun)
    735 {
    736         dev_add_ref(fun->dev);
    737         atomic_inc(&fun->refcnt);
    738 }
    739 
    740 /** Decrease function reference count.
    741  *
    742  * Free the function structure if the reference count drops to zero.
    743  */
    744 static void fun_del_ref(ddf_fun_t *fun)
    745 {
    746         ddf_dev_t *dev = fun->dev;
    747 
    748         if (atomic_predec(&fun->refcnt) == 0)
    749                 delete_function(fun);
    750 
    751         dev_del_ref(dev);
    752 }
    753 
    754 /** Allocate driver-specific device data. */
    755 extern void *ddf_dev_data_alloc(ddf_dev_t *dev, size_t size)
    756 {
    757         void *data;
    758 
    759         assert(dev->driver_data == NULL);
    760 
    761         data = calloc(1, size);
    762         if (data == NULL)
    763                 return NULL;
    764 
    765         dev->driver_data = data;
    766         return data;
    767 }
    768 
    769515/** Create a DDF function node.
    770516 *
     
    798544                return NULL;
    799545
    800         /* Add one reference that will be dropped by ddf_fun_destroy() */
     546        fun->bound = false;
    801547        fun->dev = dev;
    802         fun_add_ref(fun);
    803 
    804         fun->bound = false;
    805548        fun->ftype = ftype;
    806549
     
    814557}
    815558
    816 /** Allocate driver-specific function data. */
    817 extern void *ddf_fun_data_alloc(ddf_fun_t *fun, size_t size)
    818 {
    819         void *data;
    820 
    821         assert(fun->bound == false);
    822         assert(fun->driver_data == NULL);
    823 
    824         data = calloc(1, size);
    825         if (data == NULL)
    826                 return NULL;
    827 
    828         fun->driver_data = data;
    829         return data;
    830 }
    831 
    832559/** Destroy DDF function node.
    833560 *
     
    840567{
    841568        assert(fun->bound == false);
    842 
    843         /*
    844          * Drop the reference added by ddf_fun_create(). This will deallocate
    845          * the function as soon as all other references are dropped (i.e.
    846          * as soon control leaves all driver entry points called in context
    847          * of this function.
    848          */
    849         fun_del_ref(fun);
     569        delete_function(fun);
    850570}
    851571
     
    894614 * the function invisible to the system.
    895615 *
    896  * @param fun           Function to unbind
     616 * @param fun           Function to bind
    897617 * @return              EOK on success or negative error code
    898618 */
     
    903623        assert(fun->bound == true);
    904624       
     625        add_to_functions_list(fun);
    905626        res = devman_remove_function(fun->handle);
    906627        if (res != EOK)
     
    910631       
    911632        fun->bound = false;
    912         return EOK;
    913 }
    914 
    915 /** Online function.
    916  *
    917  * @param fun           Function to online
    918  * @return              EOK on success or negative error code
    919  */
    920 int ddf_fun_online(ddf_fun_t *fun)
    921 {
    922         int res;
    923        
    924         assert(fun->bound == true);
    925        
    926         res = devman_drv_fun_online(fun->handle);
    927         if (res != EOK)
    928                 return res;
    929        
    930         return EOK;
    931 }
    932 
    933 /** Offline function.
    934  *
    935  * @param fun           Function to offline
    936  * @return              EOK on success or negative error code
    937  */
    938 int ddf_fun_offline(ddf_fun_t *fun)
    939 {
    940         int res;
    941        
    942         assert(fun->bound == true);
    943        
    944         res = devman_drv_fun_offline(fun->handle);
    945         if (res != EOK)
    946                 return res;
    947        
    948633        return EOK;
    949634}
     
    972657       
    973658        match_id->id = str_dup(match_id_str);
    974         match_id->score = match_score;
     659        match_id->score = 90;
    975660       
    976661        add_match_id(&fun->match_ids, match_id);
     
    1018703         * incoming connections.
    1019704         */
    1020         async_set_client_connection(driver_connection);
    1021         rc = devman_driver_register(driver->name);
     705        rc = devman_driver_register(driver->name, driver_connection);
    1022706        if (rc != EOK) {
    1023707                printf("Error: Failed to register driver with device manager "
Note: See TracChangeset for help on using the changeset viewer.