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
{
# AddBootModuleSymlinks <targets> ;
+13
View File
@@ -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 */
+1
View File
@@ -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"
@@ -9,6 +9,13 @@
#include "acpi_priv.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;
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 }
};
@@ -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.
@@ -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 }
@@ -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;
}
@@ -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);
+3 -3
View File
@@ -23,7 +23,7 @@
#include <string.h>
#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:
+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
* 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
+16 -8
View File
@@ -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;
}
+1
View File
@@ -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
{