Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/devman/main.c

    r422722e rd0dd7b5  
    6565static dev_tree_t device_tree;
    6666
    67 static int init_running_drv(void *drv);
    68 
    6967/** Register running driver. */
    70 static driver_t *devman_driver_register(ipc_callid_t callid, ipc_call_t *call)
    71 {
     68static driver_t *devman_driver_register(void)
     69{
     70        ipc_call_t icall;
     71        ipc_callid_t iid;
    7272        driver_t *driver = NULL;
     73
     74        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       
    7382        char *drv_name = NULL;
    74 
    75         log_msg(LVL_DEBUG, "devman_driver_register");
    7683       
    7784        /* Get driver name. */
    7885        int rc = async_data_write_accept((void **) &drv_name, true, 0, 0, 0, 0);
    7986        if (rc != EOK) {
    80                 async_answer_0(callid, rc);
     87                async_answer_0(iid, rc);
    8188                return NULL;
    8289        }
     
    9198                free(drv_name);
    9299                drv_name = NULL;
    93                 async_answer_0(callid, ENOENT);
     100                async_answer_0(iid, ENOENT);
    94101                return NULL;
    95102        }
     
    105112                    driver->name);
    106113                fibril_mutex_unlock(&driver->driver_mutex);
    107                 async_answer_0(callid, EEXISTS);
     114                async_answer_0(iid, EEXISTS);
    108115                return NULL;
    109116        }
     
    127134        log_msg(LVL_DEBUG, "Creating connection to the `%s' driver.",
    128135            driver->name);
    129         driver->sess = async_callback_receive(EXCHANGE_PARALLEL);
     136        driver->sess = async_callback_receive(EXCHANGE_SERIALIZE);
    130137        if (!driver->sess) {
    131138                fibril_mutex_unlock(&driver->driver_mutex);
    132                 async_answer_0(callid, ENOTSUP);
     139                async_answer_0(iid, ENOTSUP);
    133140                return NULL;
    134141        }
    135         /* FIXME: Work around problem with callback sessions */
    136         async_sess_args_set(driver->sess, DRIVER_DEVMAN, 0, 0);
     142       
     143        fibril_mutex_unlock(&driver->driver_mutex);
    137144       
    138145        log_msg(LVL_NOTE,
     
    140147            driver->name);
    141148       
    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);
     149        async_answer_0(iid, EOK);
     150       
    160151        return driver;
    161152}
     
    438429static void devman_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
    439430{
    440         client_t *client;
    441         driver_t *driver;
    442        
    443431        /* Accept the connection. */
    444432        async_answer_0(iid, EOK);
    445433       
    446         client = async_get_client_data();
    447         if (client == NULL) {
    448                 log_msg(LVL_ERROR, "Failed to allocate client data.");
    449                 return;
    450         }
     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);
    451450       
    452451        while (true) {
     
    457456                        break;
    458457               
    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                
    470458                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;
    481459                case DEVMAN_ADD_FUNCTION:
    482460                        devman_add_function(callid, &call);
     
    519497}
    520498
    521 /** Get device name. */
    522 static void devman_fun_get_name(ipc_callid_t iid, ipc_call_t *icall)
     499/** Find device path by its handle. */
     500static void devman_get_device_path_by_handle(ipc_callid_t iid,
     501    ipc_call_t *icall)
    523502{
    524503        devman_handle_t handle = IPC_GET_ARG1(*icall);
     
    544523        }
    545524
    546         size_t sent_length = str_size(fun->name);
    547         if (sent_length > data_len) {
    548                 sent_length = data_len;
    549         }
    550 
    551         async_data_read_finalize(data_callid, fun->name, sent_length);
    552         async_answer_0(iid, EOK);
    553 
    554         free(buffer);
    555 }
    556 
    557 
    558 /** Get device path. */
    559 static void devman_fun_get_path(ipc_callid_t iid, ipc_call_t *icall)
    560 {
    561         devman_handle_t handle = IPC_GET_ARG1(*icall);
    562 
    563         fun_node_t *fun = find_fun_node(&device_tree, handle);
    564         if (fun == NULL) {
    565                 async_answer_0(iid, ENOMEM);
    566                 return;
    567         }
    568 
    569         ipc_callid_t data_callid;
    570         size_t data_len;
    571         if (!async_data_read_receive(&data_callid, &data_len)) {
    572                 async_answer_0(iid, EINVAL);
    573                 return;
    574         }
    575 
    576         void *buffer = malloc(data_len);
    577         if (buffer == NULL) {
    578                 async_answer_0(data_callid, ENOMEM);
    579                 async_answer_0(iid, ENOMEM);
    580                 return;
    581         }
    582 
    583525        size_t sent_length = str_size(fun->pathname);
    584526        if (sent_length > data_len) {
     
    590532
    591533        free(buffer);
    592 }
    593 
    594 static void devman_dev_get_functions(ipc_callid_t iid, ipc_call_t *icall)
    595 {
    596         ipc_callid_t callid;
    597         size_t size;
    598         size_t act_size;
    599         int rc;
    600        
    601         if (!async_data_read_receive(&callid, &size)) {
    602                 async_answer_0(callid, EREFUSED);
    603                 async_answer_0(iid, EREFUSED);
    604                 return;
    605         }
    606        
    607         fibril_rwlock_read_lock(&device_tree.rwlock);
    608        
    609         dev_node_t *dev = find_dev_node_no_lock(&device_tree,
    610             IPC_GET_ARG1(*icall));
    611         if (dev == NULL) {
    612                 fibril_rwlock_read_unlock(&device_tree.rwlock);
    613                 async_answer_0(callid, ENOENT);
    614                 async_answer_0(iid, ENOENT);
    615                 return;
    616         }
    617        
    618         devman_handle_t *hdl_buf = (devman_handle_t *) malloc(size);
    619         if (hdl_buf == NULL) {
    620                 fibril_rwlock_read_unlock(&device_tree.rwlock);
    621                 async_answer_0(callid, ENOMEM);
    622                 async_answer_0(iid, ENOMEM);
    623                 return;
    624         }
    625        
    626         rc = dev_get_functions(&device_tree, dev, hdl_buf, size, &act_size);
    627         if (rc != EOK) {
    628                 fibril_rwlock_read_unlock(&device_tree.rwlock);
    629                 async_answer_0(callid, rc);
    630                 async_answer_0(iid, rc);
    631                 return;
    632         }
    633        
    634         fibril_rwlock_read_unlock(&device_tree.rwlock);
    635        
    636         sysarg_t retval = async_data_read_finalize(callid, hdl_buf, size);
    637         free(hdl_buf);
    638        
    639         async_answer_1(iid, retval, act_size);
    640 }
    641 
    642 
    643 /** Get handle for child device of a function. */
    644 static void devman_fun_get_child(ipc_callid_t iid, ipc_call_t *icall)
    645 {
    646         fun_node_t *fun;
    647        
    648         fibril_rwlock_read_lock(&device_tree.rwlock);
    649        
    650         fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
    651         if (fun == NULL) {
    652                 fibril_rwlock_read_unlock(&device_tree.rwlock);
    653                 async_answer_0(iid, ENOENT);
    654                 return;
    655         }
    656        
    657         if (fun->child == NULL) {
    658                 fibril_rwlock_read_unlock(&device_tree.rwlock);
    659                 async_answer_0(iid, ENOENT);
    660                 return;
    661         }
    662        
    663         async_answer_1(iid, EOK, fun->child->handle);
    664        
    665         fibril_rwlock_read_unlock(&device_tree.rwlock);
    666534}
    667535
     
    698566                        devman_function_get_handle(callid, &call);
    699567                        break;
    700                 case DEVMAN_DEV_GET_FUNCTIONS:
    701                         devman_dev_get_functions(callid, &call);
    702                         break;
    703                 case DEVMAN_FUN_GET_CHILD:
    704                         devman_fun_get_child(callid, &call);
    705                         break;
    706                 case DEVMAN_FUN_GET_NAME:
    707                         devman_fun_get_name(callid, &call);
    708                         break;
    709                 case DEVMAN_FUN_GET_PATH:
    710                         devman_fun_get_path(callid, &call);
     568                case DEVMAN_DEVICE_GET_DEVICE_PATH:
     569                        devman_get_device_path_by_handle(callid, &call);
    711570                        break;
    712571                case DEVMAN_FUN_SID_TO_HANDLE:
     
    836695static void devman_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    837696{
    838         /* Select port. */
     697        /* Select interface. */
    839698        switch ((sysarg_t) (IPC_GET_ARG1(*icall))) {
    840699        case DEVMAN_DRIVER:
     
    862721}
    863722
    864 static 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 
    876 static void devman_client_data_destroy(void *data)
    877 {
    878         free(data);
    879 }
    880 
    881723/** Initialize device manager internal structures. */
    882724static bool devman_init(void)
     
    925767        }
    926768       
    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);
     769        /* Set a handler of incomming connections. */
    930770        async_set_client_connection(devman_connection);
    931771
Note: See TracChangeset for help on using the changeset viewer.