added a jam rule AddDriverRegistrationToHaikuImage to add device mappings on the image

commented the insertion of the attribute name in patterns in the case of a string attribute
notify_probe_by_file chooses a module based on a bus specific suffix
dm_register_child_device has a parameter to optionally check the support for the node
added scanning of bus devices after the boot filesystem is mounted
fixed dm_rescan, locking was misbehaving
fixed SYSTEM_DRIVER_REGISTRATION definition
added B_DRIVER_MAPPING attributes for PCI and ACPI devices:
  %vendor%_%device% for PCI, hid_%hid% and type_%type% for ACPI
moved acpi_device_module_info definition to public ACPI.h


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19394 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jérôme Duval
2006-11-29 19:09:45 +00:00
parent 2bd388f696
commit c20e9eefcd
12 changed files with 146 additions and 89 deletions
+20
View File
@@ -181,6 +181,26 @@ rule AddDriversToHaikuImage
} }
} }
rule AddDriverRegistrationToHaikuImage
{
# AddDriverRegistrationToHaikuImage <directory> : <link target> : <link names> ] ;
#
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 rule AddBootModuleSymlinks
{ {
# AddBootModuleSymlinks <targets> ; # AddBootModuleSymlinks <targets> ;
+13
View File
@@ -129,5 +129,18 @@ struct acpi_object_type {
typedef struct acpi_device_info *acpi_device; 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 */ #endif /* _ACPI_H */
+1
View File
@@ -50,6 +50,7 @@ extern "C" {
extern status_t probe_for_device_type(const char *type); 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(struct kernel_args *args);
extern status_t device_manager_init_post_modules(struct kernel_args *args);
// temporary/optional device manager syscall API // temporary/optional device manager syscall API
#define DEVICE_MANAGER_SYSCALLS "device_manager" #define DEVICE_MANAGER_SYSCALLS "device_manager"
@@ -9,6 +9,13 @@
#include "acpi_priv.h" #include "acpi_priv.h"
#include <PCI.h> #include <PCI.h>
//#define TRACE_ACPI_MODULE
#ifdef TRACE_ACPI_MODULE
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
device_manager_info *gDeviceManager; device_manager_info *gDeviceManager;
pci_module_info *gPCIManager; pci_module_info *gPCIManager;
@@ -73,7 +80,7 @@ acpi_enumerate_child_devices(device_node_handle node, const char *root)
char result[255]; char result[255];
void *counter = NULL; 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) { while (get_next_entry(ACPI_TYPE_ANY, root, result, 255, &counter) == B_OK) {
uint32 type = get_object_type(result); 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 }}, { ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { ui32: type }},
// consumer specification // 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 } { 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 }}, { ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { ui32: type }},
// consumer specification // 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 } { NULL }
}; };
@@ -23,18 +23,7 @@
extern device_manager_info *gDeviceManager; 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. // ACPI root.
@@ -118,6 +118,8 @@ pci_module_register_child_devices(void *cookie)
// consumer specification // consumer specification
{ B_DRIVER_BUS, B_STRING_TYPE, { string: "pci" }}, { 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 // ToDo: this is a hack
{ B_DRIVER_DEVICE_TYPE, B_STRING_TYPE, { string: device.class_base == 1 ? "drivers/dev/disk" : "drivers/dev" }}, { B_DRIVER_DEVICE_TYPE, B_STRING_TYPE, { string: device.class_base == 1 ? "drivers/dev/disk" : "drivers/dev" }},
{ NULL } { NULL }
@@ -171,3 +171,32 @@ device_manager_init(struct kernel_args *args)
return B_OK; 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;
}
@@ -23,7 +23,7 @@
// driver registration directories // driver registration directories
#define PNP_DIR #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/" #define COMMON_DRIVER_REGISTRATION "/boot/home/config/add-ons/kernel/"PNP_DIR"registration/"
// module directories // module directories
@@ -197,7 +197,7 @@ status_t pnp_expand_pattern_attr(device_node_info *node, const char *attr_name,
// probe.cpp // 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_fixed_child_devices(device_node_info *node);
status_t dm_register_dynamic_child_devices(device_node_info *node); status_t dm_register_dynamic_child_devices(device_node_info *node);
+3 -3
View File
@@ -23,7 +23,7 @@
#include <string.h> #include <string.h>
#define TRACE_PATTERNS //#define TRACE_PATTERNS
#ifdef TRACE_PATTERNS #ifdef TRACE_PATTERNS
# define TRACE(x) dprintf x # define TRACE(x) dprintf x
#else #else
@@ -91,7 +91,7 @@ expand_attr(device_node_info *node, const char **pattern, char *buffer, char *ds
case B_STRING_TYPE: { case B_STRING_TYPE: {
const char *str; const char *str;
strlcat(dst, "\"", PATH_MAX); //strlcat(dst, "\"", PATH_MAX);
for (str = attr->attr.value.string; *str; ++str) { for (str = attr->attr.value.string; *str; ++str) {
char ch; 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, buffer, PATH_MAX);
} }
strlcat(dst, "\"", PATH_MAX); //strlcat(dst, "\"", PATH_MAX);
break; break;
} }
case B_RAW_TYPE: case B_RAW_TYPE:
+43 -62
View File
@@ -355,7 +355,6 @@ remove_device_nodes(struct list *list)
} }
#if 0
/** notify a consumer that a device he might handle is added /** notify a consumer that a device he might handle is added
* fileName - file name of consumer * fileName - file name of consumer
* (moved to end of file to avoid inlining) * (moved to end of file to avoid inlining)
@@ -364,68 +363,40 @@ remove_device_nodes(struct list *list)
static status_t static status_t
notify_probe_by_file(device_node_info *node, const char *fileName) notify_probe_by_file(device_node_info *node, const char *fileName)
{ {
char *type; char *bus;
char *resolved_path; int i, suffix_length;
char *module_name; const char *module_name;
int i; const char device_suffix[] = "_device_v1";
bool valid_module_name;
status_t res; status_t res;
TRACE(("notify_probe_by_file(%s)\n", fileName)); 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) if (res != B_OK)
return res; return res;
// resolve link to actual driver file // check if it's a driver module
resolved_path = (char *)malloc(B_PATH_NAME_LENGTH + 1); module_info **modules;
if (resolved_path == NULL) { if ((res = load_module(fileName, &modules)) != B_OK) {
res = B_NO_MEMORY; goto err;
goto err;
} }
// ToDo: do something about this; realpath() doesn't exist in the kernel! suffix_length = strlen(bus) + sizeof(device_suffix);
//module_name = pnp_boot_safe_realpath(consumer_name, resolved_path); for (i=0; modules[i]; i++) {
module_name = NULL; module_name = modules[i]->name;
if (module_name == NULL) { TRACE(("notify_probe_by_file trying %s %s %s\n", module_name, bus, module_name + (strlen(module_name) - suffix_length + 1)));
// broken link or something if (strlen(module_name) > suffix_length
dprintf("Cannot resolve driver file name: %s\n", fileName); && !strncmp(module_name + (strlen(module_name) - suffix_length + 1), bus, strlen(bus))
res = errno; && !strncmp(module_name + (strlen(module_name) - sizeof(device_suffix) + 1), device_suffix, sizeof(device_suffix))) {
goto err2; // found the module
} res = dm_register_child_device(node, module_name, true);
// 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;
break; break;
} }
} }
if (!valid_module_name) { unload_module(fileName);
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);
err: err:
free(type); free(bus);
return res; return res;
} }
@@ -455,7 +426,7 @@ compose_driver_names(device_node_info *node, const char *dir,
strlcpy(path, dir, B_PATH_NAME_LENGTH); strlcpy(path, dir, B_PATH_NAME_LENGTH);
strlcat(path, "/", 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); 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) { for (i = num_parts - 1; i >= 0; --i) {
int j; int j;
TRACE(("%d: %lu\n", i, term_array[i])); //TRACE(("%d: %lu\n", i, term_array[i]));
path[term_array[i]] = 0; path[term_array[i]] = 0;
// first, check for user driver, then system driver // first, check for user driver, then system driver
@@ -585,8 +556,7 @@ find_normal_child(device_node_info *node, const char *dir,
// got him! // got him!
break; break;
} else { } else {
/*SHOW_ERROR( 4, "Specific driver %s doesn't exists", TRACE(("Specific driver %s doesn't exist\n", buffer ));
buffer );*/
} }
} }
} }
@@ -731,6 +701,7 @@ register_dynamic_child_device(device_node_info *node, const char *bus,
goto err; goto err;
} }
#if 0
// tell universal drivers // tell universal drivers
strlcpy(buffers, bus, B_PATH_NAME_LENGTH); strlcpy(buffers, bus, B_PATH_NAME_LENGTH);
strlcat(buffers, UNIVERSAL_SUBDIR, 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) if (status != B_OK && status != B_NAME_NOT_FOUND)
// again, only abort on real problems // again, only abort on real problems
goto err; goto err;
#endif
free(buffers); free(buffers);
@@ -749,7 +721,6 @@ err:
free(buffers); free(buffers);
return status; return status;
} }
#endif
static path_entry * static path_entry *
@@ -1041,7 +1012,7 @@ get_nodes_for_device_type(device_node_info *node, struct list *list, const char
*/ */
status_t 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; driver_module_info *child;
status_t status; status_t status;
@@ -1054,6 +1025,19 @@ dm_register_child_device(device_node_info *node, const char *childName)
return status; 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) { if (child->register_device != NULL) {
status = child->register_device(node); status = child->register_device(node);
if (status != B_OK) { if (status != B_OK) {
@@ -1065,6 +1049,7 @@ dm_register_child_device(device_node_info *node, const char *childName)
status = B_ERROR; status = B_ERROR;
} }
err:
put_module(childName); put_module(childName);
return status; return status;
} }
@@ -1091,6 +1076,7 @@ dm_register_dynamic_child_devices(device_node_info *node)
TRACE((" Search bus: \"%s\"\n", bus)); TRACE((" Search bus: \"%s\"\n", bus));
if (gBootDevice < 0) { if (gBootDevice < 0) {
TRACE((" Scanning built-in modules only\n"));
// there is no boot device yet, we have to scan the already // there is no boot device yet, we have to scan the already
// loaded and built-in modules // loaded and built-in modules
struct list modules; struct list modules;
@@ -1103,9 +1089,6 @@ dm_register_dynamic_child_devices(device_node_info *node)
register_supporting_child_devices(node, &modules); register_supporting_child_devices(node, &modules);
return B_OK; return B_OK;
} else { } else {
// ToDo: this is completely outdated and must be redone!
status = B_ERROR;
#if 0
buffer = (char *)malloc(B_PATH_NAME_LENGTH + 1); buffer = (char *)malloc(B_PATH_NAME_LENGTH + 1);
if (buffer == NULL) { if (buffer == NULL) {
status = B_NO_MEMORY; status = B_NO_MEMORY;
@@ -1142,9 +1125,8 @@ dm_register_dynamic_child_devices(device_node_info *node)
break; break;
} }
} }
#endif
} }
#if 0
if (found == 0) { if (found == 0) {
// no requirement for a special mapping, so we're just scanning the bus directory // no requirement for a special mapping, so we're just scanning the bus directory
bool noSpecificDriver = false; bool noSpecificDriver = false;
@@ -1153,7 +1135,6 @@ dm_register_dynamic_child_devices(device_node_info *node)
// supposed to go through // supposed to go through
free(buffer); free(buffer);
#endif
err: err:
free(bus); free(bus);
return status; return status;
@@ -1188,7 +1169,7 @@ dm_register_fixed_child_devices(device_node_info *node)
TRACE(("Consumer %ld: %s\n", i, childName)); 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); dprintf("Cannot register fixed child device %s\n", childName);
// report error if fixed consumers couldn't be loaded // report error if fixed consumers couldn't be loaded
+16 -8
View File
@@ -196,16 +196,19 @@ scan(device_node_info *node, bool rescan)
} }
free(deviceType); free(deviceType);
} else {
if (!isBus)
status = dm_register_dynamic_child_devices(node);
} }
benaphore_lock(&gNodeLock);
// scan children recursively; // scan children recursively;
// keep the node_lock to make sure noone removes children meanwhile // 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); status = recursive_scan(node);
benaphore_unlock(&gNodeLock);
benaphore_unlock(&gNodeLock); }
TRACE(("scan(): done (%p) - %s\n", node, strerror(status))); TRACE(("scan(): done (%p) - %s\n", node, strerror(status)));
return status; return status;
@@ -220,13 +223,18 @@ scan(device_node_info *node, bool rescan)
status_t status_t
dm_rescan(device_node_info *node) dm_rescan(device_node_info *node)
{ {
status_t err;
// only allow a single rescan at a time // 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); atomic_add(&sRescanning, -1);
return B_BUSY; return B_BUSY;
} }
return scan(node, true); err = scan(node, true);
atomic_add(&sRescanning, -1);
return err;
} }
+1
View File
@@ -227,6 +227,7 @@ main2(void *unused)
cpu_init_post_modules(&sKernelArgs); cpu_init_post_modules(&sKernelArgs);
vm_init_post_modules(&sKernelArgs); vm_init_post_modules(&sKernelArgs);
debug_init_post_modules(&sKernelArgs); debug_init_post_modules(&sKernelArgs);
device_manager_init_post_modules(&sKernelArgs);
// start the init process // start the init process
{ {