From 34d976b4993bc76978d1fd4b10e0d002543aac83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 26 May 2008 18:07:04 +0000 Subject: [PATCH] Forgot to remove now unused files. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25664 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/device_manager/attributes.c | 532 -------------- .../kernel/device_manager/device_manager.c | 204 ------ src/system/kernel/device_manager/dl_list.h | 86 --- .../kernel/device_manager/driver_loader.c | 343 --------- src/system/kernel/device_manager/nodes.c | 679 ------------------ .../kernel/device_manager/notifications.c | 178 ----- src/system/kernel/device_manager/patterns.c | 243 ------- .../kernel/device_manager/registration.c | 382 ---------- src/system/kernel/device_manager/root_node.c | 96 --- src/system/kernel/device_manager/scan.c | 248 ------- 10 files changed, 2991 deletions(-) delete mode 100644 src/system/kernel/device_manager/attributes.c delete mode 100644 src/system/kernel/device_manager/device_manager.c delete mode 100644 src/system/kernel/device_manager/dl_list.h delete mode 100644 src/system/kernel/device_manager/driver_loader.c delete mode 100644 src/system/kernel/device_manager/nodes.c delete mode 100644 src/system/kernel/device_manager/notifications.c delete mode 100644 src/system/kernel/device_manager/patterns.c delete mode 100644 src/system/kernel/device_manager/registration.c delete mode 100644 src/system/kernel/device_manager/root_node.c delete mode 100644 src/system/kernel/device_manager/scan.c diff --git a/src/system/kernel/device_manager/attributes.c b/src/system/kernel/device_manager/attributes.c deleted file mode 100644 index c44e00a851..0000000000 --- a/src/system/kernel/device_manager/attributes.c +++ /dev/null @@ -1,532 +0,0 @@ -/* - * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. - * Copyright 2002-2004, Thomas Kurschel. All rights reserved. - * - * Distributed under the terms of the MIT License. - */ - -/* - Part of Device Manager - Node attributes handling. -*/ - - -#include "device_manager_private.h" -#include "dl_list.h" - -#include - -#include -#include - - -static bool is_fixed_attribute(const char *name); - - -status_t -pnp_get_attr_uint8(device_node_handle node, const char *name, - uint8 *value, bool recursive) -{ - status_t status; - - benaphore_lock(&gNodeLock); - status = pnp_get_attr_uint8_nolock(node, name, value, recursive); - benaphore_unlock(&gNodeLock); - - return status; -} - - -status_t -pnp_get_attr_uint8_nolock(device_node_handle node, const char *name, - uint8 *value, bool recursive) -{ - device_attr_info *attr = pnp_find_attr_nolock(node, name, recursive, B_UINT8_TYPE); - if (attr == NULL) - return B_NAME_NOT_FOUND; - - *value = attr->attr.value.ui8; - return B_OK; -} - - -status_t -pnp_get_attr_uint16(device_node_handle node, const char *name, - uint16 *value, bool recursive) -{ - status_t status; - - benaphore_lock(&gNodeLock); - status = pnp_get_attr_uint16_nolock(node, name, value, recursive); - benaphore_unlock(&gNodeLock); - - return status; -} - - -status_t -pnp_get_attr_uint16_nolock(device_node_handle node, const char *name, - uint16 *value, bool recursive) -{ - device_attr_info *attr = pnp_find_attr_nolock(node, name, recursive, B_UINT16_TYPE); - if (attr == NULL) - return B_NAME_NOT_FOUND; - - *value = attr->attr.value.ui16; - return B_OK; -} - - -status_t -pnp_get_attr_uint32(device_node_handle node, const char *name, - uint32 *value, bool recursive) -{ - status_t status; - - benaphore_lock(&gNodeLock); - status = pnp_get_attr_uint32_nolock(node, name, value, recursive); - benaphore_unlock(&gNodeLock); - - return status; -} - - -status_t -pnp_get_attr_uint32_nolock(device_node_handle node, const char *name, - uint32 *value, bool recursive) -{ - device_attr_info *attr = pnp_find_attr_nolock(node, name, recursive, B_UINT32_TYPE); - if (attr == NULL) - return B_NAME_NOT_FOUND; - - *value = attr->attr.value.ui32; - return B_OK; -} - - -status_t -pnp_get_attr_uint64(device_node_handle node, const char *name, - uint64 *value, bool recursive) -{ - status_t status; - - benaphore_lock(&gNodeLock); - status = pnp_get_attr_uint64_nolock(node, name, value, recursive); - benaphore_unlock(&gNodeLock); - - return status; -} - - -status_t -pnp_get_attr_uint64_nolock(device_node_handle node, const char *name, - uint64 *value, bool recursive) -{ - device_attr_info *attr = pnp_find_attr_nolock(node, name, recursive, B_UINT64_TYPE); - if (attr == NULL) - return B_NAME_NOT_FOUND; - - *value = attr->attr.value.ui64; - return B_OK; -} - - -status_t -pnp_get_attr_string(device_node_handle node, const char *name, - char **value, bool recursive) -{ - status_t status; - const char *orig_value; - - benaphore_lock(&gNodeLock); - - status = pnp_get_attr_string_nolock(node, name, &orig_value, recursive); - if (status == B_OK) { - *value = strdup(orig_value); - if (orig_value != NULL && *value == NULL) - status = B_NO_MEMORY; - } - - benaphore_unlock(&gNodeLock); - - return status; -} - - -status_t -pnp_get_attr_string_nolock(device_node_handle node, const char *name, - const char **value, bool recursive) -{ - device_attr_info *attr = pnp_find_attr_nolock(node, name, recursive, B_STRING_TYPE); - if (attr == NULL) - return B_NAME_NOT_FOUND; - - *value = attr->attr.value.string; - return B_OK; -} - - -status_t -pnp_get_attr_raw(device_node_handle node, const char *name, - void **data, size_t *length, bool recursive) -{ - const void *orig_data; - status_t status; - - benaphore_lock(&gNodeLock); - - status = pnp_get_attr_raw_nolock( node, name, &orig_data, length, recursive ); - - if (status == B_OK) { - void *tmp_data = malloc(*length); - if (tmp_data != NULL) { - memcpy(tmp_data, orig_data, *length); - *data = tmp_data; - } else - status = B_NO_MEMORY; - } - - benaphore_unlock(&gNodeLock); - - return status; -} - - -status_t -pnp_get_attr_raw_nolock(device_node_handle node, const char *name, - const void **data, size_t *length, bool recursive) -{ - device_attr_info *attr = pnp_find_attr_nolock(node, name, recursive, B_RAW_TYPE); - if (attr == NULL) - return B_NAME_NOT_FOUND; - - *data = attr->attr.value.raw.data; - *length = attr->attr.value.raw.length; - return B_OK; -} - - -/** Compare two attributes for */ - -int -pnp_compare_attrs(const device_attr *attrA, const device_attr *attrB) -{ - if (attrA->type != attrB->type) - return -1; - - switch (attrA->type) { - case B_UINT8_TYPE: - return (int)attrA->value.ui8 - (int)attrB->value.ui8; - - case B_UINT16_TYPE: - return (int)attrA->value.ui16 - (int)attrB->value.ui16; - - case B_UINT32_TYPE: - if (attrA->value.ui32 > attrB->value.ui32) - return 1; - if (attrA->value.ui32 < attrB->value.ui32) - return -1; - return 0; - - case B_UINT64_TYPE: - if (attrA->value.ui64 > attrB->value.ui64) - return 1; - if (attrA->value.ui64 < attrB->value.ui64) - return -1; - return 0; - - case B_STRING_TYPE: - return strcmp(attrA->value.string, attrB->value.string); - - case B_RAW_TYPE: - if (attrA->value.raw.length != attrB->value.raw.length) - return -1; - - return memcmp(attrA->value.raw.data, attrB->value.raw.data, attrA->value.raw.length); - } - - return -1; -} - - -// free node attribute - -void -pnp_free_node_attr(device_attr_info *attr) -{ - free((char *)attr->attr.name); - - switch (attr->attr.type) { - case B_STRING_TYPE: - free((char *)attr->attr.value.string); - break; - case B_RAW_TYPE: - free(attr->attr.value.raw.data); - break; - } - - free(attr); -} - - -// duplicate node attribute - -status_t -pnp_duplicate_node_attr(const device_attr *src, device_attr_info **dest_out) -{ - device_attr_info *dest; - status_t res; - - dest = malloc(sizeof(*dest)); - if (dest == NULL) - return B_NO_MEMORY; - - memset(dest, 0, sizeof(*dest)); - dest->ref_count = 1; - dest->attr.name = strdup(src->name); - dest->attr.type = src->type; - - switch (src->type) { - case B_UINT8_TYPE: - case B_UINT16_TYPE: - case B_UINT32_TYPE: - case B_UINT64_TYPE: - dest->attr.value.ui64 = src->value.ui64; - break; - - case B_STRING_TYPE: - dest->attr.value.string = strdup(src->value.string); - if (dest->attr.value.string == NULL) { - res = B_NO_MEMORY; - goto err; - } - break; - - case B_RAW_TYPE: - dest->attr.value.raw.data = malloc(src->value.raw.length); - if (dest->attr.value.raw.data == NULL) { - res = B_NO_MEMORY; - goto err; - } - - dest->attr.value.raw.length = src->value.raw.length; - memcpy(dest->attr.value.raw.data, src->value.raw.data, - src->value.raw.length); - break; - - default: - res = B_BAD_VALUE; - goto err; - } - - *dest_out = dest; - return B_OK; - -err: - free(dest); - return res; -} - - -// public: get first/next attribute of node - -status_t -pnp_get_next_attr(device_node_handle node, device_attr_handle *attr) -{ - device_attr_info *next; - - benaphore_lock(&gNodeLock); - - if (*attr != NULL) { - // next attribute - next = (*attr)->next; - // implicit release of previous attribute - if (--(*attr)->ref_count == 0) - pnp_free_node_attr(*attr); - } else { - // first attribute - next = node->attributes; - } - - if (next) - ++next->ref_count; - *attr = next; - - benaphore_unlock(&gNodeLock); - return next ? B_OK : B_ENTRY_NOT_FOUND; -} - - -// public: release attribute of node explicitely - -status_t -pnp_release_attr(device_node_handle node, device_attr_handle attr) -{ - benaphore_lock(&gNodeLock); - - if (--attr->ref_count == 0) - pnp_free_node_attr(attr); - - benaphore_unlock(&gNodeLock); - return B_OK; -} - - -// public: retrieve data of attribute - -status_t -pnp_retrieve_attr(device_attr_handle attr, const device_attr **attr_content) -{ - *attr_content = &attr->attr; - return B_OK; -} - - -// remove attribute from node, freeing it if not in use -// node_lock must be hold - -void -pnp_remove_attr_int(device_node_handle node, device_attr_info *attr) -{ - REMOVE_DL_LIST(attr, node->attributes, ); - - if (--attr->ref_count == 0) - pnp_free_node_attr(attr); -} - - -// public: remove attribute from node - -status_t -pnp_remove_attr(device_node_handle node, const char *name) -{ - device_attr_info *attr; - - // don't remove holy attributes - if (is_fixed_attribute(name)) - return B_NOT_ALLOWED; - - benaphore_lock(&gNodeLock); - - // find attribute in list - attr = pnp_find_attr_nolock(node, name, false, B_ANY_TYPE); - if (attr != NULL) { - // and remove it from it - pnp_remove_attr_int(node, attr); - } - - benaphore_unlock(&gNodeLock); - - return attr ? B_OK : B_ENTRY_NOT_FOUND; -} - - -// public: modify attribute's content - -status_t -pnp_write_attr(device_node_handle node, const device_attr *attr) -{ - device_attr_info *old_attr, *new_attr; - status_t res; - - // don't touch holy attributes - if (is_fixed_attribute(attr->name)) - return B_NOT_ALLOWED; - - res = pnp_duplicate_node_attr(attr, &new_attr); - if (res != B_OK) - return res; - - benaphore_lock(&gNodeLock); - - // check whether it's an add or modify - for (old_attr = node->attributes; old_attr != NULL; old_attr = old_attr->next) { - if (!strcmp(attr->name, old_attr->attr.name)) - break; - } - - if (old_attr != NULL) { - // it's a modify - // we first insert new attribute after old one... - // (so it appears at same position in attribute list) - new_attr->prev = old_attr; - new_attr->next = old_attr->next; - - if (old_attr->next == NULL) - old_attr->next->prev = new_attr; - - old_attr->next = new_attr; - - // ...and get rid of the old one - REMOVE_DL_LIST(old_attr, node->attributes, ); - - if (--old_attr->ref_count == 0) - pnp_free_node_attr(old_attr); - } else { - // it's an add - // append to end of list; - // this is really something to optimize - if (node->attributes == NULL) { - ADD_DL_LIST_HEAD(new_attr, node->attributes, ); - } else { - device_attr_info *last_attr; - - for (last_attr = node->attributes; last_attr->next != NULL; last_attr = last_attr->next) - ; - - last_attr->next = new_attr; - new_attr->prev = last_attr; - new_attr->next = NULL; - } - } - - benaphore_unlock(&gNodeLock); - return B_OK; -} - - -// check whether attribute cannot be modified; -// returns true, if that's forbidden - -static bool -is_fixed_attribute(const char *name) -{ - static const char *forbidden_list[] = { - B_DRIVER_MODULE, // never change driver - PNP_BUS_IS_BUS, // never switch between bus/not bus mode - }; - uint32 i; - - // some attributes are to important to get modified or removed directly - for (i = 0; i < sizeof(forbidden_list) / sizeof(forbidden_list[0]); ++i) { - if (!strcmp(name, forbidden_list[i])) - return true; - } - - return false; -} - - -// same as pnp_find_attr(), but node_lock must be hold and is never released - -device_attr_info * -pnp_find_attr_nolock(device_node_handle node, const char *name, - bool recursive, type_code type) -{ - do { - device_attr_info *attr; - - for (attr = node->attributes; attr != NULL; attr = attr->next) { - if (type != B_ANY_TYPE && attr->attr.type != type) - continue; - - if (!strcmp(attr->attr.name, name)) - return attr; - } - - node = node->parent; - } while (node != NULL && recursive); - - return NULL; -} - diff --git a/src/system/kernel/device_manager/device_manager.c b/src/system/kernel/device_manager/device_manager.c deleted file mode 100644 index 65e612c2bc..0000000000 --- a/src/system/kernel/device_manager/device_manager.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved. - * Copyright 2002-2004, Thomas Kurschel. All rights reserved. - * - * Distributed under the terms of the MIT License. - */ - -/* - Part of Device Manager - - Main file. -*/ - -#include "device_manager_private.h" -#include - -#include -#include - -#include -#include - - -//#define TRACE_DEVICE_MANAGER -#ifdef TRACE_DEVICE_MANAGER -# define TRACE(x) dprintf x -#else -# define TRACE(x) ; -#endif - - -device_node_info *gRootNode; - -bool disable_useraddons; - -int pnp_resource_wait_count; -sem_id pnp_resource_wait_sem; - -io_resource_info *io_mem_list, *io_port_list, *isa_dma_list; - - -static int -dump_device_nodes(int argc, char **argv) -{ - dm_dump_node(gRootNode, 0); - return 0; -} - - -static status_t -std_ops(int32 op, ...) -{ - switch (op) { - case B_MODULE_INIT: - case B_MODULE_UNINIT: - return B_OK; - - default: - return B_ERROR; - } -} - - -// ToDo: the device manager exports these for now, so that Thomas's driver -// can work on both R5 and Haiku without too much hassle. -// We might also want to keep it in order to have the possibility to make -// substantial changes without breaking compatibility, and eventually -// separate it from the kernel for whatever reason. - -device_manager_info gDeviceManagerModule = { - { - B_DEVICE_MANAGER_MODULE_NAME, - 0, - std_ops - }, - - pnp_load_driver, - pnp_unload_driver, - - dm_rescan, - - dm_register_node, - dm_unregister_node, - - dm_get_root, - dm_get_next_child_node, - dm_get_parent, - dm_put_node, - - dm_acquire_io_resources, - dm_release_io_resources, - - dm_create_id, - dm_free_id, - - pnp_get_attr_uint8, - pnp_get_attr_uint16, - pnp_get_attr_uint32, - pnp_get_attr_uint64, - pnp_get_attr_string, - pnp_get_attr_raw, - - pnp_get_next_attr, - pnp_release_attr, - pnp_retrieve_attr, - pnp_write_attr, - NULL // remove_attr -}; - - -// #pragma mark - - - -status_t -device_manager_init(struct kernel_args *args) -{ - status_t status; -// char name[B_FILE_NAME_LENGTH]; -// size_t size = sizeof(name); -// int32 cookie; - - TRACE(("device manager init\n")); - - status = dm_init_id_generator(); - if (status < B_OK) { - panic("could not initialize ID generator\n"); - return status; - } - - status = dm_init_nodes(); - if (status < B_OK) { - panic("could not initialize device nodes\n"); - return status; - } - - pnp_resource_wait_sem = create_sem(0, "pnp_resource_wait_sem"); - if (pnp_resource_wait_sem < 0) { - panic("could not create resource wait sem\n"); - return pnp_resource_wait_sem; - } - - pnp_resource_wait_count = 0; - io_mem_list = io_port_list = isa_dma_list = NULL; - pnp_fs_emulation_nesting = 0; - - dm_init_root_node(); - -#ifdef TRACE_DEVICE_MANAGER - { - // dump root node - device_node_info *node = gRootNode; - while (node && node->parent != NULL) - node = node->parent; - dm_dump_node(node, 0); - } -#endif - - // build initial device tree; register all root bus_managers - -#if 0 - cookie = 0; - while (get_next_loaded_module_name(&cookie, name, &size) == B_OK) { - if (strncmp(name, "bus_managers", 12)) - continue; - - dprintf(": %s\n", name); - size = sizeof(name); - } -#endif - - add_debugger_command("dm_tree", &dump_device_nodes, "dump device node tree"); - register_generic_syscall(DEVICE_MANAGER_SYSCALLS, device_manager_control, 1, 0); - return B_OK; -} - - -// hold gNodeLock -static void -device_manager_rescan_bus(device_node_info *parent) -{ - device_node_info *node = NULL; - char *dummy; - - if (pnp_get_attr_string(parent, B_DRIVER_BUS, &dummy, false) == B_OK) { - free(dummy); - dm_rescan(parent); - } - - while ((node = (device_node_info *)list_get_next_item(&parent->children, node)) != NULL) { - device_manager_rescan_bus(node); - } -} - - - -status_t -device_manager_init_post_modules(struct kernel_args *args) -{ - TRACE(("device_manager_init_post_modules()\n")); - device_manager_rescan_bus(gRootNode); - TRACE(("device_manager_init_post_modules() rescan done\n")); - return B_OK; -} - diff --git a/src/system/kernel/device_manager/dl_list.h b/src/system/kernel/device_manager/dl_list.h deleted file mode 100644 index 3df3c8bc93..0000000000 --- a/src/system/kernel/device_manager/dl_list.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - Copyright 2002/03, Thomas Kurschel. All rights reserved. - Distributed under the terms of the NewOS License. - - Macros for double linked lists -*/ - -#ifndef _DL_LIST_H -#define _DL_LIST_H - -#define REMOVE_DL_LIST( item, head, prefix ) \ - do { \ - if( item->prefix##prev ) \ - item->prefix##prev->prefix##next = item->prefix##next; \ - else \ - head = item->prefix##next; \ -\ - if( item->prefix##next ) \ - item->prefix##next->prefix##prev = item->prefix##prev; \ - } while( 0 ) - -#define ADD_DL_LIST_HEAD( item, head, prefix ) \ - do { \ - item->prefix##next = head; \ - item->prefix##prev = NULL; \ -\ - if( (head) ) \ - (head)->prefix##prev = item; \ -\ - (head) = item; \ - } while( 0 ) - -#define REMOVE_CDL_LIST( item, head, prefix ) \ - do { \ - item->prefix##next->prefix##prev = item->prefix##prev; \ - item->prefix##prev->prefix##next = item->prefix##next; \ - \ - if( item == (head) ) { \ - if( item->prefix##next != item ) \ - (head) = item->prefix##next; \ - else \ - (head) = NULL; \ - } \ - } while( 0 ) - -#define ADD_CDL_LIST_TAIL( item, type, head, prefix ) \ - do { \ - type *old_head = head; \ - \ - if( old_head ) { \ - type *first, *last; \ - \ - first = old_head; \ - last = first->prefix##prev; \ - \ - item->prefix##next = first; \ - item->prefix##prev = last; \ - first->prefix##prev = item; \ - last->prefix##next = item; \ - } else { \ - head = item; \ - item->prefix##next = item->prefix##prev = item; \ - } \ - } while( 0 ) - -#define ADD_CDL_LIST_HEAD( item, type, head, prefix ) \ - do { \ - type *old_head = head; \ - \ - head = item; \ - if( old_head ) { \ - type *first, *last; \ - \ - first = old_head; \ - last = first->prefix##prev; \ - \ - item->prefix##next = first; \ - item->prefix##prev = last; \ - first->prefix##prev = item; \ - last->prefix##next = item; \ - } else { \ - item->prefix##next = item->prefix##prev = item; \ - } \ - } while( 0 ) - -#endif diff --git a/src/system/kernel/device_manager/driver_loader.c b/src/system/kernel/device_manager/driver_loader.c deleted file mode 100644 index c5b29291fd..0000000000 --- a/src/system/kernel/device_manager/driver_loader.c +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. - * Copyright 2002-2004, Thomas Kurschel. All rights reserved. - * - * Distributed under the terms of the MIT License. - */ - -/* - Part of Device Manager - - device driver loader. -*/ - -#include "device_manager_private.h" - -#include - -#include -#include - - -//#define TRACE_DRIVER_LOADER -#ifdef TRACE_DRIVER_LOADER -# define TRACE(x) dprintf x -#else -# define TRACE(x) ; -#endif - - -/** unblock loading of driver - * node_lock must be hold - */ - -void -pnp_unblock_load(device_node_info *node) -{ - if (--node->load_block_count == 0 && node->num_blocked_loads > 0) { - TRACE(("Releasing blocked loads of %p\n", node)); - - release_sem_etc(node->load_block_sem, - node->num_blocked_loads, B_DO_NOT_RESCHEDULE); - - node->num_blocked_loads = 0; - } -} - - -/** if loading of driver is blocked, wait until it is unblocked - * node_lock must be hold - */ - -static void -pnp_wait_load_block(device_node_info *node) -{ - if (node->load_block_count > 0) { - TRACE(("Loading of %p is blocked - wait until unblock\n", node)); - - // make sure we get informed about unblock - ++node->num_blocked_loads; - - benaphore_unlock(&gNodeLock); - - acquire_sem(node->load_block_sem); - - benaphore_lock(&gNodeLock); - - TRACE(("Continuing loading of %p\n", node)); - } -} - - -/** load driver for real - * (loader_lock must be hold) - */ - -static status_t -load_driver_int(device_node_info *node, void *user_cookie) -{ - driver_module_info *driver; - char *moduleName; - void *cookie; - status_t status; - - TRACE(("load_driver_int()\n")); - - status = pnp_get_attr_string(node, B_DRIVER_MODULE, &moduleName, false); - if (status != B_OK) - return status; - - TRACE(("%s\n", moduleName)); - - status = get_module(moduleName, (module_info **)&driver); - if (status < B_OK) { - dprintf("Cannot load module %s\n", moduleName); - goto err1; - } - - if (driver->init_driver == NULL) { - dprintf("Driver %s has no init_driver hook\n", moduleName); - status = B_ERROR; - goto err2; - } - - status = driver->init_driver(node, user_cookie, &cookie); - if (status < B_OK) { - dprintf("init driver failed (node %p, %s): %s\n", node, moduleName, strerror(status)); - goto err2; - } - - node->driver = driver; - node->cookie = cookie; - - free(moduleName); - return B_OK; - -err2: - put_module(moduleName); -err1: - free(moduleName); - return status; -} - - -/** public: load driver */ - -status_t -pnp_load_driver(device_node_handle node, void *user_cookie, - driver_module_info **interface, void **cookie) -{ - status_t res; - - TRACE(("pnp_load_driver()\n")); - - if (node == NULL) - return B_BAD_VALUE; - - benaphore_lock(&gNodeLock); - - if (!node->registered) { - benaphore_unlock(&gNodeLock); - - TRACE(("Refused loading as driver got unregistered\n")); - return B_NAME_NOT_FOUND; - } - - // increase ref_count whenever someone loads the driver - // to keep node information alive - ++node->ref_count; - - if (node->load_count == 0) { - // driver is not loaded - // tell others that someone will load the driver - // (after this, noone is allowed to block loading) - ++node->loading; - - // wait until loading is not blocked - pnp_wait_load_block(node); - - // make sure noone else load/unloads/notifies the driver - pnp_start_hook_call_nolock(node); - - if (!node->registered) { - // device got lost meanwhile - TRACE(("Device got lost during wait\n")); - res = B_NAME_NOT_FOUND; - } else if (node->load_count == 0) { - // noone loaded the driver meanwhile, so - // we have to do that - benaphore_unlock(&gNodeLock); - - TRACE(("Driver will be loaded\n")); - - res = load_driver_int(node, user_cookie); - - benaphore_lock(&gNodeLock); - } else { - // some other thread loaded the driver meanwhile - TRACE(("Driver got loaded during wait\n")); - res = B_OK; - } - - // info: the next statements may have a strange order, - // but as we own node_lock, order is not important - - // finish loading officially - // (don't release node_lock before load_count gets increased!) - --node->loading; - - // unblock concurrent load/unload/notification - pnp_finish_hook_call_nolock(node); - - if (res == B_OK) { - // everything went fine - increase load counter - ++node->load_count; - } else { - // loading failed or device got removed - restore reference count; - // but first (i.e. as long as ref_count is increased) get - // rid of waiting children - dm_put_node_nolock(node); - } - } else { - // driver is already loaded, so increase load_count - ++node->load_count; - res = B_OK; - } - - benaphore_unlock(&gNodeLock); - - if (res == B_OK) { - if (interface) - *interface = node->driver; - - if (cookie) - *cookie = node->cookie; - - TRACE(("load_driver: Success \"%s\"\n", - ((struct module_info *)node->driver)->name)); - } else { - TRACE(("load_driver: Failure (%s)\n", strerror(res))); - } - - return res; -} - - -/** unload driver for real */ - -static status_t -unload_driver_int(device_node_info *node) -{ - driver_module_info *driver = node->driver; - char *moduleName; - status_t status; - - status = pnp_get_attr_string(node, B_DRIVER_MODULE, &moduleName, false); - if (status != B_OK) - return status; - - TRACE(("unload_driver_int: %s\n", moduleName)); - - if (driver->uninit_driver == NULL) { - // it has no uninit - we can't unload it, so it stays in memory forever - TRACE(("Driver %s has no uninit_device hook\n", moduleName)); - status = B_ERROR; - goto out; - } - - status = driver->uninit_driver(node->cookie); - if (status != B_OK) { - TRACE(("Failed to uninit driver %s (%s)\n", moduleName, strerror(status))); - goto out; - } - - // if it was unregistered a while ago but couldn't get cleaned up - // because it was in use, do the cleanup now - if (!node->registered) { - if (driver->device_cleanup != NULL) - driver->device_cleanup(node); - } - - put_module(moduleName); - -out: - free(moduleName); - return status; -} - - -/** public: unload driver */ - -status_t -pnp_unload_driver(device_node_handle node) -{ - status_t res; - - TRACE(("pnp_unload_driver: %p\n", node)); - - if (node == NULL) - return B_BAD_VALUE; - - benaphore_lock(&gNodeLock); - - if (node->loading > 0 || node->load_count == 1) { - // we may have to unload the driver because: - // - load_count will be zero after decrement, or - // - there is a concurrent load/unload call, so we - // don't know what the future load_count will be - - // signal active unload; - // don't decrease load_count - the driver is still loaded! - ++node->loading; - - // wait for concurrent load/unload/notification - pnp_start_hook_call_nolock(node); - - if (node->load_count == 1) { - // node is still to be unloaded - benaphore_unlock(&gNodeLock); - - TRACE(("unloading %p\n", node)); - res = unload_driver_int(node); - - benaphore_lock(&gNodeLock); - } else { - // concurrent load/unload either unloaded the driver or - // increased load_count so unload is not necessary or forbidden - TRACE(("don't unload as current load_count is %ld\n", - node->load_count)); - res = B_OK; - } - - // signal unload finished - --node->loading; - - if (res == B_OK) { - // everything is fine, so decrease load_count ... - --node->load_count; - // ... and reference count - dm_put_node_nolock(node); - } else { - // unloading failed: leave loaded in memory forever - // as load_count is not decreased, the driver will never - // be unloaded, and as reference count is not decreased, - // the node will exist forever - TRACE(("Unload failed - leaving driver of %p in memory\n", node)); - } - - // unblock others - pnp_finish_hook_call_nolock(node); - } else { - // no concurrent load/unload and load_count won't reach zero - --node->load_count; - // each load increased reference count by one - time to undo that - dm_put_node_nolock(node); - - res = B_OK; - } - - benaphore_unlock(&gNodeLock); - - return res; -} - diff --git a/src/system/kernel/device_manager/nodes.c b/src/system/kernel/device_manager/nodes.c deleted file mode 100644 index 2b613d220c..0000000000 --- a/src/system/kernel/device_manager/nodes.c +++ /dev/null @@ -1,679 +0,0 @@ -/* - * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. - * Copyright 2002-2004, Thomas Kurschel. All rights reserved. - * - * Distributed under the terms of the MIT License. - */ - -/* - Part of Device Manager - - device node handling. - - To make sure that nodes persist as long as somebody is using them, we - maintain a reference count (ref_count) which is increased - - when the node is officially registered - - if someone loads the corresponding driver - - for each child - - node_lock must be hold when updating of reference count, children - dependency list and during (un)-registration. -*/ - - -#include "device_manager_private.h" -#include "dl_list.h" - -#include - -#include -#include - -#include -#include - - -//#define TRACE_NODES -#ifdef TRACE_NODES -# define TRACE(x) dprintf x -#else -# define TRACE(x) ; -#endif - - -benaphore gNodeLock; - -uint32 sNodeID; // nodes counter - - -static void -put_level(int32 level) -{ - while (level-- > 0) - dprintf(" "); -} - - -static void -dump_attribute(device_attr_info *attr, int32 level) -{ - if (attr == NULL) - return; - - put_level(level + 2); - dprintf("\"%s\" : ", attr->attr.name); - switch (attr->attr.type) { - case B_STRING_TYPE: - dprintf("string : \"%s\"", attr->attr.value.string); - break; - case B_UINT8_TYPE: - dprintf("uint8 : %u (%#x)", attr->attr.value.ui8, attr->attr.value.ui8); - break; - case B_UINT16_TYPE: - dprintf("uint16 : %u (%#x)", attr->attr.value.ui16, attr->attr.value.ui16); - break; - case B_UINT32_TYPE: - dprintf("uint32 : %lu (%#lx)", attr->attr.value.ui32, attr->attr.value.ui32); - break; - case B_UINT64_TYPE: - dprintf("uint64 : %Lu (%#Lx)", attr->attr.value.ui64, attr->attr.value.ui64); - break; - default: - dprintf("raw data"); - } - dprintf("\n"); - - dump_attribute(attr->next, level); -} - - -/** free attributes of node - * if an attribute is still in use, it's deletion is postponed - */ - -static void -free_node_attrs(device_node_info *node) -{ - device_attr_info *attr, *next_attr; - - for (attr = node->attributes; attr != NULL; attr = next_attr) { - next_attr = attr->next; - - pnp_remove_attr_int(node, attr); - } - - node->attributes = NULL; -} - - -// free node's I/O resource list, setting it to NULL -// (resources must have been released already) - -static void -free_node_resources(device_node_info *node) -{ - free(node->io_resources); - node->io_resources = NULL; -} - - -// free node -// (node lock must be hold) - -static void -free_node(device_node_info *node) -{ - const char *generator_name, *driver_name; - uint32 auto_id; - - // ToDo: we lose memory here if the attributes are available! - if (pnp_get_attr_string_nolock(node, B_DRIVER_MODULE, &driver_name, false) != B_OK) - driver_name = "?"; - - TRACE(("free_node(node: %p, driver: %s)\n", node, driver_name)); - - // free associated auto ID, if requested - if (pnp_get_attr_string_nolock(node, PNP_MANAGER_ID_GENERATOR, - &generator_name, false) == B_OK) { - if (pnp_get_attr_uint32(node, PNP_MANAGER_AUTO_ID, &auto_id, false) != B_OK) { - TRACE(("Cannot find corresponding auto_id of generator %s", generator_name)); - } else - dm_free_id(generator_name, auto_id); - } - - dm_release_node_resources(node); - - delete_sem(node->hook_sem); - delete_sem(node->load_block_sem); - - free_node_attrs(node); - free_node_resources(node); - free(node); -} - - -// copy node attributes into node's attribute list - -static status_t -copy_node_attrs(device_node_info *node, const device_attr *src) -{ - status_t res; - const device_attr *src_attr; - device_attr_info *last_attr = NULL; - - node->attributes = NULL; - - // take care to keep attributes in same order; - // this is (currently) not necessary but a naive implementation would - // reverse order, which looks a bit odd (at least for the driver writer) - for (src_attr = src; src_attr->name != NULL; ++src_attr) { - device_attr_info *new_attr; - - res = pnp_duplicate_node_attr( src_attr, &new_attr ); - if (res != B_OK) - goto err; - - //list_add_link_to_head(&node->attributes, new_attr); - ADD_DL_LIST_HEAD( new_attr, node->attributes, ); - - last_attr = new_attr; - } - - return B_OK; - -err: - free_node_attrs(node); - return res; -} - - -// allocate array of node I/O resources; -// all resource handles are set to zero, so if something goes wrong -// later on, resources aren't transferred to node - -static status_t -allocate_node_resource_array(device_node_info *node, const io_resource_handle *resources) -{ - const io_resource_handle *resource; - int num_resources = 0; - - if (resources != NULL) { - for (resource = resources; *resource != NULL; ++resource) - ++num_resources; - } - - node->num_io_resources = num_resources; - - node->io_resources = malloc((num_resources + 1) * sizeof(io_resource_handle)); - if (node->io_resources == NULL) - return B_NO_MEMORY; - - memset(node->io_resources, 0, (num_resources + 1) * sizeof(io_resource_handle)); - return B_OK; -} - - -// #pragma mark - -// Device Manager private functions - - -/** allocate device node info structure; - * initially, ref_count is one to make sure node won't get destroyed by mistake - */ - -status_t -dm_allocate_node(const device_attr *attrs, const io_resource_handle *resources, - device_node_info **_node) -{ - device_node_info *node; - status_t res; - - node = calloc(1, sizeof(*node)); - if (node == NULL) - return B_NO_MEMORY; - - res = copy_node_attrs(node, attrs); - if (res < 0) - goto err; - - res = allocate_node_resource_array(node, resources); - if (res < 0) - goto err2; - - res = node->hook_sem = create_sem(0, "pnp_hook"); - if (res < 0) - goto err3; - - res = node->load_block_sem = create_sem(0, "pnp_load_block"); - if (res < 0) - goto err4; - - list_init(&node->children); - - node->parent = NULL; - node->rescan_depth = 0; - node->registered = false; -#if 0 - node->verifying = false; - node->redetected = false; - node->init_finished = false; -#endif - node->ref_count = 1; - node->load_count = 0; - node->blocked_by_rescan = false; - node->automatically_loaded = false; - - node->num_waiting_hooks = 0; - node->num_blocked_loads = 0; - node->load_block_count = 0; - node->loading = 0; - node->internal_id = sNodeID++; - - TRACE(("dm_allocate_node(): new node %p\n", node)); - - *_node = node; - - return B_OK; - -err4: - delete_sem(node->hook_sem); -err3: - free_node_resources(node); -err2: - free_node_attrs(node); -err: - free(node); - return res; -} - - -void -dm_add_child_node(device_node_info *parent, device_node_info *node) -{ - TRACE(("dm_add_child_node(parent = %p, child = %p)\n", parent, node)); - - if (parent == NULL) - return; - - benaphore_lock(&gNodeLock); - - // parent must not be destroyed as long as it has children - parent->ref_count++; - node->parent = parent; - - // tell parent about us, so we get unregistered automatically if parent - // gets unregistered - list_add_item(&parent->children, node); - - benaphore_unlock(&gNodeLock); -} - - -void -dm_get_node_nolock(device_node_info *node) -{ - node->ref_count++; -} - - -// increase ref_count of node - -void -dm_get_node(device_node_info *node) -{ - TRACE(("dm_get_device_node(%p)\n", node)); - - if (node == NULL) - return; - - benaphore_lock(&gNodeLock); - node->ref_count++; - benaphore_unlock(&gNodeLock); -} - - -// remove node reference and clean it up if necessary -// (gNodeLock must be hold) - -void -dm_put_node_nolock(device_node_info *node) -{ - do { - device_node_info *parent; - - TRACE(("pnp_remove_node_ref_internal(ref_count of %p: %ld)\n", node, node->ref_count - 1)); - - // unregistered devices lose their I/O resources as soon as they - // are unloaded - if (!node->registered && node->loading == 0 && node->load_count == 0) - dm_release_node_resources(node); - - if (--node->ref_count > 0) - return; - - TRACE(("cleaning up %p (parent: %p)\n", node, node->parent)); - - // time to clean up - parent = node->parent; - - if (parent != NULL) - list_remove_item(&parent->children, node); - - free_node(node); - - // unrolled recursive call: decrease ref_count of parent as well - node = parent; - } while (node != NULL); -} - - -#if 0 -// public: find node with some node attributes given - -device_node_info * -dm_find_device(device_node_info *parent, const device_attr *attrs) -{ - device_node_info *node, *found_node; - - found_node = NULL; - - benaphore_lock(&gNodeLock); - - for (node = gNodeList; node; node = node->next) { - const device_attr *attr; - - // list contains removed devices too, so skip them - if (!node->registered) - continue; - - if (parent != (device_node_info *)-1 && parent != node->parent) - continue; - - for (attr = attrs; attr && attr->name; ++attr) { - device_attr_info *other = pnp_find_attr_nolock(node, attr->name, false, attr->type); - if (other == NULL || pnp_compare_attrs(attr, &other->attr)) - break; - } - - if (attr != NULL && attr->name != NULL) - continue; - - // we found a node - if (found_node != NULL) - // but it wasn't the only one - return NULL; - - // even though we found a node, keep on search to make sure no other - // node is matched too - found_node = node; - } - -err: - benaphore_unlock(&gNodeLock); - - return found_node; -} -#endif - - -void -dm_dump_node(device_node_info *node, int32 level) -{ - device_node_info *child = NULL; - - if (node == NULL) - return; - - put_level(level); - dprintf("(%ld) @%p \"%s\"\n", level, node, node->driver ? node->driver->info.name : "---"); - dump_attribute(node->attributes, level); - - while ((child = (device_node_info *)list_get_next_item(&node->children, child)) != NULL) { - dm_dump_node(child, level + 1); - } -} - - -status_t -dm_init_nodes(void) -{ - sNodeID = 1; - return benaphore_init(&gNodeLock, "device nodes"); -} - - -// #pragma mark - -// Functions part of the module API - - -/** remove node reference and clean it up if necessary */ - -void -dm_put_node(device_node_info *node) -{ - TRACE(("dm_put_node(%p)\n", node)); - - benaphore_lock(&gNodeLock); - dm_put_node_nolock(node); - benaphore_unlock(&gNodeLock); -} - - -device_node_info * -dm_get_root(void) -{ - dm_get_node(gRootNode); - return gRootNode; -} - - -device_node_info * -dm_get_parent(device_node_info *node) -{ - dm_get_node(node->parent); - return node->parent; -} - - -status_t -dm_get_next_child_node(device_node_info *parent, device_node_info **_node, - const device_attr *attrs) -{ - device_node_info *node = *_node; - device_node_info *nodeToPut = node; - - benaphore_lock(&gNodeLock); - - while ((node = (device_node_info *)list_get_next_item(&parent->children, node)) != NULL) { - const device_attr *attr; - - // list contains removed devices too, so skip them - if (!node->registered) - continue; - - for (attr = attrs; attr && attr->name; ++attr) { - device_attr_info *other = pnp_find_attr_nolock(node, attr->name, false, attr->type); - if (other == NULL || pnp_compare_attrs(attr, &other->attr)) - break; - } - - if (attr != NULL && attr->name != NULL) - continue; - - // 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; -} - - -// hold gNodeLock -static device_node_info * -device_manager_find_device(device_node_info *parent, uint32 id) -{ - device_node_info *node = NULL; - - if (parent->internal_id == id) - return parent; - - while ((node = (device_node_info *)list_get_next_item(&parent->children, node)) != NULL) { - device_node_info *child = device_manager_find_device(node, id); - if (child != NULL) - return child; - } - return NULL; -} - - -status_t -device_manager_control(const char *subsystem, uint32 function, void *buffer, size_t bufferSize) -{ - switch (function) { - case DM_GET_ROOT: { - uint32 cookie; - if (!IS_USER_ADDRESS(buffer)) - return B_BAD_ADDRESS; - if (bufferSize < sizeof(uint32)) - return B_BAD_VALUE; - cookie = gRootNode->internal_id; - - // copy back to user space - if (user_memcpy(buffer, &cookie, sizeof(uint32)) < B_OK) - return B_BAD_ADDRESS; - return B_OK; - } - case DM_GET_CHILD: { - uint32 cookie; - device_node_info *node; - device_node_info *child; - - if (!IS_USER_ADDRESS(buffer)) - return B_BAD_ADDRESS; - if (bufferSize < sizeof(uint32)) - return B_BAD_VALUE; - if (user_memcpy(&cookie, buffer, sizeof(uint32)) < B_OK) - return B_BAD_ADDRESS; - - benaphore_lock(&gNodeLock); - node = device_manager_find_device(gRootNode, cookie); - if (!node) { - benaphore_unlock(&gNodeLock); - return B_BAD_VALUE; - } - - child = (device_node_info *)list_get_next_item(&node->children, NULL); - if (child) - cookie = child->internal_id; - benaphore_unlock(&gNodeLock); - - if (!child) - return B_ENTRY_NOT_FOUND; - - // copy back to user space - if (user_memcpy(buffer, &cookie, sizeof(uint32)) < B_OK) - return B_BAD_ADDRESS; - return B_OK; - } - case DM_GET_NEXT_CHILD: { - uint32 cookie; - device_node_info *node; - device_node_info *child; - - if (!IS_USER_ADDRESS(buffer)) - return B_BAD_ADDRESS; - if (bufferSize < sizeof(uint32)) - return B_BAD_VALUE; - if (user_memcpy(&cookie, buffer, sizeof(uint32)) < B_OK) - return B_BAD_ADDRESS; - - benaphore_lock(&gNodeLock); - node = device_manager_find_device(gRootNode, cookie); - if (!node) { - benaphore_unlock(&gNodeLock); - return B_BAD_VALUE; - } - child = (device_node_info *)list_get_next_item(&node->parent->children, node); - if (child) - cookie = child->internal_id; - benaphore_unlock(&gNodeLock); - - if (!child) - return B_ENTRY_NOT_FOUND; - // copy back to user space - if (user_memcpy(buffer, &cookie, sizeof(uint32)) < B_OK) - return B_BAD_ADDRESS; - return B_OK; - } - case DM_GET_NEXT_ATTRIBUTE: { - struct dev_attr attr; - device_node_info *node; - uint32 i = 0; - device_attr_info *attr_info; - if (!IS_USER_ADDRESS(buffer)) - return B_BAD_ADDRESS; - if (bufferSize < sizeof(struct dev_attr)) - return B_BAD_VALUE; - if (user_memcpy(&attr, buffer, sizeof(struct dev_attr)) < B_OK) - return B_BAD_ADDRESS; - - benaphore_lock(&gNodeLock); - node = device_manager_find_device(gRootNode, attr.node_cookie); - if (!node) { - benaphore_unlock(&gNodeLock); - return B_BAD_VALUE; - } - for (attr_info = node->attributes; attr.cookie > i && attr_info != NULL; attr_info = attr_info->next) { - i++; - } - - if (!attr_info) { - benaphore_unlock(&gNodeLock); - return B_ENTRY_NOT_FOUND; - } - - attr.cookie++; - - strlcpy(attr.name, attr_info->attr.name, 254); - attr.type = attr_info->attr.type; - switch (attr_info->attr.type) { - case B_UINT8_TYPE: - attr.value.ui8 = attr_info->attr.value.ui8; break; - case B_UINT16_TYPE: - attr.value.ui16 = attr_info->attr.value.ui16; break; - case B_UINT32_TYPE: - attr.value.ui32 = attr_info->attr.value.ui32; break; - case B_UINT64_TYPE: - attr.value.ui64 = attr_info->attr.value.ui64; break; - case B_STRING_TYPE: - strlcpy(attr.value.string, attr_info->attr.value.string, 254); break; - /*case B_RAW_TYPE: - if (attr.value.raw.length > attr_info->attr.value.raw.length) - attr.value.raw.length = attr_info->attr.value.raw.length; - user_memcpy(attr.value.raw.data, attr_info->attr.value.raw.data, - attr.value.raw.length); - break;*/ - } - - benaphore_unlock(&gNodeLock); - - // copy back to user space - if (user_memcpy(buffer, &attr, sizeof(struct dev_attr)) < B_OK) - return B_BAD_ADDRESS; - return B_OK; - } - }; - return B_BAD_HANDLER; -} diff --git a/src/system/kernel/device_manager/notifications.c b/src/system/kernel/device_manager/notifications.c deleted file mode 100644 index 4c7e868525..0000000000 --- a/src/system/kernel/device_manager/notifications.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. - * Copyright 2002-2004, Thomas Kurschel. All rights reserved. - * - * Distributed under the terms of the MIT License. - */ - -/* - Part of Device Manager - - Execution and synchronization of driver hook calls. -*/ - - -#include "device_manager_private.h" - -#include - -#include -#include - - -#define TRACE_NOTIFICATIONS -#ifdef TRACE_NOTIFICATIONS -# define TRACE(x) dprintf x -#else -# define TRACE(x) ; -#endif - - -/** notify driver that it's device got removed */ - -status_t -dm_notify_unregistration(device_node_info *node) -{ - driver_module_info *driver; - bool loaded; - char *module_name; - void *cookie; - status_t res; - - res = pnp_get_attr_string(node, B_DRIVER_MODULE, &module_name, false); - if (res != B_OK) - return res; - - TRACE(("notify_device_removed(node: %p, consumer: %s)\n", node, module_name)); - - // block concurrent load/unload calls - pnp_start_hook_call(node); - -#if 0 - // don't notify driver if it doesn't know that the device was - // published - if (!node->init_finished) - goto skip; -#endif - - // don't take node->loading into account - we want to know - // whether driver is loaded, not whether it is about to get loaded - loaded = node->load_count > 0; - - if (loaded) { - TRACE(("Already loaded\n")); - driver = node->driver; - cookie = node->cookie; - } else { - TRACE(("Not loaded yet\n")); - - // driver is not loaded - load it temporarily without - // calling init_device and pass =NULL to tell - // the driver about - res = get_module(module_name, (module_info **)&driver); - if (res < B_OK) - goto err; - - cookie = NULL; - } - - // this hook is optional, so ignore it silently if NULL - if (driver->device_removed != NULL) - driver->device_removed(node, cookie); - else - dprintf("Driver %s has no device_removed hook\n", module_name); - - // if driver wasn't loaded, call its cleanup method - if (!loaded) { - // again: this hook is optional - if (driver->device_cleanup != NULL) - driver->device_cleanup(node); - } - - if (!loaded) - put_module(module_name); - -skip: - pnp_finish_hook_call(node); - free(module_name); - return B_OK; - -err: - free(module_name); - return res; -} - - -/** start driver hook call; must be called before a - * load/unload/notification hook is called - */ - -void -pnp_start_hook_call(device_node_info *node) -{ - bool blocked; - - benaphore_lock(&gNodeLock); - - blocked = ++node->num_waiting_hooks > 1; - - benaphore_unlock(&gNodeLock); - - if (blocked) { - TRACE(("Hook call of %p is blocked\n", node)); - - acquire_sem(node->hook_sem); - } -} - - -/** start driver hook call; same pnp_start_hook_call(), but - * node_lock must be hold - */ - -void -pnp_start_hook_call_nolock(device_node_info *node) -{ - if (++node->num_waiting_hooks > 1) { - benaphore_unlock(&gNodeLock); - - TRACE(("Hook call of %p is blocked\n", node)); - acquire_sem(node->hook_sem); - - benaphore_lock(&gNodeLock); - } -} - - -/** finish driver hook call; must be called after a load/unload/notification - * hook is called - */ - -void -pnp_finish_hook_call(device_node_info *node) -{ - benaphore_lock(&gNodeLock); - - if (--node->num_waiting_hooks > 1) { - TRACE(("Releasing other hook calls of %p\n", node)); - - release_sem(node->hook_sem); - } - - benaphore_unlock(&gNodeLock); -} - - -/** finish driver hook call; same pnp_finish_hook_call(), but - * node_lock must be hold - */ - -void -pnp_finish_hook_call_nolock(device_node_info *node) -{ - if (--node->num_waiting_hooks > 1) { - TRACE(("Releasing other hook calls of %p\n", node)); - - release_sem(node->hook_sem); - } -} diff --git a/src/system/kernel/device_manager/patterns.c b/src/system/kernel/device_manager/patterns.c deleted file mode 100644 index a31436d797..0000000000 --- a/src/system/kernel/device_manager/patterns.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. - * Copyright 2002-2004, Thomas Kurschel. All rights reserved. - * - * Distributed under the terms of the MIT License. - */ - -/* - Part of Device Manager - - Expansion of patterns. - Used to expand consumer/connector/device names etc. -*/ - - -#include "device_manager_private.h" - -#include -#include - -#include -#include -#include - - -//#define TRACE_PATTERNS -#ifdef TRACE_PATTERNS -# define TRACE(x) dprintf x -#else -# define TRACE(x) ; -#endif - - -/** expand node attribute - * node - node to get attributes from - * *pattern - name of attribute, ending with "%" (takes care of "^" sequences) - * on return, *patterns points to trailing "%" - * buffer - buffer for name - * dst - string to write content to - * node_lock must be hold - */ - -static status_t -expand_attr(device_node_info *node, const char **pattern, char *buffer, char *dst) -{ - device_attr_info *attr; - const char *str; - int buffer_len; - - // extract attribute name - buffer_len = 0; - - for (str = *pattern; *str; ++str) { - if (*str == '^' && *(str + 1) != 0) - // copy escaped character directly - ++str; - else if (*str == '%') - break; - - buffer[buffer_len++] = *str; - } - - *pattern = str; - - buffer[buffer_len] = '\0'; - - // get attribute content and add it to path - attr = pnp_find_attr_nolock(node, buffer, true, B_ANY_TYPE); - if (attr == NULL) { - dprintf("Reference to unknown attribute %s\n", buffer); - return B_NAME_NOT_FOUND; - } - - switch (attr->attr.type) { - case B_UINT8_TYPE: - sprintf(buffer, "%02x", attr->attr.value.ui8); - strlcat(dst, buffer, PATH_MAX); - break; - case B_UINT16_TYPE: - sprintf(buffer, "%04x", attr->attr.value.ui16); - strlcat(dst, buffer, PATH_MAX); - break; - case B_UINT32_TYPE: - sprintf(buffer, "%08lx", attr->attr.value.ui32); - strlcat(dst, buffer, PATH_MAX); - break; - case B_UINT64_TYPE: - sprintf(buffer, "%16Lx", attr->attr.value.ui64); - strlcat(dst, buffer, PATH_MAX); - break; - case B_STRING_TYPE: { - const char *str; - - //strlcat(dst, "\"", PATH_MAX); - - for (str = attr->attr.value.string; *str; ++str) { - char ch; - - ch = *str; - if (ch >= 32 && ch <= 126 && ch != '/' && ch != '%' && ch != '"') { - buffer[0] = ch; - buffer[1] = 0; - } else { - // convert unprintable/forbidden characters to numbers - sprintf(buffer, "%%%u%%", (unsigned char)ch); - } - - strlcat(dst, buffer, PATH_MAX); - } - - //strlcat(dst, "\"", PATH_MAX); - break; - } - case B_RAW_TYPE: - default: - benaphore_unlock(&gNodeLock); - return B_BAD_VALUE; - } - - benaphore_unlock(&gNodeLock); - return B_OK; -} - - -/** expand pattern. - * the pattern is both expanded and the position of inidiual parts returned - * pattern - pattern to expand - * dest - expanded name is appended to this string - * buffer - buffer of MAX_PATH+1 size supplied by caller - * term_array - list of lengths of individual sub-names - * with index 0 containing the length of the shortest and - * num_parts-1 - length of the longest sub-name - * and can be NULL - * node_lock must be hold - */ - -status_t -pnp_expand_pattern(device_node_info *node, const char *pattern, char *dest, - char *buffer, size_t *term_array, int *num_parts) -{ - const char *str; - int id; - status_t res; - int buffer_len = 0; - - TRACE(("expand_pattern(pattern: %s)\n", pattern)); - - for (str = pattern, id = 0; *str; ++str) { - switch (*str) { - case '^': - // character following "^" is copied directly - // exception: if there is a trailing "^" at end of string, - // we copy it directly - if (*(str + 1) != 0) - ++str; - - buffer[buffer_len++] = *str; - break; - - case '|': - // end of one name part - buffer[buffer_len] = '\0'; - buffer_len = 0; - strlcat(dest, buffer, PATH_MAX); - - TRACE(("%d: %s\n", id, dest)); - - if (term_array != NULL) - term_array[id++] = strlen(dest); - break; - - case '%': - // begin of place-holder - buffer[buffer_len] = '\0'; - buffer_len = 0; - strlcat(dest, buffer, PATH_MAX); - - // skip "%" - ++str; - - res = expand_attr(node, &str, buffer, dest); - if (res != B_OK) - return res; - break; - - default: - // normal character - buffer[buffer_len++] = *str; - } - - // avoid overflow of buffer - if (buffer_len > PATH_MAX) - buffer_len = PATH_MAX; - } - - // append trailing characters - buffer[buffer_len] = 0; - buffer_len = 0; - strlcat(dest, buffer, PATH_MAX); - - if (term_array != NULL) - term_array[id++] = strlen(dest); - - if (num_parts != NULL) - *num_parts = id; - - TRACE(("result: %s\n", dest)); - - return B_OK; -} - - -/** expand pattern as specified by attribute - * node_lock must be hold - */ - -status_t -pnp_expand_pattern_attr(device_node_info *node, const char *attr_name, - char **expanded) -{ - const char *pattern; - status_t res; - - TRACE(("pnp_expand_pattern_attr()\n")); - - if (pnp_get_attr_string_nolock(node, attr_name, &pattern, false) != B_OK) { - *expanded = strdup(""); - return B_OK; - } - - *expanded = malloc((PATH_MAX + 1) * 2); - if (*expanded == NULL) - return B_NO_MEMORY; - - **expanded = 0; - res = pnp_expand_pattern(node, pattern, - *expanded, *expanded + PATH_MAX + 1, NULL, NULL); - - if (res != B_OK) - free(*expanded); - - return res; -} diff --git a/src/system/kernel/device_manager/registration.c b/src/system/kernel/device_manager/registration.c deleted file mode 100644 index baefc86502..0000000000 --- a/src/system/kernel/device_manager/registration.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. - * Copyright 2002-2004, Thomas Kurschel. All rights reserved. - * - * Distributed under the terms of the MIT License. - */ - -/* - Part of Device Manager - - Device Node Registration. -*/ - - -#include "device_manager_private.h" -#include "dl_list.h" - -#include - -#include -#include - - -//#define TRACE_REGISTRATION -#ifdef TRACE_REGISTRATION -# define TRACE(x) dprintf x -#else -# define TRACE(x) ; -#endif - - -/** mark node being registered, so it can be accessed via load_driver() */ - -static status_t -mark_node_registered(device_node_info *node) -{ - status_t res; - - TRACE(("mark_node_registered(%p)\n", node)); - - benaphore_lock(&gNodeLock); - - if (node->parent && !node->parent->registered) { - TRACE(("Cannot mark registered: parent is already unregistered\n")); - res = B_NOT_ALLOWED; - } else { - res = B_OK; - node->registered = true; - ++node->ref_count; - } - - benaphore_unlock(&gNodeLock); - return res; -} - -#if 0 -/** Checks whether the device is redetected and removes any other - * device that is on same connection and has the same device identifier. - * \a redetected is set true if device is already registered; - * the node must not yet be linked into parent node's children list - */ - -static status_t -is_device_redetected(device_node_info *node, device_node_info *parent, bool *redetected) -{ - device_node_info *sibling; - status_t res; - bool found = false; - bool same_device = false; - bool unregister_sibling; - - TRACE(("Checking %p, parent %p\n", node, parent)); - - *redetected = false; - - if (parent == NULL) { - TRACE(("done\n")); - return false; - } - - // we keep the lock very long, but this is the only way to be sure that - // no one else (un)-registers a conflicting note during the tests - benaphore_lock(&gNodeLock); - - { - char *connection, *device_identifier; - - // get our connection and device id... - if (pnp_expand_pattern_attr(node, PNP_DRIVER_CONNECTION, &connection) != B_OK) - connection = strdup(""); - - if (pnp_expand_pattern_attr(node, PNP_DRIVER_DEVICE_IDENTIFIER, - &device_identifier) != B_OK) - device_identifier = strdup(""); - - TRACE(("connection: %s, device_identifier: %s\n", connection, device_identifier)); - - // ...and compare it with our siblings - for (sibling = parent->children; sibling != NULL; sibling = sibling->siblings_next) { - char *sibling_connection, *sibling_device_identifier; - bool same_connection; - - // ignore dead siblings - if (!sibling->registered) - break; - - TRACE(("%p\n", sibling)); - - if (pnp_expand_pattern_attr(sibling, PNP_DRIVER_CONNECTION, - &sibling_connection) != B_OK) - sibling_connection = strdup(""); - - same_connection = !strcmp(connection, sibling_connection); - free(sibling_connection); - - if (!same_connection) - continue; - - // found a device on same connection - check whether it's the same device - found = true; - - if (pnp_expand_pattern_attr(sibling, PNP_DRIVER_DEVICE_IDENTIFIER, - &sibling_device_identifier) != B_OK) - sibling_device_identifier = strdup(""); - - TRACE(("device %s is on same connection\n", sibling_device_identifier)); - - same_device = !strcmp(device_identifier, sibling_device_identifier); - free(sibling_device_identifier); - break; - } - - free(connection); - free(device_identifier); - } - - if (found) { - TRACE(("found device on same connection\n")); - if (!same_device) { - // there is a different device on the same connection - - // kick out the old device - TRACE(("different device was detected\n")); - - *redetected = false; - unregister_sibling = true; - } else { - const char *driver_name, *old_driver_name; - const char *driver_type, *old_driver_type; - - TRACE(("it's the same device\n")); - - // found same device on same connection - make sure it's still the same driver - if (pnp_get_attr_string_nolock(node, PNP_DRIVER_DRIVER, &driver_name, false) != B_OK - || pnp_get_attr_string_nolock(sibling, PNP_DRIVER_DRIVER, &old_driver_name, false) != B_OK - || pnp_get_attr_string_nolock(node, PNP_DRIVER_TYPE, &driver_type, false) != B_OK - || pnp_get_attr_string_nolock(sibling, PNP_DRIVER_TYPE, &old_driver_type, false) != B_OK) { - // these attributes _must_ be there, so this cannot happen - // (but we are prepared) - res = B_ERROR; - goto err; - } - - if (strcmp(driver_name, old_driver_name) != 0 - || strcmp(driver_type, old_driver_type) != 0) { - // driver has changed - replace device node - TRACE(("driver got replaced\n")); - - *redetected = false; - unregister_sibling = true; - } else { - // it's the same driver for the same device - TRACE(("redetected device\n")); - - *redetected = true; - unregister_sibling = false; - } - } - } else { - // no collision on the device's connection - TRACE(("no collision\n")); - - *redetected = false; - unregister_sibling = false; - } - - if (*redetected && sibling->verifying) - sibling->redetected = true; - - if (unregister_sibling) { - // increase ref_count to make sure node still exists - // when gNodeLock has been released - ++sibling->ref_count; - benaphore_unlock(&gNodeLock); - - pnp_unregister_device(sibling); - pnp_remove_node_ref_nolock(sibling); - } else - benaphore_unlock(&gNodeLock); - - return B_OK; - -err: - benaphore_unlock(&gNodeLock); - return res; -} -#endif - - -static status_t -push_node_on_stack(struct list *list, device_node_info *node) -{ - struct node_entry *entry = (struct node_entry *)malloc(sizeof(struct node_entry)); - if (entry == NULL) - return B_NO_MEMORY; - - dm_get_node_nolock(node); - entry->node = node; - list_add_item(list, entry); - return B_OK; -} - - -static device_node_info * -pop_node_from_stack(struct list *list) -{ - device_node_info *node; - - struct node_entry *entry = (struct node_entry *)list_remove_head_item(list); - if (entry == NULL) - return NULL; - - node = entry->node; - free(entry); - - return node; -} - - -// #pragma mark - -// Public functions part of the module API - - -/** Register device node. - * In terms of I/O resources: if registration fails, they are freed; reason is - * that they may have been transferred to node before error and back-transferring - * them would be complicated. - */ - -status_t -dm_register_node(device_node_handle parent, const device_attr *attrs, - const io_resource_handle *ioResources, device_node_handle *_node) -{ - device_node_info *newNode; - char *driverName = NULL; - status_t status = B_OK; - struct list stack; - - status = dm_allocate_node(attrs, ioResources, &newNode); - if (status != B_OK) { - // always "consume" I/O resources - dm_release_io_resources(ioResources); - return status; - } - - if (pnp_get_attr_string(newNode, B_DRIVER_MODULE, &driverName, false) != B_OK) - status = B_BAD_VALUE; - - TRACE(("dm_register_node(driver = %s)\n", driverName)); - - free(driverName); - - if (status != B_OK) { - dprintf("device_manager: Missing driver module name.\n"); - goto err; - } - - // transfer resources to device, unregistering all colliding devices; - // this cannot fail - we've already allocated the resource handle array - dm_assign_io_resources(newNode, ioResources); - - // make it public - dm_add_child_node(parent, newNode); - - // The following is done to reduce the stack usage of deeply nested - // child device nodes. - // There is no other need to delay the complete registration process - // the way done here. This approach is also slightly different as - // the registration might fail later than it used in case of errors. - - if (parent == NULL || parent->registered) { - // register all device nodes not yet registered - build a list - // that contain all of them, and then empty it one by one (during - // iteration, there might be new nodes added) - - device_node_info *node = newNode; - - list_init(&stack); - push_node_on_stack(&stack, newNode); - - while ((node = pop_node_from_stack(&stack)) != NULL) { - device_node_info *child = NULL; - - // register all fixed child device nodes as well - status = dm_register_fixed_child_devices(node); - if (status != B_OK) - goto err2; - - node->registered = true; - - // and now let it register all child devices, if it's a bus - status = dm_register_child_devices(node); - if (status != B_OK) - goto err2; - - // push all new nodes on the stack - - benaphore_lock(&gNodeLock); - - while ((child = (device_node_info *)list_get_next_item(&node->children, child)) != NULL) { - if (!child->registered) - push_node_on_stack(&stack, child); - } - benaphore_unlock(&gNodeLock); - - dm_put_node(node); - } - } - - if (_node) - *_node = newNode; - - return B_OK; - -err2: - { - // nodes popped from the stack also need their reference count released - device_node_info *node; - while ((node = pop_node_from_stack(&stack)) != NULL) { - dm_put_node(node); - } - } -err: - // this also releases the I/O resources - dm_put_node(newNode); - return status; -} - - -/** Unregister device node. - * This also makes sure that all children of this node are unregistered. - */ - -status_t -dm_unregister_node(device_node_info *node) -{ - device_node_info *child, *nextChild; - - TRACE(("pnp_unregister_device(%p)\n", node)); - - if (node == NULL) - return B_OK; - - // unregistered node and all children - benaphore_lock(&gNodeLock); - if (node->parent != NULL) - list_remove_item(&node->parent->children, node); - benaphore_unlock(&gNodeLock); - - // tell driver about their unregistration - dm_notify_unregistration(node); - - // unregister children recursively - for (child = list_get_first_item(&node->children); child; child = nextChild) { - nextChild = (device_node_info *)child->siblings.next; - dm_unregister_node(child); - } - - dm_put_node(node); - - return B_OK; -} - diff --git a/src/system/kernel/device_manager/root_node.c b/src/system/kernel/device_manager/root_node.c deleted file mode 100644 index 720b0d7369..0000000000 --- a/src/system/kernel/device_manager/root_node.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. - * Copyright 2002/2003, Thomas Kurschel. All rights reserved. - * - * Distributed under the terms of the MIT License. - */ - -/* - Part of Device Manager - - Interface of device root module. - - This module creates the root devices (usually PCI and ISA) to - initiate the PnP device scan. -*/ - - -#include -#include - -#include "device_manager_private.h" - - -#define TRACE_ROOT_NODE -#ifdef TRACE_ROOT_NODE -# define TRACE(x) dprintf x -#else -# define TRACE(x) ; -#endif - - -#define PNP_ROOT_MODULE_NAME "system/devices_root/driver_v1" - - -void -dm_init_root_node(void) -{ - device_attr attrs[] = { - { B_DRIVER_MODULE, B_STRING_TYPE, { string: PNP_ROOT_MODULE_NAME }}, - { B_DRIVER_PRETTY_NAME, B_STRING_TYPE, { string: "Devices Root" }}, - - { B_DRIVER_BUS, B_STRING_TYPE, { string: "root" }}, - { NULL } - }; - - if (dm_register_node(NULL, attrs, NULL, &gRootNode) != B_OK) { - // ToDo: don't panic for now - dprintf("Cannot register Devices Root Node\n"); - } -} - - -static status_t -root_init_driver(device_node_handle node, void *user_cookie, void **_cookie) -{ - *_cookie = NULL; - return B_OK; -} - - -static status_t -root_uninit_driver(void *cookie) -{ - return B_OK; -} - - -static status_t -root_std_ops(int32 op, ...) -{ - switch (op) { - case B_MODULE_INIT: - case B_MODULE_UNINIT: - return B_OK; - - default: - return B_ERROR; - } -} - - -driver_module_info gDeviceRootModule = { - { - PNP_ROOT_MODULE_NAME, - 0, - root_std_ops, - }, - - NULL, // supported devices - NULL, // register device - root_init_driver, - root_uninit_driver, - NULL, - NULL -}; - diff --git a/src/system/kernel/device_manager/scan.c b/src/system/kernel/device_manager/scan.c deleted file mode 100644 index cc508f96da..0000000000 --- a/src/system/kernel/device_manager/scan.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright 2004-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved. - * Copyright 2002-2004, Thomas Kurschel. All rights reserved. - * - * Distributed under the terms of the MIT License. - */ - -/* - Scanning for consumers. - - Logic to execute (re)scanning of nodes. - - During initial registration, problems with fixed consumers are - fatal. During rescan, this is ignored - (TODO: should this be done more consistently?) -*/ - - -#include "device_manager_private.h" - -#include - -#include -#include - - -//#define TRACE_SCAN -#ifdef TRACE_SCAN -# define TRACE(x) dprintf x -#else -# define TRACE(x) ; -#endif - -static status_t scan(device_node_info *node, bool rescan); - - -static int32 sRescanning = 0; - - -#if 0 -// execute deferred probing of children -// (node_lock must be hold) - -void -pnp_probe_waiting_children_nolock(device_node_info *node) -{ - TRACE(("execute deferred probing of parent %p\n", node)); - - while (node->unprobed_children) { - device_node_info *child = node->unprobed_children; - - REMOVE_DL_LIST(child, node->unprobed_children, unprobed_); - - // child may have been removed meanwhile - if (child->registered) { - benaphore_unlock(&gNodeLock); - - if (pnp_initial_scan(child) == B_OK) - pnp_load_driver_automatically(node, false); - - benaphore_lock(&gNodeLock); - } - - // reference count was increment to keep node alive in wannabe list; - // this is not necessary anymore - pnp_remove_node_ref(node); - } - - TRACE((".. done.\n")); -} - - -// execute deferred probing of children - -void -pnp_probe_waiting_children(device_node_info *node) -{ - benaphore_lock(&gNodeLock); - - pnp_probe_waiting_children_nolock(node); - - benaphore_unlock(&gNodeLock); -} - -#endif - - -/** ask bus to (re-)scan for connected devices */ - -static void -scan_bus(device_node_info *node, bool rescan) -{ - // busses can register their children themselves - bus_module_info *interface; - status_t status; - void *cookie; - - // load driver during rescan - - status = pnp_load_driver(node, NULL, (driver_module_info **)&interface, &cookie); - if (status < B_OK) { - // we couldn't load a driver that had already registered itself... - return; - } - - TRACE(("scan bus\n")); - - // block other notifications (currently, only "removed" could be - // called as driver is/will stay loaded and scanning the bus - // concurrently has been assured to not happen) - pnp_start_hook_call(node); - - if (rescan) { - if (interface->rescan_bus != NULL) - interface->rescan_bus(cookie); - } else { - if (interface->register_child_devices != NULL) - interface->register_child_devices(cookie); - } - - pnp_finish_hook_call(node); - - pnp_unload_driver(node); - - // time to execute delayed probing -// pnp_probe_waiting_children(node); -} - - -/** recursively scan children of node (using depth-scan). - * node_lock must be hold - */ - -static status_t -recursive_scan(device_node_info *node) -{ - device_node_info *child = NULL; - status_t status; - - TRACE(("recursive_scan(node = %p)\n", node)); - - while ((child = list_get_next_item(&node->children, child)) != NULL) { - dm_get_node_nolock(child); - - // during rescan, we must release node_lock to not deadlock - benaphore_unlock(&gNodeLock); - - status = scan(child, true); - - benaphore_lock(&gNodeLock); - - // unlock current child as it's not accessed anymore - dm_put_node_nolock(child); - - // ignore errors because of touching unregistered nodes - if (status != B_OK && status != B_NAME_NOT_FOUND) - return status; - } - - // no need unlock last child (don't be loop already) - TRACE(("recursive_scan(): done\n")); - return B_OK; -} - - -/** (re)scan for child nodes - */ - -static status_t -scan(device_node_info *node, bool rescan) -{ - status_t status = B_OK; - uint8 dummy; - bool isBus; - - TRACE(("scan(node = %p, mode: %s)\n", node, rescan ? "rescan" : "register")); - - isBus = pnp_get_attr_uint8(node, PNP_BUS_IS_BUS, &dummy, false) == B_OK; - - // do the real thing - scan node - if (!rescan) { - uint8 loadDriversLater = false; - char *deviceType = NULL; - pnp_get_attr_uint8(node, B_DRIVER_FIND_DEVICES_ON_DEMAND, &loadDriversLater, false); - pnp_get_attr_string(node, B_DRIVER_DEVICE_TYPE, &deviceType, false); - - if (isBus) - scan_bus(node, false); - - // ask possible children to register their nodes - - if (!loadDriversLater && deviceType == NULL) { - status = dm_register_dynamic_child_devices(node); - if (status != B_OK) - return status; - } - - free(deviceType); - } else { - if (!isBus) - status = dm_register_dynamic_child_devices(node); - } - - // scan children recursively; - // keep the node_lock to make sure noone removes children meanwhile - if (rescan && isBus) { - scan_bus(node, true); - benaphore_lock(&gNodeLock); - status = recursive_scan(node); - benaphore_unlock(&gNodeLock); - } - - TRACE(("scan(): done (%p) - %s\n", node, strerror(status))); - return status; -} - - -// #pragma mark - - - -/** Rescan device node (only works if it's a bus) */ - -status_t -dm_rescan(device_node_info *node) -{ - status_t err; - - // only allow a single rescan at a time - if (atomic_add(&sRescanning, 1) > 1) { - dprintf("dm_rescan already scanning\n"); - atomic_add(&sRescanning, -1); - return B_BUSY; - } - - err = scan(node, true); - atomic_add(&sRescanning, -1); - return err; -} - - -/** execute registration of fully constructed node */ - -status_t -dm_register_child_devices(device_node_info *node) -{ - return scan(node, false); -} -