Changeset 041b026 in mainline


Ignore:
Timestamp:
2013-09-10T18:10:32Z (11 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
d1bafbf
Parents:
5b08d750
Message:

Move driver-related devman functionality to a separate module.

Location:
uspace/srv/devman
Files:
2 added
4 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/devman/Makefile

    r5b08d750 r041b026  
    3333
    3434SOURCES = \
     35        devman.c \
     36        driver.c \
    3537        main.c \
    36         devman.c \
    3738        match.c \
    3839        util.c
  • uspace/srv/devman/devman.c

    r5b08d750 r041b026  
    6161
    6262#include "devman.h"
     63#include "driver.h"
    6364
    6465static fun_node_t *find_node_child(dev_tree_t *, fun_node_t *, const char *);
     
    141142        .remove_callback = NULL
    142143};
    143 
    144 /**
    145  * Initialize the list of device driver's.
    146  *
    147  * @param drv_list the list of device driver's.
    148  *
    149  */
    150 void init_driver_list(driver_list_t *drv_list)
    151 {
    152         assert(drv_list != NULL);
    153        
    154         list_initialize(&drv_list->drivers);
    155         fibril_mutex_initialize(&drv_list->drivers_mutex);
    156 }
    157 
    158 /** Allocate and initialize a new driver structure.
    159  *
    160  * @return      Driver structure.
    161  */
    162 driver_t *create_driver(void)
    163 {
    164         driver_t *res = malloc(sizeof(driver_t));
    165         if (res != NULL)
    166                 init_driver(res);
    167         return res;
    168 }
    169 
    170 /** Add a driver to the list of drivers.
    171  *
    172  * @param drivers_list  List of drivers.
    173  * @param drv           Driver structure.
    174  */
    175 void add_driver(driver_list_t *drivers_list, driver_t *drv)
    176 {
    177         fibril_mutex_lock(&drivers_list->drivers_mutex);
    178         list_prepend(&drv->drivers, &drivers_list->drivers);
    179         fibril_mutex_unlock(&drivers_list->drivers_mutex);
    180 
    181         log_msg(LOG_DEFAULT, LVL_NOTE, "Driver `%s' was added to the list of available "
    182             "drivers.", drv->name);
    183 }
    184144
    185145/** Read match id at the specified position of a string and set the position in
     
    320280}
    321281
    322 /**
    323  * Get information about a driver.
    324  *
    325  * Each driver has its own directory in the base directory.
    326  * The name of the driver's directory is the same as the name of the driver.
    327  * The driver's directory contains driver's binary (named as the driver without
    328  * extension) and the configuration file with match ids for device-to-driver
    329  *  matching (named as the driver with a special extension).
    330  *
    331  * This function searches for the driver's directory and containing
    332  * configuration files. If all the files needed are found, they are parsed and
    333  * the information about the driver is stored in the driver's structure.
    334  *
    335  * @param base_path     The base directory, in which we look for driver's
    336  *                      subdirectory.
    337  * @param name          The name of the driver.
    338  * @param drv           The driver structure to fill information in.
    339  *
    340  * @return              True on success, false otherwise.
    341  */
    342 bool get_driver_info(const char *base_path, const char *name, driver_t *drv)
    343 {
    344         log_msg(LOG_DEFAULT, LVL_DEBUG, "get_driver_info(base_path=\"%s\", name=\"%s\")",
    345             base_path, name);
    346        
    347         assert(base_path != NULL && name != NULL && drv != NULL);
    348        
    349         bool suc = false;
    350         char *match_path = NULL;
    351         size_t name_size = 0;
    352        
    353         /* Read the list of match ids from the driver's configuration file. */
    354         match_path = get_abs_path(base_path, name, MATCH_EXT);
    355         if (match_path == NULL)
    356                 goto cleanup;
    357        
    358         if (!read_match_ids(match_path, &drv->match_ids))
    359                 goto cleanup;
    360        
    361         /* Allocate and fill driver's name. */
    362         name_size = str_size(name) + 1;
    363         drv->name = malloc(name_size);
    364         if (drv->name == NULL)
    365                 goto cleanup;
    366         str_cpy(drv->name, name_size, name);
    367        
    368         /* Initialize path with driver's binary. */
    369         drv->binary_path = get_abs_path(base_path, name, "");
    370         if (drv->binary_path == NULL)
    371                 goto cleanup;
    372        
    373         /* Check whether the driver's binary exists. */
    374         struct stat s;
    375         if (stat(drv->binary_path, &s) == ENOENT) { /* FIXME!! */
    376                 log_msg(LOG_DEFAULT, LVL_ERROR, "Driver not found at path `%s'.",
    377                     drv->binary_path);
    378                 goto cleanup;
    379         }
    380        
    381         suc = true;
    382        
    383 cleanup:
    384         if (!suc) {
    385                 free(drv->binary_path);
    386                 free(drv->name);
    387                 /* Set the driver structure to the default state. */
    388                 init_driver(drv);
    389         }
    390        
    391         free(match_path);
    392        
    393         return suc;
    394 }
    395 
    396 /** Lookup drivers in the directory.
    397  *
    398  * @param drivers_list  The list of available drivers.
    399  * @param dir_path      The path to the directory where we search for drivers.
    400  * @return              Number of drivers which were found.
    401  */
    402 int lookup_available_drivers(driver_list_t *drivers_list, const char *dir_path)
    403 {
    404         log_msg(LOG_DEFAULT, LVL_DEBUG, "lookup_available_drivers(dir=\"%s\")", dir_path);
    405        
    406         int drv_cnt = 0;
    407         DIR *dir = NULL;
    408         struct dirent *diren;
    409 
    410         dir = opendir(dir_path);
    411        
    412         if (dir != NULL) {
    413                 driver_t *drv = create_driver();
    414                 while ((diren = readdir(dir))) {
    415                         if (get_driver_info(dir_path, diren->d_name, drv)) {
    416                                 add_driver(drivers_list, drv);
    417                                 drv_cnt++;
    418                                 drv = create_driver();
    419                         }
    420                 }
    421                 delete_driver(drv);
    422                 closedir(dir);
    423         }
    424        
    425         return drv_cnt;
    426 }
    427 
    428282/** Create root device and function node in the device tree.
    429283 *
     
    477331       
    478332        return dev != NULL;
    479 }
    480 
    481 /** Lookup the best matching driver for the specified device in the list of
    482  * drivers.
    483  *
    484  * A match between a device and a driver is found if one of the driver's match
    485  * ids match one of the device's match ids. The score of the match is the
    486  * product of the driver's and device's score associated with the matching id.
    487  * The best matching driver for a device is the driver with the highest score
    488  * of the match between the device and the driver.
    489  *
    490  * @param drivers_list  The list of drivers, where we look for the driver
    491  *                      suitable for handling the device.
    492  * @param node          The device node structure of the device.
    493  * @return              The best matching driver or NULL if no matching driver
    494  *                      is found.
    495  */
    496 driver_t *find_best_match_driver(driver_list_t *drivers_list, dev_node_t *node)
    497 {
    498         driver_t *best_drv = NULL, *drv = NULL;
    499         int best_score = 0, score = 0;
    500        
    501         fibril_mutex_lock(&drivers_list->drivers_mutex);
    502        
    503         list_foreach(drivers_list->drivers, link) {
    504                 drv = list_get_instance(link, driver_t, drivers);
    505                 score = get_match_score(drv, node);
    506                 if (score > best_score) {
    507                         best_score = score;
    508                         best_drv = drv;
    509                 }
    510         }
    511        
    512         fibril_mutex_unlock(&drivers_list->drivers_mutex);
    513        
    514         return best_drv;
    515 }
    516 
    517 /** Assign a driver to a device.
    518  *
    519  * @param tree          Device tree
    520  * @param node          The device's node in the device tree.
    521  * @param drv           The driver.
    522  */
    523 void attach_driver(dev_tree_t *tree, dev_node_t *dev, driver_t *drv)
    524 {
    525         log_msg(LOG_DEFAULT, LVL_DEBUG, "attach_driver(dev=\"%s\",drv=\"%s\")",
    526             dev->pfun->pathname, drv->name);
    527        
    528         fibril_mutex_lock(&drv->driver_mutex);
    529         fibril_rwlock_write_lock(&tree->rwlock);
    530        
    531         dev->drv = drv;
    532         list_append(&dev->driver_devices, &drv->devices);
    533        
    534         fibril_rwlock_write_unlock(&tree->rwlock);
    535         fibril_mutex_unlock(&drv->driver_mutex);
    536 }
    537 
    538 /** Detach driver from device.
    539  *
    540  * @param tree          Device tree
    541  * @param node          The device's node in the device tree.
    542  * @param drv           The driver.
    543  */
    544 void detach_driver(dev_tree_t *tree, dev_node_t *dev)
    545 {
    546         driver_t *drv = dev->drv;
    547        
    548         assert(drv != NULL);
    549        
    550         log_msg(LOG_DEFAULT, LVL_DEBUG, "detach_driver(dev=\"%s\",drv=\"%s\")",
    551             dev->pfun->pathname, drv->name);
    552        
    553         fibril_mutex_lock(&drv->driver_mutex);
    554         fibril_rwlock_write_lock(&tree->rwlock);
    555        
    556         dev->drv = NULL;
    557         list_remove(&dev->driver_devices);
    558        
    559         fibril_rwlock_write_unlock(&tree->rwlock);
    560         fibril_mutex_unlock(&drv->driver_mutex);
    561 }
    562 
    563 /** Start a driver
    564  *
    565  * @param drv           The driver's structure.
    566  * @return              True if the driver's task is successfully spawned, false
    567  *                      otherwise.
    568  */
    569 bool start_driver(driver_t *drv)
    570 {
    571         int rc;
    572 
    573         assert(fibril_mutex_is_locked(&drv->driver_mutex));
    574        
    575         log_msg(LOG_DEFAULT, LVL_DEBUG, "start_driver(drv=\"%s\")", drv->name);
    576        
    577         rc = task_spawnl(NULL, drv->binary_path, drv->binary_path, NULL);
    578         if (rc != EOK) {
    579                 log_msg(LOG_DEFAULT, LVL_ERROR, "Spawning driver `%s' (%s) failed: %s.",
    580                     drv->name, drv->binary_path, str_error(rc));
    581                 return false;
    582         }
    583        
    584         drv->state = DRIVER_STARTING;
    585         return true;
    586 }
    587 
    588 /** Find device driver in the list of device drivers.
    589  *
    590  * @param drv_list      The list of device drivers.
    591  * @param drv_name      The name of the device driver which is searched.
    592  * @return              The device driver of the specified name, if it is in the
    593  *                      list, NULL otherwise.
    594  */
    595 driver_t *find_driver(driver_list_t *drv_list, const char *drv_name)
    596 {
    597         driver_t *res = NULL;
    598         driver_t *drv = NULL;
    599        
    600         fibril_mutex_lock(&drv_list->drivers_mutex);
    601        
    602         list_foreach(drv_list->drivers, link) {
    603                 drv = list_get_instance(link, driver_t, drivers);
    604                 if (str_cmp(drv->name, drv_name) == 0) {
    605                         res = drv;
    606                         break;
    607                 }
    608         }
    609        
    610         fibril_mutex_unlock(&drv_list->drivers_mutex);
    611        
    612         return res;
    613 }
    614 
    615 /** Notify driver about the devices to which it was assigned.
    616  *
    617  * @param driver        The driver to which the devices are passed.
    618  */
    619 static void pass_devices_to_driver(driver_t *driver, dev_tree_t *tree)
    620 {
    621         dev_node_t *dev;
    622         link_t *link;
    623 
    624         log_msg(LOG_DEFAULT, LVL_DEBUG, "pass_devices_to_driver(driver=\"%s\")",
    625             driver->name);
    626 
    627         fibril_mutex_lock(&driver->driver_mutex);
    628 
    629         /*
    630          * Go through devices list as long as there is some device
    631          * that has not been passed to the driver.
    632          */
    633         link = driver->devices.head.next;
    634         while (link != &driver->devices.head) {
    635                 dev = list_get_instance(link, dev_node_t, driver_devices);
    636                 fibril_rwlock_write_lock(&tree->rwlock);
    637                
    638                 if (dev->passed_to_driver) {
    639                         fibril_rwlock_write_unlock(&tree->rwlock);
    640                         link = link->next;
    641                         continue;
    642                 }
    643 
    644                 log_msg(LOG_DEFAULT, LVL_DEBUG, "pass_devices_to_driver: dev->refcnt=%d\n",
    645                     (int)atomic_get(&dev->refcnt));
    646                 dev_add_ref(dev);
    647 
    648                 /*
    649                  * Unlock to avoid deadlock when adding device
    650                  * handled by itself.
    651                  */
    652                 fibril_mutex_unlock(&driver->driver_mutex);
    653                 fibril_rwlock_write_unlock(&tree->rwlock);
    654 
    655                 add_device(driver, dev, tree);
    656 
    657                 dev_del_ref(dev);
    658 
    659                 /*
    660                  * Lock again as we will work with driver's
    661                  * structure.
    662                  */
    663                 fibril_mutex_lock(&driver->driver_mutex);
    664 
    665                 /*
    666                  * Restart the cycle to go through all devices again.
    667                  */
    668                 link = driver->devices.head.next;
    669         }
    670 
    671         /*
    672          * Once we passed all devices to the driver, we need to mark the
    673          * driver as running.
    674          * It is vital to do it here and inside critical section.
    675          *
    676          * If we would change the state earlier, other devices added to
    677          * the driver would be added to the device list and started
    678          * immediately and possibly started here as well.
    679          */
    680         log_msg(LOG_DEFAULT, LVL_DEBUG, "Driver `%s' enters running state.", driver->name);
    681         driver->state = DRIVER_RUNNING;
    682 
    683         fibril_mutex_unlock(&driver->driver_mutex);
    684 }
    685 
    686 /** Finish the initialization of a driver after it has succesfully started
    687  * and after it has registered itself by the device manager.
    688  *
    689  * Pass devices formerly matched to the driver to the driver and remember the
    690  * driver is running and fully functional now.
    691  *
    692  * @param driver        The driver which registered itself as running by the
    693  *                      device manager.
    694  */
    695 void initialize_running_driver(driver_t *driver, dev_tree_t *tree)
    696 {
    697         log_msg(LOG_DEFAULT, LVL_DEBUG, "initialize_running_driver(driver=\"%s\")",
    698             driver->name);
    699        
    700         /*
    701          * Pass devices which have been already assigned to the driver to the
    702          * driver.
    703          */
    704         pass_devices_to_driver(driver, tree);
    705 }
    706 
    707 /** Initialize device driver structure.
    708  *
    709  * @param drv           The device driver structure.
    710  */
    711 void init_driver(driver_t *drv)
    712 {
    713         assert(drv != NULL);
    714 
    715         memset(drv, 0, sizeof(driver_t));
    716         list_initialize(&drv->match_ids.ids);
    717         list_initialize(&drv->devices);
    718         fibril_mutex_initialize(&drv->driver_mutex);
    719         drv->sess = NULL;
    720 }
    721 
    722 /** Device driver structure clean-up.
    723  *
    724  * @param drv           The device driver structure.
    725  */
    726 void clean_driver(driver_t *drv)
    727 {
    728         assert(drv != NULL);
    729 
    730         free(drv->name);
    731         free(drv->binary_path);
    732 
    733         clean_match_ids(&drv->match_ids);
    734 
    735         init_driver(drv);
    736 }
    737 
    738 /** Delete device driver structure.
    739  *
    740  * @param drv           The device driver structure.
    741  */
    742 void delete_driver(driver_t *drv)
    743 {
    744         assert(drv != NULL);
    745        
    746         clean_driver(drv);
    747         free(drv);
    748333}
    749334
     
    834419
    835420        return;
    836 }
    837 
    838 /** Find suitable driver for a device and assign the driver to it.
    839  *
    840  * @param node          The device node of the device in the device tree.
    841  * @param drivers_list  The list of available drivers.
    842  * @return              True if the suitable driver is found and
    843  *                      successfully assigned to the device, false otherwise.
    844  */
    845 bool assign_driver(dev_node_t *dev, driver_list_t *drivers_list,
    846     dev_tree_t *tree)
    847 {
    848         assert(dev != NULL);
    849         assert(drivers_list != NULL);
    850         assert(tree != NULL);
    851        
    852         /*
    853          * Find the driver which is the most suitable for handling this device.
    854          */
    855         driver_t *drv = find_best_match_driver(drivers_list, dev);
    856         if (drv == NULL) {
    857                 log_msg(LOG_DEFAULT, LVL_ERROR, "No driver found for device `%s'.",
    858                     dev->pfun->pathname);
    859                 return false;
    860         }
    861        
    862         /* Attach the driver to the device. */
    863         attach_driver(tree, dev, drv);
    864        
    865         fibril_mutex_lock(&drv->driver_mutex);
    866         if (drv->state == DRIVER_NOT_STARTED) {
    867                 /* Start the driver. */
    868                 start_driver(drv);
    869         }
    870         bool is_running = drv->state == DRIVER_RUNNING;
    871         fibril_mutex_unlock(&drv->driver_mutex);
    872 
    873         /* Notify the driver about the new device. */
    874         if (is_running)
    875                 add_device(drv, dev, tree);
    876        
    877         fibril_mutex_lock(&drv->driver_mutex);
    878         fibril_mutex_unlock(&drv->driver_mutex);
    879 
    880         fibril_rwlock_write_lock(&tree->rwlock);
    881         if (dev->pfun != NULL) {
    882                 dev->pfun->state = FUN_ON_LINE;
    883         }
    884         fibril_rwlock_write_unlock(&tree->rwlock);
    885         return true;
    886 }
    887 
    888 int driver_dev_remove(dev_tree_t *tree, dev_node_t *dev)
    889 {
    890         async_exch_t *exch;
    891         sysarg_t retval;
    892         driver_t *drv;
    893         devman_handle_t handle;
    894        
    895         assert(dev != NULL);
    896        
    897         log_msg(LOG_DEFAULT, LVL_DEBUG, "driver_dev_remove(%p)", dev);
    898        
    899         fibril_rwlock_read_lock(&tree->rwlock);
    900         drv = dev->drv;
    901         handle = dev->handle;
    902         fibril_rwlock_read_unlock(&tree->rwlock);
    903        
    904         exch = async_exchange_begin(drv->sess);
    905         retval = async_req_1_0(exch, DRIVER_DEV_REMOVE, handle);
    906         async_exchange_end(exch);
    907        
    908         return retval;
    909 }
    910 
    911 int driver_dev_gone(dev_tree_t *tree, dev_node_t *dev)
    912 {
    913         async_exch_t *exch;
    914         sysarg_t retval;
    915         driver_t *drv;
    916         devman_handle_t handle;
    917        
    918         assert(dev != NULL);
    919        
    920         log_msg(LOG_DEFAULT, LVL_DEBUG, "driver_dev_gone(%p)", dev);
    921        
    922         fibril_rwlock_read_lock(&tree->rwlock);
    923         drv = dev->drv;
    924         handle = dev->handle;
    925         fibril_rwlock_read_unlock(&tree->rwlock);
    926        
    927         exch = async_exchange_begin(drv->sess);
    928         retval = async_req_1_0(exch, DRIVER_DEV_GONE, handle);
    929         async_exchange_end(exch);
    930        
    931         return retval;
    932 }
    933 
    934 int driver_fun_online(dev_tree_t *tree, fun_node_t *fun)
    935 {
    936         async_exch_t *exch;
    937         sysarg_t retval;
    938         driver_t *drv;
    939         devman_handle_t handle;
    940        
    941         log_msg(LOG_DEFAULT, LVL_DEBUG, "driver_fun_online(%p)", fun);
    942 
    943         fibril_rwlock_read_lock(&tree->rwlock);
    944        
    945         if (fun->dev == NULL) {
    946                 /* XXX root function? */
    947                 fibril_rwlock_read_unlock(&tree->rwlock);
    948                 return EINVAL;
    949         }
    950        
    951         drv = fun->dev->drv;
    952         handle = fun->handle;
    953         fibril_rwlock_read_unlock(&tree->rwlock);
    954        
    955         exch = async_exchange_begin(drv->sess);
    956         retval = async_req_1_0(exch, DRIVER_FUN_ONLINE, handle);
    957         loc_exchange_end(exch);
    958        
    959         return retval;
    960 }
    961 
    962 int driver_fun_offline(dev_tree_t *tree, fun_node_t *fun)
    963 {
    964         async_exch_t *exch;
    965         sysarg_t retval;
    966         driver_t *drv;
    967         devman_handle_t handle;
    968        
    969         log_msg(LOG_DEFAULT, LVL_DEBUG, "driver_fun_offline(%p)", fun);
    970 
    971         fibril_rwlock_read_lock(&tree->rwlock);
    972         if (fun->dev == NULL) {
    973                 /* XXX root function? */
    974                 fibril_rwlock_read_unlock(&tree->rwlock);
    975                 return EINVAL;
    976         }
    977        
    978         drv = fun->dev->drv;
    979         handle = fun->handle;
    980         fibril_rwlock_read_unlock(&tree->rwlock);
    981        
    982         exch = async_exchange_begin(drv->sess);
    983         retval = async_req_1_0(exch, DRIVER_FUN_OFFLINE, handle);
    984         loc_exchange_end(exch);
    985        
    986         return retval;
    987 
    988421}
    989422
  • uspace/srv/devman/devman.h

    r5b08d750 r041b026  
    247247extern char *read_id(const char **);
    248248
    249 /* Drivers */
    250 
    251 extern void init_driver_list(driver_list_t *);
    252 extern driver_t *create_driver(void);
    253 extern bool get_driver_info(const char *, const char *, driver_t *);
    254 extern int lookup_available_drivers(driver_list_t *, const char *);
    255 
    256 extern driver_t *find_best_match_driver(driver_list_t *, dev_node_t *);
    257 extern bool assign_driver(dev_node_t *, driver_list_t *, dev_tree_t *);
    258 
    259 extern void add_driver(driver_list_t *, driver_t *);
    260 extern void attach_driver(dev_tree_t *, dev_node_t *, driver_t *);
    261 extern void detach_driver(dev_tree_t *, dev_node_t *);
    262 extern void add_device(driver_t *, dev_node_t *, dev_tree_t *);
    263 extern bool start_driver(driver_t *);
    264 extern int driver_dev_remove(dev_tree_t *, dev_node_t *);
    265 extern int driver_dev_gone(dev_tree_t *, dev_node_t *);
    266 extern int driver_fun_online(dev_tree_t *, fun_node_t *);
    267 extern int driver_fun_offline(dev_tree_t *, fun_node_t *);
    268 
    269 extern driver_t *find_driver(driver_list_t *, const char *);
    270 extern void initialize_running_driver(driver_t *, dev_tree_t *);
    271 
    272 extern void init_driver(driver_t *);
    273 extern void clean_driver(driver_t *);
    274 extern void delete_driver(driver_t *);
    275 
    276249/* Device nodes */
    277250
  • uspace/srv/devman/main.c

    r5b08d750 r041b026  
    5959
    6060#include "devman.h"
     61#include "driver.h"
    6162
    6263#define DRIVER_DEFAULT_STORE  "/drv"
Note: See TracChangeset for help on using the changeset viewer.