2 * Copyright 2008-2009, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
7 #include <kdevice_manager.h>
15 #include <KernelExport.h>
20 #include <boot_device.h>
21 #include <device_manager_defs.h>
25 #include <generic_syscall.h>
26 #include <util/AutoLock.h>
27 #include <util/DoublyLinkedList.h>
28 #include <util/Stack.h>
30 #include "AbstractModuleDevice.h"
31 #include "devfs_private.h"
32 #include "id_generator.h"
33 #include "IORequest.h"
34 #include "io_resources.h"
35 #include "IOSchedulerRoster.h"
38 //#define TRACE_DEVICE_MANAGER
39 #ifdef TRACE_DEVICE_MANAGER
40 # define TRACE(a) dprintf a
46 #define DEVICE_MANAGER_ROOT_NAME "system/devices_root/driver_v1"
47 #define DEVICE_MANAGER_GENERIC_NAME "system/devices_generic/driver_v1"
50 struct device_attr_private
: device_attr
,
51 DoublyLinkedListLinkImpl
<device_attr_private
> {
52 device_attr_private();
53 device_attr_private(const device_attr
& attr
);
54 ~device_attr_private();
57 status_t
CopyFrom(const device_attr
& attr
);
59 static int Compare(const device_attr
* attrA
,
60 const device_attr
*attrB
);
66 typedef DoublyLinkedList
<device_attr_private
> AttributeList
;
69 typedef struct io_resource_info
{
70 struct io_resource_info
*prev
, *next
;
71 device_node
* owner
; // associated node; NULL for temporary allocation
72 io_resource resource
; // info about actual resource
79 class Device
: public AbstractModuleDevice
,
80 public DoublyLinkedListLinkImpl
<Device
> {
82 Device(device_node
* node
, const char* moduleName
);
85 status_t
InitCheck() const;
87 const char* ModuleName() const { return fModuleName
; }
89 virtual status_t
InitDevice();
90 virtual void UninitDevice();
92 virtual void Removed();
94 void SetRemovedFromParent(bool removed
)
95 { fRemovedFromParent
= removed
; }
98 const char* fModuleName
;
99 bool fRemovedFromParent
;
103 } // unnamed namespace
106 typedef DoublyLinkedList
<Device
> DeviceList
;
107 typedef DoublyLinkedList
<device_node
> NodeList
;
109 struct device_node
: DoublyLinkedListLinkImpl
<device_node
> {
110 device_node(const char* moduleName
,
111 const device_attr
* attrs
);
114 status_t
InitCheck() const;
116 status_t
AcquireResources(const io_resource
* resources
);
118 const char* ModuleName() const { return fModuleName
; }
119 device_node
* Parent() const { return fParent
; }
120 AttributeList
& Attributes() { return fAttributes
; }
121 const AttributeList
& Attributes() const { return fAttributes
; }
123 status_t
InitDriver();
125 void UninitUnusedDriver();
127 // The following two are only valid, if the node's driver is
129 driver_module_info
* DriverModule() const { return fDriver
; }
130 void* DriverData() const { return fDriverData
; }
132 void AddChild(device_node
*node
);
133 void RemoveChild(device_node
*node
);
134 const NodeList
& Children() const { return fChildren
; }
135 void DeviceRemoved();
137 status_t
Register(device_node
* parent
);
138 status_t
Probe(const char* devicePath
, uint32 updateCycle
);
142 bool IsRegistered() const { return fRegistered
; }
143 bool IsInitialized() const { return fInitialized
> 0; }
144 bool IsProbed() const { return fLastUpdateCycle
!= 0; }
145 uint32
Flags() const { return fFlags
; }
150 const DeviceList
& Devices() const { return fDevices
; }
151 void AddDevice(Device
* device
);
152 void RemoveDevice(Device
* device
);
154 int CompareTo(const device_attr
* attributes
) const;
155 device_node
* FindChild(const device_attr
* attributes
) const;
156 device_node
* FindChild(const char* moduleName
) const;
160 void Dump(int32 level
= 0);
163 status_t
_RegisterFixed(uint32
& registered
);
164 bool _AlwaysRegisterDynamic();
165 status_t
_AddPath(Stack
<KPath
*>& stack
, const char* path
,
166 const char* subPath
= NULL
);
167 status_t
_GetNextDriverPath(void*& cookie
, KPath
& _path
);
168 status_t
_GetNextDriver(void* list
,
169 driver_module_info
*& driver
);
170 status_t
_FindBestDriver(const char* path
,
171 driver_module_info
*& bestDriver
,
173 device_node
* previous
= NULL
);
174 status_t
_RegisterPath(const char* path
);
175 status_t
_RegisterDynamic(device_node
* previous
= NULL
);
176 status_t
_RemoveChildren();
177 device_node
* _FindCurrentChild();
179 void _ReleaseWaiting();
181 device_node
* fParent
;
187 float fSupportsParent
;
188 uint32 fLastUpdateCycle
;
190 const char* fModuleName
;
192 driver_module_info
* fDriver
;
196 AttributeList fAttributes
;
197 ResourceList fResources
;
200 // flags in addition to those specified by B_DEVICE_FLAGS
202 NODE_FLAG_REGISTER_INITIALIZED
= 0x00010000,
203 NODE_FLAG_DEVICE_REMOVED
= 0x00020000,
204 NODE_FLAG_OBSOLETE_DRIVER
= 0x00040000,
205 NODE_FLAG_WAITING_FOR_DRIVER
= 0x00080000,
207 NODE_FLAG_PUBLIC_MASK
= 0x0000ffff
211 static device_node
*sRootNode
;
212 static recursive_lock sLock
;
213 static const char* sGenericContextPath
;
219 static device_attr_private
*
220 find_attr(const device_node
* node
, const char* name
, bool recursive
,
224 AttributeList::ConstIterator iterator
225 = node
->Attributes().GetIterator();
227 while (iterator
.HasNext()) {
228 device_attr_private
* attr
= iterator
.Next();
230 if (type
!= B_ANY_TYPE
&& attr
->type
!= type
)
233 if (!strcmp(attr
->name
, name
))
237 node
= node
->Parent();
238 } while (node
!= NULL
&& recursive
);
245 put_level(int32 level
)
253 dump_attribute(device_attr
* attr
, int32 level
)
258 put_level(level
+ 2);
259 kprintf("\"%s\" : ", attr
->name
);
260 switch (attr
->type
) {
262 kprintf("string : \"%s\"", attr
->value
.string
);
266 kprintf("uint8 : %" B_PRIu8
" (%#" B_PRIx8
")", attr
->value
.ui8
,
271 kprintf("uint16 : %" B_PRIu16
" (%#" B_PRIx16
")", attr
->value
.ui16
,
276 kprintf("uint32 : %" B_PRIu32
" (%#" B_PRIx32
")", attr
->value
.ui32
,
281 kprintf("uint64 : %" B_PRIu64
" (%#" B_PRIx64
")", attr
->value
.ui64
,
292 dump_io_scheduler(int argc
, char** argv
)
295 print_debugger_command_usage(argv
[0]);
299 IOScheduler
* scheduler
= (IOScheduler
*)parse_expression(argv
[1]);
306 dump_io_request_owner(int argc
, char** argv
)
309 print_debugger_command_usage(argv
[0]);
313 IORequestOwner
* owner
= (IORequestOwner
*)parse_expression(argv
[1]);
320 dump_io_request(int argc
, char** argv
)
322 if (argc
!= 2 || !strcmp(argv
[1], "--help")) {
323 kprintf("usage: %s <ptr-to-io-request>\n", argv
[0]);
327 IORequest
* request
= (IORequest
*)parse_expression(argv
[1]);
334 dump_io_operation(int argc
, char** argv
)
336 if (argc
!= 2 || !strcmp(argv
[1], "--help")) {
337 kprintf("usage: %s <ptr-to-io-operation>\n", argv
[0]);
341 IOOperation
* operation
= (IOOperation
*)parse_expression(argv
[1]);
348 dump_io_buffer(int argc
, char** argv
)
350 if (argc
!= 2 || !strcmp(argv
[1], "--help")) {
351 kprintf("usage: %s <ptr-to-io-buffer>\n", argv
[0]);
355 IOBuffer
* buffer
= (IOBuffer
*)parse_expression(argv
[1]);
362 dump_dma_buffer(int argc
, char** argv
)
364 if (argc
!= 2 || !strcmp(argv
[1], "--help")) {
365 kprintf("usage: %s <ptr-to-dma-buffer>\n", argv
[0]);
369 DMABuffer
* buffer
= (DMABuffer
*)parse_expression(argv
[1]);
376 dump_device_nodes(int argc
, char** argv
)
384 publish_directories(const char* subPath
)
386 if (gBootDevice
< 0) {
388 // we only support the top-level directory for modules
392 // we can only iterate over the known modules to find all directories
393 KPath
path("drivers");
394 if (path
.Append(subPath
) != B_OK
)
397 size_t length
= strlen(path
.Path()) + 1;
398 // account for the separating '/'
400 void* list
= open_module_list_etc(path
.Path(), "driver_v1");
401 char name
[B_FILE_NAME_LENGTH
];
402 size_t nameLength
= sizeof(name
);
403 while (read_next_module_name(list
, name
, &nameLength
) == B_OK
) {
404 if (nameLength
== length
)
407 char* leaf
= name
+ length
;
408 char* end
= strchr(leaf
, '/');
415 devfs_publish_directory(path
.Path());
417 close_module_list(list
);
419 // TODO: implement module directory traversal!
425 control_device_manager(const char* subsystem
, uint32 function
, void* buffer
,
428 // TODO: this function passes pointers to userland, and uses pointers
429 // to device nodes that came from userland - this is completely unsafe
430 // and should be changed.
434 device_node_cookie cookie
;
435 if (!IS_USER_ADDRESS(buffer
))
436 return B_BAD_ADDRESS
;
437 if (bufferSize
!= sizeof(device_node_cookie
))
439 cookie
= (device_node_cookie
)sRootNode
;
441 // copy back to user space
442 return user_memcpy(buffer
, &cookie
, sizeof(device_node_cookie
));
447 if (!IS_USER_ADDRESS(buffer
))
448 return B_BAD_ADDRESS
;
449 if (bufferSize
!= sizeof(device_node_cookie
))
452 device_node_cookie cookie
;
453 if (user_memcpy(&cookie
, buffer
, sizeof(device_node_cookie
)) < B_OK
)
454 return B_BAD_ADDRESS
;
456 device_node
* node
= (device_node
*)cookie
;
457 NodeList::ConstIterator iterator
= node
->Children().GetIterator();
459 if (!iterator
.HasNext()) {
460 return B_ENTRY_NOT_FOUND
;
462 node
= iterator
.Next();
463 cookie
= (device_node_cookie
)node
;
465 // copy back to user space
466 return user_memcpy(buffer
, &cookie
, sizeof(device_node_cookie
));
469 case DM_GET_NEXT_CHILD
:
471 if (!IS_USER_ADDRESS(buffer
))
472 return B_BAD_ADDRESS
;
473 if (bufferSize
!= sizeof(device_node_cookie
))
476 device_node_cookie cookie
;
477 if (user_memcpy(&cookie
, buffer
, sizeof(device_node_cookie
)) < B_OK
)
478 return B_BAD_ADDRESS
;
480 device_node
* last
= (device_node
*)cookie
;
482 return B_ENTRY_NOT_FOUND
;
484 NodeList::ConstIterator iterator
485 = last
->Parent()->Children().GetIterator();
487 // skip those we already traversed
488 while (iterator
.HasNext()) {
489 device_node
* node
= iterator
.Next();
495 if (!iterator
.HasNext())
496 return B_ENTRY_NOT_FOUND
;
497 device_node
* node
= iterator
.Next();
498 cookie
= (device_node_cookie
)node
;
500 // copy back to user space
501 return user_memcpy(buffer
, &cookie
, sizeof(device_node_cookie
));
504 case DM_GET_NEXT_ATTRIBUTE
:
506 struct device_attr_info attrInfo
;
507 if (!IS_USER_ADDRESS(buffer
))
508 return B_BAD_ADDRESS
;
509 if (bufferSize
!= sizeof(device_attr_info
))
511 if (user_memcpy(&attrInfo
, buffer
, sizeof(device_attr_info
)) < B_OK
)
512 return B_BAD_ADDRESS
;
514 device_node
* node
= (device_node
*)attrInfo
.node_cookie
;
515 device_attr
* last
= (device_attr
*)attrInfo
.cookie
;
516 AttributeList::Iterator iterator
= node
->Attributes().GetIterator();
517 // skip those we already traversed
518 while (iterator
.HasNext() && last
!= NULL
) {
519 device_attr
* attr
= iterator
.Next();
525 if (!iterator
.HasNext()) {
527 return B_ENTRY_NOT_FOUND
;
530 device_attr
* attr
= iterator
.Next();
531 attrInfo
.cookie
= (device_node_cookie
)attr
;
532 strlcpy(attrInfo
.name
, attr
->name
, 254);
533 attrInfo
.type
= attr
->type
;
534 switch (attrInfo
.type
) {
536 attrInfo
.value
.ui8
= attr
->value
.ui8
;
539 attrInfo
.value
.ui16
= attr
->value
.ui16
;
542 attrInfo
.value
.ui32
= attr
->value
.ui32
;
545 attrInfo
.value
.ui64
= attr
->value
.ui64
;
548 strlcpy(attrInfo
.value
.string
, attr
->value
.string
, 254);
551 if (attr.value.raw.length > attr_info->attr.value.raw.length)
552 attr.value.raw.length = attr_info->attr.value.raw.length;
553 user_memcpy(attr.value.raw.data, attr_info->attr.value.raw.data,
554 attr.value.raw.length);
558 // copy back to user space
559 return user_memcpy(buffer
, &attrInfo
, sizeof(device_attr_info
));
563 return B_BAD_HANDLER
;
567 // #pragma mark - Device Manager module API
571 rescan_node(device_node
* node
)
573 RecursiveLocker
_(sLock
);
574 return node
->Rescan();
579 register_node(device_node
* parent
, const char* moduleName
,
580 const device_attr
* attrs
, const io_resource
* ioResources
,
583 if ((parent
== NULL
&& sRootNode
!= NULL
) || moduleName
== NULL
)
586 if (parent
!= NULL
&& parent
->FindChild(attrs
) != NULL
) {
587 // A node like this one already exists for this parent
588 return B_NAME_IN_USE
;
591 RecursiveLocker
_(sLock
);
593 device_node
* newNode
= new(std::nothrow
) device_node(moduleName
, attrs
);
597 TRACE(("%p: register node \"%s\", parent %p\n", newNode
, moduleName
,
600 status_t status
= newNode
->InitCheck();
602 status
= newNode
->AcquireResources(ioResources
);
604 status
= newNode
->Register(parent
);
606 if (status
!= B_OK
) {
618 /*! Unregisters the device \a node.
620 If the node is currently in use, this function will return B_BUSY to
621 indicate that the node hasn't been removed yet - it will still remove
622 the node as soon as possible.
625 unregister_node(device_node
* node
)
627 TRACE(("unregister_node(node %p)\n", node
));
628 RecursiveLocker
_(sLock
);
630 bool initialized
= node
->IsInitialized();
632 node
->DeviceRemoved();
634 return initialized
? B_BUSY
: B_OK
;
639 get_driver(device_node
* node
, driver_module_info
** _module
, void** _data
)
641 if (node
->DriverModule() == NULL
)
645 *_module
= node
->DriverModule();
647 *_data
= node
->DriverData();
656 if (sRootNode
!= NULL
)
657 sRootNode
->Acquire();
664 get_next_child_node(device_node
* parent
, const device_attr
* attributes
,
667 RecursiveLocker
_(sLock
);
669 NodeList::ConstIterator iterator
= parent
->Children().GetIterator();
670 device_node
* last
= *_node
;
672 // skip those we already traversed
673 while (iterator
.HasNext() && last
!= NULL
) {
674 device_node
* node
= iterator
.Next();
680 // find the next one that fits
681 while (iterator
.HasNext()) {
682 device_node
* node
= iterator
.Next();
684 if (!node
->IsRegistered())
687 if (!node
->CompareTo(attributes
)) {
700 return B_ENTRY_NOT_FOUND
;
705 get_parent_node(device_node
* node
)
710 RecursiveLocker
_(sLock
);
712 device_node
* parent
= node
->Parent();
720 put_node(device_node
* node
)
722 RecursiveLocker
_(sLock
);
728 publish_device(device_node
*node
, const char *path
, const char *moduleName
)
730 if (path
== NULL
|| !path
[0] || moduleName
== NULL
|| !moduleName
[0])
733 RecursiveLocker
_(sLock
);
734 dprintf("publish device: node %p, path %s, module %s\n", node
, path
,
737 Device
* device
= new(std::nothrow
) Device(node
, moduleName
);
741 status_t status
= device
->InitCheck();
743 status
= devfs_publish_device(path
, device
);
744 if (status
!= B_OK
) {
749 node
->AddDevice(device
);
755 unpublish_device(device_node
*node
, const char *path
)
760 BaseDevice
* baseDevice
;
761 status_t error
= devfs_get_device(path
, baseDevice
);
764 CObjectDeleter
<BaseDevice
> baseDevicePutter(baseDevice
, &devfs_put_device
);
766 Device
* device
= dynamic_cast<Device
*>(baseDevice
);
767 if (device
== NULL
|| device
->Node() != node
)
770 return devfs_unpublish_device(device
, true);
775 get_attr_uint8(const device_node
* node
, const char* name
, uint8
* _value
,
778 if (node
== NULL
|| name
== NULL
|| _value
== NULL
)
781 device_attr_private
* attr
= find_attr(node
, name
, recursive
, B_UINT8_TYPE
);
783 return B_NAME_NOT_FOUND
;
785 *_value
= attr
->value
.ui8
;
791 get_attr_uint16(const device_node
* node
, const char* name
, uint16
* _value
,
794 if (node
== NULL
|| name
== NULL
|| _value
== NULL
)
797 device_attr_private
* attr
= find_attr(node
, name
, recursive
, B_UINT16_TYPE
);
799 return B_NAME_NOT_FOUND
;
801 *_value
= attr
->value
.ui16
;
807 get_attr_uint32(const device_node
* node
, const char* name
, uint32
* _value
,
810 if (node
== NULL
|| name
== NULL
|| _value
== NULL
)
813 device_attr_private
* attr
= find_attr(node
, name
, recursive
, B_UINT32_TYPE
);
815 return B_NAME_NOT_FOUND
;
817 *_value
= attr
->value
.ui32
;
823 get_attr_uint64(const device_node
* node
, const char* name
,
824 uint64
* _value
, bool recursive
)
826 if (node
== NULL
|| name
== NULL
|| _value
== NULL
)
829 device_attr_private
* attr
= find_attr(node
, name
, recursive
, B_UINT64_TYPE
);
831 return B_NAME_NOT_FOUND
;
833 *_value
= attr
->value
.ui64
;
839 get_attr_string(const device_node
* node
, const char* name
,
840 const char** _value
, bool recursive
)
842 if (node
== NULL
|| name
== NULL
|| _value
== NULL
)
845 device_attr_private
* attr
= find_attr(node
, name
, recursive
, B_STRING_TYPE
);
847 return B_NAME_NOT_FOUND
;
849 *_value
= attr
->value
.string
;
855 get_attr_raw(const device_node
* node
, const char* name
, const void** _data
,
856 size_t* _length
, bool recursive
)
858 if (node
== NULL
|| name
== NULL
|| (_data
== NULL
&& _length
== NULL
))
861 device_attr_private
* attr
= find_attr(node
, name
, recursive
, B_RAW_TYPE
);
863 return B_NAME_NOT_FOUND
;
866 *_data
= attr
->value
.raw
.data
;
868 *_length
= attr
->value
.raw
.length
;
874 get_next_attr(device_node
* node
, device_attr
** _attr
)
879 device_attr_private
* next
;
880 device_attr_private
* attr
= *(device_attr_private
**)_attr
;
884 next
= attr
->GetDoublyLinkedListLink()->next
;
887 next
= node
->Attributes().First();
892 return next
? B_OK
: B_ENTRY_NOT_FOUND
;
896 struct device_manager_info gDeviceManagerModule
= {
898 B_DEVICE_MANAGER_MODULE_NAME
,
934 // #pragma mark - device_attr
937 device_attr_private::device_attr_private()
941 value
.raw
.data
= NULL
;
942 value
.raw
.length
= 0;
946 device_attr_private::device_attr_private(const device_attr
& attr
)
952 device_attr_private::~device_attr_private()
959 device_attr_private::InitCheck()
961 return name
!= NULL
? B_OK
: B_NO_INIT
;
966 device_attr_private::CopyFrom(const device_attr
& attr
)
968 name
= strdup(attr
.name
);
979 value
.ui64
= attr
.value
.ui64
;
983 if (attr
.value
.string
!= NULL
) {
984 value
.string
= strdup(attr
.value
.string
);
985 if (value
.string
== NULL
) {
994 value
.raw
.data
= malloc(attr
.value
.raw
.length
);
995 if (value
.raw
.data
== NULL
) {
1000 value
.raw
.length
= attr
.value
.raw
.length
;
1001 memcpy((void*)value
.raw
.data
, attr
.value
.raw
.data
,
1002 attr
.value
.raw
.length
);
1014 device_attr_private::_Unset()
1016 if (type
== B_STRING_TYPE
)
1017 free((char*)value
.string
);
1018 else if (type
== B_RAW_TYPE
)
1019 free((void*)value
.raw
.data
);
1024 value
.raw
.data
= NULL
;
1025 value
.raw
.length
= 0;
1030 device_attr_private::Compare(const device_attr
* attrA
, const device_attr
*attrB
)
1032 if (attrA
->type
!= attrB
->type
)
1035 switch (attrA
->type
) {
1037 return (int)attrA
->value
.ui8
- (int)attrB
->value
.ui8
;
1040 return (int)attrA
->value
.ui16
- (int)attrB
->value
.ui16
;
1043 if (attrA
->value
.ui32
> attrB
->value
.ui32
)
1045 if (attrA
->value
.ui32
< attrB
->value
.ui32
)
1050 if (attrA
->value
.ui64
> attrB
->value
.ui64
)
1052 if (attrA
->value
.ui64
< attrB
->value
.ui64
)
1057 return strcmp(attrA
->value
.string
, attrB
->value
.string
);
1060 if (attrA
->value
.raw
.length
!= attrB
->value
.raw
.length
)
1063 return memcmp(attrA
->value
.raw
.data
, attrB
->value
.raw
.data
,
1064 attrA
->value
.raw
.length
);
1071 // #pragma mark - Device
1074 Device::Device(device_node
* node
, const char* moduleName
)
1076 fModuleName(strdup(moduleName
)),
1077 fRemovedFromParent(false)
1085 free((char*)fModuleName
);
1090 Device::InitCheck() const
1092 return fModuleName
!= NULL
? B_OK
: B_NO_MEMORY
;
1097 Device::InitDevice()
1099 RecursiveLocker
_(sLock
);
1101 if ((fNode
->Flags() & NODE_FLAG_DEVICE_REMOVED
) != 0) {
1102 // TODO: maybe the device should be unlinked in devfs, too
1105 if ((fNode
->Flags() & NODE_FLAG_WAITING_FOR_DRIVER
) != 0)
1108 if (fInitialized
++ > 0) {
1109 fNode
->InitDriver();
1110 // acquire another reference to our parent as well
1114 status_t status
= get_module(ModuleName(), (module_info
**)&fDeviceModule
);
1115 if (status
== B_OK
) {
1116 // our parent always has to be initialized
1117 status
= fNode
->InitDriver();
1119 if (status
< B_OK
) {
1124 if (Module()->init_device
!= NULL
)
1125 status
= Module()->init_device(fNode
->DriverData(), &fDeviceData
);
1127 if (status
< B_OK
) {
1128 fNode
->UninitDriver();
1131 put_module(ModuleName());
1132 fDeviceModule
= NULL
;
1141 Device::UninitDevice()
1143 RecursiveLocker
_(sLock
);
1145 if (fInitialized
-- > 1) {
1146 fNode
->UninitDriver();
1150 TRACE(("uninit driver for node %p\n", this));
1152 if (Module()->uninit_device
!= NULL
)
1153 Module()->uninit_device(fDeviceData
);
1155 fDeviceModule
= NULL
;
1158 put_module(ModuleName());
1160 fNode
->UninitDriver();
1167 RecursiveLocker
_(sLock
);
1169 if (!fRemovedFromParent
)
1170 fNode
->RemoveDevice(this);
1176 // #pragma mark - device_node
1179 device_node::device_node(const char* moduleName
, const device_attr
* attrs
)
1181 fModuleName
= strdup(moduleName
);
1182 if (fModuleName
== NULL
)
1188 fRegistered
= false;
1190 fSupportsParent
= 0.0;
1191 fLastUpdateCycle
= 0;
1197 while (attrs
!= NULL
&& attrs
->name
!= NULL
) {
1198 device_attr_private
* attr
1199 = new(std::nothrow
) device_attr_private(*attrs
);
1203 fAttributes
.Add(attr
);
1207 get_attr_uint32(this, B_DEVICE_FLAGS
, &fFlags
, false);
1208 fFlags
&= NODE_FLAG_PUBLIC_MASK
;
1212 device_node::~device_node()
1214 TRACE(("delete node %p\n", this));
1215 ASSERT(DriverModule() == NULL
);
1217 if (Parent() != NULL
) {
1218 if ((fFlags
& NODE_FLAG_OBSOLETE_DRIVER
) != 0) {
1219 // This driver has been obsoleted; another driver has been waiting
1220 // for us - make it available
1221 Parent()->_ReleaseWaiting();
1223 Parent()->RemoveChild(this);
1227 while (device_node
* child
= fChildren
.RemoveHead()) {
1232 while (Device
* device
= fDevices
.RemoveHead()) {
1233 device
->SetRemovedFromParent(true);
1234 devfs_unpublish_device(device
, true);
1237 // Delete attributes
1238 while (device_attr_private
* attr
= fAttributes
.RemoveHead()) {
1243 while (io_resource_private
* resource
= fResources
.RemoveHead()) {
1247 free((char*)fModuleName
);
1252 device_node::InitCheck() const
1254 return fModuleName
!= NULL
? B_OK
: B_NO_MEMORY
;
1259 device_node::AcquireResources(const io_resource
* resources
)
1261 if (resources
== NULL
)
1264 for (uint32 i
= 0; resources
[i
].type
!= 0; i
++) {
1265 io_resource_private
* resource
= new(std::nothrow
) io_resource_private
;
1266 if (resource
== NULL
)
1269 status_t status
= resource
->Acquire(resources
[i
]);
1270 if (status
!= B_OK
) {
1275 fResources
.Add(resource
);
1283 device_node::InitDriver()
1285 if (fInitialized
++ > 0) {
1286 if (Parent() != NULL
) {
1287 Parent()->InitDriver();
1288 // acquire another reference to our parent as well
1294 status_t status
= get_module(ModuleName(), (module_info
**)&fDriver
);
1295 if (status
== B_OK
&& Parent() != NULL
) {
1296 // our parent always has to be initialized
1297 status
= Parent()->InitDriver();
1299 if (status
< B_OK
) {
1304 if (fDriver
->init_driver
!= NULL
) {
1305 status
= fDriver
->init_driver(this, &fDriverData
);
1306 if (status
!= B_OK
) {
1307 dprintf("driver %s init failed: %s\n", ModuleName(),
1312 if (status
< B_OK
) {
1313 if (Parent() != NULL
)
1314 Parent()->UninitDriver();
1317 put_module(ModuleName());
1329 device_node::UninitDriver()
1331 if (fInitialized
-- > 1) {
1332 if (Parent() != NULL
)
1333 Parent()->UninitDriver();
1338 TRACE(("uninit driver for node %p\n", this));
1340 if (fDriver
->uninit_driver
!= NULL
)
1341 fDriver
->uninit_driver(fDriverData
);
1346 put_module(ModuleName());
1348 if (Parent() != NULL
)
1349 Parent()->UninitDriver();
1357 device_node::AddChild(device_node
* node
)
1359 // we must not be destroyed as long as we have children
1361 node
->fParent
= this;
1363 int32 priority
= node
->Priority();
1365 // Enforce an order in which the children are traversed - from most
1366 // specific to least specific child.
1367 NodeList::Iterator iterator
= fChildren
.GetIterator();
1368 device_node
* before
= NULL
;
1369 while (iterator
.HasNext()) {
1370 device_node
* child
= iterator
.Next();
1371 if (child
->Priority() <= priority
) {
1377 fChildren
.Insert(before
, node
);
1382 device_node::RemoveChild(device_node
* node
)
1384 node
->fParent
= NULL
;
1385 fChildren
.Remove(node
);
1390 /*! Registers this node, and all of its children that have to be registered.
1391 Also initializes the driver and keeps it that way on return in case
1392 it returns successfully.
1395 device_node::Register(device_node
* parent
)
1399 parent
->AddChild(this);
1403 status_t status
= InitDriver();
1407 if ((fFlags
& B_KEEP_DRIVER_LOADED
) != 0) {
1408 // We keep this driver loaded by having it always initialized
1412 fFlags
|= NODE_FLAG_REGISTER_INITIALIZED
;
1413 // We don't uninitialize the driver - this is done by the caller
1414 // in order to save reinitializing during driver loading.
1416 uint32 registeredFixedCount
;
1417 status
= _RegisterFixed(registeredFixedCount
);
1418 if (status
!= B_OK
) {
1419 UninitUnusedDriver();
1423 // Register the children the driver wants
1425 if (DriverModule()->register_child_devices
!= NULL
) {
1426 status
= DriverModule()->register_child_devices(DriverData());
1427 if (status
!= B_OK
) {
1428 UninitUnusedDriver();
1432 if (!fChildren
.IsEmpty()) {
1438 if (registeredFixedCount
> 0) {
1439 // Nodes with fixed children cannot have any dynamic children, so bail
1445 // Register all possible child device nodes
1447 status
= _RegisterDynamic();
1451 UninitUnusedDriver();
1457 /*! Registers any children that are identified via the B_DEVICE_FIXED_CHILD
1459 If any of these children cannot be registered, this call will fail (we
1460 don't remove children we already registered up to this point in this case).
1463 device_node::_RegisterFixed(uint32
& registered
)
1465 AttributeList::Iterator iterator
= fAttributes
.GetIterator();
1468 while (iterator
.HasNext()) {
1469 device_attr_private
* attr
= iterator
.Next();
1470 if (strcmp(attr
->name
, B_DEVICE_FIXED_CHILD
))
1473 driver_module_info
* driver
;
1474 status_t status
= get_module(attr
->value
.string
,
1475 (module_info
**)&driver
);
1476 if (status
!= B_OK
) {
1477 TRACE(("register fixed child %s failed: %s\n", attr
->value
.string
,
1482 if (driver
->register_device
!= NULL
) {
1483 status
= driver
->register_device(this);
1488 put_module(attr
->value
.string
);
1499 device_node::_AddPath(Stack
<KPath
*>& stack
, const char* basePath
,
1500 const char* subPath
)
1502 KPath
* path
= new(std::nothrow
) KPath
;
1506 status_t status
= path
->SetTo(basePath
);
1507 if (status
== B_OK
&& subPath
!= NULL
&& subPath
[0])
1508 status
= path
->Append(subPath
);
1510 status
= stack
.Push(path
);
1512 TRACE((" add path: \"%s\", %" B_PRId32
"\n", path
->Path(), status
));
1522 device_node::_GetNextDriverPath(void*& cookie
, KPath
& _path
)
1524 Stack
<KPath
*>* stack
= NULL
;
1526 if (cookie
== NULL
) {
1527 // find all paths and add them
1528 stack
= new(std::nothrow
) Stack
<KPath
*>();
1532 StackDeleter
<KPath
*> stackDeleter(stack
);
1534 bool generic
= false;
1537 uint16 interface
= 0;
1538 if (get_attr_uint16(this, B_DEVICE_TYPE
, &type
, false) != B_OK
1539 || get_attr_uint16(this, B_DEVICE_SUB_TYPE
, &subType
, false)
1543 get_attr_uint16(this, B_DEVICE_INTERFACE
, &interface
, false);
1545 // TODO: maybe make this extendible via settings file?
1547 case PCI_mass_storage
:
1550 _AddPath(*stack
, "busses", "scsi");
1551 _AddPath(*stack
, "busses", "virtio");
1554 _AddPath(*stack
, "busses", "ata");
1555 _AddPath(*stack
, "busses", "ide");
1558 // TODO: check for ahci interface
1559 _AddPath(*stack
, "busses", "scsi");
1560 _AddPath(*stack
, "busses", "ata");
1561 _AddPath(*stack
, "busses", "ide");
1564 _AddPath(*stack
, "busses");
1568 case PCI_serial_bus
:
1571 _AddPath(*stack
, "busses", "firewire");
1574 _AddPath(*stack
, "busses", "usb");
1577 _AddPath(*stack
, "busses");
1582 _AddPath(*stack
, "drivers", "net");
1583 _AddPath(*stack
, "busses", "virtio");
1586 _AddPath(*stack
, "drivers", "graphics");
1588 case PCI_multimedia
:
1592 _AddPath(*stack
, "drivers", "audio");
1595 _AddPath(*stack
, "drivers", "video");
1598 _AddPath(*stack
, "drivers");
1603 if (sRootNode
== this) {
1604 _AddPath(*stack
, "busses/pci");
1605 _AddPath(*stack
, "bus_managers");
1606 } else if (!generic
) {
1607 _AddPath(*stack
, "busses", "virtio");
1608 _AddPath(*stack
, "drivers");
1610 // For generic drivers, we only allow busses when the
1611 // request is more specified
1612 if (sGenericContextPath
!= NULL
1613 && (!strcmp(sGenericContextPath
, "disk")
1614 || !strcmp(sGenericContextPath
, "ports")
1615 || !strcmp(sGenericContextPath
, "bus"))) {
1616 _AddPath(*stack
, "busses");
1618 _AddPath(*stack
, "drivers", sGenericContextPath
);
1619 _AddPath(*stack
, "busses/scsi");
1620 _AddPath(*stack
, "busses/random");
1625 stackDeleter
.Detach();
1627 cookie
= (void*)stack
;
1629 stack
= static_cast<Stack
<KPath
*>*>(cookie
);
1632 if (stack
->Pop(&path
)) {
1639 return B_ENTRY_NOT_FOUND
;
1644 device_node::_GetNextDriver(void* list
, driver_module_info
*& driver
)
1647 char name
[B_FILE_NAME_LENGTH
];
1648 size_t nameLength
= sizeof(name
);
1650 status_t status
= read_next_module_name(list
, name
, &nameLength
);
1654 if (!strcmp(fModuleName
, name
))
1657 if (get_module(name
, (module_info
**)&driver
) != B_OK
)
1660 if (driver
->supports_device
== NULL
1661 || driver
->register_device
== NULL
) {
1672 device_node::_FindBestDriver(const char* path
, driver_module_info
*& bestDriver
,
1673 float& bestSupport
, device_node
* previous
)
1675 if (bestDriver
== NULL
)
1676 bestSupport
= previous
!= NULL
? previous
->fSupportsParent
: 0.0f
;
1678 void* list
= open_module_list_etc(path
, "driver_v1");
1679 driver_module_info
* driver
;
1680 while (_GetNextDriver(list
, driver
) == B_OK
) {
1681 if (previous
!= NULL
&& driver
== previous
->DriverModule()) {
1682 put_module(driver
->info
.name
);
1686 float support
= driver
->supports_device(this);
1687 if (support
> bestSupport
) {
1688 if (bestDriver
!= NULL
)
1689 put_module(bestDriver
->info
.name
);
1691 bestDriver
= driver
;
1692 bestSupport
= support
;
1694 // keep reference to best module around
1697 put_module(driver
->info
.name
);
1699 close_module_list(list
);
1701 return bestDriver
!= NULL
? B_OK
: B_ENTRY_NOT_FOUND
;
1706 device_node::_RegisterPath(const char* path
)
1708 void* list
= open_module_list_etc(path
, "driver_v1");
1709 driver_module_info
* driver
;
1712 while (_GetNextDriver(list
, driver
) == B_OK
) {
1713 float support
= driver
->supports_device(this);
1714 if (support
> 0.0) {
1715 TRACE((" register module \"%s\", support %f\n", driver
->info
.name
,
1717 if (driver
->register_device(this) == B_OK
)
1721 put_module(driver
->info
.name
);
1723 close_module_list(list
);
1725 return count
> 0 ? B_OK
: B_ENTRY_NOT_FOUND
;
1730 device_node::_AlwaysRegisterDynamic()
1734 get_attr_uint16(this, B_DEVICE_TYPE
, &type
, false);
1735 get_attr_uint16(this, B_DEVICE_SUB_TYPE
, &subType
, false);
1737 return type
== PCI_serial_bus
|| type
== PCI_bridge
|| type
== 0;
1738 // TODO: we may want to be a bit more specific in the future
1743 device_node::_RegisterDynamic(device_node
* previous
)
1745 // If this is not a bus, we don't have to scan it
1746 if (find_attr(this, B_DEVICE_BUS
, false, B_STRING_TYPE
) == NULL
)
1749 // If we're not being probed, we honour the B_FIND_CHILD_ON_DEMAND
1751 if (!IsProbed() && (fFlags
& B_FIND_CHILD_ON_DEMAND
) != 0
1752 && !_AlwaysRegisterDynamic())
1757 if ((fFlags
& B_FIND_MULTIPLE_CHILDREN
) == 0) {
1758 // find the one driver
1759 driver_module_info
* bestDriver
= NULL
;
1760 float bestSupport
= 0.0;
1761 void* cookie
= NULL
;
1763 while (_GetNextDriverPath(cookie
, path
) == B_OK
) {
1764 _FindBestDriver(path
.Path(), bestDriver
, bestSupport
, previous
);
1767 if (bestDriver
!= NULL
) {
1768 TRACE((" register best module \"%s\", support %f\n",
1769 bestDriver
->info
.name
, bestSupport
));
1770 if (bestDriver
->register_device(this) == B_OK
) {
1771 // There can only be one node of this driver
1772 // (usually only one at all, but there might be a new driver
1773 // "waiting" for its turn)
1774 device_node
* child
= FindChild(bestDriver
->info
.name
);
1775 if (child
!= NULL
) {
1776 child
->fSupportsParent
= bestSupport
;
1777 if (previous
!= NULL
) {
1778 previous
->fFlags
|= NODE_FLAG_OBSOLETE_DRIVER
;
1779 previous
->Release();
1780 child
->fFlags
|= NODE_FLAG_WAITING_FOR_DRIVER
;
1783 // TODO: if this fails, we could try the second best driver,
1786 put_module(bestDriver
->info
.name
);
1789 // register all drivers that match
1790 void* cookie
= NULL
;
1791 while (_GetNextDriverPath(cookie
, path
) == B_OK
) {
1792 _RegisterPath(path
.Path());
1801 device_node::_ReleaseWaiting()
1803 NodeList::Iterator iterator
= fChildren
.GetIterator();
1804 while (iterator
.HasNext()) {
1805 device_node
* child
= iterator
.Next();
1807 child
->fFlags
&= ~NODE_FLAG_WAITING_FOR_DRIVER
;
1813 device_node::_RemoveChildren()
1815 NodeList::Iterator iterator
= fChildren
.GetIterator();
1816 while (iterator
.HasNext()) {
1817 device_node
* child
= iterator
.Next();
1821 return fChildren
.IsEmpty() ? B_OK
: B_BUSY
;
1826 device_node::_FindCurrentChild()
1828 NodeList::Iterator iterator
= fChildren
.GetIterator();
1829 while (iterator
.HasNext()) {
1830 device_node
* child
= iterator
.Next();
1832 if ((child
->Flags() & NODE_FLAG_WAITING_FOR_DRIVER
) == 0)
1841 device_node::_Probe()
1843 device_node
* previous
= NULL
;
1845 if (IsProbed() && !fChildren
.IsEmpty()
1846 && (fFlags
& (B_FIND_CHILD_ON_DEMAND
| B_FIND_MULTIPLE_CHILDREN
))
1847 == B_FIND_CHILD_ON_DEMAND
) {
1848 // We already have a driver that claims this node; remove all
1849 // (unused) nodes, and evaluate it again
1852 previous
= _FindCurrentChild();
1853 if (previous
!= NULL
) {
1854 // This driver is still active - give it back the reference
1855 // that was stolen by _RemoveChildren() - _RegisterDynamic()
1856 // will release it, if it really isn't needed anymore
1857 previous
->Acquire();
1861 return _RegisterDynamic(previous
);
1866 device_node::Probe(const char* devicePath
, uint32 updateCycle
)
1868 if ((fFlags
& NODE_FLAG_DEVICE_REMOVED
) != 0
1869 || updateCycle
== fLastUpdateCycle
)
1872 status_t status
= InitDriver();
1876 MethodDeleter
<device_node
, bool> uninit(this,
1877 &device_node::UninitDriver
);
1879 if ((fFlags
& B_FIND_CHILD_ON_DEMAND
) != 0) {
1880 bool matches
= false;
1883 if (get_attr_uint16(this, B_DEVICE_SUB_TYPE
, &subType
, false) == B_OK
1884 && get_attr_uint16(this, B_DEVICE_TYPE
, &type
, false) == B_OK
) {
1885 // Check if this node matches the device path
1886 // TODO: maybe make this extendible via settings file?
1887 if (!strcmp(devicePath
, "disk")) {
1888 matches
= type
== PCI_mass_storage
;
1889 } else if (!strcmp(devicePath
, "audio")) {
1890 matches
= type
== PCI_multimedia
1891 && (subType
== PCI_audio
|| subType
== PCI_hd_audio
);
1892 } else if (!strcmp(devicePath
, "net")) {
1893 matches
= type
== PCI_network
;
1894 } else if (!strcmp(devicePath
, "graphics")) {
1895 matches
= type
== PCI_display
;
1896 } else if (!strcmp(devicePath
, "video")) {
1897 matches
= type
== PCI_multimedia
&& subType
== PCI_video
;
1900 // This driver does not support types, but still wants to its
1901 // children explored on demand only.
1903 sGenericContextPath
= devicePath
;
1907 fLastUpdateCycle
= updateCycle
;
1908 // This node will be probed in this update cycle
1912 sGenericContextPath
= NULL
;
1919 NodeList::Iterator iterator
= fChildren
.GetIterator();
1920 while (iterator
.HasNext()) {
1921 device_node
* child
= iterator
.Next();
1923 status
= child
->Probe(devicePath
, updateCycle
);
1933 device_node::Reprobe()
1935 status_t status
= InitDriver();
1939 MethodDeleter
<device_node
, bool> uninit(this,
1940 &device_node::UninitDriver
);
1942 // If this child has been probed already, probe it again
1947 NodeList::Iterator iterator
= fChildren
.GetIterator();
1948 while (iterator
.HasNext()) {
1949 device_node
* child
= iterator
.Next();
1951 status
= child
->Reprobe();
1961 device_node::Rescan()
1963 status_t status
= InitDriver();
1967 MethodDeleter
<device_node
, bool> uninit(this,
1968 &device_node::UninitDriver
);
1970 if (DriverModule()->rescan_child_devices
!= NULL
) {
1971 status
= DriverModule()->rescan_child_devices(DriverData());
1976 NodeList::Iterator iterator
= fChildren
.GetIterator();
1977 while (iterator
.HasNext()) {
1978 device_node
* child
= iterator
.Next();
1980 status
= child
->Rescan();
1989 /*! Uninitializes all temporary references to the driver. The registration
1990 process keeps the driver initialized to optimize the startup procedure;
1991 this function gives this reference away again.
1994 device_node::UninitUnusedDriver()
1996 // First, we need to go to the leaf, and go back from there
1998 NodeList::Iterator iterator
= fChildren
.GetIterator();
1999 while (iterator
.HasNext()) {
2000 device_node
* child
= iterator
.Next();
2002 child
->UninitUnusedDriver();
2005 if (!IsInitialized()
2006 || (fFlags
& NODE_FLAG_REGISTER_INITIALIZED
) == 0)
2009 fFlags
&= ~NODE_FLAG_REGISTER_INITIALIZED
;
2015 /*! Calls device_removed() on this node and all of its children - starting
2016 with the deepest and last child.
2017 It will also remove the one reference that every node gets on its creation.
2020 device_node::DeviceRemoved()
2023 NodeList::ConstIterator iterator
= Children().GetIterator();
2024 while (iterator
.HasNext()) {
2025 device_node
* child
= iterator
.Next();
2027 child
->DeviceRemoved();
2031 DeviceList::ConstIterator deviceIterator
= Devices().GetIterator();
2032 while (deviceIterator
.HasNext()) {
2033 Device
* device
= deviceIterator
.Next();
2035 if (device
->Module() != NULL
2036 && device
->Module()->device_removed
!= NULL
)
2037 device
->Module()->device_removed(device
->Data());
2040 fFlags
|= NODE_FLAG_DEVICE_REMOVED
;
2042 if (IsInitialized() && DriverModule()->device_removed
!= NULL
)
2043 DriverModule()->device_removed(this);
2045 if ((fFlags
& B_KEEP_DRIVER_LOADED
) != 0) {
2046 // There is no point in keeping this driver loaded when its device
2051 UninitUnusedDriver();
2057 device_node::Acquire()
2059 atomic_add(&fRefCount
, 1);
2064 device_node::Release()
2066 if (atomic_add(&fRefCount
, -1) > 1)
2075 device_node::AddDevice(Device
* device
)
2077 fDevices
.Add(device
);
2082 device_node::RemoveDevice(Device
* device
)
2084 fDevices
.Remove(device
);
2089 device_node::CompareTo(const device_attr
* attributes
) const
2091 if (attributes
== NULL
)
2094 for (; attributes
->name
!= NULL
; attributes
++) {
2095 // find corresponding attribute
2096 AttributeList::ConstIterator iterator
= Attributes().GetIterator();
2097 device_attr_private
* attr
= NULL
;
2100 while (iterator
.HasNext()) {
2101 attr
= iterator
.Next();
2103 if (!strcmp(attr
->name
, attributes
->name
)) {
2111 int compare
= device_attr_private::Compare(attr
, attributes
);
2121 device_node::FindChild(const device_attr
* attributes
) const
2123 if (attributes
== NULL
)
2126 NodeList::ConstIterator iterator
= Children().GetIterator();
2127 while (iterator
.HasNext()) {
2128 device_node
* child
= iterator
.Next();
2130 // ignore nodes that are pending to be removed
2131 if ((child
->Flags() & NODE_FLAG_DEVICE_REMOVED
) == 0
2132 && !child
->CompareTo(attributes
))
2141 device_node::FindChild(const char* moduleName
) const
2143 if (moduleName
== NULL
)
2146 NodeList::ConstIterator iterator
= Children().GetIterator();
2147 while (iterator
.HasNext()) {
2148 device_node
* child
= iterator
.Next();
2150 if (!strcmp(child
->ModuleName(), moduleName
))
2158 /*! This returns the priority or importance of this node. Nodes with higher
2159 priority are registered/probed first.
2160 Currently, only the B_FIND_MULTIPLE_CHILDREN flag alters the priority;
2161 it might make sense to be able to directly set the priority via an
2165 device_node::Priority()
2167 return (fFlags
& B_FIND_MULTIPLE_CHILDREN
) != 0 ? 0 : 100;
2172 device_node::Dump(int32 level
)
2175 kprintf("(%" B_PRId32
") @%p \"%s\" (ref %" B_PRId32
", init %" B_PRId32
2176 ", module %p, data %p)\n", level
, this, ModuleName(), fRefCount
,
2177 fInitialized
, DriverModule(), DriverData());
2179 AttributeList::Iterator attribute
= Attributes().GetIterator();
2180 while (attribute
.HasNext()) {
2181 dump_attribute(attribute
.Next(), level
);
2184 DeviceList::Iterator deviceIterator
= fDevices
.GetIterator();
2185 while (deviceIterator
.HasNext()) {
2186 Device
* device
= deviceIterator
.Next();
2188 kprintf("device: %s, %p\n", device
->ModuleName(), device
->Data());
2191 NodeList::ConstIterator iterator
= Children().GetIterator();
2192 while (iterator
.HasNext()) {
2193 iterator
.Next()->Dump(level
+ 1);
2198 // #pragma mark - root node
2202 init_node_tree(void)
2204 device_attr attrs
[] = {
2205 {B_DEVICE_PRETTY_NAME
, B_STRING_TYPE
, {string
: "Devices Root"}},
2206 {B_DEVICE_BUS
, B_STRING_TYPE
, {string
: "root"}},
2207 {B_DEVICE_FLAGS
, B_UINT32_TYPE
,
2208 {ui32
: B_FIND_MULTIPLE_CHILDREN
| B_KEEP_DRIVER_LOADED
}},
2212 device_node
* node
= NULL
;
2213 if (register_node(NULL
, DEVICE_MANAGER_ROOT_NAME
, attrs
, NULL
, &node
)
2215 dprintf("Cannot register Devices Root Node\n");
2218 device_attr genericAttrs
[] = {
2219 {B_DEVICE_PRETTY_NAME
, B_STRING_TYPE
, {string
: "Generic"}},
2220 {B_DEVICE_BUS
, B_STRING_TYPE
, {string
: "generic"}},
2221 {B_DEVICE_FLAGS
, B_UINT32_TYPE
, {ui32
: B_FIND_MULTIPLE_CHILDREN
2222 | B_KEEP_DRIVER_LOADED
| B_FIND_CHILD_ON_DEMAND
}},
2226 if (register_node(node
, DEVICE_MANAGER_GENERIC_NAME
, genericAttrs
, NULL
,
2228 dprintf("Cannot register Generic Devices Node\n");
2233 driver_module_info gDeviceRootModule
= {
2235 DEVICE_MANAGER_ROOT_NAME
,
2242 driver_module_info gDeviceGenericModule
= {
2244 DEVICE_MANAGER_GENERIC_NAME
,
2252 // #pragma mark - private kernel API
2256 device_manager_probe(const char* path
, uint32 updateCycle
)
2258 TRACE(("device_manager_probe(\"%s\")\n", path
));
2259 RecursiveLocker
_(sLock
);
2261 // first, publish directories in the driver directory
2262 publish_directories(path
);
2264 return sRootNode
->Probe(path
, updateCycle
);
2269 device_manager_init(struct kernel_args
* args
)
2271 TRACE(("device manager init\n"));
2273 IOSchedulerRoster::Init();
2275 dm_init_id_generator();
2276 dm_init_io_resources();
2278 recursive_lock_init(&sLock
, "device manager");
2280 register_generic_syscall(DEVICE_MANAGER_SYSCALLS
, control_device_manager
,
2283 add_debugger_command("dm_tree", &dump_device_nodes
,
2284 "dump device node tree");
2285 add_debugger_command_etc("io_scheduler", &dump_io_scheduler
,
2286 "Dump an I/O scheduler",
2288 "Dumps I/O scheduler at address <scheduler>.\n", 0);
2289 add_debugger_command_etc("io_request_owner", &dump_io_request_owner
,
2290 "Dump an I/O request owner",
2292 "Dumps I/O request owner at address <owner>.\n", 0);
2293 add_debugger_command("io_request", &dump_io_request
, "dump an I/O request");
2294 add_debugger_command("io_operation", &dump_io_operation
,
2295 "dump an I/O operation");
2296 add_debugger_command("io_buffer", &dump_io_buffer
, "dump an I/O buffer");
2297 add_debugger_command("dma_buffer", &dump_dma_buffer
, "dump a DMA buffer");
2306 device_manager_init_post_modules(struct kernel_args
* args
)
2308 RecursiveLocker
_(sLock
);
2309 return sRootNode
->Reprobe();