More work-in-progress:
* Added a generic (for all devices) and specific (for a specific device) video driver to be able to play with the replace mechanism (which is not yet done, but works well for the one usage case tested). * Added reference counting and initialize counting: now, each node owns a reference of its parent, and each initialized node owns an initialization reference of its parent. * Added locking. * Moved dump functionality into a member function. * The same node can now only added once - ie. if a bus tries to register the same device twice, it will fail. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25453 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
dd6eebabfe
commit
548c508ff7
@ -12,6 +12,8 @@ SimpleTest device_manager :
|
||||
|
||||
bus.cpp
|
||||
driver.cpp
|
||||
generic_video_driver.cpp
|
||||
specific_video_driver.cpp
|
||||
|
||||
: be libkernelland_emu.so
|
||||
;
|
||||
|
@ -71,6 +71,7 @@ register_child_devices(device_node *node)
|
||||
} kDevices[] = {
|
||||
{0x1000, 0x0001, PCI_mass_storage, PCI_sata, PCI_sata_ahci},
|
||||
{0x1001, 0x0001, PCI_network, PCI_ethernet, 0},
|
||||
{0x1001, 0x0002, PCI_display, 0, 0},
|
||||
{0x1002, 0x0001, PCI_multimedia, PCI_audio, 0},
|
||||
{0x1002, 0x0002, PCI_serial_bus, PCI_usb, PCI_usb_ehci},
|
||||
};
|
||||
|
@ -29,6 +29,10 @@
|
||||
|
||||
extern struct device_module_info gDeviceModuleInfo;
|
||||
extern struct driver_module_info gDriverModuleInfo;
|
||||
extern struct device_module_info gGenericVideoDeviceModuleInfo;
|
||||
extern struct driver_module_info gGenericVideoDriverModuleInfo;
|
||||
extern struct device_module_info gSpecificVideoDeviceModuleInfo;
|
||||
extern struct driver_module_info gSpecificVideoDriverModuleInfo;
|
||||
extern struct driver_module_info gBusModuleInfo;
|
||||
extern struct driver_module_info gBusDriverModuleInfo;
|
||||
|
||||
@ -113,6 +117,14 @@ struct device_node : DoublyLinkedListLinkImpl<device_node> {
|
||||
bool IsRegistered() const { return fRegistered; }
|
||||
bool IsInitialized() const { return fInitialized > 0; }
|
||||
|
||||
void Acquire();
|
||||
bool Release();
|
||||
|
||||
int CompareTo(const device_attr* attributes) const;
|
||||
device_node* FindChild(const device_attr* attributes) const;
|
||||
|
||||
void Dump(int32 level = 0);
|
||||
|
||||
private:
|
||||
status_t _RegisterFixed(uint32& registered);
|
||||
bool _AlwaysRegisterDynamic();
|
||||
@ -361,27 +373,6 @@ dump_attribute(device_attr* attr, int32 level)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
dm_dump_node(device_node* node, int32 level)
|
||||
{
|
||||
if (node == NULL)
|
||||
return;
|
||||
|
||||
put_level(level);
|
||||
dprintf("(%ld) @%p \"%s\"\n", level, node, node->ModuleName());
|
||||
|
||||
AttributeList::Iterator attribute = node->Attributes().GetIterator();
|
||||
while (attribute.HasNext()) {
|
||||
dump_attribute(attribute.Next(), level);
|
||||
}
|
||||
|
||||
NodeList::ConstIterator iterator = node->Children().GetIterator();
|
||||
while (iterator.HasNext()) {
|
||||
dm_dump_node(iterator.Next(), level + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
uninit_unused()
|
||||
{
|
||||
@ -434,6 +425,8 @@ device_node::device_node(const char* moduleName, const device_attr* attrs,
|
||||
|
||||
device_node::~device_node()
|
||||
{
|
||||
TRACE(("delete node %p\n", this));
|
||||
|
||||
// Delete children
|
||||
NodeList::Iterator nodeIterator = fChildren.GetIterator();
|
||||
while (nodeIterator.HasNext()) {
|
||||
@ -464,10 +457,20 @@ device_node::InitCheck()
|
||||
status_t
|
||||
device_node::InitDriver()
|
||||
{
|
||||
if (fInitialized++ > 0)
|
||||
if (fInitialized++ > 0) {
|
||||
if (Parent() != NULL) {
|
||||
Parent()->InitDriver();
|
||||
// acquire another reference to our parent as well
|
||||
}
|
||||
Acquire();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t status = get_module(ModuleName(), (module_info**)&fDriver);
|
||||
if (status == B_OK && Parent() != NULL) {
|
||||
// our parent always have to be initialized
|
||||
status = Parent()->InitDriver();
|
||||
}
|
||||
if (status < B_OK) {
|
||||
fInitialized--;
|
||||
return status;
|
||||
@ -475,12 +478,17 @@ device_node::InitDriver()
|
||||
|
||||
if (fDriver->init_driver != NULL)
|
||||
status = fDriver->init_driver(this, &fDriverData);
|
||||
|
||||
if (status < B_OK) {
|
||||
fInitialized--;
|
||||
|
||||
put_module(ModuleName());
|
||||
fDriver = NULL;
|
||||
fDriverData = NULL;
|
||||
return status;
|
||||
}
|
||||
|
||||
Acquire();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -488,8 +496,11 @@ device_node::InitDriver()
|
||||
bool
|
||||
device_node::UninitDriver()
|
||||
{
|
||||
if (fInitialized-- > 1)
|
||||
if (fInitialized-- > 1) {
|
||||
Release();
|
||||
return false;
|
||||
}
|
||||
TRACE(("uninit driver for node %p\n", this));
|
||||
|
||||
if (fDriver->uninit_driver != NULL)
|
||||
fDriver->uninit_driver(this);
|
||||
@ -499,8 +510,12 @@ device_node::UninitDriver()
|
||||
|
||||
put_module(ModuleName());
|
||||
|
||||
Release();
|
||||
if (Parent() != NULL)
|
||||
Parent()->UninitDriver();
|
||||
|
||||
if ((fFlags & NODE_FLAG_REMOVE_ON_UNINIT) != 0)
|
||||
delete this;
|
||||
Release();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -510,7 +525,7 @@ void
|
||||
device_node::AddChild(device_node* node)
|
||||
{
|
||||
// we must not be destroyed as long as we have children
|
||||
fRefCount++;
|
||||
Acquire();
|
||||
node->fParent = this;
|
||||
fChildren.Add(node);
|
||||
}
|
||||
@ -519,10 +534,9 @@ device_node::AddChild(device_node* node)
|
||||
void
|
||||
device_node::RemoveChild(device_node* node)
|
||||
{
|
||||
fRefCount--;
|
||||
// TODO: we may need to destruct ourselves here!
|
||||
node->fParent = NULL;
|
||||
fChildren.Remove(node);
|
||||
Release();
|
||||
}
|
||||
|
||||
|
||||
@ -784,7 +798,8 @@ device_node::_RegisterPath(const char* path)
|
||||
while (_GetNextDriver(list, driver) == B_OK) {
|
||||
float support = driver->supports_device(this);
|
||||
if (support > 0.0) {
|
||||
printf(" register module \"%s\", support %f\n", driver->info.name, support);
|
||||
TRACE((" register module \"%s\", support %f\n", driver->info.name,
|
||||
support));
|
||||
if (driver->register_device(this) == B_OK)
|
||||
count++;
|
||||
}
|
||||
@ -835,7 +850,8 @@ device_node::_RegisterDynamic()
|
||||
}
|
||||
|
||||
if (bestDriver != NULL) {
|
||||
printf(" register best module \"%s\", support %f\n", bestDriver->info.name, bestSupport);
|
||||
TRACE((" register best module \"%s\", support %f\n",
|
||||
bestDriver->info.name, bestSupport));
|
||||
bestDriver->register_device(this);
|
||||
put_module(bestDriver->info.name);
|
||||
}
|
||||
@ -861,9 +877,10 @@ device_node::_RemoveChildren()
|
||||
if (!child->IsInitialized()) {
|
||||
// this child is not used currently, and can be removed safely
|
||||
iterator.Remove();
|
||||
fRefCount--;
|
||||
child->fParent = NULL;
|
||||
delete child;
|
||||
if (Release())
|
||||
panic("died early");
|
||||
} else
|
||||
child->fFlags |= NODE_FLAG_REMOVE_ON_UNINIT;
|
||||
}
|
||||
@ -875,6 +892,12 @@ device_node::_RemoveChildren()
|
||||
status_t
|
||||
device_node::Probe(const char* devicePath)
|
||||
{
|
||||
status_t status = InitDriver();
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
MethodDeleter<device_node, bool> uninit(this, &device_node::UninitDriver);
|
||||
|
||||
uint16 type = 0;
|
||||
uint16 subType = 0;
|
||||
if (dm_get_attr_uint16(this, B_DEVICE_TYPE, &type, false) == B_OK
|
||||
@ -917,7 +940,7 @@ device_node::Probe(const char* devicePath)
|
||||
while (iterator.HasNext()) {
|
||||
device_node* child = iterator.Next();
|
||||
|
||||
status_t status = child->Probe(devicePath);
|
||||
status = child->Probe(devicePath);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
}
|
||||
@ -965,6 +988,91 @@ device_node::UninitUnusedChildren()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
device_node::Acquire()
|
||||
{
|
||||
atomic_add(&fRefCount, 1);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
device_node::Release()
|
||||
{
|
||||
if (atomic_add(&fRefCount, -1) > 1)
|
||||
return false;
|
||||
|
||||
if (Parent() != NULL)
|
||||
Parent()->RemoveChild(this);
|
||||
delete this;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
device_node::CompareTo(const device_attr* attributes) const
|
||||
{
|
||||
if (attributes == NULL)
|
||||
return -1;
|
||||
|
||||
for (; attributes->name != NULL; attributes++) {
|
||||
// find corresponding attribute
|
||||
AttributeList::ConstIterator iterator = Attributes().GetIterator();
|
||||
device_attr_private* attr = NULL;
|
||||
while (iterator.HasNext()) {
|
||||
attr = iterator.Next();
|
||||
|
||||
if (!strcmp(attr->name, attributes->name))
|
||||
break;
|
||||
}
|
||||
if (!iterator.HasNext())
|
||||
return -1;
|
||||
|
||||
int compare = device_attr_private::Compare(attr, attributes);
|
||||
if (compare != 0)
|
||||
return compare;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
device_node*
|
||||
device_node::FindChild(const device_attr* attributes) const
|
||||
{
|
||||
if (attributes == NULL)
|
||||
return NULL;
|
||||
|
||||
NodeList::ConstIterator iterator = Children().GetIterator();
|
||||
while (iterator.HasNext()) {
|
||||
device_node* child = iterator.Next();
|
||||
|
||||
if (!child->CompareTo(attributes))
|
||||
return child;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
device_node::Dump(int32 level = 0)
|
||||
{
|
||||
put_level(level);
|
||||
dprintf("(%ld) @%p \"%s\" (ref %ld, init %ld)\n", level, this, ModuleName(),
|
||||
fRefCount, fInitialized);
|
||||
|
||||
AttributeList::Iterator attribute = Attributes().GetIterator();
|
||||
while (attribute.HasNext()) {
|
||||
dump_attribute(attribute.Next(), level);
|
||||
}
|
||||
|
||||
NodeList::ConstIterator iterator = Children().GetIterator();
|
||||
while (iterator.HasNext()) {
|
||||
iterator.Next()->Dump(level + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - Device Manager module API
|
||||
|
||||
|
||||
@ -983,6 +1091,11 @@ register_device(device_node* parent, const char* moduleName,
|
||||
if ((parent == NULL && sRootNode != NULL) || moduleName == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (parent != NULL && parent->FindChild(attrs) != NULL) {
|
||||
// A node like this one already exists for this parent
|
||||
return B_NAME_IN_USE;
|
||||
}
|
||||
|
||||
// TODO: handle I/O resources!
|
||||
|
||||
device_node *newNode = new(std::nothrow) device_node(moduleName, attrs,
|
||||
@ -999,16 +1112,16 @@ register_device(device_node* parent, const char* moduleName,
|
||||
if (status != B_OK)
|
||||
goto err1;
|
||||
|
||||
status = newNode->InitDriver();
|
||||
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.
|
||||
@ -1063,8 +1176,11 @@ get_driver(device_node* node, driver_module_info** _module, void** _data)
|
||||
|
||||
|
||||
static device_node*
|
||||
device_root(void)
|
||||
get_device_root(void)
|
||||
{
|
||||
if (sRootNode != NULL)
|
||||
sRootNode->Acquire();
|
||||
|
||||
return sRootNode;
|
||||
}
|
||||
|
||||
@ -1080,13 +1196,23 @@ get_next_child_device(device_node* parent, device_node* _node,
|
||||
static device_node*
|
||||
get_parent(device_node* node)
|
||||
{
|
||||
return NULL;
|
||||
if (node == NULL)
|
||||
return NULL;
|
||||
|
||||
RecursiveLocker _(sLock);
|
||||
|
||||
device_node* parent = node->Parent();
|
||||
parent->Acquire();
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
put_device_node(device_node* node)
|
||||
{
|
||||
RecursiveLocker _(sLock);
|
||||
node->Release();
|
||||
}
|
||||
|
||||
|
||||
@ -1229,7 +1355,7 @@ static struct device_manager_info sDeviceManagerModule = {
|
||||
register_device,
|
||||
unregister_device,
|
||||
get_driver,
|
||||
device_root,
|
||||
get_device_root,
|
||||
get_next_child_device,
|
||||
get_parent,
|
||||
put_device_node,
|
||||
@ -1284,11 +1410,19 @@ main(int argc, char** argv)
|
||||
{
|
||||
_add_builtin_module((module_info*)&sDeviceManagerModule);
|
||||
_add_builtin_module((module_info*)&sDeviceRootModule);
|
||||
_add_builtin_module((module_info*)&gDeviceModuleInfo);
|
||||
_add_builtin_module((module_info*)&gDriverModuleInfo);
|
||||
|
||||
// bus
|
||||
_add_builtin_module((module_info*)&gBusModuleInfo);
|
||||
_add_builtin_module((module_info*)&gBusDriverModuleInfo);
|
||||
|
||||
// sample driver
|
||||
_add_builtin_module((module_info*)&gDriverModuleInfo);
|
||||
_add_builtin_module((module_info*)&gDeviceModuleInfo);
|
||||
|
||||
// generic video driver
|
||||
_add_builtin_module((module_info*)&gGenericVideoDriverModuleInfo);
|
||||
_add_builtin_module((module_info*)&gGenericVideoDeviceModuleInfo);
|
||||
|
||||
gDeviceManager = &sDeviceManagerModule;
|
||||
|
||||
status_t status = _get_builtin_dependencies();
|
||||
@ -1301,9 +1435,21 @@ main(int argc, char** argv)
|
||||
recursive_lock_init(&sLock, "device manager");
|
||||
|
||||
dm_init_root_node();
|
||||
dm_dump_node(sRootNode, 0);
|
||||
sRootNode->Dump();
|
||||
|
||||
probe_path("net");
|
||||
probe_path("graphics");
|
||||
// TODO: opened devices need to keep a "initialized" reference of the
|
||||
// device_node
|
||||
|
||||
sRootNode->Dump();
|
||||
uninit_unused();
|
||||
|
||||
// add specific video driver - ie. simulate installing it
|
||||
_add_builtin_module((module_info*)&gSpecificVideoDriverModuleInfo);
|
||||
_add_builtin_module((module_info*)&gSpecificVideoDeviceModuleInfo);
|
||||
probe_path("graphics");
|
||||
|
||||
uninit_unused();
|
||||
|
||||
recursive_lock_destroy(&sLock);
|
||||
|
@ -72,7 +72,7 @@ typedef struct device_manager_info {
|
||||
status_t (*get_driver)(device_node *node, driver_module_info **_module,
|
||||
void **_cookie);
|
||||
|
||||
device_node *(*root_device)();
|
||||
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);
|
||||
|
@ -159,7 +159,7 @@ struct driver_module_info gDriverModuleInfo = {
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
|
||||
|
||||
supports_device,
|
||||
register_device,
|
||||
init_driver,
|
||||
|
@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "bus.h"
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <PCI.h>
|
||||
|
||||
|
||||
#define DRIVER_MODULE_NAME "drivers/graphics/generic_driver/driver_v1"
|
||||
|
||||
|
||||
// #pragma mark - driver
|
||||
|
||||
|
||||
static float
|
||||
supports_device(device_node *parent)
|
||||
{
|
||||
bus_for_driver_module_info* module;
|
||||
void* data;
|
||||
gDeviceManager->get_driver(parent, (driver_module_info**)&module, &data);
|
||||
|
||||
if (strcmp(module->info.info.name, BUS_FOR_DRIVER_NAME))
|
||||
return -1;
|
||||
|
||||
uint16 type;
|
||||
if (gDeviceManager->get_attr_uint16(parent, B_DEVICE_TYPE, &type, false)
|
||||
!= B_OK)
|
||||
return -1;
|
||||
|
||||
if (type == PCI_display)
|
||||
return 0.1;
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
register_device(device_node *parent)
|
||||
{
|
||||
return gDeviceManager->register_device(parent, DRIVER_MODULE_NAME, NULL,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
init_driver(device_node *node, void **_cookie)
|
||||
{
|
||||
// also publishes any devices/nodes with dedicated calls
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
uninit_driver(device_node *node)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
register_child_devices(device_node *node)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
device_removed(device_node *node)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - device
|
||||
|
||||
|
||||
static status_t
|
||||
init_device(void *deviceCookie)
|
||||
{
|
||||
// called once before one or several open() calls
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
uninit_device(void *deviceCookie)
|
||||
{
|
||||
// supposed to free deviceCookie, called when the last reference to
|
||||
// the device is closed
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_open(void *deviceCookie, int openMode, void **_cookie)
|
||||
{
|
||||
// deviceCookie is an object attached to the published device
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_close(void *cookie)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_free(void *cookie)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_read(void *cookie, off_t pos, void *buffer, size_t *_length)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_write(void *cookie, off_t pos, const void *buffer, size_t *_length)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_ioctl(void *cookie, int32 op, void *buffer, size_t length)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_io(void *cookie, io_request *request)
|
||||
{
|
||||
// new function to deal with I/O requests directly.
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
struct driver_module_info gGenericVideoDriverModuleInfo = {
|
||||
{
|
||||
DRIVER_MODULE_NAME,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
|
||||
supports_device,
|
||||
register_device,
|
||||
init_driver,
|
||||
uninit_driver,
|
||||
register_child_devices,
|
||||
NULL,
|
||||
device_removed,
|
||||
};
|
||||
|
||||
struct device_module_info gGenericVideoDeviceModuleInfo = {
|
||||
{
|
||||
"drivers/graphics/generic_driver/device_v1",
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
|
||||
init_device,
|
||||
uninit_device,
|
||||
|
||||
device_open,
|
||||
device_close,
|
||||
device_free,
|
||||
device_read,
|
||||
device_write,
|
||||
device_ioctl,
|
||||
device_io,
|
||||
};
|
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "bus.h"
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <PCI.h>
|
||||
|
||||
|
||||
#define DRIVER_MODULE_NAME "drivers/graphics/specific_driver/driver_v1"
|
||||
|
||||
|
||||
// #pragma mark - driver
|
||||
|
||||
|
||||
static float
|
||||
supports_device(device_node *parent)
|
||||
{
|
||||
bus_for_driver_module_info* module;
|
||||
void* data;
|
||||
gDeviceManager->get_driver(parent, (driver_module_info**)&module, &data);
|
||||
|
||||
if (strcmp(module->info.info.name, BUS_FOR_DRIVER_NAME))
|
||||
return -1;
|
||||
|
||||
bus_info info;
|
||||
if (module->get_bus_info(data, &info) == B_OK
|
||||
&& info.vendor_id == 0x1001
|
||||
&& info.device_id == 0x0002)
|
||||
return 0.8;
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
register_device(device_node *parent)
|
||||
{
|
||||
return gDeviceManager->register_device(parent, DRIVER_MODULE_NAME, NULL,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
init_driver(device_node *node, void **_cookie)
|
||||
{
|
||||
// also publishes any devices/nodes with dedicated calls
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
uninit_driver(device_node *node)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
register_child_devices(device_node *node)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
device_removed(device_node *node)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - device
|
||||
|
||||
|
||||
static status_t
|
||||
init_device(void *deviceCookie)
|
||||
{
|
||||
// called once before one or several open() calls
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
uninit_device(void *deviceCookie)
|
||||
{
|
||||
// supposed to free deviceCookie, called when the last reference to
|
||||
// the device is closed
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_open(void *deviceCookie, int openMode, void **_cookie)
|
||||
{
|
||||
// deviceCookie is an object attached to the published device
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_close(void *cookie)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_free(void *cookie)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_read(void *cookie, off_t pos, void *buffer, size_t *_length)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_write(void *cookie, off_t pos, const void *buffer, size_t *_length)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_ioctl(void *cookie, int32 op, void *buffer, size_t length)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_io(void *cookie, io_request *request)
|
||||
{
|
||||
// new function to deal with I/O requests directly.
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
struct driver_module_info gSpecificVideoDriverModuleInfo = {
|
||||
{
|
||||
DRIVER_MODULE_NAME,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
|
||||
supports_device,
|
||||
register_device,
|
||||
init_driver,
|
||||
uninit_driver,
|
||||
register_child_devices,
|
||||
NULL,
|
||||
device_removed,
|
||||
};
|
||||
|
||||
struct device_module_info gSpecificVideoDeviceModuleInfo = {
|
||||
{
|
||||
"drivers/graphics/specific_driver/device_v1",
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
|
||||
init_device,
|
||||
uninit_device,
|
||||
|
||||
device_open,
|
||||
device_close,
|
||||
device_free,
|
||||
device_read,
|
||||
device_write,
|
||||
device_ioctl,
|
||||
device_io,
|
||||
};
|
Loading…
Reference in New Issue
Block a user