Ignore:
File:
1 edited

Legend:

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

    r2a770a35 r45059d6b  
    4747#include <stdlib.h>
    4848#include <str.h>
     49#include <str_error.h>
    4950#include <ctype.h>
    5051#include <errno.h>
     
    138139find_interrupt_context_by_id(interrupt_context_list_t *list, int id)
    139140{
     141        interrupt_context_t *ctx;
     142       
    140143        fibril_mutex_lock(&list->mutex);
    141144       
    142         link_t *link = list->contexts.next;
    143         interrupt_context_t *ctx;
    144        
    145         while (link != &list->contexts) {
     145        list_foreach(list->contexts, link) {
    146146                ctx = list_get_instance(link, interrupt_context_t, link);
    147147                if (ctx->id == id) {
     
    149149                        return ctx;
    150150                }
    151                 link = link->next;
    152151        }
    153152       
     
    159158find_interrupt_context(interrupt_context_list_t *list, ddf_dev_t *dev, int irq)
    160159{
     160        interrupt_context_t *ctx;
     161       
    161162        fibril_mutex_lock(&list->mutex);
    162163       
    163         link_t *link = list->contexts.next;
    164         interrupt_context_t *ctx;
    165        
    166         while (link != &list->contexts) {
     164        list_foreach(list->contexts, link) {
    167165                ctx = list_get_instance(link, interrupt_context_t, link);
    168166                if (ctx->irq == irq && ctx->dev == dev) {
     
    170168                        return ctx;
    171169                }
    172                 link = link->next;
    173170        }
    174171       
     
    230227}
    231228
    232 static ddf_fun_t *driver_get_function(link_t *functions, devman_handle_t handle)
     229static ddf_fun_t *driver_get_function(list_t *functions, devman_handle_t handle)
    233230{
    234231        ddf_fun_t *fun = NULL;
    235232       
    236233        fibril_mutex_lock(&functions_mutex);
    237         link_t *link = functions->next;
    238        
    239         while (link != functions) {
     234       
     235        list_foreach(*functions, link) {
    240236                fun = list_get_instance(link, ddf_fun_t, link);
    241237                if (fun->handle == handle) {
     
    243239                        return fun;
    244240                }
    245                
    246                 link = link->next;
    247241        }
    248242       
     
    273267       
    274268        res = driver->driver_ops->add_device(dev);
    275         if (res == EOK) {
    276                 printf("%s: new device with handle=%" PRIun " was added.\n",
    277                     driver->name, dev_handle);
    278         } else {
    279                 printf("%s: failed to add a new device with handle = %" PRIun ".\n",
    280                     driver->name, dev_handle);
     269        if (res != EOK)
    281270                delete_device(dev);
    282         }
    283271       
    284272        async_answer_0(iid, res);
     
    290278        async_answer_0(iid, EOK);
    291279       
    292         bool cont = true;
    293         while (cont) {
     280        while (true) {
    294281                ipc_call_t call;
    295282                ipc_callid_t callid = async_get_call(&call);
    296283               
     284                if (!IPC_GET_IMETHOD(call))
     285                        break;
     286               
    297287                switch (IPC_GET_IMETHOD(call)) {
    298                 case IPC_M_PHONE_HUNGUP:
    299                         cont = false;
    300                         continue;
    301288                case DRIVER_ADD_DEVICE:
    302289                        driver_add_device(callid, &call);
     
    308295}
    309296
    310 /**
    311  * Generic client connection handler both for applications and drivers.
    312  *
    313  * @param drv           True for driver client, false for other clients
    314  *                      (applications, services etc.).
     297/** Generic client connection handler both for applications and drivers.
     298 *
     299 * @param drv True for driver client, false for other clients
     300 *            (applications, services, etc.).
     301 *
    315302 */
    316303static void driver_connection_gen(ipc_callid_t iid, ipc_call_t *icall, bool drv)
     
    322309        devman_handle_t handle = IPC_GET_ARG2(*icall);
    323310        ddf_fun_t *fun = driver_get_function(&functions, handle);
    324 
     311       
    325312        if (fun == NULL) {
    326313                printf("%s: driver_connection_gen error - no function with handle"
     
    330317        }
    331318       
     319        if (fun->conn_handler != NULL) {
     320                /* Driver has a custom connection handler. */
     321                (*fun->conn_handler)(iid, icall, (void *)fun);
     322                return;
     323        }
    332324       
    333325        /*
     
    345337                return;
    346338       
    347         while (1) {
     339        while (true) {
    348340                ipc_callid_t callid;
    349341                ipc_call_t call;
    350342                callid = async_get_call(&call);
    351343                sysarg_t method = IPC_GET_IMETHOD(call);
    352                 int iface_idx;
    353                
    354                 switch  (method) {
    355                 case IPC_M_PHONE_HUNGUP:
     344               
     345                if (!method) {
    356346                        /* Close device function */
    357347                        if (fun->ops != NULL && fun->ops->close != NULL)
     
    359349                        async_answer_0(callid, EOK);
    360350                        return;
    361                 default:
    362                         /* convert ipc interface id to interface index */
    363                        
    364                         iface_idx = DEV_IFACE_IDX(method);
    365                        
    366                         if (!is_valid_iface_idx(iface_idx)) {
    367                                 remote_handler_t *default_handler =
    368                                     function_get_default_handler(fun);
    369                                 if (default_handler != NULL) {
    370                                         (*default_handler)(fun, callid, &call);
    371                                         break;
    372                                 }
    373                                
    374                                 /*
    375                                  * Function has no such interface and
    376                                  * default handler is not provided.
    377                                  */
    378                                 printf("%s: driver_connection_gen error - "
    379                                     "invalid interface id %d.",
    380                                     driver->name, iface_idx);
    381                                 async_answer_0(callid, ENOTSUP);
    382                                 break;
    383                         }
    384                        
    385                         /* calling one of the function's interfaces */
    386                        
    387                         /* Get the interface ops structure. */
    388                         void *ops = function_get_ops(fun, iface_idx);
    389                         if (ops == NULL) {
    390                                 printf("%s: driver_connection_gen error - ",
    391                                     driver->name);
    392                                 printf("Function with handle %" PRIun " has no interface "
    393                                     "with id %d.\n", handle, iface_idx);
    394                                 async_answer_0(callid, ENOTSUP);
    395                                 break;
     351                }
     352               
     353                /* Convert ipc interface id to interface index */
     354               
     355                int iface_idx = DEV_IFACE_IDX(method);
     356               
     357                if (!is_valid_iface_idx(iface_idx)) {
     358                        remote_handler_t *default_handler =
     359                            function_get_default_handler(fun);
     360                        if (default_handler != NULL) {
     361                                (*default_handler)(fun, callid, &call);
     362                                continue;
    396363                        }
    397364                       
    398365                        /*
    399                          * Get the corresponding interface for remote request
    400                          * handling ("remote interface").
     366                         * Function has no such interface and
     367                         * default handler is not provided.
    401368                         */
    402                         remote_iface_t *rem_iface = get_remote_iface(iface_idx);
    403                         assert(rem_iface != NULL);
    404                        
    405                         /* get the method of the remote interface */
    406                         sysarg_t iface_method_idx = IPC_GET_ARG1(call);
    407                         remote_iface_func_ptr_t iface_method_ptr =
    408                             get_remote_method(rem_iface, iface_method_idx);
    409                         if (iface_method_ptr == NULL) {
    410                                 // the interface has not such method
    411                                 printf("%s: driver_connection_gen error - "
    412                                     "invalid interface method.", driver->name);
    413                                 async_answer_0(callid, ENOTSUP);
    414                                 break;
    415                         }
    416                        
    417                         /*
    418                          * Call the remote interface's method, which will
    419                          * receive parameters from the remote client and it will
    420                          * pass it to the corresponding local interface method
    421                          * associated with the function by its driver.
    422                          */
    423                         (*iface_method_ptr)(fun, ops, callid, &call);
    424                         break;
     369                        printf("%s: driver_connection_gen error - "
     370                            "invalid interface id %d.",
     371                            driver->name, iface_idx);
     372                        async_answer_0(callid, ENOTSUP);
     373                        continue;
    425374                }
     375               
     376                /* Calling one of the function's interfaces */
     377               
     378                /* Get the interface ops structure. */
     379                void *ops = function_get_ops(fun, iface_idx);
     380                if (ops == NULL) {
     381                        printf("%s: driver_connection_gen error - ", driver->name);
     382                        printf("Function with handle %" PRIun " has no interface "
     383                            "with id %d.\n", handle, iface_idx);
     384                        async_answer_0(callid, ENOTSUP);
     385                        continue;
     386                }
     387               
     388                /*
     389                 * Get the corresponding interface for remote request
     390                 * handling ("remote interface").
     391                 */
     392                remote_iface_t *rem_iface = get_remote_iface(iface_idx);
     393                assert(rem_iface != NULL);
     394               
     395                /* get the method of the remote interface */
     396                sysarg_t iface_method_idx = IPC_GET_ARG1(call);
     397                remote_iface_func_ptr_t iface_method_ptr =
     398                    get_remote_method(rem_iface, iface_method_idx);
     399                if (iface_method_ptr == NULL) {
     400                        /* The interface has not such method */
     401                        printf("%s: driver_connection_gen error - "
     402                            "invalid interface method.", driver->name);
     403                        async_answer_0(callid, ENOTSUP);
     404                        continue;
     405                }
     406               
     407                /*
     408                 * Call the remote interface's method, which will
     409                 * receive parameters from the remote client and it will
     410                 * pass it to the corresponding local interface method
     411                 * associated with the function by its driver.
     412                 */
     413                (*iface_method_ptr)(fun, ops, callid, &call);
    426414        }
    427415}
     
    438426
    439427/** Function for handling connections to device driver. */
    440 static void driver_connection(ipc_callid_t iid, ipc_call_t *icall)
    441 {
     428static void driver_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
     429{
     430        sysarg_t conn_type;
     431
     432        if (iid == 0) {
     433                /* Callback connection from devman */
     434                /* XXX Use separate handler for this type of connection */
     435                conn_type = DRIVER_DEVMAN;
     436        } else {
     437                conn_type = IPC_GET_ARG1(*icall);
     438        }
     439
    442440        /* Select interface */
    443         switch ((sysarg_t) (IPC_GET_ARG1(*icall))) {
     441        switch (conn_type) {
    444442        case DRIVER_DEVMAN:
    445443                /* Handle request from device manager */
     
    594592int ddf_fun_bind(ddf_fun_t *fun)
    595593{
     594        assert(fun->bound == false);
    596595        assert(fun->name != NULL);
    597596       
     
    610609}
    611610
     611/** Unbind a function node.
     612 *
     613 * Unbind the specified function from the system. This effectively makes
     614 * the function invisible to the system.
     615 *
     616 * @param fun           Function to bind
     617 * @return              EOK on success or negative error code
     618 */
     619int ddf_fun_unbind(ddf_fun_t *fun)
     620{
     621        int res;
     622       
     623        assert(fun->bound == true);
     624       
     625        add_to_functions_list(fun);
     626        res = devman_remove_function(fun->handle);
     627        if (res != EOK)
     628                return res;
     629
     630        remove_from_functions_list(fun);
     631       
     632        fun->bound = false;
     633        return EOK;
     634}
     635
    612636/** Add single match ID to inner function.
    613637 *
     
    632656                return ENOMEM;
    633657       
    634         match_id->id = match_id_str;
     658        match_id->id = str_dup(match_id_str);
    635659        match_id->score = 90;
    636660       
     
    647671}
    648672
    649 /** Add exposed function to class.
     673/** Add exposed function to category.
    650674 *
    651675 * Must only be called when the function is bound.
    652676 */
    653 int ddf_fun_add_to_class(ddf_fun_t *fun, const char *class_name)
     677int ddf_fun_add_to_category(ddf_fun_t *fun, const char *cat_name)
    654678{
    655679        assert(fun->bound == true);
    656680        assert(fun->ftype == fun_exposed);
    657681       
    658         return devman_add_device_to_class(fun->handle, class_name);
     682        return devman_add_device_to_category(fun->handle, cat_name);
    659683}
    660684
    661685int ddf_driver_main(driver_t *drv)
    662686{
     687        int rc;
     688
    663689        /*
    664690         * Remember the driver structure - driver_ops will be called by generic
     
    674700       
    675701        /*
    676          * Register driver by device manager with generic handler for incoming
    677          * connections.
     702         * Register driver with device manager using generic handler for
     703         * incoming connections.
    678704         */
    679         devman_driver_register(driver->name, driver_connection);
    680        
     705        rc = devman_driver_register(driver->name, driver_connection);
     706        if (rc != EOK) {
     707                printf("Error: Failed to register driver with device manager "
     708                    "(%s).\n", (rc == EEXISTS) ? "driver already started" :
     709                    str_error(rc));
     710               
     711                return 1;
     712        }
     713       
     714        /* Return success from the task since server has started. */
     715        rc = task_retval(0);
     716        if (rc != EOK)
     717                return 1;
     718
    681719        async_manager();
    682720       
Note: See TracChangeset for help on using the changeset viewer.