* 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)
#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
};
@@ -136,6 +136,8 @@ struct device_node : DoublyLinkedListLinkImpl<device_node> {
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<KPath*> 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)
{