From 557335a99102b2df15fe4e877cfe8f678bd29995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 3 Jun 2008 13:22:24 +0000 Subject: [PATCH] * device_nodes now have a priority that is used to sort them when they are added to their parent. Currently, only the existence of B_FIND_MULTIPLE_CHILDREN influences the priority. * This makes it possible to register/probe intelligent busses earlier than simple/generic busses. * Reenabled the ISA bus manager using the new device architecture; the ide_isa driver can and will now actually work. * device_node::Probe() now sets the global sGenericContextPath for generic nodes. This causes a special handling in _GetNextDriverPath(). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25779 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/kernel/bus_managers/isa/isa.c | 82 ++++++------------- .../kernel/device_manager/device_manager.cpp | 61 ++++++++++++-- 2 files changed, 82 insertions(+), 61 deletions(-) diff --git a/src/add-ons/kernel/bus_managers/isa/isa.c b/src/add-ons/kernel/bus_managers/isa/isa.c index 2e871e1c50..7ba86b7052 100644 --- a/src/add-ons/kernel/bus_managers/isa/isa.c +++ b/src/add-ons/kernel/bus_managers/isa/isa.c @@ -34,7 +34,7 @@ // (for example, the Pegasos (PPC based) also has an ISA bus) -#define ISA_MODULE_NAME "bus_managers/isa/root/device_v1" +#define ISA_MODULE_NAME "bus_managers/isa/root/driver_v1" device_manager_info *pnp; @@ -73,75 +73,54 @@ unlock_isa_dma_channel(long channel) } -#if 0 +// #pragma mark - driver module API + + static status_t -isa_init_driver(device_node_handle node, void *user_cookie, void **cookie) +isa_init_driver(device_node *node, void **cookie) { - *cookie = NULL; + *cookie = node; return B_OK; } -static status_t +static void isa_uninit_driver(void *cookie) { - return B_OK; } static float -isa_supports_device(device_node_handle parent, bool *_noConnection) +isa_supports_device(device_node *parent) { - char *bus; + const char *bus; // make sure parent is really pnp root - if (pnp->get_attr_string(parent, B_DRIVER_BUS, &bus, false)) + if (pnp->get_attr_string(parent, B_DEVICE_BUS, &bus, false)) return B_ERROR; - if (strcmp(bus, "root")) { - free(bus); + if (strcmp(bus, "root")) return 0.0; - } - free(bus); return 1.0; } static status_t -isa_register_device(device_node_handle parent) +isa_register_device(device_node *parent) { static const device_attr attrs[] = { - // info about ourself - { B_DRIVER_MODULE, B_STRING_TYPE, { string: ISA_MODULE_NAME }}, - // unique connection - { PNP_DRIVER_CONNECTION, B_STRING_TYPE, { string: "ISA" }}, - - // mark as being a bus - { PNP_BUS_IS_BUS, B_UINT8_TYPE, { ui8: 1 }}, - // tell where to look for child devices - { B_DRIVER_BUS, B_STRING_TYPE, { string: "isa" }}, - { B_DRIVER_FIND_DEVICES_ON_DEMAND, B_UINT8_TYPE, { ui8: 1 }}, - { B_DRIVER_EXPLORE_LAST, B_UINT8_TYPE, { ui8: 1 }}, - { NULL } + {B_DEVICE_BUS, B_STRING_TYPE, {string: "isa" }}, + {B_DEVICE_FLAGS, B_UINT32_TYPE, + {ui32: B_FIND_CHILD_ON_DEMAND | B_FIND_MULTIPLE_CHILDREN}}, + {} }; - return pnp->register_device(parent, attrs, NULL, NULL); + return pnp->register_node(parent, ISA_MODULE_NAME, attrs, NULL, NULL); } -static void -isa_get_paths(const char ***_bus, const char ***_device) -{ - static const char *kBus[] = {"root", NULL}; - - *_bus = kBus; - *_device = NULL; -} -#endif - - static status_t std_ops(int32 op, ...) { @@ -185,27 +164,19 @@ static isa_module_info isa_module = { &unlock_isa_dma_channel }; -#if 0 static isa2_module_info isa2_module = { { { - { - ISA_MODULE_NAME, - 0, - std_ops - }, - - isa_supports_device, - isa_register_device, - isa_init_driver, - isa_uninit_driver, - NULL, // removed device - NULL, // cleanup device - isa_get_paths, + ISA_MODULE_NAME, + 0, + std_ops }, - // as ISA relies on device drivers to detect their devices themselves, - // we don't have an universal rescan method + isa_supports_device, + isa_register_device, + isa_init_driver, + isa_uninit_driver, + NULL, // removed device NULL, // register child devices NULL, // rescan bus }, @@ -218,10 +189,9 @@ static isa2_module_info isa2_module = { arch_start_isa_dma, }; -#endif module_info *modules[] = { (module_info *)&isa_module, -// (module_info *)&isa2_module, + (module_info *)&isa2_module, NULL }; diff --git a/src/system/kernel/device_manager/device_manager.cpp b/src/system/kernel/device_manager/device_manager.cpp index b63055cecf..d3a43a1eb4 100644 --- a/src/system/kernel/device_manager/device_manager.cpp +++ b/src/system/kernel/device_manager/device_manager.cpp @@ -136,6 +136,8 @@ struct device_node : DoublyLinkedListLinkImpl { device_node* FindChild(const device_attr* attributes) const; device_node* FindChild(const char* moduleName) const; + int32 Priority(); + void Dump(int32 level = 0); private: @@ -189,6 +191,7 @@ enum node_flags { static device_node *sRootNode; static recursive_lock sLock; +static const char* sGenericContextPath; static uint32 sDriverUpdateCycle = 1; @@ -1260,7 +1263,22 @@ device_node::AddChild(device_node* node) // we must not be destroyed as long as we have children Acquire(); node->fParent = this; - fChildren.Add(node); + + int32 priority = node->Priority(); + + // Enforce an order in which the children are traversed - from most + // specific to least specific child. + NodeList::Iterator iterator = fChildren.GetIterator(); + device_node* before = NULL; + while (iterator.HasNext()) { + device_node* child = iterator.Next(); + if (child->Priority() <= priority) { + before = child; + break; + } + } + + fChildren.Insert(before, node); } @@ -1411,11 +1429,16 @@ device_node::_GetNextDriverPath(void*& cookie, KPath& _path) return B_NO_MEMORY; StackDeleter stackDeleter(stack); + + bool generic = false; uint16 type = 0; uint16 subType = 0; uint16 interface = 0; - get_attr_uint16(this, B_DEVICE_TYPE, &type, false); - get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false); + if (get_attr_uint16(this, B_DEVICE_TYPE, &type, false) != B_OK + || get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false) + != B_OK) + generic = true; + get_attr_uint16(this, B_DEVICE_INTERFACE, &interface, false); // TODO: maybe make this extendible via settings file? @@ -1475,8 +1498,19 @@ device_node::_GetNextDriverPath(void*& cookie, KPath& _path) if (sRootNode == this) { _AddPath(*stack, "busses/pci"); _AddPath(*stack, "bus_managers"); - } else + } else if (!generic) { _AddPath(*stack, "drivers"); + } else { + // For generic drivers, we only allow busses when the + // request is more specified + if (sGenericContextPath != NULL + && (!strcmp(sGenericContextPath, "disk") + || !strcmp(sGenericContextPath, "ports") + || !strcmp(sGenericContextPath, "bus"))) { + _AddPath(*stack, "busses"); + } + _AddPath(*stack, "drivers", sGenericContextPath); + } break; } @@ -1758,13 +1792,17 @@ device_node::Probe(const char* devicePath, uint32 updateCycle) // This driver does not support types, but still wants to its // children explored on demand only. matches = true; + sGenericContextPath = devicePath; } if (matches) { fLastUpdateCycle = updateCycle; // This node will be probed in this update cycle - return _Probe(); + status = _Probe(); + + sGenericContextPath = NULL; + return status; } return B_OK; @@ -2005,6 +2043,19 @@ device_node::FindChild(const char* moduleName) const } +/*! This returns the priority or importance of this node. Nodes with higher + priority are registered/probed first. + Currently, only the B_FIND_MULITPLE_CHILDREN flag alters the priority; + it might make sense to be able to directly set the priority via an + attribute. +*/ +int32 +device_node::Priority() +{ + return (fFlags & B_FIND_MULTIPLE_CHILDREN) != 0 ? 0 : 100; +} + + void device_node::Dump(int32 level) {