Work in progress:

* added [un]publish_device() calls to the device manager.
* added a very basic devfs emulation to the playground to be able to test how
  the manager reacts to opened devices.
* renamed *_device() functions to *_node() in the device manager API.
* made B_DEVICE_FIND_CHILD_FLAGS a generic flags field, and renamed it to
  B_DEVICE_FLAGS.
* added support for keeping a driver loaded as long as its device is available.
* implemented get_next_child_node().
* added test for device removal, and implemented unregister_node() for this.
* fixed some bugs in the device node reference/initialization count maintenance.
* moved more code from register_node() to device_node::Register().
* initialize the device_node::fFlags member to the value of B_DEVICE_FLAGS, and
  have additional private flags.
* renamed UninitUnusedChildren() to UninitUnusedDriver(), and fixed this
  function by adding the new flag NODE_FLAG_REGISTER_INITIALIZED.
* Now remembers the support when a driver is registered - this will be used
  later to be able to compare with a new driver without having to call
  supports_device() again.
* Removed NODE_FLAG_REMOVE_ON_UNINIT again, as that was pretty stupid - there
  is reference counting for a reason.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25498 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2008-05-14 20:05:40 +00:00
parent c27f3926a0
commit 7a6818d3fa
7 changed files with 384 additions and 136 deletions

View File

