btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / system / kernel / device_manager / device_manager.cpp
blobf42a03094d461f39bf5b52448e253283d83f7994
1 /*
2 * Copyright 2008-2009, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
7 #include <kdevice_manager.h>
9 #include <new>
10 #include <set>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
15 #include <KernelExport.h>
16 #include <Locker.h>
17 #include <module.h>
18 #include <PCI.h>
20 #include <boot_device.h>
21 #include <device_manager_defs.h>
22 #include <fs/devfs.h>
23 #include <fs/KPath.h>
24 #include <kernel.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
41 #else
42 # define TRACE(a) ;
43 #endif
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();
56 status_t InitCheck();
57 status_t CopyFrom(const device_attr& attr);
59 static int Compare(const device_attr* attrA,
60 const device_attr *attrB);
62 private:
63 void _Unset();
66 typedef DoublyLinkedList<device_attr_private> AttributeList;
68 // I/O resource
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
73 } io_resource_info;
76 namespace {
79 class Device : public AbstractModuleDevice,
80 public DoublyLinkedListLinkImpl<Device> {
81 public:
82 Device(device_node* node, const char* moduleName);
83 virtual ~Device();
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; }
97 private:
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);
112 ~device_node();
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();
124 bool UninitDriver();
125 void UninitUnusedDriver();
127 // The following two are only valid, if the node's driver is
128 // initialized
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);
139 status_t Reprobe();
140 status_t Rescan();
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; }
147 void Acquire();
148 bool Release();
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;
158 int32 Priority();
160 void Dump(int32 level = 0);
162 private:
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,
172 float& bestSupport,
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();
178 status_t _Probe();
179 void _ReleaseWaiting();
181 device_node* fParent;
182 NodeList fChildren;
183 int32 fRefCount;
184 int32 fInitialized;
185 bool fRegistered;
186 uint32 fFlags;
187 float fSupportsParent;
188 uint32 fLastUpdateCycle;
190 const char* fModuleName;
192 driver_module_info* fDriver;
193 void* fDriverData;
195 DeviceList fDevices;
196 AttributeList fAttributes;
197 ResourceList fResources;
200 // flags in addition to those specified by B_DEVICE_FLAGS
201 enum node_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;
216 // #pragma mark -
219 static device_attr_private*
220 find_attr(const device_node* node, const char* name, bool recursive,
221 type_code type)
223 do {
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)
231 continue;
233 if (!strcmp(attr->name, name))
234 return attr;
237 node = node->Parent();
238 } while (node != NULL && recursive);
240 return NULL;
244 static void
245 put_level(int32 level)
247 while (level-- > 0)
248 kprintf(" ");
252 static void
253 dump_attribute(device_attr* attr, int32 level)
255 if (attr == NULL)
256 return;
258 put_level(level + 2);
259 kprintf("\"%s\" : ", attr->name);
260 switch (attr->type) {
261 case B_STRING_TYPE:
262 kprintf("string : \"%s\"", attr->value.string);
263 break;
264 case B_INT8_TYPE:
265 case B_UINT8_TYPE:
266 kprintf("uint8 : %" B_PRIu8 " (%#" B_PRIx8 ")", attr->value.ui8,
267 attr->value.ui8);
268 break;
269 case B_INT16_TYPE:
270 case B_UINT16_TYPE:
271 kprintf("uint16 : %" B_PRIu16 " (%#" B_PRIx16 ")", attr->value.ui16,
272 attr->value.ui16);
273 break;
274 case B_INT32_TYPE:
275 case B_UINT32_TYPE:
276 kprintf("uint32 : %" B_PRIu32 " (%#" B_PRIx32 ")", attr->value.ui32,
277 attr->value.ui32);
278 break;
279 case B_INT64_TYPE:
280 case B_UINT64_TYPE:
281 kprintf("uint64 : %" B_PRIu64 " (%#" B_PRIx64 ")", attr->value.ui64,
282 attr->value.ui64);
283 break;
284 default:
285 kprintf("raw data");
287 kprintf("\n");
291 static int
292 dump_io_scheduler(int argc, char** argv)
294 if (argc != 2) {
295 print_debugger_command_usage(argv[0]);
296 return 0;
299 IOScheduler* scheduler = (IOScheduler*)parse_expression(argv[1]);
300 scheduler->Dump();
301 return 0;
305 static int
306 dump_io_request_owner(int argc, char** argv)
308 if (argc != 2) {
309 print_debugger_command_usage(argv[0]);
310 return 0;
313 IORequestOwner* owner = (IORequestOwner*)parse_expression(argv[1]);
314 owner->Dump();
315 return 0;
319 static int
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]);
324 return 0;
327 IORequest* request = (IORequest*)parse_expression(argv[1]);
328 request->Dump();
329 return 0;
333 static int
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]);
338 return 0;
341 IOOperation* operation = (IOOperation*)parse_expression(argv[1]);
342 operation->Dump();
343 return 0;
347 static int
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]);
352 return 0;
355 IOBuffer* buffer = (IOBuffer*)parse_expression(argv[1]);
356 buffer->Dump();
357 return 0;
361 static int
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]);
366 return 0;
369 DMABuffer* buffer = (DMABuffer*)parse_expression(argv[1]);
370 buffer->Dump();
371 return 0;
375 static int
376 dump_device_nodes(int argc, char** argv)
378 sRootNode->Dump();
379 return 0;
383 static void
384 publish_directories(const char* subPath)
386 if (gBootDevice < 0) {
387 if (subPath[0]) {
388 // we only support the top-level directory for modules
389 return;
392 // we can only iterate over the known modules to find all directories
393 KPath path("drivers");
394 if (path.Append(subPath) != B_OK)
395 return;
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)
405 continue;
407 char* leaf = name + length;
408 char* end = strchr(leaf, '/');
409 if (end != NULL)
410 end[0] = '\0';
412 path.SetTo(subPath);
413 path.Append(leaf);
415 devfs_publish_directory(path.Path());
417 close_module_list(list);
418 } else {
419 // TODO: implement module directory traversal!
424 static status_t
425 control_device_manager(const char* subsystem, uint32 function, void* buffer,
426 size_t bufferSize)
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.
431 switch (function) {
432 case DM_GET_ROOT:
434 device_node_cookie cookie;
435 if (!IS_USER_ADDRESS(buffer))
436 return B_BAD_ADDRESS;
437 if (bufferSize != sizeof(device_node_cookie))
438 return B_BAD_VALUE;
439 cookie = (device_node_cookie)sRootNode;
441 // copy back to user space
442 return user_memcpy(buffer, &cookie, sizeof(device_node_cookie));
445 case DM_GET_CHILD:
447 if (!IS_USER_ADDRESS(buffer))
448 return B_BAD_ADDRESS;
449 if (bufferSize != sizeof(device_node_cookie))
450 return B_BAD_VALUE;
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))
474 return B_BAD_VALUE;
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;
481 if (!last->Parent())
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();
491 if (node == last)
492 break;
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))
510 return B_BAD_VALUE;
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();
521 if (attr == last)
522 break;
525 if (!iterator.HasNext()) {
526 attrInfo.cookie = 0;
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) {
535 case B_UINT8_TYPE:
536 attrInfo.value.ui8 = attr->value.ui8;
537 break;
538 case B_UINT16_TYPE:
539 attrInfo.value.ui16 = attr->value.ui16;
540 break;
541 case B_UINT32_TYPE:
542 attrInfo.value.ui32 = attr->value.ui32;
543 break;
544 case B_UINT64_TYPE:
545 attrInfo.value.ui64 = attr->value.ui64;
546 break;
547 case B_STRING_TYPE:
548 strlcpy(attrInfo.value.string, attr->value.string, 254);
549 break;
550 /*case B_RAW_TYPE:
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);
555 break;*/
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
570 static status_t
571 rescan_node(device_node* node)
573 RecursiveLocker _(sLock);
574 return node->Rescan();
578 static status_t
579 register_node(device_node* parent, const char* moduleName,
580 const device_attr* attrs, const io_resource* ioResources,
581 device_node** _node)
583 if ((parent == NULL && sRootNode != NULL) || moduleName == NULL)
584 return B_BAD_VALUE;
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);
594 if (newNode == NULL)
595 return B_NO_MEMORY;
597 TRACE(("%p: register node \"%s\", parent %p\n", newNode, moduleName,
598 parent));
600 status_t status = newNode->InitCheck();
601 if (status == B_OK)
602 status = newNode->AcquireResources(ioResources);
603 if (status == B_OK)
604 status = newNode->Register(parent);
606 if (status != B_OK) {
607 newNode->Release();
608 return status;
611 if (_node)
612 *_node = newNode;
614 return 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.
624 static status_t
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;
638 static status_t
639 get_driver(device_node* node, driver_module_info** _module, void** _data)
641 if (node->DriverModule() == NULL)
642 return B_NO_INIT;
644 if (_module != NULL)
645 *_module = node->DriverModule();
646 if (_data != NULL)
647 *_data = node->DriverData();
649 return B_OK;
653 static device_node*
654 get_root_node(void)
656 if (sRootNode != NULL)
657 sRootNode->Acquire();
659 return sRootNode;
663 static status_t
664 get_next_child_node(device_node* parent, const device_attr* attributes,
665 device_node** _node)
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();
676 if (node != last)
677 continue;
680 // find the next one that fits
681 while (iterator.HasNext()) {
682 device_node* node = iterator.Next();
684 if (!node->IsRegistered())
685 continue;
687 if (!node->CompareTo(attributes)) {
688 if (last != NULL)
689 last->Release();
691 node->Acquire();
692 *_node = node;
693 return B_OK;
697 if (last != NULL)
698 last->Release();
700 return B_ENTRY_NOT_FOUND;
704 static device_node*
705 get_parent_node(device_node* node)
707 if (node == NULL)
708 return NULL;
710 RecursiveLocker _(sLock);
712 device_node* parent = node->Parent();
713 parent->Acquire();
715 return parent;
719 static void
720 put_node(device_node* node)
722 RecursiveLocker _(sLock);
723 node->Release();
727 static status_t
728 publish_device(device_node *node, const char *path, const char *moduleName)
730 if (path == NULL || !path[0] || moduleName == NULL || !moduleName[0])
731 return B_BAD_VALUE;
733 RecursiveLocker _(sLock);
734 dprintf("publish device: node %p, path %s, module %s\n", node, path,
735 moduleName);
737 Device* device = new(std::nothrow) Device(node, moduleName);
738 if (device == NULL)
739 return B_NO_MEMORY;
741 status_t status = device->InitCheck();
742 if (status == B_OK)
743 status = devfs_publish_device(path, device);
744 if (status != B_OK) {
745 delete device;
746 return status;
749 node->AddDevice(device);
750 return B_OK;
754 static status_t
755 unpublish_device(device_node *node, const char *path)
757 if (path == NULL)
758 return B_BAD_VALUE;
760 BaseDevice* baseDevice;
761 status_t error = devfs_get_device(path, baseDevice);
762 if (error != B_OK)
763 return error;
764 CObjectDeleter<BaseDevice> baseDevicePutter(baseDevice, &devfs_put_device);
766 Device* device = dynamic_cast<Device*>(baseDevice);
767 if (device == NULL || device->Node() != node)
768 return B_BAD_VALUE;
770 return devfs_unpublish_device(device, true);
774 static status_t
775 get_attr_uint8(const device_node* node, const char* name, uint8* _value,
776 bool recursive)
778 if (node == NULL || name == NULL || _value == NULL)
779 return B_BAD_VALUE;
781 device_attr_private* attr = find_attr(node, name, recursive, B_UINT8_TYPE);
782 if (attr == NULL)
783 return B_NAME_NOT_FOUND;
785 *_value = attr->value.ui8;
786 return B_OK;
790 static status_t
791 get_attr_uint16(const device_node* node, const char* name, uint16* _value,
792 bool recursive)
794 if (node == NULL || name == NULL || _value == NULL)
795 return B_BAD_VALUE;
797 device_attr_private* attr = find_attr(node, name, recursive, B_UINT16_TYPE);
798 if (attr == NULL)
799 return B_NAME_NOT_FOUND;
801 *_value = attr->value.ui16;
802 return B_OK;
806 static status_t
807 get_attr_uint32(const device_node* node, const char* name, uint32* _value,
808 bool recursive)
810 if (node == NULL || name == NULL || _value == NULL)
811 return B_BAD_VALUE;
813 device_attr_private* attr = find_attr(node, name, recursive, B_UINT32_TYPE);
814 if (attr == NULL)
815 return B_NAME_NOT_FOUND;
817 *_value = attr->value.ui32;
818 return B_OK;
822 static status_t
823 get_attr_uint64(const device_node* node, const char* name,
824 uint64* _value, bool recursive)
826 if (node == NULL || name == NULL || _value == NULL)
827 return B_BAD_VALUE;
829 device_attr_private* attr = find_attr(node, name, recursive, B_UINT64_TYPE);
830 if (attr == NULL)
831 return B_NAME_NOT_FOUND;
833 *_value = attr->value.ui64;
834 return B_OK;
838 static status_t
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)
843 return B_BAD_VALUE;
845 device_attr_private* attr = find_attr(node, name, recursive, B_STRING_TYPE);
846 if (attr == NULL)
847 return B_NAME_NOT_FOUND;
849 *_value = attr->value.string;
850 return B_OK;
854 static status_t
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))
859 return B_BAD_VALUE;
861 device_attr_private* attr = find_attr(node, name, recursive, B_RAW_TYPE);
862 if (attr == NULL)
863 return B_NAME_NOT_FOUND;
865 if (_data != NULL)
866 *_data = attr->value.raw.data;
867 if (_length != NULL)
868 *_length = attr->value.raw.length;
869 return B_OK;
873 static status_t
874 get_next_attr(device_node* node, device_attr** _attr)
876 if (node == NULL)
877 return B_BAD_VALUE;
879 device_attr_private* next;
880 device_attr_private* attr = *(device_attr_private**)_attr;
882 if (attr != NULL) {
883 // next attribute
884 next = attr->GetDoublyLinkedListLink()->next;
885 } else {
886 // first attribute
887 next = node->Attributes().First();
890 *_attr = next;
892 return next ? B_OK : B_ENTRY_NOT_FOUND;
896 struct device_manager_info gDeviceManagerModule = {
898 B_DEVICE_MANAGER_MODULE_NAME,
900 NULL
903 // device nodes
904 rescan_node,
905 register_node,
906 unregister_node,
907 get_driver,
908 get_root_node,
909 get_next_child_node,
910 get_parent_node,
911 put_node,
913 // devices
914 publish_device,
915 unpublish_device,
917 // I/O resources
919 // ID generator
920 dm_create_id,
921 dm_free_id,
923 // attributes
924 get_attr_uint8,
925 get_attr_uint16,
926 get_attr_uint32,
927 get_attr_uint64,
928 get_attr_string,
929 get_attr_raw,
930 get_next_attr,
934 // #pragma mark - device_attr
937 device_attr_private::device_attr_private()
939 name = NULL;
940 type = 0;
941 value.raw.data = NULL;
942 value.raw.length = 0;
946 device_attr_private::device_attr_private(const device_attr& attr)
948 CopyFrom(attr);
952 device_attr_private::~device_attr_private()
954 _Unset();
958 status_t
959 device_attr_private::InitCheck()
961 return name != NULL ? B_OK : B_NO_INIT;
965 status_t
966 device_attr_private::CopyFrom(const device_attr& attr)
968 name = strdup(attr.name);
969 if (name == NULL)
970 return B_NO_MEMORY;
972 type = attr.type;
974 switch (type) {
975 case B_UINT8_TYPE:
976 case B_UINT16_TYPE:
977 case B_UINT32_TYPE:
978 case B_UINT64_TYPE:
979 value.ui64 = attr.value.ui64;
980 break;
982 case B_STRING_TYPE:
983 if (attr.value.string != NULL) {
984 value.string = strdup(attr.value.string);
985 if (value.string == NULL) {
986 _Unset();
987 return B_NO_MEMORY;
989 } else
990 value.string = NULL;
991 break;
993 case B_RAW_TYPE:
994 value.raw.data = malloc(attr.value.raw.length);
995 if (value.raw.data == NULL) {
996 _Unset();
997 return B_NO_MEMORY;
1000 value.raw.length = attr.value.raw.length;
1001 memcpy((void*)value.raw.data, attr.value.raw.data,
1002 attr.value.raw.length);
1003 break;
1005 default:
1006 return B_BAD_VALUE;
1009 return B_OK;
1013 void
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);
1021 free((char*)name);
1023 name = NULL;
1024 value.raw.data = NULL;
1025 value.raw.length = 0;
1029 /*static*/ int
1030 device_attr_private::Compare(const device_attr* attrA, const device_attr *attrB)
1032 if (attrA->type != attrB->type)
1033 return -1;
1035 switch (attrA->type) {
1036 case B_UINT8_TYPE:
1037 return (int)attrA->value.ui8 - (int)attrB->value.ui8;
1039 case B_UINT16_TYPE:
1040 return (int)attrA->value.ui16 - (int)attrB->value.ui16;
1042 case B_UINT32_TYPE:
1043 if (attrA->value.ui32 > attrB->value.ui32)
1044 return 1;
1045 if (attrA->value.ui32 < attrB->value.ui32)
1046 return -1;
1047 return 0;
1049 case B_UINT64_TYPE:
1050 if (attrA->value.ui64 > attrB->value.ui64)
1051 return 1;
1052 if (attrA->value.ui64 < attrB->value.ui64)
1053 return -1;
1054 return 0;
1056 case B_STRING_TYPE:
1057 return strcmp(attrA->value.string, attrB->value.string);
1059 case B_RAW_TYPE:
1060 if (attrA->value.raw.length != attrB->value.raw.length)
1061 return -1;
1063 return memcmp(attrA->value.raw.data, attrB->value.raw.data,
1064 attrA->value.raw.length);
1067 return -1;
1071 // #pragma mark - Device
1074 Device::Device(device_node* node, const char* moduleName)
1076 fModuleName(strdup(moduleName)),
1077 fRemovedFromParent(false)
1079 fNode = node;
1083 Device::~Device()
1085 free((char*)fModuleName);
1089 status_t
1090 Device::InitCheck() const
1092 return fModuleName != NULL ? B_OK : B_NO_MEMORY;
1096 status_t
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
1103 return ENODEV;
1105 if ((fNode->Flags() & NODE_FLAG_WAITING_FOR_DRIVER) != 0)
1106 return B_BUSY;
1108 if (fInitialized++ > 0) {
1109 fNode->InitDriver();
1110 // acquire another reference to our parent as well
1111 return B_OK;
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) {
1120 fInitialized--;
1121 return status;
1124 if (Module()->init_device != NULL)
1125 status = Module()->init_device(fNode->DriverData(), &fDeviceData);
1127 if (status < B_OK) {
1128 fNode->UninitDriver();
1129 fInitialized--;
1131 put_module(ModuleName());
1132 fDeviceModule = NULL;
1133 fDeviceData = NULL;
1136 return status;
1140 void
1141 Device::UninitDevice()
1143 RecursiveLocker _(sLock);
1145 if (fInitialized-- > 1) {
1146 fNode->UninitDriver();
1147 return;
1150 TRACE(("uninit driver for node %p\n", this));
1152 if (Module()->uninit_device != NULL)
1153 Module()->uninit_device(fDeviceData);
1155 fDeviceModule = NULL;
1156 fDeviceData = NULL;
1158 put_module(ModuleName());
1160 fNode->UninitDriver();
1164 void
1165 Device::Removed()
1167 RecursiveLocker _(sLock);
1169 if (!fRemovedFromParent)
1170 fNode->RemoveDevice(this);
1172 delete 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)
1183 return;
1185 fParent = NULL;
1186 fRefCount = 1;
1187 fInitialized = 0;
1188 fRegistered = false;
1189 fFlags = 0;
1190 fSupportsParent = 0.0;
1191 fLastUpdateCycle = 0;
1192 fDriver = NULL;
1193 fDriverData = NULL;
1195 // copy attributes
1197 while (attrs != NULL && attrs->name != NULL) {
1198 device_attr_private* attr
1199 = new(std::nothrow) device_attr_private(*attrs);
1200 if (attr == NULL)
1201 break;
1203 fAttributes.Add(attr);
1204 attrs++;
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);
1226 // Delete children
1227 while (device_node* child = fChildren.RemoveHead()) {
1228 delete child;
1231 // Delete devices
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()) {
1239 delete attr;
1242 // Delete resources
1243 while (io_resource_private* resource = fResources.RemoveHead()) {
1244 delete resource;
1247 free((char*)fModuleName);
1251 status_t
1252 device_node::InitCheck() const
1254 return fModuleName != NULL ? B_OK : B_NO_MEMORY;
1258 status_t
1259 device_node::AcquireResources(const io_resource* resources)
1261 if (resources == NULL)
1262 return B_OK;
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)
1267 return B_NO_MEMORY;
1269 status_t status = resource->Acquire(resources[i]);
1270 if (status != B_OK) {
1271 delete resource;
1272 return status;
1275 fResources.Add(resource);
1278 return B_OK;
1282 status_t
1283 device_node::InitDriver()
1285 if (fInitialized++ > 0) {
1286 if (Parent() != NULL) {
1287 Parent()->InitDriver();
1288 // acquire another reference to our parent as well
1290 Acquire();
1291 return B_OK;
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) {
1300 fInitialized--;
1301 return status;
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(),
1308 strerror(status));
1312 if (status < B_OK) {
1313 if (Parent() != NULL)
1314 Parent()->UninitDriver();
1315 fInitialized--;
1317 put_module(ModuleName());
1318 fDriver = NULL;
1319 fDriverData = NULL;
1320 return status;
1323 Acquire();
1324 return B_OK;
1328 bool
1329 device_node::UninitDriver()
1331 if (fInitialized-- > 1) {
1332 if (Parent() != NULL)
1333 Parent()->UninitDriver();
1334 Release();
1335 return false;
1338 TRACE(("uninit driver for node %p\n", this));
1340 if (fDriver->uninit_driver != NULL)
1341 fDriver->uninit_driver(fDriverData);
1343 fDriver = NULL;
1344 fDriverData = NULL;
1346 put_module(ModuleName());
1348 if (Parent() != NULL)
1349 Parent()->UninitDriver();
1350 Release();
1352 return true;
1356 void
1357 device_node::AddChild(device_node* node)
1359 // we must not be destroyed as long as we have children
1360 Acquire();
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) {
1372 before = child;
1373 break;
1377 fChildren.Insert(before, node);
1381 void
1382 device_node::RemoveChild(device_node* node)
1384 node->fParent = NULL;
1385 fChildren.Remove(node);
1386 Release();
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.
1394 status_t
1395 device_node::Register(device_node* parent)
1397 // make it public
1398 if (parent != NULL)
1399 parent->AddChild(this);
1400 else
1401 sRootNode = this;
1403 status_t status = InitDriver();
1404 if (status != B_OK)
1405 return status;
1407 if ((fFlags & B_KEEP_DRIVER_LOADED) != 0) {
1408 // We keep this driver loaded by having it always initialized
1409 InitDriver();
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();
1420 return status;
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();
1429 return status;
1432 if (!fChildren.IsEmpty()) {
1433 fRegistered = true;
1434 return B_OK;
1438 if (registeredFixedCount > 0) {
1439 // Nodes with fixed children cannot have any dynamic children, so bail
1440 // out here
1441 fRegistered = true;
1442 return B_OK;
1445 // Register all possible child device nodes
1447 status = _RegisterDynamic();
1448 if (status == B_OK)
1449 fRegistered = true;
1450 else
1451 UninitUnusedDriver();
1453 return status;
1457 /*! Registers any children that are identified via the B_DEVICE_FIXED_CHILD
1458 attribute.
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).
1462 status_t
1463 device_node::_RegisterFixed(uint32& registered)
1465 AttributeList::Iterator iterator = fAttributes.GetIterator();
1466 registered = 0;
1468 while (iterator.HasNext()) {
1469 device_attr_private* attr = iterator.Next();
1470 if (strcmp(attr->name, B_DEVICE_FIXED_CHILD))
1471 continue;
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,
1478 strerror(status)));
1479 return status;
1482 if (driver->register_device != NULL) {
1483 status = driver->register_device(this);
1484 if (status == B_OK)
1485 registered++;
1488 put_module(attr->value.string);
1490 if (status != B_OK)
1491 return status;
1494 return B_OK;
1498 status_t
1499 device_node::_AddPath(Stack<KPath*>& stack, const char* basePath,
1500 const char* subPath)
1502 KPath* path = new(std::nothrow) KPath;
1503 if (path == NULL)
1504 return B_NO_MEMORY;
1506 status_t status = path->SetTo(basePath);
1507 if (status == B_OK && subPath != NULL && subPath[0])
1508 status = path->Append(subPath);
1509 if (status == B_OK)
1510 status = stack.Push(path);
1512 TRACE((" add path: \"%s\", %" B_PRId32 "\n", path->Path(), status));
1514 if (status != B_OK)
1515 delete path;
1517 return status;
1521 status_t
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*>();
1529 if (stack == NULL)
1530 return B_NO_MEMORY;
1532 StackDeleter<KPath*> stackDeleter(stack);
1534 bool generic = false;
1535 uint16 type = 0;
1536 uint16 subType = 0;
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)
1540 != B_OK)
1541 generic = true;
1543 get_attr_uint16(this, B_DEVICE_INTERFACE, &interface, false);
1545 // TODO: maybe make this extendible via settings file?
1546 switch (type) {
1547 case PCI_mass_storage:
1548 switch (subType) {
1549 case PCI_scsi:
1550 _AddPath(*stack, "busses", "scsi");
1551 _AddPath(*stack, "busses", "virtio");
1552 break;
1553 case PCI_ide:
1554 _AddPath(*stack, "busses", "ata");
1555 _AddPath(*stack, "busses", "ide");
1556 break;
1557 case PCI_sata:
1558 // TODO: check for ahci interface
1559 _AddPath(*stack, "busses", "scsi");
1560 _AddPath(*stack, "busses", "ata");
1561 _AddPath(*stack, "busses", "ide");
1562 break;
1563 default:
1564 _AddPath(*stack, "busses");
1565 break;
1567 break;
1568 case PCI_serial_bus:
1569 switch (subType) {
1570 case PCI_firewire:
1571 _AddPath(*stack, "busses", "firewire");
1572 break;
1573 case PCI_usb:
1574 _AddPath(*stack, "busses", "usb");
1575 break;
1576 default:
1577 _AddPath(*stack, "busses");
1578 break;
1580 break;
1581 case PCI_network:
1582 _AddPath(*stack, "drivers", "net");
1583 _AddPath(*stack, "busses", "virtio");
1584 break;
1585 case PCI_display:
1586 _AddPath(*stack, "drivers", "graphics");
1587 break;
1588 case PCI_multimedia:
1589 switch (subType) {
1590 case PCI_audio:
1591 case PCI_hd_audio:
1592 _AddPath(*stack, "drivers", "audio");
1593 break;
1594 case PCI_video:
1595 _AddPath(*stack, "drivers", "video");
1596 break;
1597 default:
1598 _AddPath(*stack, "drivers");
1599 break;
1601 break;
1602 default:
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");
1609 } else {
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");
1622 break;
1625 stackDeleter.Detach();
1627 cookie = (void*)stack;
1628 } else
1629 stack = static_cast<Stack<KPath*>*>(cookie);
1631 KPath* path;
1632 if (stack->Pop(&path)) {
1633 _path.Adopt(*path);
1634 delete path;
1635 return B_OK;
1638 delete stack;
1639 return B_ENTRY_NOT_FOUND;
1643 status_t
1644 device_node::_GetNextDriver(void* list, driver_module_info*& driver)
1646 while (true) {
1647 char name[B_FILE_NAME_LENGTH];
1648 size_t nameLength = sizeof(name);
1650 status_t status = read_next_module_name(list, name, &nameLength);
1651 if (status != B_OK)
1652 return status;
1654 if (!strcmp(fModuleName, name))
1655 continue;
1657 if (get_module(name, (module_info**)&driver) != B_OK)
1658 continue;
1660 if (driver->supports_device == NULL
1661 || driver->register_device == NULL) {
1662 put_module(name);
1663 continue;
1666 return B_OK;
1671 status_t
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);
1683 continue;
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;
1693 continue;
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;
1705 status_t
1706 device_node::_RegisterPath(const char* path)
1708 void* list = open_module_list_etc(path, "driver_v1");
1709 driver_module_info* driver;
1710 uint32 count = 0;
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,
1716 support));
1717 if (driver->register_device(this) == B_OK)
1718 count++;
1721 put_module(driver->info.name);
1723 close_module_list(list);
1725 return count > 0 ? B_OK : B_ENTRY_NOT_FOUND;
1729 bool
1730 device_node::_AlwaysRegisterDynamic()
1732 uint16 type = 0;
1733 uint16 subType = 0;
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
1742 status_t
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)
1747 return B_OK;
1749 // If we're not being probed, we honour the B_FIND_CHILD_ON_DEMAND
1750 // requirements
1751 if (!IsProbed() && (fFlags & B_FIND_CHILD_ON_DEMAND) != 0
1752 && !_AlwaysRegisterDynamic())
1753 return B_OK;
1755 KPath path;
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,
1784 // and so on...
1786 put_module(bestDriver->info.name);
1788 } else {
1789 // register all drivers that match
1790 void* cookie = NULL;
1791 while (_GetNextDriverPath(cookie, path) == B_OK) {
1792 _RegisterPath(path.Path());
1796 return B_OK;
1800 void
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;
1812 status_t
1813 device_node::_RemoveChildren()
1815 NodeList::Iterator iterator = fChildren.GetIterator();
1816 while (iterator.HasNext()) {
1817 device_node* child = iterator.Next();
1818 child->Release();
1821 return fChildren.IsEmpty() ? B_OK : B_BUSY;
1825 device_node*
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)
1833 return child;
1836 return NULL;
1840 status_t
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
1850 _RemoveChildren();
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);
1865 status_t
1866 device_node::Probe(const char* devicePath, uint32 updateCycle)
1868 if ((fFlags & NODE_FLAG_DEVICE_REMOVED) != 0
1869 || updateCycle == fLastUpdateCycle)
1870 return B_OK;
1872 status_t status = InitDriver();
1873 if (status < B_OK)
1874 return status;
1876 MethodDeleter<device_node, bool> uninit(this,
1877 &device_node::UninitDriver);
1879 if ((fFlags & B_FIND_CHILD_ON_DEMAND) != 0) {
1880 bool matches = false;
1881 uint16 type = 0;
1882 uint16 subType = 0;
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;
1899 } else {
1900 // This driver does not support types, but still wants to its
1901 // children explored on demand only.
1902 matches = true;
1903 sGenericContextPath = devicePath;
1906 if (matches) {
1907 fLastUpdateCycle = updateCycle;
1908 // This node will be probed in this update cycle
1910 status = _Probe();
1912 sGenericContextPath = NULL;
1913 return status;
1916 return B_OK;
1919 NodeList::Iterator iterator = fChildren.GetIterator();
1920 while (iterator.HasNext()) {
1921 device_node* child = iterator.Next();
1923 status = child->Probe(devicePath, updateCycle);
1924 if (status != B_OK)
1925 return status;
1928 return B_OK;
1932 status_t
1933 device_node::Reprobe()
1935 status_t status = InitDriver();
1936 if (status < B_OK)
1937 return status;
1939 MethodDeleter<device_node, bool> uninit(this,
1940 &device_node::UninitDriver);
1942 // If this child has been probed already, probe it again
1943 status = _Probe();
1944 if (status != B_OK)
1945 return status;
1947 NodeList::Iterator iterator = fChildren.GetIterator();
1948 while (iterator.HasNext()) {
1949 device_node* child = iterator.Next();
1951 status = child->Reprobe();
1952 if (status != B_OK)
1953 return status;
1956 return B_OK;
1960 status_t
1961 device_node::Rescan()
1963 status_t status = InitDriver();
1964 if (status < B_OK)
1965 return status;
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());
1972 if (status != B_OK)
1973 return status;
1976 NodeList::Iterator iterator = fChildren.GetIterator();
1977 while (iterator.HasNext()) {
1978 device_node* child = iterator.Next();
1980 status = child->Rescan();
1981 if (status != B_OK)
1982 return status;
1985 return B_OK;
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.
1993 void
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)
2007 return;
2009 fFlags &= ~NODE_FLAG_REGISTER_INITIALIZED;
2011 UninitDriver();
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.
2019 void
2020 device_node::DeviceRemoved()
2022 // notify children
2023 NodeList::ConstIterator iterator = Children().GetIterator();
2024 while (iterator.HasNext()) {
2025 device_node* child = iterator.Next();
2027 child->DeviceRemoved();
2030 // notify devices
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
2047 // is gone
2048 UninitDriver();
2051 UninitUnusedDriver();
2052 Release();
2056 void
2057 device_node::Acquire()
2059 atomic_add(&fRefCount, 1);
2063 bool
2064 device_node::Release()
2066 if (atomic_add(&fRefCount, -1) > 1)
2067 return false;
2069 delete this;
2070 return true;
2074 void
2075 device_node::AddDevice(Device* device)
2077 fDevices.Add(device);
2081 void
2082 device_node::RemoveDevice(Device* device)
2084 fDevices.Remove(device);
2089 device_node::CompareTo(const device_attr* attributes) const
2091 if (attributes == NULL)
2092 return -1;
2094 for (; attributes->name != NULL; attributes++) {
2095 // find corresponding attribute
2096 AttributeList::ConstIterator iterator = Attributes().GetIterator();
2097 device_attr_private* attr = NULL;
2098 bool found = false;
2100 while (iterator.HasNext()) {
2101 attr = iterator.Next();
2103 if (!strcmp(attr->name, attributes->name)) {
2104 found = true;
2105 break;
2108 if (!found)
2109 return -1;
2111 int compare = device_attr_private::Compare(attr, attributes);
2112 if (compare != 0)
2113 return compare;
2116 return 0;
2120 device_node*
2121 device_node::FindChild(const device_attr* attributes) const
2123 if (attributes == NULL)
2124 return 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))
2133 return child;
2136 return NULL;
2140 device_node*
2141 device_node::FindChild(const char* moduleName) const
2143 if (moduleName == NULL)
2144 return NULL;
2146 NodeList::ConstIterator iterator = Children().GetIterator();
2147 while (iterator.HasNext()) {
2148 device_node* child = iterator.Next();
2150 if (!strcmp(child->ModuleName(), moduleName))
2151 return child;
2154 return NULL;
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
2162 attribute.
2164 int32
2165 device_node::Priority()
2167 return (fFlags & B_FIND_MULTIPLE_CHILDREN) != 0 ? 0 : 100;
2171 void
2172 device_node::Dump(int32 level)
2174 put_level(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();
2187 put_level(level);
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
2201 static void
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 }},
2209 {NULL}
2212 device_node* node = NULL;
2213 if (register_node(NULL, DEVICE_MANAGER_ROOT_NAME, attrs, NULL, &node)
2214 != B_OK) {
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}},
2223 {NULL}
2226 if (register_node(node, DEVICE_MANAGER_GENERIC_NAME, genericAttrs, NULL,
2227 NULL) != B_OK) {
2228 dprintf("Cannot register Generic Devices Node\n");
2233 driver_module_info gDeviceRootModule = {
2235 DEVICE_MANAGER_ROOT_NAME,
2237 NULL,
2242 driver_module_info gDeviceGenericModule = {
2244 DEVICE_MANAGER_GENERIC_NAME,
2246 NULL,
2248 NULL
2252 // #pragma mark - private kernel API
2255 status_t
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);
2268 status_t
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,
2281 1, 0);
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",
2287 "<scheduler>\n"
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",
2291 "<owner>\n"
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");
2299 init_node_tree();
2301 return B_OK;
2305 status_t
2306 device_manager_init_post_modules(struct kernel_args* args)
2308 RecursiveLocker _(sLock);
2309 return sRootNode->Reprobe();