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


Ignore:
Timestamp:
2011-06-01T08:43:42Z (15 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
8d6c1f1
Parents:
9e2e715 (diff), e51a514 (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:

Huuuuuge merge from development - all the work actually :)

File:
1 edited

Legend:

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

    r9e2e715 reb522e8  
    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>
    3940#include <str_error.h>
     41#include <stdio.h>
    4042
    4143#include "devman.h"
     44
     45fun_node_t *find_node_child(fun_node_t *parent, const char *name);
    4246
    4347/* hash table operations */
     
    5155    link_t *item)
    5256{
    53         node_t *dev = hash_table_get_instance(item, node_t, devman_link);
    54         return (dev->handle == (device_handle_t) key[0]);
    55 }
    56 
    57 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,
    5862    link_t *item)
    5963{
    60         node_t *dev = hash_table_get_instance(item, node_t, devmap_link);
    61         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]);
    6283}
    6384
     
    7293};
    7394
     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
    74101static hash_table_operations_t devmap_devices_ops = {
    75102        .hash = devices_hash,
    76         .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,
    77110        .remove_callback = devices_remove_callback
    78111};
     
    115148        fibril_mutex_unlock(&drivers_list->drivers_mutex);
    116149
    117         printf(NAME": the '%s' driver was added to the list of available "
    118             "drivers.\n", drv->name);
     150        log_msg(LVL_NOTE, "Driver `%s' was added to the list of available "
     151            "drivers.", drv->name);
    119152}
    120153
     
    206239bool read_match_ids(const char *conf_path, match_id_list_t *ids)
    207240{
    208         printf(NAME ": read_match_ids conf_path = %s.\n", conf_path);
     241        log_msg(LVL_DEBUG, "read_match_ids(conf_path=\"%s\")", conf_path);
    209242       
    210243        bool suc = false;
     
    216249        fd = open(conf_path, O_RDONLY);
    217250        if (fd < 0) {
    218                 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));
    219253                goto cleanup;
    220254        }
     
    224258        lseek(fd, 0, SEEK_SET);
    225259        if (len == 0) {
    226                 printf(NAME ": configuration file '%s' is empty.\n", conf_path);
     260                log_msg(LVL_ERROR, "Configuration file '%s' is empty.",
     261                    conf_path);
    227262                goto cleanup;
    228263        }
     
    230265        buf = malloc(len + 1);
    231266        if (buf == NULL) {
    232                 printf(NAME ": memory allocation failed when parsing file "
    233                     "'%s'.\n", conf_path);
     267                log_msg(LVL_ERROR, "Memory allocation failed when parsing file "
     268                    "'%s'.", conf_path);
    234269                goto cleanup;
    235270        }
    236271       
    237         if (read(fd, buf, len) <= 0) {
    238                 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);
    239275                goto cleanup;
    240276        }
    241         buf[len] = 0;
     277        buf[read_bytes] = 0;
    242278       
    243279        suc = parse_match_ids(buf, ids);
     
    274310bool get_driver_info(const char *base_path, const char *name, driver_t *drv)
    275311{
    276         printf(NAME ": get_driver_info base_path = %s, name = %s.\n",
     312        log_msg(LVL_DEBUG, "get_driver_info(base_path=\"%s\", name=\"%s\")",
    277313            base_path, name);
    278314       
     
    306342        struct stat s;
    307343        if (stat(drv->binary_path, &s) == ENOENT) { /* FIXME!! */
    308                 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);
    309346                goto cleanup;
    310347        }
     
    333370int lookup_available_drivers(driver_list_t *drivers_list, const char *dir_path)
    334371{
    335         printf(NAME ": lookup_available_drivers, dir = %s \n", dir_path);
     372        log_msg(LVL_DEBUG, "lookup_available_drivers(dir=\"%s\")", dir_path);
    336373       
    337374        int drv_cnt = 0;
     
    357394}
    358395
    359 /** Create root device node in the device tree.
     396/** Create root device and function node in the device tree.
    360397 *
    361398 * @param tree  The device tree.
    362399 * @return      True on success, false otherwise.
    363400 */
    364 bool create_root_node(dev_tree_t *tree)
    365 {
    366         node_t *node;
    367 
    368         printf(NAME ": create_root_node\n");
    369 
    370         node = create_dev_node();
    371         if (node != NULL) {
    372                 insert_dev_node(tree, node, clone_string(""), NULL);
    373                 match_id_t *id = create_match_id();
    374                 id->id = clone_string("root");
    375                 id->score = 100;
    376                 add_match_id(&node->match_ids, id);
    377                 tree->root_node = node;
    378         }
    379 
    380         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;
    381444}
    382445
     
    396459 *                      is found.
    397460 */
    398 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)
    399462{
    400463        driver_t *best_drv = NULL, *drv = NULL;
     
    424487 * @param drv           The driver.
    425488 */
    426 void attach_driver(node_t *node, driver_t *drv)
    427 {
    428         printf(NAME ": attach_driver %s to device %s\n",
    429             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);
    430493       
    431494        fibril_mutex_lock(&drv->driver_mutex);
    432495       
    433         node->drv = drv;
    434         list_append(&node->driver_devices, &drv->devices);
     496        dev->drv = drv;
     497        list_append(&dev->driver_devices, &drv->devices);
    435498       
    436499        fibril_mutex_unlock(&drv->driver_mutex);
     
    438501
    439502/** Start a driver
    440  *
    441  * The driver's mutex is assumed to be locked.
    442503 *
    443504 * @param drv           The driver's structure.
     
    449510        int rc;
    450511
    451         printf(NAME ": start_driver '%s'\n", drv->name);
     512        assert(fibril_mutex_is_locked(&drv->driver_mutex));
     513       
     514        log_msg(LVL_DEBUG, "start_driver(drv=\"%s\")", drv->name);
    452515       
    453516        rc = task_spawnl(NULL, drv->binary_path, drv->binary_path, NULL);
    454517        if (rc != EOK) {
    455                 printf(NAME ": error spawning %s (%s)\n",
    456                     drv->name, str_error(rc));
     518                log_msg(LVL_ERROR, "Spawning driver `%s' (%s) failed: %s.",
     519                    drv->name, drv->binary_path, str_error(rc));
    457520                return false;
    458521        }
     
    493556}
    494557
    495 /** Remember the driver's phone.
    496  *
    497  * @param driver        The driver.
    498  * @param phone         The phone to the driver.
    499  */
    500 void set_driver_phone(driver_t *driver, ipcarg_t phone)
    501 {
    502         fibril_mutex_lock(&driver->driver_mutex);
    503         assert(driver->state == DRIVER_STARTING);
    504         driver->phone = phone;
    505         fibril_mutex_unlock(&driver->driver_mutex);
    506 }
    507 
    508558/** Notify driver about the devices to which it was assigned.
    509559 *
    510  * The driver's mutex must be locked.
    511  *
    512560 * @param driver        The driver to which the devices are passed.
    513561 */
    514562static void pass_devices_to_driver(driver_t *driver, dev_tree_t *tree)
    515563{
    516         node_t *dev;
     564        dev_node_t *dev;
    517565        link_t *link;
    518566        int phone;
    519567
    520         printf(NAME ": pass_devices_to_driver\n");
    521 
    522         phone = ipc_connect_me_to(driver->phone, DRIVER_DEVMAN, 0, 0);
    523         if (phone > 0) {
    524                
     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                 */
    525622                link = driver->devices.next;
    526                 while (link != &driver->devices) {
    527                         dev = list_get_instance(link, node_t, driver_devices);
    528                         add_device(phone, driver, dev, tree);
    529                         link = link->next;
    530                 }
    531                
    532                 ipc_hangup(phone);
    533         }
     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);
    534640}
    535641
     
    545651void initialize_running_driver(driver_t *driver, dev_tree_t *tree)
    546652{
    547         printf(NAME ": initialize_running_driver\n");
    548         fibril_mutex_lock(&driver->driver_mutex);
     653        log_msg(LVL_DEBUG, "initialize_running_driver(driver=\"%s\")",
     654            driver->name);
    549655       
    550656        /*
     
    553659         */
    554660        pass_devices_to_driver(driver, tree);
    555        
    556         /* Change driver's state to running. */
    557         driver->state = DRIVER_RUNNING;
    558        
    559         fibril_mutex_unlock(&driver->driver_mutex);
    560661}
    561662
     
    572673        list_initialize(&drv->devices);
    573674        fibril_mutex_initialize(&drv->driver_mutex);
     675        drv->phone = -1;
    574676}
    575677
     
    602704}
    603705
    604 /** Create devmap path and name for the device. */
    605 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)
    606708{
    607709        char *devmap_pathname = NULL;
    608710        char *devmap_name = NULL;
    609711       
    610         asprintf(&devmap_name, "%s", node->pathname);
     712        asprintf(&devmap_name, "%s", fun->pathname);
    611713        if (devmap_name == NULL)
    612714                return;
     
    621723        }
    622724       
    623         devmap_device_register(devmap_pathname, &node->devmap_handle);
    624        
    625         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);
    626729       
    627730        free(devmap_name);
     
    629732}
    630733
    631 
    632734/** Pass a device to running driver.
    633735 *
     
    635737 * @param node          The device's node in the device tree.
    636738 */
    637 void add_device(int phone, driver_t *drv, node_t *node, dev_tree_t *tree)
    638 {
    639         printf(NAME ": add_device\n");
    640        
    641         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;
    642749        ipc_call_t answer;
    643750       
    644751        /* Send the device to the driver. */
    645         aid_t req = async_send_1(phone, DRIVER_ADD_DEVICE, node->handle,
    646             &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);
    647761       
    648762        /* Send the device's name to the driver. */
    649         rc = async_data_write_start(phone, node->name,
    650             str_size(node->name) + 1);
     763        rc = async_data_write_start(phone, dev->pfun->name,
     764            str_size(dev->pfun->name) + 1);
    651765        if (rc != EOK) {
    652766                /* TODO handle error */
    653767        }
    654        
     768
    655769        /* Wait for answer from the driver. */
    656770        async_wait_for(req, &rc);
     771
    657772        switch(rc) {
    658773        case EOK:
    659                 node->state = DEVICE_USABLE;
    660                 devmap_register_tree_device(node, tree);
     774                dev->state = DEVICE_USABLE;
    661775                break;
    662776        case ENOENT:
    663                 node->state = DEVICE_NOT_PRESENT;
     777                dev->state = DEVICE_NOT_PRESENT;
    664778                break;
    665779        default:
    666                 node->state = DEVICE_INVALID;
    667         }
    668        
     780                dev->state = DEVICE_INVALID;
     781        }
     782       
     783        dev->passed_to_driver = true;
     784
    669785        return;
    670786}
     
    677793 *                      successfully assigned to the device, false otherwise.
    678794 */
    679 bool assign_driver(node_t *node, driver_list_t *drivers_list, dev_tree_t *tree)
    680 {
     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       
    681802        /*
    682803         * Find the driver which is the most suitable for handling this device.
    683804         */
    684         driver_t *drv = find_best_match_driver(drivers_list, node);
     805        driver_t *drv = find_best_match_driver(drivers_list, dev);
    685806        if (drv == NULL) {
    686                 printf(NAME ": no driver found for device '%s'.\n",
    687                     node->pathname);
     807                log_msg(LVL_ERROR, "No driver found for device `%s'.",
     808                    dev->pfun->pathname);
    688809                return false;
    689810        }
    690811       
    691812        /* Attach the driver to the device. */
    692         attach_driver(node, drv);
    693        
     813        attach_driver(dev, drv);
     814       
     815        fibril_mutex_lock(&drv->driver_mutex);
    694816        if (drv->state == DRIVER_NOT_STARTED) {
    695817                /* Start the driver. */
    696818                start_driver(drv);
    697819        }
    698        
    699         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) {
    700824                /* Notify the driver about the new device. */
    701                 int phone = ipc_connect_me_to(drv->phone, DRIVER_DEVMAN, 0, 0);
    702                 if (phone > 0) {
    703                         add_device(phone, drv, node, tree);
    704                         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);
    705829                }
    706830        }
     
    719843bool init_device_tree(dev_tree_t *tree, driver_list_t *drivers_list)
    720844{
    721         printf(NAME ": init_device_tree.\n");
     845        log_msg(LVL_DEBUG, "init_device_tree()");
    722846       
    723847        tree->current_handle = 0;
     
    725849        hash_table_create(&tree->devman_devices, DEVICE_BUCKETS, 1,
    726850            &devman_devices_ops);
    727         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,
    728854            &devmap_devices_ops);
    729855       
    730856        fibril_rwlock_initialize(&tree->rwlock);
    731857       
    732         /* Create root node and add it to the device tree. */
    733         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))
    734860                return false;
    735861
    736862        /* Find suitable driver and start it. */
    737         return assign_driver(tree->root_node, drivers_list, tree);
     863        return assign_driver(tree->root_node->child, drivers_list, tree);
    738864}
    739865
     
    744870 * @return              A device node structure.
    745871 */
    746 node_t *create_dev_node(void)
    747 {
    748         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));
    749875       
    750876        if (res != NULL) {
    751                 memset(res, 0, sizeof(node_t));
    752                 list_initialize(&res->children);
    753                 list_initialize(&res->match_ids.ids);
    754                 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);
    755881        }
    756882       
     
    762888 * @param node          The device node structure.
    763889 */
    764 void delete_dev_node(node_t *node)
    765 {
    766         assert(list_empty(&node->children));
    767         assert(node->parent == NULL);
    768         assert(node->drv == NULL);
    769        
    770         clean_match_ids(&node->match_ids);
    771         free_not_null(node->name);
    772         free_not_null(node->pathname);
    773         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);
    774897}
    775898
    776899/** Find the device node structure of the device witch has the specified handle.
    777  *
    778  * Device tree's rwlock should be held at least for reading.
    779900 *
    780901 * @param tree          The device tree where we look for the device node.
     
    782903 * @return              The device node.
    783904 */
    784 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)
    785906{
    786907        unsigned long key = handle;
    787         link_t *link = hash_table_find(&tree->devman_devices, &key);
    788         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);
    789914}
    790915
     
    795920 * @return              The device node.
    796921 */
    797 node_t *find_dev_node(dev_tree_t *tree, device_handle_t handle)
    798 {
    799         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;
    800925       
    801926        fibril_rwlock_read_lock(&tree->rwlock);
    802         node = find_dev_node_no_lock(tree, handle);
     927        dev = find_dev_node_no_lock(tree, handle);
    803928        fibril_rwlock_read_unlock(&tree->rwlock);
    804929       
    805         return node;
    806 }
    807 
     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}
    8081006
    8091007/** Create and set device's full path in device tree.
     
    8141012 *                      resources etc.).
    8151013 */
    816 static bool set_dev_path(node_t *node, node_t *parent)
    817 {
    818         assert(node->name != NULL);
    819        
    820         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);
    8211019        if (parent != NULL)
    8221020                pathsize += str_size(parent->pathname) + 1;
    8231021       
    824         node->pathname = (char *) malloc(pathsize);
    825         if (node->pathname == NULL) {
    826                 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.");
    8271025                return false;
    8281026        }
    8291027       
    8301028        if (parent != NULL) {
    831                 str_cpy(node->pathname, pathsize, parent->pathname);
    832                 str_append(node->pathname, pathsize, "/");
    833                 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);
    8341032        } else {
    835                 str_cpy(node->pathname, pathsize, node->name);
     1033                str_cpy(fun->pathname, pathsize, fun->name);
    8361034        }
    8371035       
     
    8401038
    8411039/** Insert new device into device tree.
    842  *
    843  * The device tree's rwlock should be already held exclusively when calling this
    844  * function.
    8451040 *
    8461041 * @param tree          The device tree.
     
    8521047 *                      etc.).
    8531048 */
    854 bool insert_dev_node(dev_tree_t *tree, node_t *node, char *dev_name,
    855     node_t *parent)
    856 {
    857         assert(node != NULL);
     1049bool insert_dev_node(dev_tree_t *tree, dev_node_t *dev, fun_node_t *pfun)
     1050{
     1051        assert(dev != NULL);
    8581052        assert(tree != NULL);
    859         assert(dev_name != NULL);
    860        
    861         node->name = dev_name;
    862         if (!set_dev_path(node, parent)) {
    863                 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)) {
    8641098                return false;
    8651099        }
    8661100       
    8671101        /* Add the node to the handle-to-node map. */
    868         node->handle = ++tree->current_handle;
    869         unsigned long key = node->handle;
    870         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);
    8711105
    8721106        /* Add the node to the list of its parent's children. */
    873         node->parent = parent;
    874         if (parent != NULL)
    875                 list_append(&node->sibling, &parent->children);
     1107        fun->dev = dev;
     1108        if (dev != NULL)
     1109                list_append(&fun->dev_functions, &dev->functions);
    8761110       
    8771111        return true;
    8781112}
    8791113
    880 /** Find device node with a specified path in the device tree.
     1114/** Find function node with a specified path in the device tree.
    8811115 *
    882  * @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.
    8831117 * @param tree          The device tree.
    884  * @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
    8851119 *                      otherwise.
    8861120 */
    887 node_t *find_dev_node_by_path(dev_tree_t *tree, char *path)
    888 {
     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
    8891130        fibril_rwlock_read_lock(&tree->rwlock);
    8901131       
    891         node_t *dev = tree->root_node;
     1132        fun_node_t *fun = tree->root_node;
    8921133        /*
    893          * 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
    8941135         * beginning)
    8951136         */
    8961137        char *rel_path = path;
    8971138        char *next_path_elem = NULL;
    898         bool cont = (rel_path[0] == '/');
    899        
    900         while (cont && dev != NULL) {
     1139        bool cont = true;
     1140       
     1141        while (cont && fun != NULL) {
    9011142                next_path_elem  = get_path_elem_end(rel_path + 1);
    9021143                if (next_path_elem[0] == '/') {
     
    9071148                }
    9081149               
    909                 dev = find_node_child(dev, rel_path + 1);
     1150                fun = find_node_child(fun, rel_path + 1);
    9101151               
    9111152                if (cont) {
     
    9181159        fibril_rwlock_read_unlock(&tree->rwlock);
    9191160       
    920         return dev;
    921 }
    922 
    923 /** Find child device node with a specified name.
     1161        return fun;
     1162}
     1163
     1164/** Find function with a specified name belonging to given device.
    9241165 *
    9251166 * Device tree rwlock should be held at least for reading.
    9261167 *
    927  * @param parent        The parent device node.
    928  * @param name          The name of the child device node.
    929  * @return              The child device node.
    930  */
    931 node_t *find_node_child(node_t *parent, const char *name)
    932 {
    933         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;
    9341179        link_t *link;
    935        
    936         link = parent->children.next;
    937        
    938         while (link != &parent->children) {
    939                 dev = list_get_instance(link, node_t, sibling);
    940                
    941                 if (str_cmp(name, dev->name) == 0)
    942                         return dev;
    943                
    944                 link = link->next;
    945         }
    946        
     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
    9471190        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);
    9481234}
    9491235
     
    9771263       
    9781264        info = (dev_class_info_t *) malloc(sizeof(dev_class_info_t));
    979         if (info != NULL)
     1265        if (info != NULL) {
    9801266                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        }
    9811271       
    9821272        return info;
     
    10141304       
    10151305        size_t idx = get_new_class_dev_idx(cl);
    1016         asprintf(&dev_name, "%s%d", base_name, idx);
     1306        asprintf(&dev_name, "%s%zu", base_name, idx);
    10171307       
    10181308        return dev_name;
    10191309}
    10201310
    1021 /** Add the device to the class.
     1311/** Add the device function to the class.
    10221312 *
    10231313 * The device may be added to multiple classes and a class may contain multiple
     
    10321322 *                      with the class.
    10331323 */
    1034 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,
    10351325    const char *base_dev_name)
    10361326{
    1037         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
    10381334       
    10391335        if (info != NULL) {
    10401336                info->dev_class = cl;
    1041                 info->dev = dev;
     1337                info->fun = fun;
    10421338               
    10431339                /* Add the device to the class. */
     
    10471343               
    10481344                /* Add the class to the device. */
    1049                 list_append(&info->dev_classes, &dev->classes);
     1345                list_append(&info->dev_classes, &fun->classes);
    10501346               
    10511347                /* Create unique name for the device within the class. */
     
    10831379        while (link != &class_list->classes) {
    10841380                cl = list_get_instance(link, dev_class_t, link);
    1085                 if (str_cmp(cl->name, class_name) == 0)
     1381                if (str_cmp(cl->name, class_name) == 0) {
    10861382                        return cl;
     1383                }
     1384                link = link->next;
    10871385        }
    10881386       
     
    10931391{
    10941392        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;
    10951413}
    10961414
     
    10991417        list_initialize(&class_list->classes);
    11001418        fibril_rwlock_initialize(&class_list->rwlock);
    1101         hash_table_create(&class_list->devmap_devices, DEVICE_BUCKETS, 1,
    1102             &devmap_devices_ops);
     1419        hash_table_create(&class_list->devmap_functions, DEVICE_BUCKETS, 1,
     1420            &devmap_devices_class_ops);
    11031421}
    11041422
     
    11061424/* Devmap devices */
    11071425
    1108 node_t *find_devmap_tree_device(dev_tree_t *tree, dev_handle_t devmap_handle)
    1109 {
    1110         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;
    11111429        link_t *link;
    11121430        unsigned long key = (unsigned long) devmap_handle;
    11131431       
    11141432        fibril_rwlock_read_lock(&tree->rwlock);
    1115         link = hash_table_find(&tree->devmap_devices, &key);
     1433        link = hash_table_find(&tree->devmap_functions, &key);
    11161434        if (link != NULL)
    1117                 dev = hash_table_get_instance(link, node_t, devmap_link);
     1435                fun = hash_table_get_instance(link, fun_node_t, devmap_fun);
    11181436        fibril_rwlock_read_unlock(&tree->rwlock);
    11191437       
    1120         return dev;
    1121 }
    1122 
    1123 node_t *find_devmap_class_device(class_list_t *classes,
    1124     dev_handle_t devmap_handle)
    1125 {
    1126         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;
    11271445        dev_class_info_t *cli;
    11281446        link_t *link;
     
    11301448       
    11311449        fibril_rwlock_read_lock(&classes->rwlock);
    1132         link = hash_table_find(&classes->devmap_devices, &key);
     1450        link = hash_table_find(&classes->devmap_functions, &key);
    11331451        if (link != NULL) {
    11341452                cli = hash_table_get_instance(link, dev_class_info_t,
    11351453                    devmap_link);
    1136                 dev = cli->dev;
     1454                fun = cli->fun;
    11371455        }
    11381456        fibril_rwlock_read_unlock(&classes->rwlock);
    11391457       
    1140         return dev;
    1141 }
    1142 
    1143 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)
    11441462{
    11451463        unsigned long key = (unsigned long) cli->devmap_handle;
    11461464       
    11471465        fibril_rwlock_write_lock(&class_list->rwlock);
    1148         hash_table_insert(&class_list->devmap_devices, &key, &cli->devmap_link);
     1466        hash_table_insert(&class_list->devmap_functions, &key, &cli->devmap_link);
    11491467        fibril_rwlock_write_unlock(&class_list->rwlock);
    1150 }
    1151 
    1152 void tree_add_devmap_device(dev_tree_t *tree, node_t *node)
    1153 {
    1154         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;
    11551475        fibril_rwlock_write_lock(&tree->rwlock);
    1156         hash_table_insert(&tree->devmap_devices, &key, &node->devmap_link);
     1476        hash_table_insert(&tree->devmap_functions, &key, &fun->devmap_fun);
    11571477        fibril_rwlock_write_unlock(&tree->rwlock);
    11581478}
Note: See TracChangeset for help on using the changeset viewer.