diff --git a/headers/os/drivers/device_manager.h b/headers/os/drivers/device_manager.h index 539aa882e7..4df541a108 100644 --- a/headers/os/drivers/device_manager.h +++ b/headers/os/drivers/device_manager.h @@ -77,6 +77,7 @@ typedef struct device_manager_info { device_node_handle *node); status_t (*unregister_device)(device_node_handle node); + device_node_handle (*get_root)(); status_t (*get_next_child_device)(device_node_handle parent, device_node_handle *_node, const device_attr *attrs); device_node_handle (*get_parent)(device_node_handle node); @@ -165,6 +166,7 @@ struct driver_module_info { #define B_MISC_DRIVER_TYPE "misc" #define B_NETWORK_DRIVER_TYPE "net" #define B_VIDEO_DRIVER_TYPE "video" +#define B_INTERRUPT_CONTROLLER_DRIVER_TYPE "interrupt controller" #define PNP_DRIVER_CONNECTION "connection" // connection of parent the device is attached to (optional, string) diff --git a/src/system/kernel/device_manager/device_manager.c b/src/system/kernel/device_manager/device_manager.c index 4d0e4c67e2..c994a429d1 100644 --- a/src/system/kernel/device_manager/device_manager.c +++ b/src/system/kernel/device_manager/device_manager.c @@ -79,6 +79,7 @@ device_manager_info gDeviceManagerModule = { dm_register_node, dm_unregister_node, + dm_get_root, dm_get_next_child_node, dm_get_parent, dm_put_node, diff --git a/src/system/kernel/device_manager/device_manager_private.h b/src/system/kernel/device_manager/device_manager_private.h index 212c7244f3..6ddf8a6a18 100644 --- a/src/system/kernel/device_manager/device_manager_private.h +++ b/src/system/kernel/device_manager/device_manager_private.h @@ -173,6 +173,7 @@ status_t dm_init_nodes(void); void dm_put_node(device_node_info *node); status_t dm_get_next_child_node(device_node_info *parent, device_node_info **_node, const device_attr *attrs); +device_node_info *dm_get_root(void); device_node_info *dm_get_parent(device_node_info *node); diff --git a/src/system/kernel/device_manager/nodes.c b/src/system/kernel/device_manager/nodes.c index 5eb629e405..309fc7e7fd 100644 --- a/src/system/kernel/device_manager/nodes.c +++ b/src/system/kernel/device_manager/nodes.c @@ -328,7 +328,7 @@ dm_get_node(device_node_info *node) // remove node reference and clean it up if necessary -// (node_lock must be hold) +// (gNodeLock must be hold) void dm_put_node_nolock(device_node_info *node) @@ -453,6 +453,14 @@ dm_put_node(device_node_info *node) } +device_node_info * +dm_get_root(void) +{ + dm_get_node(gRootNode); + return gRootNode; +} + + device_node_info * dm_get_parent(device_node_info *node) { @@ -466,9 +474,8 @@ dm_get_next_child_node(device_node_info *parent, device_node_info **_node, const device_attr *attrs) { device_node_info *node = *_node; - if (node != NULL) - dm_put_node(node); - + device_node_info *nodeToPut = node; + benaphore_lock(&gNodeLock); while ((node = (device_node_info *)list_get_next_item(&parent->children, node)) != NULL) { @@ -490,10 +497,18 @@ dm_get_next_child_node(device_node_info *parent, device_node_info **_node, // we found a node dm_get_node_nolock(node); *_node = node; + + if (nodeToPut != NULL) + dm_put_node_nolock(nodeToPut); + benaphore_unlock(&gNodeLock); + return B_OK; } + if (nodeToPut != NULL) + dm_put_node_nolock(nodeToPut); + benaphore_unlock(&gNodeLock); return B_ENTRY_NOT_FOUND; }