HelenOS sources
This source file includes following definitions.
- handle_key_hash
- devman_devices_hash
- devman_functions_hash
- devman_devices_key_equal
- devman_functions_key_equal
- service_id_key_hash
- loc_functions_hash
- loc_functions_key_equal
- create_root_nodes
- init_device_tree
- insert_dev_node
- remove_dev_node
- insert_fun_node
- remove_fun_node
#include <errno.h>
#include <io/log.h>
#include "dev.h"
#include "devtree.h"
#include "devman.h"
#include "driver.h"
#include "fun.h"
static inline size_t handle_key_hash(const void *key)
{
const devman_handle_t *handle = key;
return *handle;
}
static size_t devman_devices_hash(const ht_link_t *item)
{
dev_node_t *dev = hash_table_get_inst(item, dev_node_t, devman_dev);
return handle_key_hash(&dev->handle);
}
static size_t devman_functions_hash(const ht_link_t *item)
{
fun_node_t *fun = hash_table_get_inst(item, fun_node_t, devman_fun);
return handle_key_hash(&fun->handle);
}
static bool devman_devices_key_equal(const void *key, const ht_link_t *item)
{
const devman_handle_t *handle = key;
dev_node_t *dev = hash_table_get_inst(item, dev_node_t, devman_dev);
return dev->handle == *handle;
}
static bool devman_functions_key_equal(const void *key, const ht_link_t *item)
{
const devman_handle_t *handle = key;
fun_node_t *fun = hash_table_get_inst(item, fun_node_t, devman_fun);
return fun->handle == *handle;
}
static inline size_t service_id_key_hash(const void *key)
{
const service_id_t *service_id = key;
return *service_id;
}
static size_t loc_functions_hash(const ht_link_t *item)
{
fun_node_t *fun = hash_table_get_inst(item, fun_node_t, loc_fun);
return service_id_key_hash(&fun->service_id);
}
static bool loc_functions_key_equal(const void *key, const ht_link_t *item)
{
const service_id_t *service_id = key;
fun_node_t *fun = hash_table_get_inst(item, fun_node_t, loc_fun);
return fun->service_id == *service_id;
}
static const hash_table_ops_t devman_devices_ops = {
.hash = devman_devices_hash,
.key_hash = handle_key_hash,
.key_equal = devman_devices_key_equal,
.equal = NULL,
.remove_callback = NULL
};
static const hash_table_ops_t devman_functions_ops = {
.hash = devman_functions_hash,
.key_hash = handle_key_hash,
.key_equal = devman_functions_key_equal,
.equal = NULL,
.remove_callback = NULL
};
static const hash_table_ops_t loc_devices_ops = {
.hash = loc_functions_hash,
.key_hash = service_id_key_hash,
.key_equal = loc_functions_key_equal,
.equal = NULL,
.remove_callback = NULL
};
bool create_root_nodes(dev_tree_t *tree)
{
fun_node_t *fun;
dev_node_t *dev;
log_msg(LOG_DEFAULT, LVL_DEBUG, "create_root_nodes()");
fibril_rwlock_write_lock(&tree->rwlock);
fun = create_fun_node();
if (fun == NULL) {
fibril_rwlock_write_unlock(&tree->rwlock);
return false;
}
if (!insert_fun_node(tree, fun, str_dup(""), NULL)) {
fun_del_ref(fun);
fibril_rwlock_write_unlock(&tree->rwlock);
return false;
}
match_id_t *id = create_match_id();
id->id = str_dup("root");
id->score = 100;
add_match_id(&fun->match_ids, id);
tree->root_node = fun;
dev = create_dev_node();
if (dev == NULL) {
fibril_rwlock_write_unlock(&tree->rwlock);
return false;
}
insert_dev_node(tree, dev, fun);
fibril_rwlock_write_unlock(&tree->rwlock);
return dev != NULL;
}
bool init_device_tree(dev_tree_t *tree, driver_list_t *drivers_list)
{
log_msg(LOG_DEFAULT, LVL_DEBUG, "init_device_tree()");
tree->current_handle = 0;
hash_table_create(&tree->devman_devices, 0, 0, &devman_devices_ops);
hash_table_create(&tree->devman_functions, 0, 0, &devman_functions_ops);
hash_table_create(&tree->loc_functions, 0, 0, &loc_devices_ops);
fibril_rwlock_initialize(&tree->rwlock);
if (!create_root_nodes(tree))
return false;
dev_node_t *rdev = tree->root_node->child;
dev_add_ref(rdev);
bool rc = assign_driver(rdev, drivers_list, tree);
dev_del_ref(rdev);
return rc;
}
bool insert_dev_node(dev_tree_t *tree, dev_node_t *dev, fun_node_t *pfun)
{
assert(fibril_rwlock_is_write_locked(&tree->rwlock));
log_msg(LOG_DEFAULT, LVL_DEBUG, "insert_dev_node(dev=%p, pfun=%p [\"%s\"])",
dev, pfun, pfun->pathname);
dev->handle = ++tree->current_handle;
hash_table_insert(&tree->devman_devices, &dev->devman_dev);
dev->pfun = pfun;
pfun->child = dev;
return true;
}
void remove_dev_node(dev_tree_t *tree, dev_node_t *dev)
{
assert(fibril_rwlock_is_write_locked(&tree->rwlock));
log_msg(LOG_DEFAULT, LVL_DEBUG, "remove_dev_node(dev=%p)", dev);
hash_table_remove(&tree->devman_devices, &dev->handle);
dev->pfun->child = NULL;
dev->pfun = NULL;
dev->state = DEVICE_REMOVED;
}
bool insert_fun_node(dev_tree_t *tree, fun_node_t *fun, char *fun_name,
dev_node_t *dev)
{
fun_node_t *pfun;
assert(fun_name != NULL);
assert(fibril_rwlock_is_write_locked(&tree->rwlock));
pfun = (dev != NULL) ? dev->pfun : NULL;
fun->name = fun_name;
if (!set_fun_path(tree, fun, pfun)) {
return false;
}
fun->handle = ++tree->current_handle;
hash_table_insert(&tree->devman_functions, &fun->devman_fun);
fun->dev = dev;
if (dev != NULL)
list_append(&fun->dev_functions, &dev->functions);
return true;
}
void remove_fun_node(dev_tree_t *tree, fun_node_t *fun)
{
assert(fibril_rwlock_is_write_locked(&tree->rwlock));
hash_table_remove(&tree->devman_functions, &fun->handle);
if (fun->dev != NULL)
list_remove(&fun->dev_functions);
fun->dev = NULL;
fun->state = FUN_REMOVED;
}
HelenOS homepage, sources at GitHub