Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset e64df9a in mainline


Ignore:
Timestamp:
2011-08-20T15:32:44Z (10 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master
Children:
1a5b252, c22531fc
Parents:
4e6577c (diff), 422722e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge devman-driver and driver-devman parallel exchange support.

Location:
uspace
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/async.c

    r4e6577c re64df9a  
    16561656       
    16571657        return sess;
     1658}
     1659
     1660/** Set arguments for new connections.
     1661 *
     1662 * FIXME This is an ugly hack to work around the problem that parallel
     1663 * exchanges are implemented using parallel connections. When we create
     1664 * a callback session, the framework does not know arguments for the new
     1665 * connections.
     1666 *
     1667 * The proper solution seems to be to implement parallel exchanges using
     1668 * tagging.
     1669 */
     1670void async_sess_args_set(async_sess_t *sess, sysarg_t arg1, sysarg_t arg2,
     1671    sysarg_t arg3)
     1672{
     1673        sess->arg1 = arg1;
     1674        sess->arg2 = arg2;
     1675        sess->arg3 = arg3;
    16581676}
    16591677
  • uspace/lib/c/generic/devman.c

    r4e6577c re64df9a  
    8989                        if (devman_driver_block_sess == NULL)
    9090                                devman_driver_block_sess =
    91                                     service_connect_blocking(EXCHANGE_SERIALIZE,
     91                                    service_connect_blocking(EXCHANGE_PARALLEL,
    9292                                    SERVICE_DEVMAN, DEVMAN_DRIVER, 0);
    9393                }
     
    138138                if (devman_driver_sess == NULL)
    139139                        devman_driver_sess =
    140                             service_connect(EXCHANGE_SERIALIZE, SERVICE_DEVMAN,
     140                            service_connect(EXCHANGE_PARALLEL, SERVICE_DEVMAN,
    141141                            DEVMAN_DRIVER, 0);
    142142               
  • uspace/lib/c/generic/ns.c

    r4e6577c re64df9a  
    5656        async_exchange_end(exch);
    5757       
     58        /*
     59         * FIXME Ugly hack to work around limitation of implementing
     60         * parallel exchanges using multiple connections. Shift out
     61         * first argument for non-initial connections.
     62         */
     63        async_sess_args_set(sess, arg2, arg3, 0);
     64       
    5865        return sess;
    5966}
     
    6673            async_connect_me_to_blocking(mgmt, exch, service, arg2, arg3);
    6774        async_exchange_end(exch);
     75       
     76        /*
     77         * FIXME Ugly hack to work around limitation of implementing
     78         * parallel exchanges using multiple connections. Shift out
     79         * first argument for non-initial connections.
     80         */
     81        async_sess_args_set(sess, arg2, arg3, 0);
    6882       
    6983        return sess;
  • uspace/lib/c/include/async.h

    r4e6577c re64df9a  
    337337
    338338/*
     339 * FIXME These functions just work around problems with parallel exchange
     340 * management. Proper solution needs to be implemented.
     341 */
     342void async_sess_args_set(async_sess_t *sess, sysarg_t, sysarg_t, sysarg_t);
     343
     344/*
    339345 * User-friendly wrappers for async_share_in_start().
    340346 */
  • uspace/srv/devman/devman.h

    r4e6577c re64df9a  
    6363typedef struct fun_node fun_node_t;
    6464
     65typedef struct {
     66        fibril_mutex_t mutex;
     67        struct driver *driver;
     68} client_t;
     69
    6570typedef enum {
    6671        /** Driver has not been started. */
  • uspace/srv/devman/main.c

    r4e6577c re64df9a  
    6565static dev_tree_t device_tree;
    6666
     67static int init_running_drv(void *drv);
     68
    6769/** Register running driver. */
    68 static driver_t *devman_driver_register(void)
    69 {
    70         ipc_call_t icall;
    71         ipc_callid_t iid;
     70static driver_t *devman_driver_register(ipc_callid_t callid, ipc_call_t *call)
     71{
    7272        driver_t *driver = NULL;
     73        char *drv_name = NULL;
    7374
    7475        log_msg(LVL_DEBUG, "devman_driver_register");
    75        
    76         iid = async_get_call(&icall);
    77         if (IPC_GET_IMETHOD(icall) != DEVMAN_DRIVER_REGISTER) {
    78                 async_answer_0(iid, EREFUSED);
    79                 return NULL;
    80         }
    81        
    82         char *drv_name = NULL;
    8376       
    8477        /* Get driver name. */
    8578        int rc = async_data_write_accept((void **) &drv_name, true, 0, 0, 0, 0);
    8679        if (rc != EOK) {
    87                 async_answer_0(iid, rc);
     80                async_answer_0(callid, rc);
    8881                return NULL;
    8982        }
     
    9891                free(drv_name);
    9992                drv_name = NULL;
    100                 async_answer_0(iid, ENOENT);
     93                async_answer_0(callid, ENOENT);
    10194                return NULL;
    10295        }
     
    112105                    driver->name);
    113106                fibril_mutex_unlock(&driver->driver_mutex);
    114                 async_answer_0(iid, EEXISTS);
     107                async_answer_0(callid, EEXISTS);
    115108                return NULL;
    116109        }
     
    134127        log_msg(LVL_DEBUG, "Creating connection to the `%s' driver.",
    135128            driver->name);
    136         driver->sess = async_callback_receive(EXCHANGE_SERIALIZE);
     129        driver->sess = async_callback_receive(EXCHANGE_PARALLEL);
    137130        if (!driver->sess) {
    138131                fibril_mutex_unlock(&driver->driver_mutex);
    139                 async_answer_0(iid, ENOTSUP);
     132                async_answer_0(callid, ENOTSUP);
    140133                return NULL;
    141134        }
    142        
    143         fibril_mutex_unlock(&driver->driver_mutex);
     135        /* FIXME: Work around problem with callback sessions */
     136        async_sess_args_set(driver->sess, DRIVER_DEVMAN, 0, 0);
    144137       
    145138        log_msg(LVL_NOTE,
     
    147140            driver->name);
    148141       
    149         async_answer_0(iid, EOK);
    150        
     142        /*
     143         * Initialize the driver as running (e.g. pass assigned devices to it)
     144         * in a separate fibril; the separate fibril is used to enable the
     145         * driver to use devman service during the driver's initialization.
     146         */
     147        fid_t fid = fibril_create(init_running_drv, driver);
     148        if (fid == 0) {
     149                log_msg(LVL_ERROR, "Failed to create initialization fibril " \
     150                    "for driver `%s'.", driver->name);
     151                fibril_mutex_unlock(&driver->driver_mutex);
     152                async_answer_0(callid, ENOMEM);
     153                return NULL;
     154        }
     155       
     156        fibril_add_ready(fid);
     157        fibril_mutex_unlock(&driver->driver_mutex);
     158       
     159        async_answer_0(callid, EOK);
    151160        return driver;
    152161}
     
    429438static void devman_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
    430439{
     440        client_t *client;
     441        driver_t *driver;
     442       
    431443        /* Accept the connection. */
    432444        async_answer_0(iid, EOK);
    433445       
    434         driver_t *driver = devman_driver_register();
    435         if (driver == NULL)
    436                 return;
    437        
    438         /*
    439          * Initialize the driver as running (e.g. pass assigned devices to it)
    440          * in a separate fibril; the separate fibril is used to enable the
    441          * driver to use devman service during the driver's initialization.
    442          */
    443         fid_t fid = fibril_create(init_running_drv, driver);
    444         if (fid == 0) {
    445                 log_msg(LVL_ERROR, "Failed to create initialization fibril " \
    446                     "for driver `%s'.", driver->name);
    447                 return;
    448         }
    449         fibril_add_ready(fid);
     446        client = async_get_client_data();
     447        if (client == NULL) {
     448                log_msg(LVL_ERROR, "Failed to allocate client data.");
     449                return;
     450        }
    450451       
    451452        while (true) {
     
    456457                        break;
    457458               
     459                if (IPC_GET_IMETHOD(call) != DEVMAN_DRIVER_REGISTER) {
     460                        fibril_mutex_lock(&client->mutex);
     461                        driver = client->driver;
     462                        fibril_mutex_unlock(&client->mutex);
     463                        if (driver == NULL) {
     464                                /* First call must be to DEVMAN_DRIVER_REGISTER */
     465                                async_answer_0(callid, ENOTSUP);
     466                                continue;
     467                        }
     468                }
     469               
    458470                switch (IPC_GET_IMETHOD(call)) {
     471                case DEVMAN_DRIVER_REGISTER:
     472                        fibril_mutex_lock(&client->mutex);
     473                        if (client->driver != NULL) {
     474                                fibril_mutex_unlock(&client->mutex);
     475                                async_answer_0(callid, EINVAL);
     476                                continue;
     477                        }
     478                        client->driver = devman_driver_register(callid, &call);
     479                        fibril_mutex_unlock(&client->mutex);
     480                        break;
    459481                case DEVMAN_ADD_FUNCTION:
    460482                        devman_add_function(callid, &call);
     
    814836static void devman_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    815837{
    816         /* Select interface. */
     838        /* Select port. */
    817839        switch ((sysarg_t) (IPC_GET_ARG1(*icall))) {
    818840        case DEVMAN_DRIVER:
     
    840862}
    841863
     864static void *devman_client_data_create(void)
     865{
     866        client_t *client;
     867       
     868        client = calloc(1, sizeof(client_t));
     869        if (client == NULL)
     870                return NULL;
     871       
     872        fibril_mutex_initialize(&client->mutex);
     873        return client;
     874}
     875
     876static void devman_client_data_destroy(void *data)
     877{
     878        free(data);
     879}
     880
    842881/** Initialize device manager internal structures. */
    843882static bool devman_init(void)
     
    886925        }
    887926       
    888         /* Set a handler of incomming connections. */
     927        /* Set handlers for incoming connections. */
     928        async_set_client_data_constructor(devman_client_data_create);
     929        async_set_client_data_destructor(devman_client_data_destroy);
    889930        async_set_client_connection(devman_connection);
    890931
Note: See TracChangeset for help on using the changeset viewer.