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:
@@ -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> ;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user