@ -10,7 +10,27 @@
#include <PCI.h>
#define BUS_MODULE_NAME "bus_managers/sample_bus/driver_v1"
void
bus_trigger_device_removed(device_node* node)
{
// the network device
device_attr attrs[] = {
{B_DEVICE_VENDOR_ID, B_UINT16_TYPE, {ui16: 0x1001}},
{B_DEVICE_ID, B_UINT16_TYPE, {ui16: 0x0001}},
{NULL}
};
device_node* child = NULL;
while (gDeviceManager->get_next_child_node(node, attrs, &child) == B_OK) {
gDeviceManager->unregister_node(child);
}
}
void
bus_trigger_device_added(device_node* node)
{
}
// #pragma mark - bus
@ -40,7 +60,7 @@ register_device(device_node *parent)
{NULL}
};
return gDeviceManager->register_device(parent, BUS_MODULE_NAME, attrs, NULL,
return gDeviceManager->register_node(parent, BUS_MODULE_NAME, attrs, NULL,
NULL);
}
@ -90,12 +110,11 @@ register_child_devices(device_node *node)
{B_DEVICE_INTERFACE, B_UINT16_TYPE,
{ui16: kDevices[i].interface}},
{B_DEVICE_FIND_CHILD_FLAGS, B_UINT32_TYPE,
{ui32: B_FIND_CHILD_ON_DEMAND}},
{B_DEVICE_FLAGS, B_UINT32_TYPE, {ui32: B_FIND_CHILD_ON_DEMAND}},
{NULL}
};
gDeviceManager->register_device(node, BUS_FOR_DRIVER_NAME, attrs, NULL,
gDeviceManager->register_node(node, BUS_FOR_DRIVER_NAME, attrs, NULL,
NULL);
}
@ -107,7 +126,7 @@ register_child_devices(device_node *node)
#if 1
// this is supposed to fail
dprintf("non-existing child: %ld\n", gDeviceManager->register_device(node,
dprintf("non-existing child: %ld\n", gDeviceManager->register_node(node,
BUS_FOR_DRIVER_NAME, attrs, NULL, NULL));
#endif
return B_OK;

View File

@ -20,7 +20,14 @@ struct bus_for_driver_module_info {
status_t (*get_bus_info)(void* cookie, bus_info* info);
};
// Note: this file is also used by the device manager test to control the bus
// driver
#define BUS_MODULE_NAME "bus_managers/sample_bus/driver_v1"
#define BUS_FOR_DRIVER_NAME "bus_managers/sample_bus/device/driver_v1"
#define BUS_NAME "mybus"
extern void bus_trigger_device_removed(device_node* node);
extern void bus_trigger_device_added(device_node* node);
#endif // BUS_H

View File

@ -22,6 +22,7 @@
#include <util/DoublyLinkedList.h>
#include <util/Stack.h>
#include "bus.h"
#define TRACE(a) dprintf a
@ -69,7 +70,6 @@ private:
typedef DoublyLinkedList<device_attr_private> AttributeList;
// I/O resource
typedef struct io_resource_info {
struct io_resource_info *prev, *next;
@ -77,13 +77,20 @@ typedef struct io_resource_info {
io_resource resource; // info about actual resource
} io_resource_info;
struct device : DoublyLinkedListLinkImpl<device> {
device() : node(NULL), path(NULL), module_name(NULL) {}
~device()
{
free((char*)path);
free((char*)module_name);
}
// a structure to put nodes into lists
struct node_entry {
struct list_link link;
device_node* node;
const char* path;
const char* module_name;
};
typedef DoublyLinkedList<device> DeviceList;
typedef DoublyLinkedList<device_node> NodeList;
struct device_node : DoublyLinkedListLinkImpl<device_node> {
@ -101,6 +108,7 @@ struct device_node : DoublyLinkedListLinkImpl<device_node> {
status_t InitDriver();
bool UninitDriver();
void UninitUnusedDriver();
// The following two are only valid, if the node's driver is
// initialized
@ -110,9 +118,9 @@ struct device_node : DoublyLinkedListLinkImpl<device_node> {
void AddChild(device_node *node);
void RemoveChild(device_node *node);
const NodeList& Children() const { return fChildren; }
void UninitUnusedChildren();
void DeviceRemoved();
status_t Register();
status_t Register(device_node* parent);
status_t Probe(const char* devicePath);
bool IsRegistered() const { return fRegistered; }
bool IsInitialized() const { return fInitialized > 0; }
@ -122,6 +130,7 @@ struct device_node : DoublyLinkedListLinkImpl<device_node> {
int CompareTo(const device_attr* attributes) const;
device_node* FindChild(const device_attr* attributes) const;
device_node* FindChild(const char* moduleName) const;
void Dump(int32 level = 0);
@ -139,7 +148,6 @@ private:
status_t _RegisterPath(const char* path);
status_t _RegisterDynamic();
status_t _RemoveChildren();
bool _UninitUnusedChildren();
device_node* fParent;
NodeList fChildren;
@ -147,16 +155,21 @@ private:
int32 fInitialized;
bool fRegistered;
uint32 fFlags;
float fSupportsParent;
const char* fModuleName;
driver_module_info* fDriver;
void* fDriverData;
AttributeList fAttributes;
};
// flags in addition to those specified by B_DEVICE_FLAGS
enum node_flags {
NODE_FLAG_REMOVE_ON_UNINIT = 0x01
NODE_FLAG_REGISTER_INITIALIZED = 0x00010000,
NODE_FLAG_PUBLIC_MASK = 0x0000ffff
};
device_manager_info *gDeviceManager;
@ -164,6 +177,9 @@ device_manager_info *gDeviceManager;
static device_node *sRootNode;
static recursive_lock sLock;
static DeviceList sDeviceList;
// this is a *very* basic devfs emulation
// #pragma mark - device_attr
@ -376,19 +392,51 @@ dump_attribute(device_attr* attr, int32 level)
static void
uninit_unused()
{
puts("uninit unused");
RecursiveLocker _(sLock);
sRootNode->UninitUnusedChildren();
sRootNode->UninitUnusedDriver();
}
static status_t
probe_path(const char* path)
{
printf("probe path \"%s\"\n", path);
RecursiveLocker _(sLock);
return sRootNode->Probe(path);
}
static void
close_path(void* cookie)
{
struct device* device = (struct device*)cookie;
printf("close path \"%s\" (node %p)\n", device->path, device->node);
device->node->UninitDriver();
}
static void*
open_path(const char* path)
{
DeviceList::Iterator iterator = sDeviceList.GetIterator();
while (iterator.HasNext()) {
struct device* device = iterator.Next();
if (!strcmp(device->path, path)) {
status_t status = device->node->InitDriver();
if (status != B_OK)
return NULL;
printf("open path \"%s\" (node %p)\n", device->path, device->node);
return device;
}
}
return NULL;
}
// #pragma mark - device_node
@ -406,6 +454,8 @@ device_node::device_node(const char* moduleName, const device_attr* attrs,
fRefCount = 1;
fInitialized = 0;
fRegistered = false;
fFlags = 0;
fSupportsParent = 0.0;
fDriver = NULL;
fDriverData = NULL;
@ -420,12 +470,19 @@ device_node::device_node(const char* moduleName, const device_attr* attrs,
fAttributes.Add(attr);
attrs++;
}
dm_get_attr_uint32(this, B_DEVICE_FLAGS, &fFlags, false);
fFlags &= NODE_FLAG_PUBLIC_MASK;
}
device_node::~device_node()
{
TRACE(("delete node %p\n", this));
ASSERT(DriverModule() == NULL);
if (Parent() != NULL)
Parent()->RemoveChild(this);
// Delete children
NodeList::Iterator nodeIterator = fChildren.GetIterator();
@ -468,7 +525,7 @@ device_node::InitDriver()
status_t status = get_module(ModuleName(), (module_info**)&fDriver);
if (status == B_OK && Parent() != NULL) {
// our parent always have to be initialized
// our parent always has to be initialized
status = Parent()->InitDriver();
}
if (status < B_OK) {
@ -480,6 +537,8 @@ device_node::InitDriver()
status = fDriver->init_driver(this, &fDriverData);
if (status < B_OK) {
if (Parent() != NULL)
Parent()->UninitDriver();
fInitialized--;
put_module(ModuleName());
@ -497,9 +556,12 @@ bool
device_node::UninitDriver()
{
if (fInitialized-- > 1) {
if (Parent() != NULL)
Parent()->UninitDriver();
Release();
return false;
}
TRACE(("uninit driver for node %p\n", this));
if (fDriver->uninit_driver != NULL)
@ -510,12 +572,9 @@ device_node::UninitDriver()
put_module(ModuleName());
Release();
if (Parent() != NULL)
Parent()->UninitDriver();
if ((fFlags & NODE_FLAG_REMOVE_ON_UNINIT) != 0)
Release();
Release();
return true;
}
@ -540,13 +599,38 @@ device_node::RemoveChild(device_node* node)
}
/*! Registers this node, and all of its children that have to be registered.
Also initializes the driver and keeps it that way on return in case
it returns successfully.
*/
status_t
device_node::Register()
device_node::Register(device_node* parent)
{
uint32 registered;
status_t status = _RegisterFixed(registered);
// make it public
if (parent != NULL)
parent->AddChild(this);
else
sRootNode = this;
status_t status = InitDriver();
if (status != B_OK)
return status;
if ((fFlags & B_KEEP_DRIVER_LOADED) != 0) {
// We keep this driver loaded by having it always initialized
InitDriver();
}
fFlags |= NODE_FLAG_REGISTER_INITIALIZED;
// We don't uninitialize the driver - this is done by the caller
// in order to save reinitializing during driver loading.
uint32 registered;
status = _RegisterFixed(registered);
if (status != B_OK) {
UninitUnusedDriver();
return status;
}
if (registered > 0) {
fRegistered = true;
return B_OK;
@ -556,8 +640,10 @@ device_node::Register()
if (DriverModule()->register_child_devices != NULL) {
status = DriverModule()->register_child_devices(this);
if (status != B_OK)
if (status != B_OK) {
UninitUnusedDriver();
return status;
}
if (!fChildren.IsEmpty()) {
fRegistered = true;
@ -570,6 +656,8 @@ device_node::Register()
status = _RegisterDynamic();
if (status == B_OK)
fRegistered = true;
else
UninitUnusedDriver();
return status;
}
@ -578,7 +666,7 @@ device_node::Register()
/*! Registers any children that are identified via the B_DRIVER_FIXED_CHILD
attribute.
If any of these children cannot be registered, this call will fail (we
don't remove already registered children in this case).
don't remove children we already registered up to this point in this case).
*/
status_t
device_node::_RegisterFixed(uint32& registered)
@ -828,18 +916,15 @@ device_node::_AlwaysRegisterDynamic()
status_t
device_node::_RegisterDynamic()
{
uint32 findFlags = 0;
dm_get_attr_uint32(this, B_DEVICE_FIND_CHILD_FLAGS, &findFlags, false);
// If this is our initial registration, we honour the B_FIND_CHILD_ON_DEMAND
// requirements
if (!fRegistered && (findFlags & B_FIND_CHILD_ON_DEMAND) != 0
if (!fRegistered && (fFlags & B_FIND_CHILD_ON_DEMAND) != 0
&& !_AlwaysRegisterDynamic())
return B_OK;
KPath path;
if ((findFlags & B_FIND_MULTIPLE_CHILDREN) == 0) {
if ((fFlags & B_FIND_MULTIPLE_CHILDREN) == 0) {
// find the one driver
driver_module_info* bestDriver = NULL;
float bestSupport = 0.0;
@ -852,7 +937,16 @@ device_node::_RegisterDynamic()
if (bestDriver != NULL) {
TRACE((" register best module \"%s\", support %f\n",
bestDriver->info.name, bestSupport));
bestDriver->register_device(this);
if (bestDriver->register_device(this) == B_OK) {
// There can only be one node of this driver
// (usually only one at all, but there might be a new driver
// "waiting" for its turn)
device_node* child = FindChild(bestDriver->info.name);
if (child != NULL)
child->fSupportsParent = bestSupport;
// TODO: if this fails, we could try the second best driver,
// and so on...
}
put_module(bestDriver->info.name);
}
} else {
@ -878,11 +972,12 @@ device_node::_RemoveChildren()
// this child is not used currently, and can be removed safely
iterator.Remove();
child->fParent = NULL;
delete child;
child->Release();
if (Release())
panic("died early");
} else
child->fFlags |= NODE_FLAG_REMOVE_ON_UNINIT;
child->Release();
}
return fChildren.IsEmpty() ? B_OK : B_BUSY;
@ -939,7 +1034,7 @@ device_node::Probe(const char* devicePath)
NodeList::Iterator iterator = fChildren.GetIterator();
while (iterator.HasNext()) {
device_node* child = iterator.Next();
status = child->Probe(devicePath);
if (status != B_OK)
return status;
@ -949,42 +1044,57 @@ device_node::Probe(const char* devicePath)
}
bool
device_node::_UninitUnusedChildren()
/*! Uninitializes all temporary references to the driver. The registration
process keeps the driver initialized to optimize the startup procedure;
this function gives this reference away again.
*/
void
device_node::UninitUnusedDriver()
{
// First, we need to go to the leaf, and go back from there
bool uninit = true;
NodeList::Iterator iterator = fChildren.GetIterator();
while (iterator.HasNext()) {
device_node* child = iterator.Next();
if (!child->_UninitUnusedChildren())
uninit = false;
child->UninitUnusedDriver();
}
// Not all of our children could be uninitialized
if (!uninit)
return false;
if (!IsInitialized()
|| (fFlags & NODE_FLAG_REGISTER_INITIALIZED) == 0)
return;
if (!IsInitialized())
return true;
fFlags &= ~NODE_FLAG_REGISTER_INITIALIZED;
if ((DriverModule()->info.flags & B_KEEP_LOADED) != 0) {
// We must not get unloaded
return false;
}
return UninitDriver();
UninitDriver();
}
/*! Calls device_removed() on this node and all of its children - starting
with the deepest and last child.
It will also remove the one reference that every node gets on its creation.
*/
void
device_node::UninitUnusedChildren()
device_node::DeviceRemoved()
{
_UninitUnusedChildren();
NodeList::ConstIterator iterator = Children().GetIterator();
while (iterator.HasNext()) {
device_node* child = iterator.Next();
child->DeviceRemoved();
}
if (IsInitialized() && DriverModule()->device_removed != NULL)
DriverModule()->device_removed(this);
if ((fFlags & B_KEEP_DRIVER_LOADED) != 0) {
// There is no point in keeping this driver loaded when its device
// is gone
UninitDriver();
}
UninitUnusedDriver();
Release();
}
@ -1001,8 +1111,6 @@ device_node::Release()
if (atomic_add(&fRefCount, -1) > 1)
return false;
if (Parent() != NULL)
Parent()->RemoveChild(this);
delete this;
return true;
}
@ -1054,6 +1162,24 @@ device_node::FindChild(const device_attr* attributes) const
}
device_node*
device_node::FindChild(const char* moduleName) const
{
if (moduleName == NULL)
return NULL;
NodeList::ConstIterator iterator = Children().GetIterator();
while (iterator.HasNext()) {
device_node* child = iterator.Next();
if (!strcmp(child->ModuleName(), moduleName))
return child;
}
return NULL;
}
void
device_node::Dump(int32 level = 0)
{
@ -1077,14 +1203,14 @@ device_node::Dump(int32 level = 0)
static status_t
rescan_device(device_node* node)
rescan_node(device_node* node)
{
return B_ERROR;
}
static status_t
register_device(device_node* parent, const char* moduleName,
register_node(device_node* parent, const char* moduleName,
const device_attr* attrs, const io_resource* ioResources,
device_node** _node)
{
@ -1103,7 +1229,7 @@ register_device(device_node* parent, const char* moduleName,
if (newNode == NULL)
return B_NO_MEMORY;
TRACE(("%p: register device \"%s\", parent %p\n", newNode, moduleName,
TRACE(("%p: register node \"%s\", parent %p\n", newNode, moduleName,
parent));
RecursiveLocker _(sLock);
@ -1112,16 +1238,6 @@ register_device(device_node* parent, const char* moduleName,
if (status != B_OK)
goto err1;
// make it public
if (parent != NULL)
parent->AddChild(newNode);
else
sRootNode = newNode;
status = newNode->InitDriver();
if (status != B_OK)
goto err1;
#if 0
// The following is done to reduce the stack usage of deeply nested
// child device nodes.
@ -1136,7 +1252,7 @@ register_device(device_node* parent, const char* moduleName,
}
#endif
status = newNode->Register();
status = newNode->Register(parent);
if (status < B_OK) {
parent->RemoveChild(newNode);
goto err1;
@ -1148,15 +1264,27 @@ register_device(device_node* parent, const char* moduleName,
return B_OK;
err1:
delete newNode;
newNode->Release();
return status;
}
static status_t
unregister_device(device_node* node)
unregister_node(device_node* node)
{
return B_ERROR;
TRACE(("unregister_node(node %p)\n", node));
RecursiveLocker _(sLock);
bool initialized = node->IsInitialized();
node->DeviceRemoved();
// TODO: We can't just remove it from its parent, as it might still be in
// use. However, we shouldn't really fail in this case, either.
// We should try to uninit the device - if it's just a bus, we can just do
// this. If it has devfs device, there are several options on how to do
// that (for example, by disconnecting the file descriptor).
return initialized ? B_BUSY : B_OK;
}
@ -1176,7 +1304,7 @@ get_driver(device_node* node, driver_module_info** _module, void** _data)
static device_node*
get_device_root(void)
get_root_node(void)
{
if (sRootNode != NULL)
sRootNode->Acquire();
@ -1186,15 +1314,48 @@ get_device_root(void)
static status_t
get_next_child_device(device_node* parent, device_node* _node,
const device_attr* attrs)
get_next_child_node(device_node* parent, const device_attr* attributes,
device_node** _node)
{
return B_ERROR;
RecursiveLocker _(sLock);
NodeList::ConstIterator iterator = parent->Children().GetIterator();
device_node* last = *_node;
// skip those we already traversed
while (iterator.HasNext() && last != NULL) {
device_node* node = iterator.Next();
if (node != last)
continue;
}
// find the next one that fits
while (iterator.HasNext()) {
device_node* node = iterator.Next();
if (!node->IsRegistered())
continue;
if (!node->CompareTo(attributes)) {
if (last != NULL)
last->Release();
node->Acquire();
*_node = node;
return B_OK;
}
}
if (last != NULL)
last->Release();
return B_ENTRY_NOT_FOUND;
}
static device_node*
get_parent(device_node* node)
get_parent_node(device_node* node)
{
if (node == NULL)
return NULL;
@ -1209,13 +1370,50 @@ get_parent(device_node* node)
static void
put_device_node(device_node* node)
put_node(device_node* node)
{
RecursiveLocker _(sLock);
node->Release();
}
static status_t
publish_device(device_node *node, const char *path, const char *moduleName)
{
RecursiveLocker _(sLock);
dprintf("publish device: node %p, path %s, module %s\n", node, path,
moduleName);
struct device* device = new(std::nothrow) ::device;
if (device == NULL)
return B_NO_MEMORY;
device->node = node;
device->path = strdup(path);
device->module_name = strdup(moduleName);
sDeviceList.Add(device);
return B_OK;
}
static status_t
unpublish_device(device_node *node, const char *path)
{
DeviceList::Iterator iterator = sDeviceList.GetIterator();
while (iterator.HasNext()) {
struct device* device = iterator.Next();
if (!strcmp(device->path, path)) {
iterator.Remove();
delete device;
return B_OK;
}
}
return B_ENTRY_NOT_FOUND;
}
status_t
dm_get_attr_uint8(const device_node* node, const char* name, uint8* _value,
bool recursive)
@ -1351,14 +1549,18 @@ static struct device_manager_info sDeviceManagerModule = {
},
// device nodes
rescan_device,
register_device,
unregister_device,
rescan_node,
register_node,
unregister_node,
get_driver,
get_device_root,
get_next_child_device,
get_parent,
put_device_node,
get_root_node,
get_next_child_node,
get_parent_node,
put_node,
// devices
publish_device,
unpublish_device,
// attributes
dm_get_attr_uint8,
@ -1380,12 +1582,12 @@ dm_init_root_node(void)
device_attr attrs[] = {
{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "Devices Root"}},
{B_DEVICE_BUS, B_STRING_TYPE, {string: "root"}},
{B_DEVICE_FIND_CHILD_FLAGS, B_UINT32_TYPE,
{ui32: B_FIND_MULTIPLE_CHILDREN}},
{B_DEVICE_FLAGS, B_UINT32_TYPE,
{ui32: B_FIND_MULTIPLE_CHILDREN | B_KEEP_DRIVER_LOADED }},
{NULL}
};
if (register_device(NULL, DEVICE_MANAGER_ROOT_NAME, attrs, NULL, NULL)
if (register_node(NULL, DEVICE_MANAGER_ROOT_NAME, attrs, NULL, NULL)
!= B_OK) {
dprintf("Cannot register Devices Root Node\n");
}
@ -1439,12 +1641,19 @@ main(int argc, char** argv)
probe_path("net");
probe_path("graphics");
// TODO: opened devices need to keep a "initialized" reference of the
// device_node
sRootNode->Dump();
void* graphicsHandle = open_path("graphics/generic/0");
// void* netHandle = open_path("net/sample/0");
uninit_unused();
puts("remove net driver");
device_node* busNode = sRootNode->FindChild(BUS_MODULE_NAME);
bus_trigger_device_removed(busNode);
close_path(graphicsHandle);
// close_path(netHandle);
// add specific video driver - ie. simulate installing it
_add_builtin_module((module_info*)&gSpecificVideoDriverModuleInfo);
_add_builtin_module((module_info*)&gSpecificVideoDeviceModuleInfo);

View File

@ -11,7 +11,7 @@
#include <module.h>
// type of I/O resource
/* type of I/O resource */
enum {
IO_MEM = 1,
IO_PORT = 2,
@ -19,33 +19,35 @@ enum {
};
// I/O resource description
/* I/O resource description */
typedef struct {
uint32 type;
// type of I/O resource
/* type of I/O resource */
uint32 base;
// I/O memory: first physical address (32 bit)
// I/O port: first port address (16 bit)
// ISA DMA channel: channel number (0-7)
/* I/O memory: first physical address (32 bit)
* I/O port: first port address (16 bit)
* ISA DMA channel: channel number (0-7)
*/
uint32 length;
// I/O memory: size of address range (32 bit)
// I/O port: size of port range (16 bit)
// ISA DMA channel: must be 1
/* I/O memory: size of address range (32 bit)
* I/O port: size of port range (16 bit)
* ISA DMA channel: must be 1
*/
} io_resource;
// attribute of a device node
/* attribute of a device node */
typedef struct {
const char *name;
type_code type; // for supported types, see value
type_code type; /* for supported types, see value */
union {
uint8 ui8; // B_UINT8_TYPE
uint16 ui16; // B_UINT16_TYPE
uint32 ui32; // B_UINT32_TYPE
uint64 ui64; // B_UINT64_TYPE
const char *string; // B_STRING_TYPE
struct { // B_RAW_TYPE
uint8 ui8; /* B_UINT8_TYPE */
uint16 ui16; /* B_UINT16_TYPE */
uint32 ui32; /* B_UINT32_TYPE */
uint64 ui64; /* B_UINT64_TYPE */
const char *string; /* B_STRING_TYPE */
struct { /* B_RAW_TYPE */
const void *data;
size_t length;
} raw;
@ -57,26 +59,30 @@ typedef struct device_node device_node;
typedef struct driver_module_info driver_module_info;
// interface of the device manager
/* interface of the device manager */
typedef struct device_manager_info {
module_info info;
status_t (*rescan)(device_node *node);
status_t (*rescan_node)(device_node *node);
status_t (*register_device)(device_node *parent, const char *moduleName,
status_t (*register_node)(device_node *parent, const char *moduleName,
const device_attr *attrs, const io_resource *ioResources,
device_node **_node);
status_t (*unregister_device)(device_node *node);
status_t (*unregister_node)(device_node *node);
status_t (*get_driver)(device_node *node, driver_module_info **_module,
void **_cookie);
device_node *(*get_root_device)();
status_t (*get_next_child_device)(device_node *parent, device_node *node,
const device_attr *attrs);
device_node *(*get_parent)(device_node *node);
void (*put_device_node)(device_node *node);
device_node *(*get_root_node)();
status_t (*get_next_child_node)(device_node *parent,
const device_attr *attrs, device_node **node);
device_node *(*get_parent_node)(device_node *node);
void (*put_node)(device_node *node);
status_t (*publish_device)(device_node *node, const char *path,
const char *deviceModuleName);
status_t (*unpublish_device)(device_node *node, const char *path);
#if 0
status_t (*acquire_io_resources)(io_resource *resources);
@ -106,7 +112,7 @@ typedef struct device_manager_info {
#define B_DEVICE_MANAGER_MODULE_NAME "system/device_manager/v1"
// interface of device driver
/* interface of device driver */
struct driver_module_info {
module_info info;
@ -128,7 +134,7 @@ struct driver_module_info {
#define B_DEVICE_MAPPING "device/mapping" /* string */
#define B_DEVICE_BUS "device/bus" /* string */
#define B_DEVICE_FIXED_CHILD "device/fixed child" /* string */
#define B_DEVICE_FIND_CHILD_FLAGS "device/find child flags" /* uint32 */
#define B_DEVICE_FLAGS "device/flags" /* uint32 */
#define B_DEVICE_VENDOR_ID "device/vendor" /* uint16 */
#define B_DEVICE_ID "device/id" /* uint16 */
@ -141,20 +147,21 @@ struct driver_module_info {
#define B_DEVICE_UNIQUE_ID "device/unique id" /* string */
// find child flags
/* device flags */
#define B_FIND_CHILD_ON_DEMAND 0x01
#define B_FIND_MULTIPLE_CHILDREN 0x02
#define B_KEEP_DRIVER_LOADED 0x04
// interface of device
/* interface of device */
typedef struct io_request io_request;
struct device_module_info {
module_info info;
status_t (*init_device)(void *cookie);
void (*uninit_device)(void *cookie);
status_t (*init_device)(device_node *node, void **_deviceCookie);
void (*uninit_device)(void *deviceCookie);
status_t (*device_open)(void *deviceCookie, int openMode, void **_cookie);
status_t (*device_close)(void *cookie);

View File

@ -10,6 +10,7 @@
#define DRIVER_MODULE_NAME "drivers/net/sample_driver/driver_v1"
#define DRIVER_DEVICE_MODULE_NAME "drivers/net/sample_driver/device_v1"
// #pragma mark - driver
@ -48,7 +49,7 @@ supports_device(device_node *parent)
static status_t
register_device(device_node *parent)
{
return gDeviceManager->register_device(parent, DRIVER_MODULE_NAME, NULL,
return gDeviceManager->register_node(parent, DRIVER_MODULE_NAME, NULL,
NULL, NULL);
}
@ -56,7 +57,6 @@ register_device(device_node *parent)
static status_t
init_driver(device_node *node, void **_cookie)
{
// also publishes any devices/nodes with dedicated calls
return B_OK;
}
@ -70,6 +70,8 @@ uninit_driver(device_node *node)
static status_t
register_child_devices(device_node *node)
{
gDeviceManager->publish_device(node, "net/sample/0",
DRIVER_DEVICE_MODULE_NAME);
return B_OK;
}
@ -84,7 +86,7 @@ device_removed(device_node *node)
static status_t
init_device(void *deviceCookie)
init_device(device_node *node, void **_deviceCookie)
{
// called once before one or several open() calls
return B_ERROR;
@ -171,7 +173,7 @@ struct driver_module_info gDriverModuleInfo = {
struct device_module_info gDeviceModuleInfo = {
{
"drivers/net/sample_driver/device_v1",
DRIVER_DEVICE_MODULE_NAME,
0,
NULL,
},

View File

@ -11,6 +11,7 @@
#define DRIVER_MODULE_NAME "drivers/graphics/generic_driver/driver_v1"
#define DRIVER_DEVICE_MODULE_NAME "drivers/graphics/generic_driver/device_v1"
// #pragma mark - driver
@ -41,7 +42,7 @@ supports_device(device_node *parent)
static status_t
register_device(device_node *parent)
{
return gDeviceManager->register_device(parent, DRIVER_MODULE_NAME, NULL,
return gDeviceManager->register_node(parent, DRIVER_MODULE_NAME, NULL,
NULL, NULL);
}
@ -49,7 +50,6 @@ register_device(device_node *parent)
static status_t
init_driver(device_node *node, void **_cookie)
{
// also publishes any devices/nodes with dedicated calls
return B_OK;
}
@ -63,6 +63,8 @@ uninit_driver(device_node *node)
static status_t
register_child_devices(device_node *node)
{
gDeviceManager->publish_device(node, "graphics/generic/0",
DRIVER_DEVICE_MODULE_NAME);
return B_OK;
}
@ -77,7 +79,7 @@ device_removed(device_node *node)
static status_t
init_device(void *deviceCookie)
init_device(device_node *node, void **_deviceCookie)
{
// called once before one or several open() calls
return B_ERROR;
@ -164,7 +166,7 @@ struct driver_module_info gGenericVideoDriverModuleInfo = {
struct device_module_info gGenericVideoDeviceModuleInfo = {
{
"drivers/graphics/generic_driver/device_v1",
DRIVER_DEVICE_MODULE_NAME,
0,
NULL,
},

View File

@ -11,6 +11,7 @@
#define DRIVER_MODULE_NAME "drivers/graphics/specific_driver/driver_v1"
#define DRIVER_DEVICE_MODULE_NAME "drivers/graphics/specific_driver/device_v1"
// #pragma mark - driver
@ -39,7 +40,7 @@ supports_device(device_node *parent)
static status_t
register_device(device_node *parent)
{
return gDeviceManager->register_device(parent, DRIVER_MODULE_NAME, NULL,
return gDeviceManager->register_node(parent, DRIVER_MODULE_NAME, NULL,
NULL, NULL);
}
@ -47,7 +48,6 @@ register_device(device_node *parent)
static status_t
init_driver(device_node *node, void **_cookie)
{
// also publishes any devices/nodes with dedicated calls
return B_OK;
}
@ -61,6 +61,8 @@ uninit_driver(device_node *node)
static status_t
register_child_devices(device_node *node)
{
gDeviceManager->publish_device(node, "graphics/specific/0",
DRIVER_DEVICE_MODULE_NAME);
return B_OK;
}
@ -75,7 +77,7 @@ device_removed(device_node *node)
static status_t
init_device(void *deviceCookie)
init_device(device_node *node, void **_deviceCookie)
{
// called once before one or several open() calls
return B_ERROR;
@ -162,7 +164,7 @@ struct driver_module_info gSpecificVideoDriverModuleInfo = {
struct device_module_info gSpecificVideoDeviceModuleInfo = {
{
"drivers/graphics/specific_driver/device_v1",
DRIVER_DEVICE_MODULE_NAME,
0,
NULL,
},