Ignore:
File:
1 edited

Legend:

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

    r58563585 r3e6a98c5  
    3636/** @file
    3737 */
     38
     39#define _DDF_DATA_IMPLANT
    3840
    3941#include <assert.h>
     
    4951#include <str_error.h>
    5052#include <ctype.h>
     53#include <errno.h>
    5154#include <inttypes.h>
    5255#include <devman.h>
     56
     57#include <ipc/driver.h>
    5358
    5459#include "dev_iface.h"
     
    5863
    5964/** Driver structure */
    60 static const driver_t *driver;
     65static driver_t *driver;
    6166
    6267/** Devices */
     
    9398static ddf_dev_t *driver_get_device(devman_handle_t handle)
    9499{
     100        ddf_dev_t *dev = NULL;
     101       
    95102        assert(fibril_mutex_is_locked(&devices_mutex));
    96103       
    97         list_foreach(devices, link, ddf_dev_t, dev) {
     104        list_foreach(devices, link) {
     105                dev = list_get_instance(link, ddf_dev_t, link);
    98106                if (dev->handle == handle)
    99107                        return dev;
     
    105113static ddf_fun_t *driver_get_function(devman_handle_t handle)
    106114{
     115        ddf_fun_t *fun = NULL;
     116       
    107117        assert(fibril_mutex_is_locked(&functions_mutex));
    108118       
    109         list_foreach(functions, link, ddf_fun_t, fun) {
     119        list_foreach(functions, link) {
     120                fun = list_get_instance(link, ddf_fun_t, link);
    110121                if (fun->handle == handle)
    111122                        return fun;
     
    120131        devman_handle_t parent_fun_handle = IPC_GET_ARG2(*icall);
    121132       
    122         char *dev_name = NULL;
    123         int rc = async_data_write_accept((void **) &dev_name, true, 0, 0, 0, 0);
    124         if (rc != EOK) {
    125                 async_answer_0(iid, rc);
    126                 return;
    127         }
    128        
    129133        ddf_dev_t *dev = create_device();
    130         if (!dev) {
    131                 free(dev_name);
    132                 async_answer_0(iid, ENOMEM);
    133                 return;
    134         }
    135134       
    136135        /* Add one reference that will be dropped by driver_dev_remove() */
    137136        dev_add_ref(dev);
    138137        dev->handle = dev_handle;
     138       
     139        char *dev_name = NULL;
     140        async_data_write_accept((void **) &dev_name, true, 0, 0, 0, 0);
    139141        dev->name = dev_name;
    140142       
     
    284286}
    285287
    286 static void driver_connection_devman(ipc_callid_t iid, ipc_call_t *icall,
    287     void *arg)
     288static void driver_connection_devman(ipc_callid_t iid, ipc_call_t *icall)
    288289{
    289290        /* Accept connection */
     
    335336        fibril_mutex_lock(&functions_mutex);
    336337        ddf_fun_t *fun = driver_get_function(handle);
    337         if (fun != NULL)
    338                 fun_add_ref(fun);
    339338        fibril_mutex_unlock(&functions_mutex);
     339        /* XXX Need a lock on fun */
    340340       
    341341        if (fun == NULL) {
     
    349349                /* Driver has a custom connection handler. */
    350350                (*fun->conn_handler)(iid, icall, (void *)fun);
    351                 fun_del_ref(fun);
    352351                return;
    353352        }
     
    364363       
    365364        async_answer_0(iid, ret);
    366         if (ret != EOK) {
    367                 fun_del_ref(fun);
     365        if (ret != EOK)
    368366                return;
    369         }
    370367       
    371368        while (true) {
     
    380377                                (*fun->ops->close)(fun);
    381378                        async_answer_0(callid, EOK);
    382                         fun_del_ref(fun);
    383379                        return;
    384380                }
     
    423419                 * handling ("remote interface").
    424420                 */
    425                 const remote_iface_t *rem_iface = get_remote_iface(iface_idx);
     421                remote_iface_t *rem_iface = get_remote_iface(iface_idx);
    426422                assert(rem_iface != NULL);
    427423               
     
    448444}
    449445
    450 static void driver_connection_driver(ipc_callid_t iid, ipc_call_t *icall,
    451     void *arg)
     446static void driver_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
    452447{
    453448        driver_connection_gen(iid, icall, true);
    454449}
    455450
    456 static void driver_connection_client(ipc_callid_t iid, ipc_call_t *icall,
    457     void *arg)
     451static void driver_connection_client(ipc_callid_t iid, ipc_call_t *icall)
    458452{
    459453        driver_connection_gen(iid, icall, false);
     454}
     455
     456/** Function for handling connections to device driver. */
     457static void driver_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
     458{
     459        sysarg_t conn_type;
     460
     461        if (iid == 0) {
     462                /* Callback connection from devman */
     463                /* XXX Use separate handler for this type of connection */
     464                conn_type = DRIVER_DEVMAN;
     465        } else {
     466                conn_type = IPC_GET_ARG1(*icall);
     467        }
     468
     469        /* Select interface */
     470        switch (conn_type) {
     471        case DRIVER_DEVMAN:
     472                /* Handle request from device manager */
     473                driver_connection_devman(iid, icall);
     474                break;
     475        case DRIVER_DRIVER:
     476                /* Handle request from drivers of child devices */
     477                driver_connection_driver(iid, icall);
     478                break;
     479        case DRIVER_CLIENT:
     480                /* Handle request from client applications */
     481                driver_connection_client(iid, icall);
     482                break;
     483        default:
     484                /* No such interface */
     485                async_answer_0(iid, ENOENT);
     486        }
    460487}
    461488
     
    503530        if (dev->driver_data != NULL)
    504531                free(dev->driver_data);
    505         if (dev->name)
    506                 free(dev->name);
    507532        free(dev);
    508533}
     
    577602}
    578603
     604/** Implant foreign driver-specific device data.
     605 *
     606 * XXX This is used to transition USB to new interface. Do not use
     607 * in new code. Use of this function must be removed.
     608 */
     609void ddf_fun_data_implant(ddf_fun_t *fun, void *data)
     610{
     611        assert(fun->driver_data == NULL);
     612        fun->driver_data = data;
     613}
     614
    579615/** Return driver-specific device data. */
    580616void *ddf_dev_data_get(ddf_dev_t *dev)
     
    603639 * The session will be automatically closed when @a dev is destroyed.
    604640 *
    605  * @param dev Device
    606  *
    607  * @return New session or NULL if session could not be created
    608  *
    609  */
    610 async_sess_t *ddf_dev_parent_sess_create(ddf_dev_t *dev)
     641 * @param dev   Device
     642 * @param mgmt  Exchange management style
     643 * @return      New session or NULL if session could not be created
     644 */
     645async_sess_t *ddf_dev_parent_sess_create(ddf_dev_t *dev, exch_mgmt_t mgmt)
    611646{
    612647        assert(dev->parent_sess == NULL);
    613         dev->parent_sess = devman_parent_device_connect(dev->handle,
     648        dev->parent_sess = devman_parent_device_connect(mgmt, dev->handle,
    614649            IPC_FLAG_BLOCKING);
    615650
     
    786821        assert(fun->bound == false);
    787822        assert(fun->name != NULL);
    788         assert(fun->dev != NULL);
    789823       
    790824        add_to_functions_list(fun);
     
    891925
    892926/** Set function ops. */
    893 void ddf_fun_set_ops(ddf_fun_t *fun, const ddf_dev_ops_t *dev_ops)
     927void ddf_fun_set_ops(ddf_fun_t *fun, ddf_dev_ops_t *dev_ops)
    894928{
    895929        assert(fun->conn_handler == NULL);
     
    901935 * This allows handling connections the non-devman way.
    902936 */
    903 void ddf_fun_set_conn_handler(ddf_fun_t *fun, async_port_handler_t conn)
     937void ddf_fun_set_conn_handler(ddf_fun_t *fun, async_client_conn_t conn)
    904938{
    905939        assert(fun->ops == NULL);
     
    928962}
    929963
    930 int ddf_driver_main(const driver_t *drv)
     964int ddf_driver_main(driver_t *drv)
    931965{
    932966        /*
     
    936970        driver = drv;
    937971       
     972        /* Initialize interrupt module */
     973        interrupt_init();
     974       
    938975        /*
    939976         * Register driver with device manager using generic handler for
    940977         * incoming connections.
    941978         */
    942         port_id_t port;
    943         int rc = async_create_port(INTERFACE_DDF_DRIVER, driver_connection_driver,
    944             NULL, &port);
    945         if (rc != EOK)
    946                 return rc;
    947        
    948         rc = async_create_port(INTERFACE_DDF_DEVMAN, driver_connection_devman,
    949             NULL, &port);
    950         if (rc != EOK)
    951                 return rc;
    952        
    953         async_set_fallback_port_handler(driver_connection_client, NULL);
    954        
    955         rc = devman_driver_register(driver->name);
     979        async_set_client_connection(driver_connection);
     980        int rc = devman_driver_register(driver->name);
    956981        if (rc != EOK) {
    957982                printf("Error: Failed to register driver with device manager "
    958                     "(%s).\n", (rc == EEXIST) ? "driver already started" :
     983                    "(%s).\n", (rc == EEXISTS) ? "driver already started" :
    959984                    str_error(rc));
    960985               
Note: See TracChangeset for help on using the changeset viewer.