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