* 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
This commit is contained in:
Axel Dörfler
2008-06-03 13:22:24 +00:00
parent 2ecef3acbe
commit 557335a991
2 changed files with 82 additions and 61 deletions
+26 -56
View File
@@ -34,7 +34,7 @@
// (for example, the Pegasos (PPC based) also has an ISA bus) // (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; device_manager_info *pnp;
@@ -73,75 +73,54 @@ unlock_isa_dma_channel(long channel)
} }
#if 0 // #pragma mark - driver module API
static status_t 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; return B_OK;
} }
static status_t static void
isa_uninit_driver(void *cookie) isa_uninit_driver(void *cookie)
{ {
return B_OK;
} }
static float 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 // 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; return B_ERROR;
if (strcmp(bus, "root")) { if (strcmp(bus, "root"))
free(bus);
return 0.0; return 0.0;
}
free(bus);
return 1.0; return 1.0;
} }
static status_t static status_t
isa_register_device(device_node_handle parent) isa_register_device(device_node *parent)
{ {
static const device_attr attrs[] = { 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 // tell where to look for child devices
{ B_DRIVER_BUS, B_STRING_TYPE, { string: "isa" }}, {B_DEVICE_BUS, B_STRING_TYPE, {string: "isa" }},
{ B_DRIVER_FIND_DEVICES_ON_DEMAND, B_UINT8_TYPE, { ui8: 1 }}, {B_DEVICE_FLAGS, B_UINT32_TYPE,
{ B_DRIVER_EXPLORE_LAST, B_UINT8_TYPE, { ui8: 1 }}, {ui32: B_FIND_CHILD_ON_DEMAND | B_FIND_MULTIPLE_CHILDREN}},
{ NULL } {}
}; };
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 static status_t
std_ops(int32 op, ...) std_ops(int32 op, ...)
{ {
@@ -185,27 +164,19 @@ static isa_module_info isa_module = {
&unlock_isa_dma_channel &unlock_isa_dma_channel
}; };
#if 0
static isa2_module_info isa2_module = { static isa2_module_info isa2_module = {
{ {
{ {
{ ISA_MODULE_NAME,
ISA_MODULE_NAME, 0,
0, std_ops
std_ops
},
isa_supports_device,
isa_register_device,
isa_init_driver,
isa_uninit_driver,
NULL, // removed device
NULL, // cleanup device
isa_get_paths,
}, },
// as ISA relies on device drivers to detect their devices themselves, isa_supports_device,
// we don't have an universal rescan method isa_register_device,
isa_init_driver,
isa_uninit_driver,
NULL, // removed device
NULL, // register child devices NULL, // register child devices
NULL, // rescan bus NULL, // rescan bus
}, },
@@ -218,10 +189,9 @@ static isa2_module_info isa2_module = {
arch_start_isa_dma, arch_start_isa_dma,
}; };
#endif
module_info *modules[] = { module_info *modules[] = {
(module_info *)&isa_module, (module_info *)&isa_module,
// (module_info *)&isa2_module, (module_info *)&isa2_module,
NULL NULL
}; };
@@ -136,6 +136,8 @@ struct device_node : DoublyLinkedListLinkImpl<device_node> {
device_node* FindChild(const device_attr* attributes) const; device_node* FindChild(const device_attr* attributes) const;
device_node* FindChild(const char* moduleName) const; device_node* FindChild(const char* moduleName) const;
int32 Priority();
void Dump(int32 level = 0); void Dump(int32 level = 0);
private: private:
@@ -189,6 +191,7 @@ enum node_flags {
static device_node *sRootNode; static device_node *sRootNode;
static recursive_lock sLock; static recursive_lock sLock;
static const char* sGenericContextPath;
static uint32 sDriverUpdateCycle = 1; 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 // we must not be destroyed as long as we have children
Acquire(); Acquire();
node->fParent = this; 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; return B_NO_MEMORY;
StackDeleter<KPath*> stackDeleter(stack); StackDeleter<KPath*> stackDeleter(stack);
bool generic = false;
uint16 type = 0; uint16 type = 0;
uint16 subType = 0; uint16 subType = 0;
uint16 interface = 0; uint16 interface = 0;
get_attr_uint16(this, B_DEVICE_TYPE, &type, false); if (get_attr_uint16(this, B_DEVICE_TYPE, &type, false) != B_OK
get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false); || get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false)
!= B_OK)
generic = true;
get_attr_uint16(this, B_DEVICE_INTERFACE, &interface, false); get_attr_uint16(this, B_DEVICE_INTERFACE, &interface, false);
// TODO: maybe make this extendible via settings file? // TODO: maybe make this extendible via settings file?
@@ -1475,8 +1498,19 @@ device_node::_GetNextDriverPath(void*& cookie, KPath& _path)
if (sRootNode == this) { if (sRootNode == this) {
_AddPath(*stack, "busses/pci"); _AddPath(*stack, "busses/pci");
_AddPath(*stack, "bus_managers"); _AddPath(*stack, "bus_managers");
} else } else if (!generic) {
_AddPath(*stack, "drivers"); _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; break;
} }
@@ -1758,13 +1792,17 @@ device_node::Probe(const char* devicePath, uint32 updateCycle)
// This driver does not support types, but still wants to its // This driver does not support types, but still wants to its
// children explored on demand only. // children explored on demand only.
matches = true; matches = true;
sGenericContextPath = devicePath;
} }
if (matches) { if (matches) {
fLastUpdateCycle = updateCycle; fLastUpdateCycle = updateCycle;
// This node will be probed in this update cycle // This node will be probed in this update cycle
return _Probe(); status = _Probe();
sGenericContextPath = NULL;
return status;
} }
return B_OK; 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 void
device_node::Dump(int32 level) device_node::Dump(int32 level)
{ {