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:
@@ -10,7 +10,27 @@
|
|||||||
#include <PCI.h>
|
#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
|
// #pragma mark - bus
|
||||||
@@ -40,7 +60,7 @@ register_device(device_node *parent)
|
|||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
return gDeviceManager->register_device(parent, BUS_MODULE_NAME, attrs, NULL,
|
return gDeviceManager->register_node(parent, BUS_MODULE_NAME, attrs, NULL,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,12 +110,11 @@ register_child_devices(device_node *node)
|
|||||||
{B_DEVICE_INTERFACE, B_UINT16_TYPE,
|
{B_DEVICE_INTERFACE, B_UINT16_TYPE,
|
||||||
{ui16: kDevices[i].interface}},
|
{ui16: kDevices[i].interface}},
|
||||||
|
|
||||||
{B_DEVICE_FIND_CHILD_FLAGS, B_UINT32_TYPE,
|
{B_DEVICE_FLAGS, B_UINT32_TYPE, {ui32: B_FIND_CHILD_ON_DEMAND}},
|
||||||
{ui32: B_FIND_CHILD_ON_DEMAND}},
|
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
gDeviceManager->register_device(node, BUS_FOR_DRIVER_NAME, attrs, NULL,
|
gDeviceManager->register_node(node, BUS_FOR_DRIVER_NAME, attrs, NULL,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +126,7 @@ register_child_devices(device_node *node)
|
|||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
// this is supposed to fail
|
// 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));
|
BUS_FOR_DRIVER_NAME, attrs, NULL, NULL));
|
||||||
#endif
|
#endif
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|||||||
@@ -20,7 +20,14 @@ struct bus_for_driver_module_info {
|
|||||||
status_t (*get_bus_info)(void* cookie, bus_info* 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_FOR_DRIVER_NAME "bus_managers/sample_bus/device/driver_v1"
|
||||||
#define BUS_NAME "mybus"
|
#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
|
#endif // BUS_H
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include <util/DoublyLinkedList.h>
|
#include <util/DoublyLinkedList.h>
|
||||||
#include <util/Stack.h>
|
#include <util/Stack.h>
|
||||||
|
|
||||||
|
#include "bus.h"
|
||||||
|
|
||||||
#define TRACE(a) dprintf a
|
#define TRACE(a) dprintf a
|
||||||
|
|
||||||
@@ -69,7 +70,6 @@ private:
|
|||||||
|
|
||||||
typedef DoublyLinkedList<device_attr_private> AttributeList;
|
typedef DoublyLinkedList<device_attr_private> AttributeList;
|
||||||
|
|
||||||
|
|
||||||
// I/O resource
|
// I/O resource
|
||||||
typedef struct io_resource_info {
|
typedef struct io_resource_info {
|
||||||
struct io_resource_info *prev, *next;
|
struct io_resource_info *prev, *next;
|
||||||
@@ -77,13 +77,20 @@ typedef struct io_resource_info {
|
|||||||
io_resource resource; // info about actual resource
|
io_resource resource; // info about actual resource
|
||||||
} io_resource_info;
|
} 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;
|
device_node* node;
|
||||||
|
const char* path;
|
||||||
|
const char* module_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef DoublyLinkedList<device> DeviceList;
|
||||||
typedef DoublyLinkedList<device_node> NodeList;
|
typedef DoublyLinkedList<device_node> NodeList;
|
||||||
|
|
||||||
struct device_node : DoublyLinkedListLinkImpl<device_node> {
|
struct device_node : DoublyLinkedListLinkImpl<device_node> {
|
||||||
@@ -101,6 +108,7 @@ struct device_node : DoublyLinkedListLinkImpl<device_node> {
|
|||||||
|
|
||||||
status_t InitDriver();
|
status_t InitDriver();
|
||||||
bool UninitDriver();
|
bool UninitDriver();
|
||||||
|
void UninitUnusedDriver();
|
||||||
|
|
||||||
// The following two are only valid, if the node's driver is
|
// The following two are only valid, if the node's driver is
|
||||||
// initialized
|
// initialized
|
||||||
@@ -110,9 +118,9 @@ struct device_node : DoublyLinkedListLinkImpl<device_node> {
|
|||||||
void AddChild(device_node *node);
|
void AddChild(device_node *node);
|
||||||
void RemoveChild(device_node *node);
|
void RemoveChild(device_node *node);
|
||||||
const NodeList& Children() const { return fChildren; }
|
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);
|
status_t Probe(const char* devicePath);
|
||||||
bool IsRegistered() const { return fRegistered; }
|
bool IsRegistered() const { return fRegistered; }
|
||||||
bool IsInitialized() const { return fInitialized > 0; }
|
bool IsInitialized() const { return fInitialized > 0; }
|
||||||
@@ -122,6 +130,7 @@ struct device_node : DoublyLinkedListLinkImpl<device_node> {
|
|||||||
|
|
||||||
int CompareTo(const device_attr* attributes) const;
|
int CompareTo(const device_attr* attributes) const;
|
||||||
device_node* FindChild(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);
|
void Dump(int32 level = 0);
|
||||||
|
|
||||||
@@ -139,7 +148,6 @@ private:
|
|||||||
status_t _RegisterPath(const char* path);
|
status_t _RegisterPath(const char* path);
|
||||||
status_t _RegisterDynamic();
|
status_t _RegisterDynamic();
|
||||||
status_t _RemoveChildren();
|
status_t _RemoveChildren();
|
||||||
bool _UninitUnusedChildren();
|
|
||||||
|
|
||||||
device_node* fParent;
|
device_node* fParent;
|
||||||
NodeList fChildren;
|
NodeList fChildren;
|
||||||
@@ -147,16 +155,21 @@ private:
|
|||||||
int32 fInitialized;
|
int32 fInitialized;
|
||||||
bool fRegistered;
|
bool fRegistered;
|
||||||
uint32 fFlags;
|
uint32 fFlags;
|
||||||
|
float fSupportsParent;
|
||||||
|
|
||||||
const char* fModuleName;
|
const char* fModuleName;
|
||||||
|
|
||||||
driver_module_info* fDriver;
|
driver_module_info* fDriver;
|
||||||
void* fDriverData;
|
void* fDriverData;
|
||||||
|
|
||||||
AttributeList fAttributes;
|
AttributeList fAttributes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// flags in addition to those specified by B_DEVICE_FLAGS
|
||||||
enum node_flags {
|
enum node_flags {
|
||||||
NODE_FLAG_REMOVE_ON_UNINIT = 0x01
|
NODE_FLAG_REGISTER_INITIALIZED = 0x00010000,
|
||||||
|
|
||||||
|
NODE_FLAG_PUBLIC_MASK = 0x0000ffff
|
||||||
};
|
};
|
||||||
|
|
||||||
device_manager_info *gDeviceManager;
|
device_manager_info *gDeviceManager;
|
||||||
@@ -164,6 +177,9 @@ device_manager_info *gDeviceManager;
|
|||||||
static device_node *sRootNode;
|
static device_node *sRootNode;
|
||||||
static recursive_lock sLock;
|
static recursive_lock sLock;
|
||||||
|
|
||||||
|
static DeviceList sDeviceList;
|
||||||
|
// this is a *very* basic devfs emulation
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - device_attr
|
// #pragma mark - device_attr
|
||||||
|
|
||||||
@@ -376,19 +392,51 @@ dump_attribute(device_attr* attr, int32 level)
|
|||||||
static void
|
static void
|
||||||
uninit_unused()
|
uninit_unused()
|
||||||
{
|
{
|
||||||
|
puts("uninit unused");
|
||||||
RecursiveLocker _(sLock);
|
RecursiveLocker _(sLock);
|
||||||
sRootNode->UninitUnusedChildren();
|
sRootNode->UninitUnusedDriver();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
probe_path(const char* path)
|
probe_path(const char* path)
|
||||||
{
|
{
|
||||||
|
printf("probe path \"%s\"\n", path);
|
||||||
RecursiveLocker _(sLock);
|
RecursiveLocker _(sLock);
|
||||||
return sRootNode->Probe(path);
|
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
|
// #pragma mark - device_node
|
||||||
|
|
||||||
|
|
||||||
@@ -406,6 +454,8 @@ device_node::device_node(const char* moduleName, const device_attr* attrs,
|
|||||||
fRefCount = 1;
|
fRefCount = 1;
|
||||||
fInitialized = 0;
|
fInitialized = 0;
|
||||||
fRegistered = false;
|
fRegistered = false;
|
||||||
|
fFlags = 0;
|
||||||
|
fSupportsParent = 0.0;
|
||||||
fDriver = NULL;
|
fDriver = NULL;
|
||||||
fDriverData = NULL;
|
fDriverData = NULL;
|
||||||
|
|
||||||
@@ -420,12 +470,19 @@ device_node::device_node(const char* moduleName, const device_attr* attrs,
|
|||||||
fAttributes.Add(attr);
|
fAttributes.Add(attr);
|
||||||
attrs++;
|
attrs++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dm_get_attr_uint32(this, B_DEVICE_FLAGS, &fFlags, false);
|
||||||
|
fFlags &= NODE_FLAG_PUBLIC_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
device_node::~device_node()
|
device_node::~device_node()
|
||||||
{
|
{
|
||||||
TRACE(("delete node %p\n", this));
|
TRACE(("delete node %p\n", this));
|
||||||
|
ASSERT(DriverModule() == NULL);
|
||||||
|
|
||||||
|
if (Parent() != NULL)
|
||||||
|
Parent()->RemoveChild(this);
|
||||||
|
|
||||||
// Delete children
|
// Delete children
|
||||||
NodeList::Iterator nodeIterator = fChildren.GetIterator();
|
NodeList::Iterator nodeIterator = fChildren.GetIterator();
|
||||||
@@ -468,7 +525,7 @@ device_node::InitDriver()
|
|||||||
|
|
||||||
status_t status = get_module(ModuleName(), (module_info**)&fDriver);
|
status_t status = get_module(ModuleName(), (module_info**)&fDriver);
|
||||||
if (status == B_OK && Parent() != NULL) {
|
if (status == B_OK && Parent() != NULL) {
|
||||||
// our parent always have to be initialized
|
// our parent always has to be initialized
|
||||||
status = Parent()->InitDriver();
|
status = Parent()->InitDriver();
|
||||||
}
|
}
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
@@ -480,6 +537,8 @@ device_node::InitDriver()
|
|||||||
status = fDriver->init_driver(this, &fDriverData);
|
status = fDriver->init_driver(this, &fDriverData);
|
||||||
|
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
|
if (Parent() != NULL)
|
||||||
|
Parent()->UninitDriver();
|
||||||
fInitialized--;
|
fInitialized--;
|
||||||
|
|
||||||
put_module(ModuleName());
|
put_module(ModuleName());
|
||||||
@@ -497,9 +556,12 @@ bool
|
|||||||
device_node::UninitDriver()
|
device_node::UninitDriver()
|
||||||
{
|
{
|
||||||
if (fInitialized-- > 1) {
|
if (fInitialized-- > 1) {
|
||||||
|
if (Parent() != NULL)
|
||||||
|
Parent()->UninitDriver();
|
||||||
Release();
|
Release();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE(("uninit driver for node %p\n", this));
|
TRACE(("uninit driver for node %p\n", this));
|
||||||
|
|
||||||
if (fDriver->uninit_driver != NULL)
|
if (fDriver->uninit_driver != NULL)
|
||||||
@@ -510,12 +572,9 @@ device_node::UninitDriver()
|
|||||||
|
|
||||||
put_module(ModuleName());
|
put_module(ModuleName());
|
||||||
|
|
||||||
Release();
|
|
||||||
if (Parent() != NULL)
|
if (Parent() != NULL)
|
||||||
Parent()->UninitDriver();
|
Parent()->UninitDriver();
|
||||||
|
Release();
|
||||||
if ((fFlags & NODE_FLAG_REMOVE_ON_UNINIT) != 0)
|
|
||||||
Release();
|
|
||||||
|
|
||||||
return true;
|
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
|
status_t
|
||||||
device_node::Register()
|
device_node::Register(device_node* parent)
|
||||||
{
|
{
|
||||||
uint32 registered;
|
// make it public
|
||||||
status_t status = _RegisterFixed(registered);
|
if (parent != NULL)
|
||||||
|
parent->AddChild(this);
|
||||||
|
else
|
||||||
|
sRootNode = this;
|
||||||
|
|
||||||
|
status_t status = InitDriver();
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
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) {
|
if (registered > 0) {
|
||||||
fRegistered = true;
|
fRegistered = true;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -556,8 +640,10 @@ device_node::Register()
|
|||||||
|
|
||||||
if (DriverModule()->register_child_devices != NULL) {
|
if (DriverModule()->register_child_devices != NULL) {
|
||||||
status = DriverModule()->register_child_devices(this);
|
status = DriverModule()->register_child_devices(this);
|
||||||
if (status != B_OK)
|
if (status != B_OK) {
|
||||||
|
UninitUnusedDriver();
|
||||||
return status;
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
if (!fChildren.IsEmpty()) {
|
if (!fChildren.IsEmpty()) {
|
||||||
fRegistered = true;
|
fRegistered = true;
|
||||||
@@ -570,6 +656,8 @@ device_node::Register()
|
|||||||
status = _RegisterDynamic();
|
status = _RegisterDynamic();
|
||||||
if (status == B_OK)
|
if (status == B_OK)
|
||||||
fRegistered = true;
|
fRegistered = true;
|
||||||
|
else
|
||||||
|
UninitUnusedDriver();
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -578,7 +666,7 @@ device_node::Register()
|
|||||||
/*! Registers any children that are identified via the B_DRIVER_FIXED_CHILD
|
/*! Registers any children that are identified via the B_DRIVER_FIXED_CHILD
|
||||||
attribute.
|
attribute.
|
||||||
If any of these children cannot be registered, this call will fail (we
|
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
|
status_t
|
||||||
device_node::_RegisterFixed(uint32& registered)
|
device_node::_RegisterFixed(uint32& registered)
|
||||||
@@ -828,18 +916,15 @@ device_node::_AlwaysRegisterDynamic()
|
|||||||
status_t
|
status_t
|
||||||
device_node::_RegisterDynamic()
|
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
|
// If this is our initial registration, we honour the B_FIND_CHILD_ON_DEMAND
|
||||||
// requirements
|
// requirements
|
||||||
if (!fRegistered && (findFlags & B_FIND_CHILD_ON_DEMAND) != 0
|
if (!fRegistered && (fFlags & B_FIND_CHILD_ON_DEMAND) != 0
|
||||||
&& !_AlwaysRegisterDynamic())
|
&& !_AlwaysRegisterDynamic())
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
KPath path;
|
KPath path;
|
||||||
|
|
||||||
if ((findFlags & B_FIND_MULTIPLE_CHILDREN) == 0) {
|
if ((fFlags & B_FIND_MULTIPLE_CHILDREN) == 0) {
|
||||||
// find the one driver
|
// find the one driver
|
||||||
driver_module_info* bestDriver = NULL;
|
driver_module_info* bestDriver = NULL;
|
||||||
float bestSupport = 0.0;
|
float bestSupport = 0.0;
|
||||||
@@ -852,7 +937,16 @@ device_node::_RegisterDynamic()
|
|||||||
if (bestDriver != NULL) {
|
if (bestDriver != NULL) {
|
||||||
TRACE((" register best module \"%s\", support %f\n",
|
TRACE((" register best module \"%s\", support %f\n",
|
||||||
bestDriver->info.name, bestSupport));
|
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);
|
put_module(bestDriver->info.name);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -878,11 +972,12 @@ device_node::_RemoveChildren()
|
|||||||
// this child is not used currently, and can be removed safely
|
// this child is not used currently, and can be removed safely
|
||||||
iterator.Remove();
|
iterator.Remove();
|
||||||
child->fParent = NULL;
|
child->fParent = NULL;
|
||||||
delete child;
|
child->Release();
|
||||||
|
|
||||||
if (Release())
|
if (Release())
|
||||||
panic("died early");
|
panic("died early");
|
||||||
} else
|
} else
|
||||||
child->fFlags |= NODE_FLAG_REMOVE_ON_UNINIT;
|
child->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
return fChildren.IsEmpty() ? B_OK : B_BUSY;
|
return fChildren.IsEmpty() ? B_OK : B_BUSY;
|
||||||
@@ -939,7 +1034,7 @@ device_node::Probe(const char* devicePath)
|
|||||||
NodeList::Iterator iterator = fChildren.GetIterator();
|
NodeList::Iterator iterator = fChildren.GetIterator();
|
||||||
while (iterator.HasNext()) {
|
while (iterator.HasNext()) {
|
||||||
device_node* child = iterator.Next();
|
device_node* child = iterator.Next();
|
||||||
|
|
||||||
status = child->Probe(devicePath);
|
status = child->Probe(devicePath);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
@@ -949,42 +1044,57 @@ device_node::Probe(const char* devicePath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
/*! Uninitializes all temporary references to the driver. The registration
|
||||||
device_node::_UninitUnusedChildren()
|
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
|
// First, we need to go to the leaf, and go back from there
|
||||||
|
|
||||||
bool uninit = true;
|
|
||||||
|
|
||||||
NodeList::Iterator iterator = fChildren.GetIterator();
|
NodeList::Iterator iterator = fChildren.GetIterator();
|
||||||
|
|
||||||
while (iterator.HasNext()) {
|
while (iterator.HasNext()) {
|
||||||
device_node* child = iterator.Next();
|
device_node* child = iterator.Next();
|
||||||
|
|
||||||
if (!child->_UninitUnusedChildren())
|
child->UninitUnusedDriver();
|
||||||
uninit = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not all of our children could be uninitialized
|
if (!IsInitialized()
|
||||||
if (!uninit)
|
|| (fFlags & NODE_FLAG_REGISTER_INITIALIZED) == 0)
|
||||||
return false;
|
return;
|
||||||
|
|
||||||
if (!IsInitialized())
|
fFlags &= ~NODE_FLAG_REGISTER_INITIALIZED;
|
||||||
return true;
|
|
||||||
|
|
||||||
if ((DriverModule()->info.flags & B_KEEP_LOADED) != 0) {
|
UninitDriver();
|
||||||
// We must not get unloaded
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 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
|
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)
|
if (atomic_add(&fRefCount, -1) > 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (Parent() != NULL)
|
|
||||||
Parent()->RemoveChild(this);
|
|
||||||
delete this;
|
delete this;
|
||||||
return true;
|
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
|
void
|
||||||
device_node::Dump(int32 level = 0)
|
device_node::Dump(int32 level = 0)
|
||||||
{
|
{
|
||||||
@@ -1077,14 +1203,14 @@ device_node::Dump(int32 level = 0)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
rescan_device(device_node* node)
|
rescan_node(device_node* node)
|
||||||
{
|
{
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
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,
|
const device_attr* attrs, const io_resource* ioResources,
|
||||||
device_node** _node)
|
device_node** _node)
|
||||||
{
|
{
|
||||||
@@ -1103,7 +1229,7 @@ register_device(device_node* parent, const char* moduleName,
|
|||||||
if (newNode == NULL)
|
if (newNode == NULL)
|
||||||
return B_NO_MEMORY;
|
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));
|
parent));
|
||||||
|
|
||||||
RecursiveLocker _(sLock);
|
RecursiveLocker _(sLock);
|
||||||
@@ -1112,16 +1238,6 @@ register_device(device_node* parent, const char* moduleName,
|
|||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
goto err1;
|
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
|
#if 0
|
||||||
// The following is done to reduce the stack usage of deeply nested
|
// The following is done to reduce the stack usage of deeply nested
|
||||||
// child device nodes.
|
// child device nodes.
|
||||||
@@ -1136,7 +1252,7 @@ register_device(device_node* parent, const char* moduleName,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
status = newNode->Register();
|
status = newNode->Register(parent);
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
parent->RemoveChild(newNode);
|
parent->RemoveChild(newNode);
|
||||||
goto err1;
|
goto err1;
|
||||||
@@ -1148,15 +1264,27 @@ register_device(device_node* parent, const char* moduleName,
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
err1:
|
err1:
|
||||||
delete newNode;
|
newNode->Release();
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
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*
|
static device_node*
|
||||||
get_device_root(void)
|
get_root_node(void)
|
||||||
{
|
{
|
||||||
if (sRootNode != NULL)
|
if (sRootNode != NULL)
|
||||||
sRootNode->Acquire();
|
sRootNode->Acquire();
|
||||||
@@ -1186,15 +1314,48 @@ get_device_root(void)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
get_next_child_device(device_node* parent, device_node* _node,
|
get_next_child_node(device_node* parent, const device_attr* attributes,
|
||||||
const device_attr* attrs)
|
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*
|
static device_node*
|
||||||
get_parent(device_node* node)
|
get_parent_node(device_node* node)
|
||||||
{
|
{
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1209,13 +1370,50 @@ get_parent(device_node* node)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
put_device_node(device_node* node)
|
put_node(device_node* node)
|
||||||
{
|
{
|
||||||
RecursiveLocker _(sLock);
|
RecursiveLocker _(sLock);
|
||||||
node->Release();
|
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
|
status_t
|
||||||
dm_get_attr_uint8(const device_node* node, const char* name, uint8* _value,
|
dm_get_attr_uint8(const device_node* node, const char* name, uint8* _value,
|
||||||
bool recursive)
|
bool recursive)
|
||||||
@@ -1351,14 +1549,18 @@ static struct device_manager_info sDeviceManagerModule = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// device nodes
|
// device nodes
|
||||||
rescan_device,
|
rescan_node,
|
||||||
register_device,
|
register_node,
|
||||||
unregister_device,
|
unregister_node,
|
||||||
get_driver,
|
get_driver,
|
||||||
get_device_root,
|
get_root_node,
|
||||||
get_next_child_device,
|
get_next_child_node,
|
||||||
get_parent,
|
get_parent_node,
|
||||||
put_device_node,
|
put_node,
|
||||||
|
|
||||||
|
// devices
|
||||||
|
publish_device,
|
||||||
|
unpublish_device,
|
||||||
|
|
||||||
// attributes
|
// attributes
|
||||||
dm_get_attr_uint8,
|
dm_get_attr_uint8,
|
||||||
@@ -1380,12 +1582,12 @@ dm_init_root_node(void)
|
|||||||
device_attr attrs[] = {
|
device_attr attrs[] = {
|
||||||
{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "Devices Root"}},
|
{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "Devices Root"}},
|
||||||
{B_DEVICE_BUS, B_STRING_TYPE, {string: "root"}},
|
{B_DEVICE_BUS, B_STRING_TYPE, {string: "root"}},
|
||||||
{B_DEVICE_FIND_CHILD_FLAGS, B_UINT32_TYPE,
|
{B_DEVICE_FLAGS, B_UINT32_TYPE,
|
||||||
{ui32: B_FIND_MULTIPLE_CHILDREN}},
|
{ui32: B_FIND_MULTIPLE_CHILDREN | B_KEEP_DRIVER_LOADED }},
|
||||||
{NULL}
|
{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) {
|
!= B_OK) {
|
||||||
dprintf("Cannot register Devices Root Node\n");
|
dprintf("Cannot register Devices Root Node\n");
|
||||||
}
|
}
|
||||||
@@ -1439,12 +1641,19 @@ main(int argc, char** argv)
|
|||||||
|
|
||||||
probe_path("net");
|
probe_path("net");
|
||||||
probe_path("graphics");
|
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();
|
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 specific video driver - ie. simulate installing it
|
||||||
_add_builtin_module((module_info*)&gSpecificVideoDriverModuleInfo);
|
_add_builtin_module((module_info*)&gSpecificVideoDriverModuleInfo);
|
||||||
_add_builtin_module((module_info*)&gSpecificVideoDeviceModuleInfo);
|
_add_builtin_module((module_info*)&gSpecificVideoDeviceModuleInfo);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
#include <module.h>
|
#include <module.h>
|
||||||
|
|
||||||
|
|
||||||
// type of I/O resource
|
/* type of I/O resource */
|
||||||
enum {
|
enum {
|
||||||
IO_MEM = 1,
|
IO_MEM = 1,
|
||||||
IO_PORT = 2,
|
IO_PORT = 2,
|
||||||
@@ -19,33 +19,35 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// I/O resource description
|
/* I/O resource description */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32 type;
|
uint32 type;
|
||||||
// type of I/O resource
|
/* type of I/O resource */
|
||||||
|
|
||||||
uint32 base;
|
uint32 base;
|
||||||
// I/O memory: first physical address (32 bit)
|
/* I/O memory: first physical address (32 bit)
|
||||||
// I/O port: first port address (16 bit)
|
* I/O port: first port address (16 bit)
|
||||||
// ISA DMA channel: channel number (0-7)
|
* ISA DMA channel: channel number (0-7)
|
||||||
|
*/
|
||||||
|
|
||||||
uint32 length;
|
uint32 length;
|
||||||
// I/O memory: size of address range (32 bit)
|
/* I/O memory: size of address range (32 bit)
|
||||||
// I/O port: size of port range (16 bit)
|
* I/O port: size of port range (16 bit)
|
||||||
// ISA DMA channel: must be 1
|
* ISA DMA channel: must be 1
|
||||||
|
*/
|
||||||
} io_resource;
|
} io_resource;
|
||||||
|
|
||||||
// attribute of a device node
|
/* attribute of a device node */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
type_code type; // for supported types, see value
|
type_code type; /* for supported types, see value */
|
||||||
union {
|
union {
|
||||||
uint8 ui8; // B_UINT8_TYPE
|
uint8 ui8; /* B_UINT8_TYPE */
|
||||||
uint16 ui16; // B_UINT16_TYPE
|
uint16 ui16; /* B_UINT16_TYPE */
|
||||||
uint32 ui32; // B_UINT32_TYPE
|
uint32 ui32; /* B_UINT32_TYPE */
|
||||||
uint64 ui64; // B_UINT64_TYPE
|
uint64 ui64; /* B_UINT64_TYPE */
|
||||||
const char *string; // B_STRING_TYPE
|
const char *string; /* B_STRING_TYPE */
|
||||||
struct { // B_RAW_TYPE
|
struct { /* B_RAW_TYPE */
|
||||||
const void *data;
|
const void *data;
|
||||||
size_t length;
|
size_t length;
|
||||||
} raw;
|
} raw;
|
||||||
@@ -57,26 +59,30 @@ typedef struct device_node device_node;
|
|||||||
typedef struct driver_module_info driver_module_info;
|
typedef struct driver_module_info driver_module_info;
|
||||||
|
|
||||||
|
|
||||||
// interface of the device manager
|
/* interface of the device manager */
|
||||||
|
|
||||||
typedef struct device_manager_info {
|
typedef struct device_manager_info {
|
||||||
module_info 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,
|
const device_attr *attrs, const io_resource *ioResources,
|
||||||
device_node **_node);
|
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,
|
status_t (*get_driver)(device_node *node, driver_module_info **_module,
|
||||||
void **_cookie);
|
void **_cookie);
|
||||||
|
|
||||||
device_node *(*get_root_device)();
|
device_node *(*get_root_node)();
|
||||||
status_t (*get_next_child_device)(device_node *parent, device_node *node,
|
status_t (*get_next_child_node)(device_node *parent,
|
||||||
const device_attr *attrs);
|
const device_attr *attrs, device_node **node);
|
||||||
device_node *(*get_parent)(device_node *node);
|
device_node *(*get_parent_node)(device_node *node);
|
||||||
void (*put_device_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
|
#if 0
|
||||||
status_t (*acquire_io_resources)(io_resource *resources);
|
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"
|
#define B_DEVICE_MANAGER_MODULE_NAME "system/device_manager/v1"
|
||||||
|
|
||||||
|
|
||||||
// interface of device driver
|
/* interface of device driver */
|
||||||
|
|
||||||
struct driver_module_info {
|
struct driver_module_info {
|
||||||
module_info info;
|
module_info info;
|
||||||
@@ -128,7 +134,7 @@ struct driver_module_info {
|
|||||||
#define B_DEVICE_MAPPING "device/mapping" /* string */
|
#define B_DEVICE_MAPPING "device/mapping" /* string */
|
||||||
#define B_DEVICE_BUS "device/bus" /* string */
|
#define B_DEVICE_BUS "device/bus" /* string */
|
||||||
#define B_DEVICE_FIXED_CHILD "device/fixed child" /* 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_VENDOR_ID "device/vendor" /* uint16 */
|
||||||
#define B_DEVICE_ID "device/id" /* 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 */
|
#define B_DEVICE_UNIQUE_ID "device/unique id" /* string */
|
||||||
|
|
||||||
// find child flags
|
/* device flags */
|
||||||
#define B_FIND_CHILD_ON_DEMAND 0x01
|
#define B_FIND_CHILD_ON_DEMAND 0x01
|
||||||
#define B_FIND_MULTIPLE_CHILDREN 0x02
|
#define B_FIND_MULTIPLE_CHILDREN 0x02
|
||||||
|
#define B_KEEP_DRIVER_LOADED 0x04
|
||||||
|
|
||||||
|
|
||||||
// interface of device
|
/* interface of device */
|
||||||
|
|
||||||
typedef struct io_request io_request;
|
typedef struct io_request io_request;
|
||||||
|
|
||||||
struct device_module_info {
|
struct device_module_info {
|
||||||
module_info info;
|
module_info info;
|
||||||
|
|
||||||
status_t (*init_device)(void *cookie);
|
status_t (*init_device)(device_node *node, void **_deviceCookie);
|
||||||
void (*uninit_device)(void *cookie);
|
void (*uninit_device)(void *deviceCookie);
|
||||||
|
|
||||||
status_t (*device_open)(void *deviceCookie, int openMode, void **_cookie);
|
status_t (*device_open)(void *deviceCookie, int openMode, void **_cookie);
|
||||||
status_t (*device_close)(void *cookie);
|
status_t (*device_close)(void *cookie);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#define DRIVER_MODULE_NAME "drivers/net/sample_driver/driver_v1"
|
#define DRIVER_MODULE_NAME "drivers/net/sample_driver/driver_v1"
|
||||||
|
#define DRIVER_DEVICE_MODULE_NAME "drivers/net/sample_driver/device_v1"
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - driver
|
// #pragma mark - driver
|
||||||
@@ -48,7 +49,7 @@ supports_device(device_node *parent)
|
|||||||
static status_t
|
static status_t
|
||||||
register_device(device_node *parent)
|
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);
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +57,6 @@ register_device(device_node *parent)
|
|||||||
static status_t
|
static status_t
|
||||||
init_driver(device_node *node, void **_cookie)
|
init_driver(device_node *node, void **_cookie)
|
||||||
{
|
{
|
||||||
// also publishes any devices/nodes with dedicated calls
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,6 +70,8 @@ uninit_driver(device_node *node)
|
|||||||
static status_t
|
static status_t
|
||||||
register_child_devices(device_node *node)
|
register_child_devices(device_node *node)
|
||||||
{
|
{
|
||||||
|
gDeviceManager->publish_device(node, "net/sample/0",
|
||||||
|
DRIVER_DEVICE_MODULE_NAME);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +86,7 @@ device_removed(device_node *node)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
init_device(void *deviceCookie)
|
init_device(device_node *node, void **_deviceCookie)
|
||||||
{
|
{
|
||||||
// called once before one or several open() calls
|
// called once before one or several open() calls
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
@@ -171,7 +173,7 @@ struct driver_module_info gDriverModuleInfo = {
|
|||||||
|
|
||||||
struct device_module_info gDeviceModuleInfo = {
|
struct device_module_info gDeviceModuleInfo = {
|
||||||
{
|
{
|
||||||
"drivers/net/sample_driver/device_v1",
|
DRIVER_DEVICE_MODULE_NAME,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#define DRIVER_MODULE_NAME "drivers/graphics/generic_driver/driver_v1"
|
#define DRIVER_MODULE_NAME "drivers/graphics/generic_driver/driver_v1"
|
||||||
|
#define DRIVER_DEVICE_MODULE_NAME "drivers/graphics/generic_driver/device_v1"
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - driver
|
// #pragma mark - driver
|
||||||
@@ -41,7 +42,7 @@ supports_device(device_node *parent)
|
|||||||
static status_t
|
static status_t
|
||||||
register_device(device_node *parent)
|
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);
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +50,6 @@ register_device(device_node *parent)
|
|||||||
static status_t
|
static status_t
|
||||||
init_driver(device_node *node, void **_cookie)
|
init_driver(device_node *node, void **_cookie)
|
||||||
{
|
{
|
||||||
// also publishes any devices/nodes with dedicated calls
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,6 +63,8 @@ uninit_driver(device_node *node)
|
|||||||
static status_t
|
static status_t
|
||||||
register_child_devices(device_node *node)
|
register_child_devices(device_node *node)
|
||||||
{
|
{
|
||||||
|
gDeviceManager->publish_device(node, "graphics/generic/0",
|
||||||
|
DRIVER_DEVICE_MODULE_NAME);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +79,7 @@ device_removed(device_node *node)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
init_device(void *deviceCookie)
|
init_device(device_node *node, void **_deviceCookie)
|
||||||
{
|
{
|
||||||
// called once before one or several open() calls
|
// called once before one or several open() calls
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
@@ -164,7 +166,7 @@ struct driver_module_info gGenericVideoDriverModuleInfo = {
|
|||||||
|
|
||||||
struct device_module_info gGenericVideoDeviceModuleInfo = {
|
struct device_module_info gGenericVideoDeviceModuleInfo = {
|
||||||
{
|
{
|
||||||
"drivers/graphics/generic_driver/device_v1",
|
DRIVER_DEVICE_MODULE_NAME,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#define DRIVER_MODULE_NAME "drivers/graphics/specific_driver/driver_v1"
|
#define DRIVER_MODULE_NAME "drivers/graphics/specific_driver/driver_v1"
|
||||||
|
#define DRIVER_DEVICE_MODULE_NAME "drivers/graphics/specific_driver/device_v1"
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - driver
|
// #pragma mark - driver
|
||||||
@@ -39,7 +40,7 @@ supports_device(device_node *parent)
|
|||||||
static status_t
|
static status_t
|
||||||
register_device(device_node *parent)
|
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);
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +48,6 @@ register_device(device_node *parent)
|
|||||||
static status_t
|
static status_t
|
||||||
init_driver(device_node *node, void **_cookie)
|
init_driver(device_node *node, void **_cookie)
|
||||||
{
|
{
|
||||||
// also publishes any devices/nodes with dedicated calls
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,6 +61,8 @@ uninit_driver(device_node *node)
|
|||||||
static status_t
|
static status_t
|
||||||
register_child_devices(device_node *node)
|
register_child_devices(device_node *node)
|
||||||
{
|
{
|
||||||
|
gDeviceManager->publish_device(node, "graphics/specific/0",
|
||||||
|
DRIVER_DEVICE_MODULE_NAME);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +77,7 @@ device_removed(device_node *node)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
init_device(void *deviceCookie)
|
init_device(device_node *node, void **_deviceCookie)
|
||||||
{
|
{
|
||||||
// called once before one or several open() calls
|
// called once before one or several open() calls
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
@@ -162,7 +164,7 @@ struct driver_module_info gSpecificVideoDriverModuleInfo = {
|
|||||||
|
|
||||||
struct device_module_info gSpecificVideoDeviceModuleInfo = {
|
struct device_module_info gSpecificVideoDeviceModuleInfo = {
|
||||||
{
|
{
|
||||||
"drivers/graphics/specific_driver/device_v1",
|
DRIVER_DEVICE_MODULE_NAME,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user