Ignore:
File:
1 edited

Legend:

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

    r609243f4 r77ad86c  
    7070FIBRIL_MUTEX_INITIALIZE(functions_mutex);
    7171
    72 /** Interrupts */
    73 static interrupt_context_list_t interrupt_contexts;
    74 
    75 static irq_cmd_t default_cmds[] = {
    76         {
    77                 .cmd = CMD_ACCEPT
    78         }
    79 };
    80 
    81 static irq_code_t default_pseudocode = {
    82         sizeof(default_cmds) / sizeof(irq_cmd_t),
    83         default_cmds
    84 };
    85 
    8672static ddf_dev_t *create_device(void);
    8773static void delete_device(ddf_dev_t *);
     
    9379static void *function_get_ops(ddf_fun_t *, dev_inferface_idx_t);
    9480
    95 static void driver_irq_handler(ipc_callid_t iid, ipc_call_t *icall)
    96 {
    97         int id = (int)IPC_GET_IMETHOD(*icall);
    98         interrupt_context_t *ctx;
    99        
    100         ctx = find_interrupt_context_by_id(&interrupt_contexts, id);
    101         if (ctx != NULL && ctx->handler != NULL)
    102                 (*ctx->handler)(ctx->dev, iid, icall);
    103 }
    104 
    105 interrupt_context_t *create_interrupt_context(void)
    106 {
    107         interrupt_context_t *ctx;
    108        
    109         ctx = (interrupt_context_t *) malloc(sizeof(interrupt_context_t));
    110         if (ctx != NULL)
    111                 memset(ctx, 0, sizeof(interrupt_context_t));
    112        
    113         return ctx;
    114 }
    115 
    116 void delete_interrupt_context(interrupt_context_t *ctx)
    117 {
    118         if (ctx != NULL)
    119                 free(ctx);
    120 }
    121 
    122 void init_interrupt_context_list(interrupt_context_list_t *list)
    123 {
    124         memset(list, 0, sizeof(interrupt_context_list_t));
    125         fibril_mutex_initialize(&list->mutex);
    126         list_initialize(&list->contexts);
    127 }
    128 
    129 void
    130 add_interrupt_context(interrupt_context_list_t *list, interrupt_context_t *ctx)
    131 {
    132         fibril_mutex_lock(&list->mutex);
    133         ctx->id = list->curr_id++;
    134         list_append(&ctx->link, &list->contexts);
    135         fibril_mutex_unlock(&list->mutex);
    136 }
    137 
    138 void remove_interrupt_context(interrupt_context_list_t *list,
    139     interrupt_context_t *ctx)
    140 {
    141         fibril_mutex_lock(&list->mutex);
    142         list_remove(&ctx->link);
    143         fibril_mutex_unlock(&list->mutex);
    144 }
    145 
    146 interrupt_context_t *
    147 find_interrupt_context_by_id(interrupt_context_list_t *list, int id)
    148 {
    149         interrupt_context_t *ctx;
    150        
    151         fibril_mutex_lock(&list->mutex);
    152        
    153         list_foreach(list->contexts, link) {
    154                 ctx = list_get_instance(link, interrupt_context_t, link);
    155                 if (ctx->id == id) {
    156                         fibril_mutex_unlock(&list->mutex);
    157                         return ctx;
    158                 }
    159         }
    160        
    161         fibril_mutex_unlock(&list->mutex);
    162         return NULL;
    163 }
    164 
    165 interrupt_context_t *
    166 find_interrupt_context(interrupt_context_list_t *list, ddf_dev_t *dev, int irq)
    167 {
    168         interrupt_context_t *ctx;
    169        
    170         fibril_mutex_lock(&list->mutex);
    171        
    172         list_foreach(list->contexts, link) {
    173                 ctx = list_get_instance(link, interrupt_context_t, link);
    174                 if (ctx->irq == irq && ctx->dev == dev) {
    175                         fibril_mutex_unlock(&list->mutex);
    176                         return ctx;
    177                 }
    178         }
    179        
    180         fibril_mutex_unlock(&list->mutex);
    181         return NULL;
    182 }
    183 
    184 
    185 int
    186 register_interrupt_handler(ddf_dev_t *dev, int irq, interrupt_handler_t *handler,
    187     irq_code_t *pseudocode)
    188 {
    189         interrupt_context_t *ctx = create_interrupt_context();
    190        
    191         ctx->dev = dev;
    192         ctx->irq = irq;
    193         ctx->handler = handler;
    194        
    195         add_interrupt_context(&interrupt_contexts, ctx);
    196        
    197         if (pseudocode == NULL)
    198                 pseudocode = &default_pseudocode;
    199        
    200         int res = register_irq(irq, dev->handle, ctx->id, pseudocode);
    201         if (res != EOK) {
    202                 remove_interrupt_context(&interrupt_contexts, ctx);
    203                 delete_interrupt_context(ctx);
    204         }
    205 
    206         return res;
    207 }
    208 
    209 int unregister_interrupt_handler(ddf_dev_t *dev, int irq)
    210 {
    211         interrupt_context_t *ctx = find_interrupt_context(&interrupt_contexts,
    212             dev, irq);
    213         int res = unregister_irq(irq, dev->handle);
    214        
    215         if (ctx != NULL) {
    216                 remove_interrupt_context(&interrupt_contexts, ctx);
    217                 delete_interrupt_context(ctx);
    218         }
    219        
    220         return res;
    221 }
    222 
    22381static void add_to_functions_list(ddf_fun_t *fun)
    22482{
     
    267125static void driver_dev_add(ipc_callid_t iid, ipc_call_t *icall)
    268126{
    269         char *dev_name = NULL;
    270         int res;
    271        
    272127        devman_handle_t dev_handle = IPC_GET_ARG1(*icall);
    273128        devman_handle_t parent_fun_handle = IPC_GET_ARG2(*icall);
    274129       
    275130        ddf_dev_t *dev = create_device();
    276 
     131       
    277132        /* Add one reference that will be dropped by driver_dev_remove() */
    278133        dev_add_ref(dev);
    279134        dev->handle = dev_handle;
    280 
     135       
     136        char *dev_name = NULL;
    281137        async_data_write_accept((void **) &dev_name, true, 0, 0, 0, 0);
    282138        dev->name = dev_name;
    283 
     139       
    284140        /*
    285141         * Currently not used, parent fun handle is stored in context
     
    288144        (void) parent_fun_handle;
    289145       
    290         res = driver->driver_ops->add_device(dev);
     146        int res = driver->driver_ops->dev_add(dev);
    291147       
    292148        if (res != EOK) {
     
    303159}
    304160
    305 static void driver_dev_added(ipc_callid_t iid, ipc_call_t *icall)
    306 {
     161static void driver_dev_remove(ipc_callid_t iid, ipc_call_t *icall)
     162{
     163        devman_handle_t devh = IPC_GET_ARG1(*icall);
     164       
    307165        fibril_mutex_lock(&devices_mutex);
    308         ddf_dev_t *dev = driver_get_device(IPC_GET_ARG1(*icall));
    309         fibril_mutex_unlock(&devices_mutex);
    310        
    311         if (dev != NULL && driver->driver_ops->device_added != NULL)
    312                 driver->driver_ops->device_added(dev);
    313 }
    314 
    315 static void driver_dev_remove(ipc_callid_t iid, ipc_call_t *icall)
    316 {
    317         devman_handle_t devh;
    318         ddf_dev_t *dev;
    319         int rc;
    320        
    321         devh = IPC_GET_ARG1(*icall);
    322        
    323         fibril_mutex_lock(&devices_mutex);
    324         dev = driver_get_device(devh);
     166        ddf_dev_t *dev = driver_get_device(devh);
    325167        if (dev != NULL)
    326168                dev_add_ref(dev);
     
    331173                return;
    332174        }
     175       
     176        int rc;
    333177       
    334178        if (driver->driver_ops->dev_remove != NULL)
     
    345189static void driver_dev_gone(ipc_callid_t iid, ipc_call_t *icall)
    346190{
    347         devman_handle_t devh;
    348         ddf_dev_t *dev;
    349         int rc;
    350        
    351         devh = IPC_GET_ARG1(*icall);
     191        devman_handle_t devh = IPC_GET_ARG1(*icall);
    352192       
    353193        fibril_mutex_lock(&devices_mutex);
    354         dev = driver_get_device(devh);
     194        ddf_dev_t *dev = driver_get_device(devh);
    355195        if (dev != NULL)
    356196                dev_add_ref(dev);
     
    361201                return;
    362202        }
     203       
     204        int rc;
    363205       
    364206        if (driver->driver_ops->dev_gone != NULL)
     
    375217static void driver_fun_online(ipc_callid_t iid, ipc_call_t *icall)
    376218{
    377         devman_handle_t funh;
    378         ddf_fun_t *fun;
    379         int rc;
    380        
    381         funh = IPC_GET_ARG1(*icall);
     219        devman_handle_t funh = IPC_GET_ARG1(*icall);
    382220       
    383221        /*
     
    388226        fibril_mutex_lock(&functions_mutex);
    389227       
    390         fun = driver_get_function(funh);
     228        ddf_fun_t *fun = driver_get_function(funh);
    391229        if (fun != NULL)
    392230                fun_add_ref(fun);
     
    400238       
    401239        /* Call driver entry point */
     240        int rc;
     241       
    402242        if (driver->driver_ops->fun_online != NULL)
    403243                rc = driver->driver_ops->fun_online(fun);
     
    412252static void driver_fun_offline(ipc_callid_t iid, ipc_call_t *icall)
    413253{
    414         devman_handle_t funh;
    415         ddf_fun_t *fun;
    416         int rc;
    417        
    418         funh = IPC_GET_ARG1(*icall);
     254        devman_handle_t funh = IPC_GET_ARG1(*icall);
    419255       
    420256        /*
     
    425261        fibril_mutex_lock(&functions_mutex);
    426262       
    427         fun = driver_get_function(funh);
     263        ddf_fun_t *fun = driver_get_function(funh);
    428264        if (fun != NULL)
    429265                fun_add_ref(fun);
     
    437273       
    438274        /* Call driver entry point */
     275        int rc;
     276       
    439277        if (driver->driver_ops->fun_offline != NULL)
    440278                rc = driver->driver_ops->fun_offline(fun);
     
    460298                case DRIVER_DEV_ADD:
    461299                        driver_dev_add(callid, &call);
    462                         break;
    463                 case DRIVER_DEV_ADDED:
    464                         async_answer_0(callid, EOK);
    465                         driver_dev_added(callid, &call);
    466300                        break;
    467301                case DRIVER_DEV_REMOVE:
     
    751585
    752586/** Allocate driver-specific device data. */
    753 extern void *ddf_dev_data_alloc(ddf_dev_t *dev, size_t size)
    754 {
    755         void *data;
    756 
     587void *ddf_dev_data_alloc(ddf_dev_t *dev, size_t size)
     588{
    757589        assert(dev->driver_data == NULL);
    758 
    759         data = calloc(1, size);
     590       
     591        void *data = calloc(1, size);
    760592        if (data == NULL)
    761593                return NULL;
    762 
     594       
    763595        dev->driver_data = data;
    764596        return data;
     
    790622ddf_fun_t *ddf_fun_create(ddf_dev_t *dev, fun_type_t ftype, const char *name)
    791623{
    792         ddf_fun_t *fun;
    793 
    794         fun = create_function();
     624        ddf_fun_t *fun = create_function();
    795625        if (fun == NULL)
    796626                return NULL;
    797 
     627       
    798628        /* Add one reference that will be dropped by ddf_fun_destroy() */
    799629        fun->dev = dev;
    800630        fun_add_ref(fun);
    801 
     631       
    802632        fun->bound = false;
    803633        fun->ftype = ftype;
    804 
     634       
    805635        fun->name = str_dup(name);
    806636        if (fun->name == NULL) {
     
    808638                return NULL;
    809639        }
    810 
     640       
    811641        return fun;
    812642}
    813643
    814644/** Allocate driver-specific function data. */
    815 extern void *ddf_fun_data_alloc(ddf_fun_t *fun, size_t size)
    816 {
    817         void *data;
    818 
     645void *ddf_fun_data_alloc(ddf_fun_t *fun, size_t size)
     646{
    819647        assert(fun->bound == false);
    820648        assert(fun->driver_data == NULL);
    821 
    822         data = calloc(1, size);
     649       
     650        void *data = calloc(1, size);
    823651        if (data == NULL)
    824652                return NULL;
    825 
     653       
    826654        fun->driver_data = data;
    827655        return data;
     
    833661 * must not be bound.
    834662 *
    835  * @param fun           Function to destroy
     663 * @param fun Function to destroy
     664 *
    836665 */
    837666void ddf_fun_destroy(ddf_fun_t *fun)
    838667{
    839668        assert(fun->bound == false);
    840 
     669       
    841670        /*
    842671         * Drop the reference added by ddf_fun_create(). This will deallocate
     
    853682        if (fun->ops == NULL)
    854683                return NULL;
     684       
    855685        return fun->ops->interfaces[idx];
    856686}
     
    865695 * the same name.
    866696 *
    867  * @param fun           Function to bind
    868  * @return              EOK on success or negative error code
     697 * @param fun Function to bind
     698 *
     699 * @return EOK on success or negative error code
     700 *
    869701 */
    870702int ddf_fun_bind(ddf_fun_t *fun)
     
    873705        assert(fun->name != NULL);
    874706       
    875         int res;
    876        
    877707        add_to_functions_list(fun);
    878         res = devman_add_function(fun->name, fun->ftype, &fun->match_ids,
     708        int res = devman_add_function(fun->name, fun->ftype, &fun->match_ids,
    879709            fun->dev->handle, &fun->handle);
    880710        if (res != EOK) {
     
    892722 * the function invisible to the system.
    893723 *
    894  * @param fun           Function to unbind
    895  * @return              EOK on success or negative error code
     724 * @param fun Function to unbind
     725 *
     726 * @return EOK on success or negative error code
     727 *
    896728 */
    897729int ddf_fun_unbind(ddf_fun_t *fun)
    898730{
    899         int res;
    900        
    901731        assert(fun->bound == true);
    902732       
    903         res = devman_remove_function(fun->handle);
     733        int res = devman_remove_function(fun->handle);
    904734        if (res != EOK)
    905735                return res;
    906 
     736       
    907737        remove_from_functions_list(fun);
    908738       
     
    913743/** Online function.
    914744 *
    915  * @param fun           Function to online
    916  * @return              EOK on success or negative error code
     745 * @param fun Function to online
     746 *
     747 * @return EOK on success or negative error code
     748 *
    917749 */
    918750int ddf_fun_online(ddf_fun_t *fun)
    919751{
    920         int res;
    921        
    922752        assert(fun->bound == true);
    923753       
    924         res = devman_drv_fun_online(fun->handle);
     754        int res = devman_drv_fun_online(fun->handle);
    925755        if (res != EOK)
    926756                return res;
     
    931761/** Offline function.
    932762 *
    933  * @param fun           Function to offline
    934  * @return              EOK on success or negative error code
     763 * @param fun Function to offline
     764 *
     765 * @return EOK on success or negative error code
     766 *
    935767 */
    936768int ddf_fun_offline(ddf_fun_t *fun)
    937769{
    938         int res;
    939        
    940770        assert(fun->bound == true);
    941771       
    942         res = devman_drv_fun_offline(fun->handle);
     772        int res = devman_drv_fun_offline(fun->handle);
    943773        if (res != EOK)
    944774                return res;
     
    952782 * Cannot be called when the function node is bound.
    953783 *
    954  * @param fun                   Function
    955  * @param match_id_str          Match string
    956  * @param match_score           Match score
    957  * @return                      EOK on success, ENOMEM if out of memory.
     784 * @param fun          Function
     785 * @param match_id_str Match string
     786 * @param match_score  Match score
     787 *
     788 * @return EOK on success.
     789 * @return ENOMEM if out of memory.
     790 *
    958791 */
    959792int ddf_fun_add_match_id(ddf_fun_t *fun, const char *match_id_str,
    960793    int match_score)
    961794{
    962         match_id_t *match_id;
    963        
    964795        assert(fun->bound == false);
    965796        assert(fun->ftype == fun_inner);
    966797       
    967         match_id = create_match_id();
     798        match_id_t *match_id = create_match_id();
    968799        if (match_id == NULL)
    969800                return ENOMEM;
    970801       
    971802        match_id->id = str_dup(match_id_str);
    972         match_id->score = 90;
     803        match_id->score = match_score;
    973804       
    974805        add_match_id(&fun->match_ids, match_id);
     
    987818 *
    988819 * Must only be called when the function is bound.
     820 *
    989821 */
    990822int ddf_fun_add_to_category(ddf_fun_t *fun, const char *cat_name)
     
    998830int ddf_driver_main(driver_t *drv)
    999831{
    1000         int rc;
    1001 
    1002832        /*
    1003833         * Remember the driver structure - driver_ops will be called by generic
     
    1006836        driver = drv;
    1007837       
    1008         /* Initialize the list of interrupt contexts. */
    1009         init_interrupt_context_list(&interrupt_contexts);
    1010        
    1011         /* Set generic interrupt handler. */
    1012         async_set_interrupt_received(driver_irq_handler);
     838        /* Initialize interrupt module */
     839        interrupt_init();
    1013840       
    1014841        /*
     
    1016843         * incoming connections.
    1017844         */
    1018         rc = devman_driver_register(driver->name, driver_connection);
     845        async_set_client_connection(driver_connection);
     846        int rc = devman_driver_register(driver->name);
    1019847        if (rc != EOK) {
    1020848                printf("Error: Failed to register driver with device manager "
     
    1022850                    str_error(rc));
    1023851               
    1024                 return 1;
     852                return rc;
    1025853        }
    1026854       
     
    1028856        rc = task_retval(0);
    1029857        if (rc != EOK)
    1030                 return 1;
    1031 
     858                return rc;
     859       
    1032860        async_manager();
    1033861       
    1034862        /* Never reached. */
    1035         return 0;
     863        return EOK;
    1036864}
    1037865
Note: See TracChangeset for help on using the changeset viewer.