Changeset b5e68c8 in mainline for uspace/srv/devman/devman.c


Ignore:
Timestamp:
2011-05-12T16:49:44Z (14 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f36787d7
Parents:
e80329d6 (diff), 750636a (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 mainline changes.

File:
1 edited

Legend:

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

    re80329d6 rb5e68c8  
    3434#include <fcntl.h>
    3535#include <sys/stat.h>
     36#include <io/log.h>
    3637#include <ipc/driver.h>
    3738#include <ipc/devman.h>
    3839#include <devmap.h>
     40#include <str_error.h>
     41#include <stdio.h>
    3942
    4043#include "devman.h"
     44
     45fun_node_t *find_node_child(fun_node_t *parent, const char *name);
    4146
    4247/* hash table operations */
     
    5055    link_t *item)
    5156{
    52         node_t *dev = hash_table_get_instance(item, node_t, devman_link);
    53         return (dev->handle == (device_handle_t) key[0]);
    54 }
    55 
    56 static int devmap_devices_compare(unsigned long key[], hash_count_t keys,
     57        dev_node_t *dev = hash_table_get_instance(item, dev_node_t, devman_dev);
     58        return (dev->handle == (devman_handle_t) key[0]);
     59}
     60
     61static int devman_functions_compare(unsigned long key[], hash_count_t keys,
    5762    link_t *item)
    5863{
    59         node_t *dev = hash_table_get_instance(item, node_t, devmap_link);
    60         return (dev->devmap_handle == (dev_handle_t) key[0]);
     64        fun_node_t *fun = hash_table_get_instance(item, fun_node_t, devman_fun);
     65        return (fun->handle == (devman_handle_t) key[0]);
     66}
     67
     68static int devmap_functions_compare(unsigned long key[], hash_count_t keys,
     69    link_t *item)
     70{
     71        fun_node_t *fun = hash_table_get_instance(item, fun_node_t, devmap_fun);
     72        return (fun->devmap_handle == (devmap_handle_t) key[0]);
     73}
     74
     75static int devmap_devices_class_compare(unsigned long key[], hash_count_t keys,
     76    link_t *item)
     77{
     78        dev_class_info_t *class_info
     79            = hash_table_get_instance(item, dev_class_info_t, devmap_link);
     80        assert(class_info != NULL);
     81
     82        return (class_info->devmap_handle == (devmap_handle_t) key[0]);
    6183}
    6284
     
    7193};
    7294
     95static hash_table_operations_t devman_functions_ops = {
     96        .hash = devices_hash,
     97        .compare = devman_functions_compare,
     98        .remove_callback = devices_remove_callback
     99};
     100
    73101static hash_table_operations_t devmap_devices_ops = {
    74102        .hash = devices_hash,
    75         .compare = devmap_devices_compare,
     103        .compare = devmap_functions_compare,
     104        .remove_callback = devices_remove_callback
     105};
     106
     107static hash_table_operations_t devmap_devices_class_ops = {
     108        .hash = devices_hash,
     109        .compare = devmap_devices_class_compare,
    76110        .remove_callback = devices_remove_callback
    77111};
     
    114148        fibril_mutex_unlock(&drivers_list->drivers_mutex);
    115149
    116         printf(NAME": the '%s' driver was added to the list of available "
    117             "drivers.\n", drv->name);
     150        log_msg(LVL_NOTE, "Driver `%s' was added to the list of available "
     151            "drivers.", drv->name);
    118152}
    119153
     
    205239bool read_match_ids(const char *conf_path, match_id_list_t *ids)
    206240{
    207         printf(NAME ": read_match_ids conf_path = %s.\n", conf_path);
     241        log_msg(LVL_DEBUG, "read_match_ids(conf_path=\"%s\")", conf_path);
    208242       
    209243        bool suc = false;
     
    215249        fd = open(conf_path, O_RDONLY);
    216250        if (fd < 0) {
    217                 printf(NAME ": unable to open %s\n", conf_path);
     251                log_msg(LVL_ERROR, "Unable to open `%s' for reading: %s.",
     252                    conf_path, str_error(fd));
    218253                goto cleanup;
    219254        }
     
    223258        lseek(fd, 0, SEEK_SET);
    224259        if (len == 0) {
    225                 printf(NAME ": configuration file '%s' is empty.\n", conf_path);
     260                log_msg(LVL_ERROR, "Configuration file '%s' is empty.",
     261                    conf_path);
    226262                goto cleanup;
    227263        }
     
    229265        buf = malloc(len + 1);
    230266        if (buf == NULL) {
    231                 printf(NAME ": memory allocation failed when parsing file "
    232                     "'%s'.\n", conf_path);
     267                log_msg(LVL_ERROR, "Memory allocation failed when parsing file "
     268                    "'%s'.", conf_path);
    233269                goto cleanup;
    234270        }
    235271       
    236         if (read(fd, buf, len) <= 0) {
    237                 printf(NAME ": unable to read file '%s'.\n", conf_path);
     272        ssize_t read_bytes = safe_read(fd, buf, len);
     273        if (read_bytes <= 0) {
     274                log_msg(LVL_ERROR, "Unable to read file '%s'.", conf_path);
    238275                goto cleanup;
    239276        }
    240         buf[len] = 0;
     277        buf[read_bytes] = 0;
    241278       
    242279        suc = parse_match_ids(buf, ids);
     
    273310bool get_driver_info(const char *base_path, const char *name, driver_t *drv)
    274311{
    275         printf(NAME ": get_driver_info base_path = %s, name = %s.\n",
     312        log_msg(LVL_DEBUG, "get_driver_info(base_path=\"%s\", name=\"%s\")",
    276313            base_path, name);
    277314       
     
    305342        struct stat s;
    306343        if (stat(drv->binary_path, &s) == ENOENT) { /* FIXME!! */
    307                 printf(NAME ": driver not found at path %s.", drv->binary_path);
     344                log_msg(LVL_ERROR, "Driver not found at path `%s'.",
     345                    drv->binary_path);
    308346                goto cleanup;
    309347        }
     
    332370int lookup_available_drivers(driver_list_t *drivers_list, const char *dir_path)
    333371{
    334         printf(NAME ": lookup_available_drivers, dir = %s \n", dir_path);
     372        log_msg(LVL_DEBUG, "lookup_available_drivers(dir=\"%s\")", dir_path);
    335373       
    336374        int drv_cnt = 0;
     
    356394}
    357395
    358 /** Create root device node in the device tree.
     396/** Create root device and function node in the device tree.
    359397 *
    360398 * @param tree  The device tree.
    361399 * @return      True on success, false otherwise.
    362400 */
    363 bool create_root_node(dev_tree_t *tree)
    364 {
    365         node_t *node;
    366 
    367         printf(NAME ": create_root_node\n");
    368 
    369         node = create_dev_node();
    370         if (node != NULL) {
    371                 insert_dev_node(tree, node, clone_string(""), NULL);
    372                 match_id_t *id = create_match_id();
    373                 id->id = clone_string("root");
    374                 id->score = 100;
    375                 add_match_id(&node->match_ids, id);
    376                 tree->root_node = node;
    377         }
    378 
    379         return node != NULL;
     401bool create_root_nodes(dev_tree_t *tree)
     402{
     403        fun_node_t *fun;
     404        dev_node_t *dev;
     405       
     406        log_msg(LVL_DEBUG, "create_root_nodes()");
     407       
     408        fibril_rwlock_write_lock(&tree->rwlock);
     409       
     410        /*
     411         * Create root function. This is a pseudo function to which
     412         * the root device node is attached. It allows us to match
     413         * the root device driver in a standard manner, i.e. against
     414         * the parent function.
     415         */
     416       
     417        fun = create_fun_node();
     418        if (fun == NULL) {
     419                fibril_rwlock_write_unlock(&tree->rwlock);
     420                return false;
     421        }
     422       
     423        insert_fun_node(tree, fun, clone_string(""), NULL);
     424        match_id_t *id = create_match_id();
     425        id->id = clone_string("root");
     426        id->score = 100;
     427        add_match_id(&fun->match_ids, id);
     428        tree->root_node = fun;
     429       
     430        /*
     431         * Create root device node.
     432         */
     433        dev = create_dev_node();
     434        if (dev == NULL) {
     435                fibril_rwlock_write_unlock(&tree->rwlock);
     436                return false;
     437        }
     438       
     439        insert_dev_node(tree, dev, fun);
     440       
     441        fibril_rwlock_write_unlock(&tree->rwlock);
     442       
     443        return dev != NULL;
    380444}
    381445
     
    395459 *                      is found.
    396460 */
    397 driver_t *find_best_match_driver(driver_list_t *drivers_list, node_t *node)
     461driver_t *find_best_match_driver(driver_list_t *drivers_list, dev_node_t *node)
    398462{
    399463        driver_t *best_drv = NULL, *drv = NULL;
     
    423487 * @param drv           The driver.
    424488 */
    425 void attach_driver(node_t *node, driver_t *drv)
    426 {
    427         printf(NAME ": attach_driver %s to device %s\n",
    428             drv->name, node->pathname);
     489void attach_driver(dev_node_t *dev, driver_t *drv)
     490{
     491        log_msg(LVL_DEBUG, "attach_driver(dev=\"%s\",drv=\"%s\")",
     492            dev->pfun->pathname, drv->name);
    429493       
    430494        fibril_mutex_lock(&drv->driver_mutex);
    431495       
    432         node->drv = drv;
    433         list_append(&node->driver_devices, &drv->devices);
     496        dev->drv = drv;
     497        list_append(&dev->driver_devices, &drv->devices);
    434498       
    435499        fibril_mutex_unlock(&drv->driver_mutex);
     
    437501
    438502/** Start a driver
    439  *
    440  * The driver's mutex is assumed to be locked.
    441503 *
    442504 * @param drv           The driver's structure.
     
    446508bool start_driver(driver_t *drv)
    447509{
    448         printf(NAME ": start_driver '%s'\n", drv->name);
    449        
    450         const char *argv[2];
    451        
    452         argv[0] = drv->name;
    453         argv[1] = NULL;
    454        
    455         int err;
    456         if (task_spawn(drv->binary_path, argv, &err) == 0) {
    457                 printf(NAME ": error spawning %s, errno = %d\n",
    458                     drv->name, err);
     510        int rc;
     511
     512        assert(fibril_mutex_is_locked(&drv->driver_mutex));
     513       
     514        log_msg(LVL_DEBUG, "start_driver(drv=\"%s\")", drv->name);
     515       
     516        rc = task_spawnl(NULL, drv->binary_path, drv->binary_path, NULL);
     517        if (rc != EOK) {
     518                log_msg(LVL_ERROR, "Spawning driver `%s' (%s) failed: %s.",
     519                    drv->name, drv->binary_path, str_error(rc));
    459520                return false;
    460521        }
     
    495556}
    496557
    497 /** Remember the driver's phone.
    498  *
    499  * @param driver        The driver.
    500  * @param phone         The phone to the driver.
    501  */
    502 void set_driver_phone(driver_t *driver, ipcarg_t phone)
    503 {
    504         fibril_mutex_lock(&driver->driver_mutex);
    505         assert(driver->state == DRIVER_STARTING);
    506         driver->phone = phone;
    507         fibril_mutex_unlock(&driver->driver_mutex);
    508 }
    509 
    510558/** Notify driver about the devices to which it was assigned.
    511559 *
    512  * The driver's mutex must be locked.
    513  *
    514560 * @param driver        The driver to which the devices are passed.
    515561 */
    516562static void pass_devices_to_driver(driver_t *driver, dev_tree_t *tree)
    517563{
    518         node_t *dev;
     564        dev_node_t *dev;
    519565        link_t *link;
    520566        int phone;
    521567
    522         printf(NAME ": pass_devices_to_driver\n");
    523 
    524         phone = ipc_connect_me_to(driver->phone, DRIVER_DEVMAN, 0, 0);
    525         if (phone > 0) {
    526                
     568        log_msg(LVL_DEBUG, "pass_devices_to_driver(driver=\"%s\")",
     569            driver->name);
     570
     571        fibril_mutex_lock(&driver->driver_mutex);
     572
     573        phone = async_connect_me_to(driver->phone, DRIVER_DEVMAN, 0, 0);
     574
     575        if (phone < 0) {
     576                fibril_mutex_unlock(&driver->driver_mutex);
     577                return;
     578        }
     579
     580        /*
     581         * Go through devices list as long as there is some device
     582         * that has not been passed to the driver.
     583         */
     584        link = driver->devices.next;
     585        while (link != &driver->devices) {
     586                dev = list_get_instance(link, dev_node_t, driver_devices);
     587                if (dev->passed_to_driver) {
     588                        link = link->next;
     589                        continue;
     590                }
     591
     592                /*
     593                 * We remove the device from the list to allow safe adding
     594                 * of new devices (no one will touch our item this way).
     595                 */
     596                list_remove(link);
     597
     598                /*
     599                 * Unlock to avoid deadlock when adding device
     600                 * handled by itself.
     601                 */
     602                fibril_mutex_unlock(&driver->driver_mutex);
     603
     604                add_device(phone, driver, dev, tree);
     605
     606                /*
     607                 * Lock again as we will work with driver's
     608                 * structure.
     609                 */
     610                fibril_mutex_lock(&driver->driver_mutex);
     611
     612                /*
     613                 * Insert the device back.
     614                 * The order is not relevant here so no harm is done
     615                 * (actually, the order would be preserved in most cases).
     616                 */
     617                list_append(link, &driver->devices);
     618
     619                /*
     620                 * Restart the cycle to go through all devices again.
     621                 */
    527622                link = driver->devices.next;
    528                 while (link != &driver->devices) {
    529                         dev = list_get_instance(link, node_t, driver_devices);
    530                         add_device(phone, driver, dev, tree);
    531                         link = link->next;
    532                 }
    533                
    534                 ipc_hangup(phone);
    535         }
     623        }
     624
     625        async_hangup(phone);
     626
     627        /*
     628         * Once we passed all devices to the driver, we need to mark the
     629         * driver as running.
     630         * It is vital to do it here and inside critical section.
     631         *
     632         * If we would change the state earlier, other devices added to
     633         * the driver would be added to the device list and started
     634         * immediately and possibly started here as well.
     635         */
     636        log_msg(LVL_DEBUG, "Driver `%s' enters running state.", driver->name);
     637        driver->state = DRIVER_RUNNING;
     638
     639        fibril_mutex_unlock(&driver->driver_mutex);
    536640}
    537641
     
    547651void initialize_running_driver(driver_t *driver, dev_tree_t *tree)
    548652{
    549         printf(NAME ": initialize_running_driver\n");
    550         fibril_mutex_lock(&driver->driver_mutex);
     653        log_msg(LVL_DEBUG, "initialize_running_driver(driver=\"%s\")",
     654            driver->name);
    551655       
    552656        /*
     
    555659         */
    556660        pass_devices_to_driver(driver, tree);
    557        
    558         /* Change driver's state to running. */
    559         driver->state = DRIVER_RUNNING;
    560        
    561         fibril_mutex_unlock(&driver->driver_mutex);
    562661}
    563662
     
    574673        list_initialize(&drv->devices);
    575674        fibril_mutex_initialize(&drv->driver_mutex);
     675        drv->phone = -1;
    576676}
    577677
     
    604704}
    605705
    606 /** Create devmap path and name for the device. */
    607 static void devmap_register_tree_device(node_t *node, dev_tree_t *tree)
     706/** Create devmap path and name for the function. */
     707void devmap_register_tree_function(fun_node_t *fun, dev_tree_t *tree)
    608708{
    609709        char *devmap_pathname = NULL;
    610710        char *devmap_name = NULL;
    611711       
    612         asprintf(&devmap_name, "%s", node->pathname);
     712        asprintf(&devmap_name, "%s", fun->pathname);
    613713        if (devmap_name == NULL)
    614714                return;
     
    623723        }
    624724       
    625         devmap_device_register(devmap_pathname, &node->devmap_handle);
    626        
    627         tree_add_devmap_device(tree, node);
     725        devmap_device_register_with_iface(devmap_pathname,
     726            &fun->devmap_handle, DEVMAN_CONNECT_FROM_DEVMAP);
     727       
     728        tree_add_devmap_function(tree, fun);
    628729       
    629730        free(devmap_name);
     
    631732}
    632733
    633 
    634734/** Pass a device to running driver.
    635735 *
     
    637737 * @param node          The device's node in the device tree.
    638738 */
    639 void add_device(int phone, driver_t *drv, node_t *node, dev_tree_t *tree)
    640 {
    641         printf(NAME ": add_device\n");
    642        
    643         ipcarg_t rc;
     739void add_device(int phone, driver_t *drv, dev_node_t *dev, dev_tree_t *tree)
     740{
     741        /*
     742         * We do not expect to have driver's mutex locked as we do not
     743         * access any structures that would affect driver_t.
     744         */
     745        log_msg(LVL_DEBUG, "add_device(drv=\"%s\", dev=\"%s\")",
     746            drv->name, dev->pfun->name);
     747       
     748        sysarg_t rc;
    644749        ipc_call_t answer;
    645750       
    646751        /* Send the device to the driver. */
    647         aid_t req = async_send_1(phone, DRIVER_ADD_DEVICE, node->handle,
    648             &answer);
     752        devman_handle_t parent_handle;
     753        if (dev->pfun) {
     754                parent_handle = dev->pfun->handle;
     755        } else {
     756                parent_handle = 0;
     757        }
     758
     759        aid_t req = async_send_2(phone, DRIVER_ADD_DEVICE, dev->handle,
     760            parent_handle, &answer);
    649761       
    650762        /* Send the device's name to the driver. */
    651         rc = async_data_write_start(phone, node->name,
    652             str_size(node->name) + 1);
     763        rc = async_data_write_start(phone, dev->pfun->name,
     764            str_size(dev->pfun->name) + 1);
    653765        if (rc != EOK) {
    654766                /* TODO handle error */
    655767        }
    656        
     768
    657769        /* Wait for answer from the driver. */
    658770        async_wait_for(req, &rc);
     771
    659772        switch(rc) {
    660773        case EOK:
    661                 node->state = DEVICE_USABLE;
    662                 devmap_register_tree_device(node, tree);
     774                dev->state = DEVICE_USABLE;
    663775                break;
    664776        case ENOENT:
    665                 node->state = DEVICE_NOT_PRESENT;
     777                dev->state = DEVICE_NOT_PRESENT;
    666778                break;
    667779        default:
    668                 node->state = DEVICE_INVALID;
    669         }
    670        
     780                dev->state = DEVICE_INVALID;
     781        }
     782       
     783        dev->passed_to_driver = true;
     784
    671785        return;
    672786}
     
    679793 *                      successfully assigned to the device, false otherwise.
    680794 */
    681 bool assign_driver(node_t *node, driver_list_t *drivers_list, dev_tree_t *tree)
    682 {
     795bool assign_driver(dev_node_t *dev, driver_list_t *drivers_list,
     796    dev_tree_t *tree)
     797{
     798        assert(dev != NULL);
     799        assert(drivers_list != NULL);
     800        assert(tree != NULL);
     801       
    683802        /*
    684803         * Find the driver which is the most suitable for handling this device.
    685804         */
    686         driver_t *drv = find_best_match_driver(drivers_list, node);
     805        driver_t *drv = find_best_match_driver(drivers_list, dev);
    687806        if (drv == NULL) {
    688                 printf(NAME ": no driver found for device '%s'.\n",
    689                     node->pathname);
     807                log_msg(LVL_ERROR, "No driver found for device `%s'.",
     808                    dev->pfun->pathname);
    690809                return false;
    691810        }
    692811       
    693812        /* Attach the driver to the device. */
    694         attach_driver(node, drv);
    695        
     813        attach_driver(dev, drv);
     814       
     815        fibril_mutex_lock(&drv->driver_mutex);
    696816        if (drv->state == DRIVER_NOT_STARTED) {
    697817                /* Start the driver. */
    698818                start_driver(drv);
    699819        }
    700        
    701         if (drv->state == DRIVER_RUNNING) {
     820        bool is_running = drv->state == DRIVER_RUNNING;
     821        fibril_mutex_unlock(&drv->driver_mutex);
     822
     823        if (is_running) {
    702824                /* Notify the driver about the new device. */
    703                 int phone = ipc_connect_me_to(drv->phone, DRIVER_DEVMAN, 0, 0);
    704                 if (phone > 0) {
    705                         add_device(phone, drv, node, tree);
    706                         ipc_hangup(phone);
     825                int phone = async_connect_me_to(drv->phone, DRIVER_DEVMAN, 0, 0);
     826                if (phone >= 0) {
     827                        add_device(phone, drv, dev, tree);
     828                        async_hangup(phone);
    707829                }
    708830        }
     
    721843bool init_device_tree(dev_tree_t *tree, driver_list_t *drivers_list)
    722844{
    723         printf(NAME ": init_device_tree.\n");
     845        log_msg(LVL_DEBUG, "init_device_tree()");
    724846       
    725847        tree->current_handle = 0;
     
    727849        hash_table_create(&tree->devman_devices, DEVICE_BUCKETS, 1,
    728850            &devman_devices_ops);
    729         hash_table_create(&tree->devmap_devices, DEVICE_BUCKETS, 1,
     851        hash_table_create(&tree->devman_functions, DEVICE_BUCKETS, 1,
     852            &devman_functions_ops);
     853        hash_table_create(&tree->devmap_functions, DEVICE_BUCKETS, 1,
    730854            &devmap_devices_ops);
    731855       
    732856        fibril_rwlock_initialize(&tree->rwlock);
    733857       
    734         /* Create root node and add it to the device tree. */
    735         if (!create_root_node(tree))
     858        /* Create root function and root device and add them to the device tree. */
     859        if (!create_root_nodes(tree))
    736860                return false;
    737861
    738862        /* Find suitable driver and start it. */
    739         return assign_driver(tree->root_node, drivers_list, tree);
     863        return assign_driver(tree->root_node->child, drivers_list, tree);
    740864}
    741865
     
    746870 * @return              A device node structure.
    747871 */
    748 node_t *create_dev_node(void)
    749 {
    750         node_t *res = malloc(sizeof(node_t));
     872dev_node_t *create_dev_node(void)
     873{
     874        dev_node_t *res = malloc(sizeof(dev_node_t));
    751875       
    752876        if (res != NULL) {
    753                 memset(res, 0, sizeof(node_t));
    754                 list_initialize(&res->children);
    755                 list_initialize(&res->match_ids.ids);
    756                 list_initialize(&res->classes);
     877                memset(res, 0, sizeof(dev_node_t));
     878                list_initialize(&res->functions);
     879                link_initialize(&res->driver_devices);
     880                link_initialize(&res->devman_dev);
    757881        }
    758882       
     
    764888 * @param node          The device node structure.
    765889 */
    766 void delete_dev_node(node_t *node)
    767 {
    768         assert(list_empty(&node->children));
    769         assert(node->parent == NULL);
    770         assert(node->drv == NULL);
    771        
    772         clean_match_ids(&node->match_ids);
    773         free_not_null(node->name);
    774         free_not_null(node->pathname);
    775         free(node);
     890void delete_dev_node(dev_node_t *dev)
     891{
     892        assert(list_empty(&dev->functions));
     893        assert(dev->pfun == NULL);
     894        assert(dev->drv == NULL);
     895       
     896        free(dev);
    776897}
    777898
    778899/** Find the device node structure of the device witch has the specified handle.
    779  *
    780  * Device tree's rwlock should be held at least for reading.
    781900 *
    782901 * @param tree          The device tree where we look for the device node.
     
    784903 * @return              The device node.
    785904 */
    786 node_t *find_dev_node_no_lock(dev_tree_t *tree, device_handle_t handle)
     905dev_node_t *find_dev_node_no_lock(dev_tree_t *tree, devman_handle_t handle)
    787906{
    788907        unsigned long key = handle;
    789         link_t *link = hash_table_find(&tree->devman_devices, &key);
    790         return hash_table_get_instance(link, node_t, devman_link);
     908        link_t *link;
     909       
     910        assert(fibril_rwlock_is_locked(&tree->rwlock));
     911       
     912        link = hash_table_find(&tree->devman_devices, &key);
     913        return hash_table_get_instance(link, dev_node_t, devman_dev);
    791914}
    792915
     
    797920 * @return              The device node.
    798921 */
    799 node_t *find_dev_node(dev_tree_t *tree, device_handle_t handle)
    800 {
    801         node_t *node = NULL;
     922dev_node_t *find_dev_node(dev_tree_t *tree, devman_handle_t handle)
     923{
     924        dev_node_t *dev = NULL;
    802925       
    803926        fibril_rwlock_read_lock(&tree->rwlock);
    804         node = find_dev_node_no_lock(tree, handle);
     927        dev = find_dev_node_no_lock(tree, handle);
    805928        fibril_rwlock_read_unlock(&tree->rwlock);
    806929       
    807         return node;
    808 }
    809 
     930        return dev;
     931}
     932
     933/* Function nodes */
     934
     935/** Create a new function node.
     936 *
     937 * @return              A function node structure.
     938 */
     939fun_node_t *create_fun_node(void)
     940{
     941        fun_node_t *res = malloc(sizeof(fun_node_t));
     942       
     943        if (res != NULL) {
     944                memset(res, 0, sizeof(fun_node_t));
     945                link_initialize(&res->dev_functions);
     946                list_initialize(&res->match_ids.ids);
     947                list_initialize(&res->classes);
     948                link_initialize(&res->devman_fun);
     949                link_initialize(&res->devmap_fun);
     950        }
     951       
     952        return res;
     953}
     954
     955/** Delete a function node.
     956 *
     957 * @param fun           The device node structure.
     958 */
     959void delete_fun_node(fun_node_t *fun)
     960{
     961        assert(fun->dev == NULL);
     962        assert(fun->child == NULL);
     963       
     964        clean_match_ids(&fun->match_ids);
     965        free_not_null(fun->name);
     966        free_not_null(fun->pathname);
     967        free(fun);
     968}
     969
     970/** Find the function node with the specified handle.
     971 *
     972 * @param tree          The device tree where we look for the device node.
     973 * @param handle        The handle of the function.
     974 * @return              The function node.
     975 */
     976fun_node_t *find_fun_node_no_lock(dev_tree_t *tree, devman_handle_t handle)
     977{
     978        unsigned long key = handle;
     979        link_t *link;
     980       
     981        assert(fibril_rwlock_is_locked(&tree->rwlock));
     982       
     983        link = hash_table_find(&tree->devman_functions, &key);
     984        if (link == NULL)
     985                return NULL;
     986       
     987        return hash_table_get_instance(link, fun_node_t, devman_fun);
     988}
     989
     990/** Find the function node with the specified handle.
     991 *
     992 * @param tree          The device tree where we look for the device node.
     993 * @param handle        The handle of the function.
     994 * @return              The function node.
     995 */
     996fun_node_t *find_fun_node(dev_tree_t *tree, devman_handle_t handle)
     997{
     998        fun_node_t *fun = NULL;
     999       
     1000        fibril_rwlock_read_lock(&tree->rwlock);
     1001        fun = find_fun_node_no_lock(tree, handle);
     1002        fibril_rwlock_read_unlock(&tree->rwlock);
     1003       
     1004        return fun;
     1005}
    8101006
    8111007/** Create and set device's full path in device tree.
     
    8161012 *                      resources etc.).
    8171013 */
    818 static bool set_dev_path(node_t *node, node_t *parent)
    819 {
    820         assert(node->name != NULL);
    821        
    822         size_t pathsize = (str_size(node->name) + 1);
     1014static bool set_fun_path(fun_node_t *fun, fun_node_t *parent)
     1015{
     1016        assert(fun->name != NULL);
     1017       
     1018        size_t pathsize = (str_size(fun->name) + 1);
    8231019        if (parent != NULL)
    8241020                pathsize += str_size(parent->pathname) + 1;
    8251021       
    826         node->pathname = (char *) malloc(pathsize);
    827         if (node->pathname == NULL) {
    828                 printf(NAME ": failed to allocate device path.\n");
     1022        fun->pathname = (char *) malloc(pathsize);
     1023        if (fun->pathname == NULL) {
     1024                log_msg(LVL_ERROR, "Failed to allocate device path.");
    8291025                return false;
    8301026        }
    8311027       
    8321028        if (parent != NULL) {
    833                 str_cpy(node->pathname, pathsize, parent->pathname);
    834                 str_append(node->pathname, pathsize, "/");
    835                 str_append(node->pathname, pathsize, node->name);
     1029                str_cpy(fun->pathname, pathsize, parent->pathname);
     1030                str_append(fun->pathname, pathsize, "/");
     1031                str_append(fun->pathname, pathsize, fun->name);
    8361032        } else {
    837                 str_cpy(node->pathname, pathsize, node->name);
     1033                str_cpy(fun->pathname, pathsize, fun->name);
    8381034        }
    8391035       
     
    8421038
    8431039/** Insert new device into device tree.
    844  *
    845  * The device tree's rwlock should be already held exclusively when calling this
    846  * function.
    8471040 *
    8481041 * @param tree          The device tree.
     
    8541047 *                      etc.).
    8551048 */
    856 bool insert_dev_node(dev_tree_t *tree, node_t *node, char *dev_name,
    857     node_t *parent)
    858 {
    859         assert(node != NULL);
     1049bool insert_dev_node(dev_tree_t *tree, dev_node_t *dev, fun_node_t *pfun)
     1050{
     1051        assert(dev != NULL);
    8601052        assert(tree != NULL);
    861         assert(dev_name != NULL);
    862        
    863         node->name = dev_name;
    864         if (!set_dev_path(node, parent)) {
    865                 fibril_rwlock_write_unlock(&tree->rwlock);
     1053        assert(fibril_rwlock_is_write_locked(&tree->rwlock));
     1054       
     1055        log_msg(LVL_DEBUG, "insert_dev_node(dev=%p, pfun=%p [\"%s\"])",
     1056            dev, pfun, pfun->pathname);
     1057
     1058        /* Add the node to the handle-to-node map. */
     1059        dev->handle = ++tree->current_handle;
     1060        unsigned long key = dev->handle;
     1061        hash_table_insert(&tree->devman_devices, &key, &dev->devman_dev);
     1062
     1063        /* Add the node to the list of its parent's children. */
     1064        dev->pfun = pfun;
     1065        pfun->child = dev;
     1066       
     1067        return true;
     1068}
     1069
     1070/** Insert new function into device tree.
     1071 *
     1072 * @param tree          The device tree.
     1073 * @param node          The newly added function node.
     1074 * @param dev_name      The name of the newly added function.
     1075 * @param parent        Owning device node.
     1076 *
     1077 * @return              True on success, false otherwise (insufficient resources
     1078 *                      etc.).
     1079 */
     1080bool insert_fun_node(dev_tree_t *tree, fun_node_t *fun, char *fun_name,
     1081    dev_node_t *dev)
     1082{
     1083        fun_node_t *pfun;
     1084       
     1085        assert(fun != NULL);
     1086        assert(tree != NULL);
     1087        assert(fun_name != NULL);
     1088        assert(fibril_rwlock_is_write_locked(&tree->rwlock));
     1089       
     1090        /*
     1091         * The root function is a special case, it does not belong to any
     1092         * device so for the root function dev == NULL.
     1093         */
     1094        pfun = (dev != NULL) ? dev->pfun : NULL;
     1095       
     1096        fun->name = fun_name;
     1097        if (!set_fun_path(fun, pfun)) {
    8661098                return false;
    8671099        }
    8681100       
    8691101        /* Add the node to the handle-to-node map. */
    870         node->handle = ++tree->current_handle;
    871         unsigned long key = node->handle;
    872         hash_table_insert(&tree->devman_devices, &key, &node->devman_link);
     1102        fun->handle = ++tree->current_handle;
     1103        unsigned long key = fun->handle;
     1104        hash_table_insert(&tree->devman_functions, &key, &fun->devman_fun);
    8731105
    8741106        /* Add the node to the list of its parent's children. */
    875         node->parent = parent;
    876         if (parent != NULL)
    877                 list_append(&node->sibling, &parent->children);
     1107        fun->dev = dev;
     1108        if (dev != NULL)
     1109                list_append(&fun->dev_functions, &dev->functions);
    8781110       
    8791111        return true;
    8801112}
    8811113
    882 /** Find device node with a specified path in the device tree.
     1114/** Find function node with a specified path in the device tree.
    8831115 *
    884  * @param path          The path of the device node in the device tree.
     1116 * @param path          The path of the function node in the device tree.
    8851117 * @param tree          The device tree.
    886  * @return              The device node if it is present in the tree, NULL
     1118 * @return              The function node if it is present in the tree, NULL
    8871119 *                      otherwise.
    8881120 */
    889 node_t *find_dev_node_by_path(dev_tree_t *tree, char *path)
    890 {
     1121fun_node_t *find_fun_node_by_path(dev_tree_t *tree, char *path)
     1122{
     1123        assert(path != NULL);
     1124
     1125        bool is_absolute = path[0] == '/';
     1126        if (!is_absolute) {
     1127                return NULL;
     1128        }
     1129
    8911130        fibril_rwlock_read_lock(&tree->rwlock);
    8921131       
    893         node_t *dev = tree->root_node;
     1132        fun_node_t *fun = tree->root_node;
    8941133        /*
    895          * Relative path to the device from its parent (but with '/' at the
     1134         * Relative path to the function from its parent (but with '/' at the
    8961135         * beginning)
    8971136         */
    8981137        char *rel_path = path;
    8991138        char *next_path_elem = NULL;
    900         bool cont = (rel_path[0] == '/');
    901        
    902         while (cont && dev != NULL) {
     1139        bool cont = true;
     1140       
     1141        while (cont && fun != NULL) {
    9031142                next_path_elem  = get_path_elem_end(rel_path + 1);
    9041143                if (next_path_elem[0] == '/') {
     
    9091148                }
    9101149               
    911                 dev = find_node_child(dev, rel_path + 1);
     1150                fun = find_node_child(fun, rel_path + 1);
    9121151               
    9131152                if (cont) {
     
    9201159        fibril_rwlock_read_unlock(&tree->rwlock);
    9211160       
    922         return dev;
    923 }
    924 
    925 /** Find child device node with a specified name.
     1161        return fun;
     1162}
     1163
     1164/** Find function with a specified name belonging to given device.
    9261165 *
    9271166 * Device tree rwlock should be held at least for reading.
    9281167 *
    929  * @param parent        The parent device node.
    930  * @param name          The name of the child device node.
    931  * @return              The child device node.
    932  */
    933 node_t *find_node_child(node_t *parent, const char *name)
    934 {
    935         node_t *dev;
     1168 * @param dev Device the function belongs to.
     1169 * @param name Function name (not path).
     1170 * @return Function node.
     1171 * @retval NULL No function with given name.
     1172 */
     1173fun_node_t *find_fun_node_in_device(dev_node_t *dev, const char *name)
     1174{
     1175        assert(dev != NULL);
     1176        assert(name != NULL);
     1177
     1178        fun_node_t *fun;
    9361179        link_t *link;
    937        
    938         link = parent->children.next;
    939        
    940         while (link != &parent->children) {
    941                 dev = list_get_instance(link, node_t, sibling);
    942                
    943                 if (str_cmp(name, dev->name) == 0)
    944                         return dev;
    945                
    946                 link = link->next;
    947         }
    948        
     1180
     1181        for (link = dev->functions.next;
     1182            link != &dev->functions;
     1183            link = link->next) {
     1184                fun = list_get_instance(link, fun_node_t, dev_functions);
     1185
     1186                if (str_cmp(name, fun->name) == 0)
     1187                        return fun;
     1188        }
     1189
    9491190        return NULL;
     1191}
     1192
     1193/** Find function node by its class name and index. */
     1194fun_node_t *find_fun_node_by_class(class_list_t *class_list,
     1195    const char *class_name, const char *dev_name)
     1196{
     1197        assert(class_list != NULL);
     1198        assert(class_name != NULL);
     1199        assert(dev_name != NULL);
     1200
     1201        fibril_rwlock_read_lock(&class_list->rwlock);
     1202
     1203        dev_class_t *cl = find_dev_class_no_lock(class_list, class_name);
     1204        if (cl == NULL) {
     1205                fibril_rwlock_read_unlock(&class_list->rwlock);
     1206                return NULL;
     1207        }
     1208
     1209        dev_class_info_t *dev = find_dev_in_class(cl, dev_name);
     1210        if (dev == NULL) {
     1211                fibril_rwlock_read_unlock(&class_list->rwlock);
     1212                return NULL;
     1213        }
     1214
     1215        fun_node_t *fun = dev->fun;
     1216
     1217        fibril_rwlock_read_unlock(&class_list->rwlock);
     1218
     1219        return fun;
     1220}
     1221
     1222
     1223/** Find child function node with a specified name.
     1224 *
     1225 * Device tree rwlock should be held at least for reading.
     1226 *
     1227 * @param parent        The parent function node.
     1228 * @param name          The name of the child function.
     1229 * @return              The child function node.
     1230 */
     1231fun_node_t *find_node_child(fun_node_t *pfun, const char *name)
     1232{
     1233        return find_fun_node_in_device(pfun->child, name);
    9501234}
    9511235
     
    9791263       
    9801264        info = (dev_class_info_t *) malloc(sizeof(dev_class_info_t));
    981         if (info != NULL)
     1265        if (info != NULL) {
    9821266                memset(info, 0, sizeof(dev_class_info_t));
     1267                link_initialize(&info->dev_classes);
     1268                link_initialize(&info->devmap_link);
     1269                link_initialize(&info->link);
     1270        }
    9831271       
    9841272        return info;
     
    10161304       
    10171305        size_t idx = get_new_class_dev_idx(cl);
    1018         asprintf(&dev_name, "%s%d", base_name, idx);
     1306        asprintf(&dev_name, "%s%zu", base_name, idx);
    10191307       
    10201308        return dev_name;
    10211309}
    10221310
    1023 /** Add the device to the class.
     1311/** Add the device function to the class.
    10241312 *
    10251313 * The device may be added to multiple classes and a class may contain multiple
     
    10341322 *                      with the class.
    10351323 */
    1036 dev_class_info_t *add_device_to_class(node_t *dev, dev_class_t *cl,
     1324dev_class_info_t *add_function_to_class(fun_node_t *fun, dev_class_t *cl,
    10371325    const char *base_dev_name)
    10381326{
    1039         dev_class_info_t *info = create_dev_class_info();
     1327        dev_class_info_t *info;
     1328
     1329        assert(fun != NULL);
     1330        assert(cl != NULL);
     1331
     1332        info = create_dev_class_info();
     1333
    10401334       
    10411335        if (info != NULL) {
    10421336                info->dev_class = cl;
    1043                 info->dev = dev;
     1337                info->fun = fun;
    10441338               
    10451339                /* Add the device to the class. */
     
    10491343               
    10501344                /* Add the class to the device. */
    1051                 list_append(&info->dev_classes, &dev->classes);
     1345                list_append(&info->dev_classes, &fun->classes);
    10521346               
    10531347                /* Create unique name for the device within the class. */
     
    10851379        while (link != &class_list->classes) {
    10861380                cl = list_get_instance(link, dev_class_t, link);
    1087                 if (str_cmp(cl->name, class_name) == 0)
     1381                if (str_cmp(cl->name, class_name) == 0) {
    10881382                        return cl;
     1383                }
     1384                link = link->next;
    10891385        }
    10901386       
     
    10951391{
    10961392        list_append(&cl->link, &class_list->classes);
     1393}
     1394
     1395dev_class_info_t *find_dev_in_class(dev_class_t *dev_class, const char *dev_name)
     1396{
     1397        assert(dev_class != NULL);
     1398        assert(dev_name != NULL);
     1399
     1400        link_t *link;
     1401        for (link = dev_class->devices.next;
     1402            link != &dev_class->devices;
     1403            link = link->next) {
     1404                dev_class_info_t *dev = list_get_instance(link,
     1405                    dev_class_info_t, link);
     1406
     1407                if (str_cmp(dev->dev_name, dev_name) == 0) {
     1408                        return dev;
     1409                }
     1410        }
     1411
     1412        return NULL;
    10971413}
    10981414
     
    11011417        list_initialize(&class_list->classes);
    11021418        fibril_rwlock_initialize(&class_list->rwlock);
    1103         hash_table_create(&class_list->devmap_devices, DEVICE_BUCKETS, 1,
    1104             &devmap_devices_ops);
     1419        hash_table_create(&class_list->devmap_functions, DEVICE_BUCKETS, 1,
     1420            &devmap_devices_class_ops);
    11051421}
    11061422
     
    11081424/* Devmap devices */
    11091425
    1110 node_t *find_devmap_tree_device(dev_tree_t *tree, dev_handle_t devmap_handle)
    1111 {
    1112         node_t *dev = NULL;
     1426fun_node_t *find_devmap_tree_function(dev_tree_t *tree, devmap_handle_t devmap_handle)
     1427{
     1428        fun_node_t *fun = NULL;
    11131429        link_t *link;
    11141430        unsigned long key = (unsigned long) devmap_handle;
    11151431       
    11161432        fibril_rwlock_read_lock(&tree->rwlock);
    1117         link = hash_table_find(&tree->devmap_devices, &key);
     1433        link = hash_table_find(&tree->devmap_functions, &key);
    11181434        if (link != NULL)
    1119                 dev = hash_table_get_instance(link, node_t, devmap_link);
     1435                fun = hash_table_get_instance(link, fun_node_t, devmap_fun);
    11201436        fibril_rwlock_read_unlock(&tree->rwlock);
    11211437       
    1122         return dev;
    1123 }
    1124 
    1125 node_t *find_devmap_class_device(class_list_t *classes,
    1126     dev_handle_t devmap_handle)
    1127 {
    1128         node_t *dev = NULL;
     1438        return fun;
     1439}
     1440
     1441fun_node_t *find_devmap_class_function(class_list_t *classes,
     1442    devmap_handle_t devmap_handle)
     1443{
     1444        fun_node_t *fun = NULL;
    11291445        dev_class_info_t *cli;
    11301446        link_t *link;
     
    11321448       
    11331449        fibril_rwlock_read_lock(&classes->rwlock);
    1134         link = hash_table_find(&classes->devmap_devices, &key);
     1450        link = hash_table_find(&classes->devmap_functions, &key);
    11351451        if (link != NULL) {
    11361452                cli = hash_table_get_instance(link, dev_class_info_t,
    11371453                    devmap_link);
    1138                 dev = cli->dev;
     1454                fun = cli->fun;
    11391455        }
    11401456        fibril_rwlock_read_unlock(&classes->rwlock);
    11411457       
    1142         return dev;
    1143 }
    1144 
    1145 void class_add_devmap_device(class_list_t *class_list, dev_class_info_t *cli)
     1458        return fun;
     1459}
     1460
     1461void class_add_devmap_function(class_list_t *class_list, dev_class_info_t *cli)
    11461462{
    11471463        unsigned long key = (unsigned long) cli->devmap_handle;
    11481464       
    11491465        fibril_rwlock_write_lock(&class_list->rwlock);
    1150         hash_table_insert(&class_list->devmap_devices, &key, &cli->devmap_link);
     1466        hash_table_insert(&class_list->devmap_functions, &key, &cli->devmap_link);
    11511467        fibril_rwlock_write_unlock(&class_list->rwlock);
    1152 }
    1153 
    1154 void tree_add_devmap_device(dev_tree_t *tree, node_t *node)
    1155 {
    1156         unsigned long key = (unsigned long) node->devmap_handle;
     1468
     1469        assert(find_devmap_class_function(class_list, cli->devmap_handle) != NULL);
     1470}
     1471
     1472void tree_add_devmap_function(dev_tree_t *tree, fun_node_t *fun)
     1473{
     1474        unsigned long key = (unsigned long) fun->devmap_handle;
    11571475        fibril_rwlock_write_lock(&tree->rwlock);
    1158         hash_table_insert(&tree->devmap_devices, &key, &node->devmap_link);
     1476        hash_table_insert(&tree->devmap_functions, &key, &fun->devmap_fun);
    11591477        fibril_rwlock_write_unlock(&tree->rwlock);
    11601478}
Note: See TracChangeset for help on using the changeset viewer.