diff --git a/build/jam/ImageRules b/build/jam/ImageRules index a492ced36a..ec160fbcfc 100644 --- a/build/jam/ImageRules +++ b/build/jam/ImageRules @@ -181,6 +181,26 @@ rule AddDriversToHaikuImage } } +rule AddDriverRegistrationToHaikuImage +{ + # AddDriverRegistrationToHaikuImage : : ] ; + # + local relativeDirectoryTokens = $(1) ; + local target = $(2) ; + local links = $(3) ; + local directoryTokens = beos system add-ons kernel registration $(relativeDirectoryTokens) ; + + # get the relative symlink path prefix + local linkPrefix = ; + for i in $(relativeDirectoryTokens) { + linkPrefix += .. ; + } + linkPrefix += .. drivers bin ; + + # add the symlink + AddSymlinkToHaikuImage $(directoryTokens) : [ FDirName $(linkPrefix) $(target:BS) ] : $(links) ; +} + rule AddBootModuleSymlinks { # AddBootModuleSymlinks ; diff --git a/headers/os/drivers/ACPI.h b/headers/os/drivers/ACPI.h index 7ce670a46d..38065a4528 100644 --- a/headers/os/drivers/ACPI.h +++ b/headers/os/drivers/ACPI.h @@ -129,5 +129,18 @@ struct acpi_object_type { typedef struct acpi_device_info *acpi_device; +// Interface to one ACPI device. +typedef struct acpi_device_module_info { + driver_module_info info; + + /* Namespace Access */ + uint32 (*get_object_type) (acpi_device device); + status_t (*get_object) (acpi_device device, const char *path, acpi_object_type **return_value); + + /* Control method execution and data acquisition */ + status_t (*evaluate_method) (acpi_device device, const char *method, acpi_object_type *return_value, size_t buf_len, acpi_object_type *args, int num_args); + +} acpi_device_module_info; + #endif /* _ACPI_H */ diff --git a/headers/private/kernel/kdevice_manager.h b/headers/private/kernel/kdevice_manager.h index 81ae60cdd6..f4851336d2 100644 --- a/headers/private/kernel/kdevice_manager.h +++ b/headers/private/kernel/kdevice_manager.h @@ -50,6 +50,7 @@ extern "C" { extern status_t probe_for_device_type(const char *type); extern status_t device_manager_init(struct kernel_args *args); +extern status_t device_manager_init_post_modules(struct kernel_args *args); // temporary/optional device manager syscall API #define DEVICE_MANAGER_SYSCALLS "device_manager" diff --git a/src/add-ons/kernel/bus_managers/acpi/acpi_module.c b/src/add-ons/kernel/bus_managers/acpi/acpi_module.c index 47bc4e00dd..4f269a8c08 100644 --- a/src/add-ons/kernel/bus_managers/acpi/acpi_module.c +++ b/src/add-ons/kernel/bus_managers/acpi/acpi_module.c @@ -9,6 +9,13 @@ #include "acpi_priv.h" #include +//#define TRACE_ACPI_MODULE +#ifdef TRACE_ACPI_MODULE +# define TRACE(x) dprintf x +#else +# define TRACE(x) ; +#endif + device_manager_info *gDeviceManager; pci_module_info *gPCIManager; @@ -73,7 +80,7 @@ acpi_enumerate_child_devices(device_node_handle node, const char *root) char result[255]; void *counter = NULL; - dprintf("acpi_enumerate_child_devices: recursing from %s\n", root); + TRACE(("acpi_enumerate_child_devices: recursing from %s\n", root)); while (get_next_entry(ACPI_TYPE_ANY, root, result, 255, &counter) == B_OK) { uint32 type = get_object_type(result); @@ -102,7 +109,11 @@ acpi_enumerate_child_devices(device_node_handle node, const char *root) { ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { ui32: type }}, // consumer specification - { B_DRIVER_BUS, B_STRING_TYPE, { string: "apci" }}, + { B_DRIVER_BUS, B_STRING_TYPE, { string: "acpi" }}, + { B_DRIVER_MAPPING, B_STRING_TYPE, { string: + "hid_%" ACPI_DEVICE_HID_ITEM "%" }}, + { B_DRIVER_MAPPING "/0", B_STRING_TYPE, { string: + "type_%" ACPI_DEVICE_TYPE_ITEM "%" }}, { NULL } }; @@ -128,7 +139,9 @@ acpi_enumerate_child_devices(device_node_handle node, const char *root) { ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { ui32: type }}, // consumer specification - { B_DRIVER_BUS, B_STRING_TYPE, { string: "apci" }}, + { B_DRIVER_BUS, B_STRING_TYPE, { string: "acpi" }}, + { B_DRIVER_MAPPING, B_STRING_TYPE, { string: + "type_%" ACPI_DEVICE_TYPE_ITEM "%" }}, { NULL } }; diff --git a/src/add-ons/kernel/bus_managers/acpi/acpi_priv.h b/src/add-ons/kernel/bus_managers/acpi/acpi_priv.h index 754369aa40..f3162ff005 100644 --- a/src/add-ons/kernel/bus_managers/acpi/acpi_priv.h +++ b/src/add-ons/kernel/bus_managers/acpi/acpi_priv.h @@ -23,18 +23,7 @@ extern device_manager_info *gDeviceManager; -// Interface to one ACPI device. -typedef struct acpi_device_module_info { - driver_module_info info; - /* Namespace Access */ - uint32 (*get_object_type) (acpi_device device); - status_t (*get_object) (acpi_device device, const char *path, acpi_object_type **return_value); - - /* Control method execution and data acquisition */ - status_t (*evaluate_method) (acpi_device device, const char *method, acpi_object_type *return_value, size_t buf_len, acpi_object_type *args, int num_args); - -} acpi_device_module_info; // ACPI root. diff --git a/src/add-ons/kernel/bus_managers/pci/pci_module.c b/src/add-ons/kernel/bus_managers/pci/pci_module.c index 4a21f0774a..71c9094f93 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci_module.c +++ b/src/add-ons/kernel/bus_managers/pci/pci_module.c @@ -118,6 +118,8 @@ pci_module_register_child_devices(void *cookie) // consumer specification { B_DRIVER_BUS, B_STRING_TYPE, { string: "pci" }}, + { B_DRIVER_MAPPING, B_STRING_TYPE, { string: "%"PCI_DEVICE_VENDOR_ID_ITEM "%|_%" PCI_DEVICE_DEVICE_ID_ITEM "%" }}, + // ToDo: this is a hack { B_DRIVER_DEVICE_TYPE, B_STRING_TYPE, { string: device.class_base == 1 ? "drivers/dev/disk" : "drivers/dev" }}, { NULL } diff --git a/src/system/kernel/device_manager/device_manager.c b/src/system/kernel/device_manager/device_manager.c index 8f817d00eb..f56bffd6ae 100644 --- a/src/system/kernel/device_manager/device_manager.c +++ b/src/system/kernel/device_manager/device_manager.c @@ -171,3 +171,32 @@ device_manager_init(struct kernel_args *args) 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/device_manager_private.h b/src/system/kernel/device_manager/device_manager_private.h index 845438aeb0..3e61149051 100644 --- a/src/system/kernel/device_manager/device_manager_private.h +++ b/src/system/kernel/device_manager/device_manager_private.h @@ -23,7 +23,7 @@ // driver registration directories #define PNP_DIR -#define SYSTEM_DRIVER_REGISTRATION "/boot/beos/add-ons/kernel/"PNP_DIR"registration/" +#define SYSTEM_DRIVER_REGISTRATION "/boot/beos/system/add-ons/kernel/"PNP_DIR"registration/" #define COMMON_DRIVER_REGISTRATION "/boot/home/config/add-ons/kernel/"PNP_DIR"registration/" // module directories @@ -197,7 +197,7 @@ status_t pnp_expand_pattern_attr(device_node_info *node, const char *attr_name, // probe.cpp -status_t dm_register_child_device(device_node_info *node, const char *childName); +status_t dm_register_child_device(device_node_info *node, const char *childName, bool checkSupport); status_t dm_register_fixed_child_devices(device_node_info *node); status_t dm_register_dynamic_child_devices(device_node_info *node); diff --git a/src/system/kernel/device_manager/patterns.c b/src/system/kernel/device_manager/patterns.c index d786ed06c6..a31436d797 100644 --- a/src/system/kernel/device_manager/patterns.c +++ b/src/system/kernel/device_manager/patterns.c @@ -23,7 +23,7 @@ #include -#define TRACE_PATTERNS +//#define TRACE_PATTERNS #ifdef TRACE_PATTERNS # define TRACE(x) dprintf x #else @@ -91,7 +91,7 @@ expand_attr(device_node_info *node, const char **pattern, char *buffer, char *ds case B_STRING_TYPE: { const char *str; - strlcat(dst, "\"", PATH_MAX); + //strlcat(dst, "\"", PATH_MAX); for (str = attr->attr.value.string; *str; ++str) { char ch; @@ -108,7 +108,7 @@ expand_attr(device_node_info *node, const char **pattern, char *buffer, char *ds strlcat(dst, buffer, PATH_MAX); } - strlcat(dst, "\"", PATH_MAX); + //strlcat(dst, "\"", PATH_MAX); break; } case B_RAW_TYPE: diff --git a/src/system/kernel/device_manager/probe.cpp b/src/system/kernel/device_manager/probe.cpp index 4af052cd4b..93bca7ff1a 100644 --- a/src/system/kernel/device_manager/probe.cpp +++ b/src/system/kernel/device_manager/probe.cpp @@ -355,7 +355,6 @@ remove_device_nodes(struct list *list) } -#if 0 /** notify a consumer that a device he might handle is added * fileName - file name of consumer * (moved to end of file to avoid inlining) @@ -364,68 +363,40 @@ remove_device_nodes(struct list *list) static status_t notify_probe_by_file(device_node_info *node, const char *fileName) { - char *type; - char *resolved_path; - char *module_name; - int i; - bool valid_module_name; + char *bus; + int i, suffix_length; + const char *module_name; + const char device_suffix[] = "_device_v1"; status_t res; TRACE(("notify_probe_by_file(%s)\n", fileName)); - res = pnp_get_attr_string(node, PNP_DRIVER_TYPE, &type, false); + res = pnp_get_attr_string(node, B_DRIVER_BUS, &bus, false); if (res != B_OK) return res; - // resolve link to actual driver file - resolved_path = (char *)malloc(B_PATH_NAME_LENGTH + 1); - if (resolved_path == NULL) { - res = B_NO_MEMORY; - goto err; + // check if it's a driver module + module_info **modules; + if ((res = load_module(fileName, &modules)) != B_OK) { + goto err; } - // ToDo: do something about this; realpath() doesn't exist in the kernel! - //module_name = pnp_boot_safe_realpath(consumer_name, resolved_path); - module_name = NULL; - if (module_name == NULL) { - // broken link or something - dprintf("Cannot resolve driver file name: %s\n", fileName); - res = errno; - goto err2; - } - - // make sure both consumer and module file are either in - // system or user modules directory - valid_module_name = false; - - for (i = 0; i < (disable_useraddons ? 1 : 2); ++i) { - int len = strlen(kModulePaths[i]); - - if (!strncmp(fileName, kModulePaths[i], len) - && !strncmp(module_name, kModulePaths[i], len)) { - valid_module_name = true; - module_name = module_name + len; + suffix_length = strlen(bus) + sizeof(device_suffix); + for (i=0; modules[i]; i++) { + module_name = modules[i]->name; + TRACE(("notify_probe_by_file trying %s %s %s\n", module_name, bus, module_name + (strlen(module_name) - suffix_length + 1))); + if (strlen(module_name) > suffix_length + && !strncmp(module_name + (strlen(module_name) - suffix_length + 1), bus, strlen(bus)) + && !strncmp(module_name + (strlen(module_name) - sizeof(device_suffix) + 1), device_suffix, sizeof(device_suffix))) { + // found the module + res = dm_register_child_device(node, module_name, true); break; } } - if (!valid_module_name) { - TRACE(("Module file %s of consumer %s is in wrong path\n", - fileName, module_name)); - res = B_NAME_NOT_FOUND; - goto err2; - } - - // append driver type to get specific module name - strlcat(module_name, "/", B_PATH_NAME_LENGTH); - strlcat(module_name, type, B_PATH_NAME_LENGTH); - - res = dm_register_child_device(node, module_name); - -err2: - free(resolved_path); + unload_module(fileName); err: - free(type); + free(bus); return res; } @@ -455,7 +426,7 @@ compose_driver_names(device_node_info *node, const char *dir, strlcpy(path, dir, B_PATH_NAME_LENGTH); strlcat(path, "/", B_PATH_NAME_LENGTH); - TRACE(("compose_drive_names(%s)\n", path)); + TRACE(("compose_driver_names(%s)\n", path)); benaphore_lock(&gNodeLock); @@ -567,7 +538,7 @@ find_normal_child(device_node_info *node, const char *dir, for (i = num_parts - 1; i >= 0; --i) { int j; - TRACE(("%d: %lu\n", i, term_array[i])); + //TRACE(("%d: %lu\n", i, term_array[i])); path[term_array[i]] = 0; // first, check for user driver, then system driver @@ -585,8 +556,7 @@ find_normal_child(device_node_info *node, const char *dir, // got him! break; } else { - /*SHOW_ERROR( 4, "Specific driver %s doesn't exists", - buffer );*/ + TRACE(("Specific driver %s doesn't exist\n", buffer )); } } } @@ -731,6 +701,7 @@ register_dynamic_child_device(device_node_info *node, const char *bus, goto err; } +#if 0 // tell universal drivers strlcpy(buffers, bus, B_PATH_NAME_LENGTH); strlcat(buffers, UNIVERSAL_SUBDIR, B_PATH_NAME_LENGTH); @@ -739,6 +710,7 @@ register_dynamic_child_device(device_node_info *node, const char *bus, if (status != B_OK && status != B_NAME_NOT_FOUND) // again, only abort on real problems goto err; +#endif free(buffers); @@ -749,7 +721,6 @@ err: free(buffers); return status; } -#endif static path_entry * @@ -1041,7 +1012,7 @@ get_nodes_for_device_type(device_node_info *node, struct list *list, const char */ status_t -dm_register_child_device(device_node_info *node, const char *childName) +dm_register_child_device(device_node_info *node, const char *childName, bool checkSupport) { driver_module_info *child; status_t status; @@ -1054,6 +1025,19 @@ dm_register_child_device(device_node_info *node, const char *childName) return status; } + status = B_ERROR; + bool hasConnection; + if (checkSupport) { + if (child->supports_device == NULL) { + dprintf("Driver %s has no support_device() hook\n", childName); + goto err; + } + if (child->supports_device(node, &hasConnection) <= 0.0) { + TRACE(("Driver %s doesn't support the device\n", childName)); + goto err; + } + } + if (child->register_device != NULL) { status = child->register_device(node); if (status != B_OK) { @@ -1065,6 +1049,7 @@ dm_register_child_device(device_node_info *node, const char *childName) status = B_ERROR; } +err: put_module(childName); return status; } @@ -1091,6 +1076,7 @@ dm_register_dynamic_child_devices(device_node_info *node) TRACE((" Search bus: \"%s\"\n", bus)); if (gBootDevice < 0) { + TRACE((" Scanning built-in modules only\n")); // there is no boot device yet, we have to scan the already // loaded and built-in modules struct list modules; @@ -1103,9 +1089,6 @@ dm_register_dynamic_child_devices(device_node_info *node) register_supporting_child_devices(node, &modules); return B_OK; } else { - // ToDo: this is completely outdated and must be redone! - status = B_ERROR; -#if 0 buffer = (char *)malloc(B_PATH_NAME_LENGTH + 1); if (buffer == NULL) { status = B_NO_MEMORY; @@ -1142,9 +1125,8 @@ dm_register_dynamic_child_devices(device_node_info *node) break; } } -#endif } -#if 0 + if (found == 0) { // no requirement for a special mapping, so we're just scanning the bus directory bool noSpecificDriver = false; @@ -1153,7 +1135,6 @@ dm_register_dynamic_child_devices(device_node_info *node) // supposed to go through free(buffer); -#endif err: free(bus); return status; @@ -1188,7 +1169,7 @@ dm_register_fixed_child_devices(device_node_info *node) TRACE(("Consumer %ld: %s\n", i, childName)); - if (dm_register_child_device(node, childName) != B_OK) { + if (dm_register_child_device(node, childName, false) != B_OK) { dprintf("Cannot register fixed child device %s\n", childName); // report error if fixed consumers couldn't be loaded diff --git a/src/system/kernel/device_manager/scan.c b/src/system/kernel/device_manager/scan.c index 8e0ab6187a..cc508f96da 100644 --- a/src/system/kernel/device_manager/scan.c +++ b/src/system/kernel/device_manager/scan.c @@ -196,16 +196,19 @@ scan(device_node_info *node, bool rescan) } free(deviceType); + } else { + if (!isBus) + status = dm_register_dynamic_child_devices(node); } - - benaphore_lock(&gNodeLock); - + // scan children recursively; // keep the node_lock to make sure noone removes children meanwhile - if (rescan && isBus) + if (rescan && isBus) { + scan_bus(node, true); + benaphore_lock(&gNodeLock); status = recursive_scan(node); - - benaphore_unlock(&gNodeLock); + benaphore_unlock(&gNodeLock); + } TRACE(("scan(): done (%p) - %s\n", node, strerror(status))); return status; @@ -220,13 +223,18 @@ scan(device_node_info *node, bool rescan) status_t dm_rescan(device_node_info *node) { + status_t err; + // only allow a single rescan at a time - if (atomic_add(&sRescanning, 1) > 0) { + if (atomic_add(&sRescanning, 1) > 1) { + dprintf("dm_rescan already scanning\n"); atomic_add(&sRescanning, -1); return B_BUSY; } - return scan(node, true); + err = scan(node, true); + atomic_add(&sRescanning, -1); + return err; } diff --git a/src/system/kernel/main.c b/src/system/kernel/main.c index 4231eaadcf..077ed4416c 100644 --- a/src/system/kernel/main.c +++ b/src/system/kernel/main.c @@ -227,6 +227,7 @@ main2(void *unused) cpu_init_post_modules(&sKernelArgs); vm_init_post_modules(&sKernelArgs); debug_init_post_modules(&sKernelArgs); + device_manager_init_post_modules(&sKernelArgs); // start the init process {