xref: /haiku/src/system/kernel/device_manager/device_manager.cpp (revision 9918c8295480d70f55fafb98008e23109b598871)
1 /*
2  * Copyright 2008-2009, Axel Dörfler, axeld@pinc-software.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <kdevice_manager.h>
8 
9 #include <new>
10 #include <set>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include <KernelExport.h>
16 #include <Locker.h>
17 #include <module.h>
18 #include <PCI.h>
19 
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>
29 
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"
36 
37 
38 //#define TRACE_DEVICE_MANAGER
39 #ifdef TRACE_DEVICE_MANAGER
40 #	define TRACE(a) dprintf a
41 #else
42 #	define TRACE(a) ;
43 #endif
44 
45 
46 #define DEVICE_MANAGER_ROOT_NAME "system/devices_root/driver_v1"
47 #define DEVICE_MANAGER_GENERIC_NAME "system/devices_generic/driver_v1"
48 
49 
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();
55 
56 			status_t	InitCheck();
57 			status_t	CopyFrom(const device_attr& attr);
58 
59 	static	int			Compare(const device_attr* attrA,
60 							const device_attr *attrB);
61 
62 private:
63 			void		_Unset();
64 };
65 
66 typedef DoublyLinkedList<device_attr_private> AttributeList;
67 
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;
74 
75 
76 namespace {
77 
78 
79 class Device : public AbstractModuleDevice,
80 	public DoublyLinkedListLinkImpl<Device> {
81 public:
82 							Device(device_node* node, const char* moduleName);
83 	virtual					~Device();
84 
85 			status_t		InitCheck() const;
86 
87 			const char*		ModuleName() const { return fModuleName; }
88 
89 	virtual	status_t		InitDevice();
90 	virtual	void			UninitDevice();
91 
92 	virtual void			Removed();
93 
94 			void			SetRemovedFromParent(bool removed)
95 								{ fRemovedFromParent = removed; }
96 
97 private:
98 	const char*				fModuleName;
99 	bool					fRemovedFromParent;
100 };
101 
102 
103 } // unnamed namespace
104 
105 
106 typedef DoublyLinkedList<Device> DeviceList;
107 typedef DoublyLinkedList<device_node> NodeList;
108 
109 struct device_node : DoublyLinkedListLinkImpl<device_node> {
110 							device_node(const char* moduleName,
111 								const device_attr* attrs);
112 							~device_node();
113 
114 			status_t		InitCheck() const;
115 
116 			status_t		AcquireResources(const io_resource* resources);
117 
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; }
122 
123 			status_t		InitDriver();
124 			bool			UninitDriver();
125 			void			UninitUnusedDriver();
126 
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; }
131 
132 			void			AddChild(device_node *node);
133 			void			RemoveChild(device_node *node);
134 			const NodeList&	Children() const { return fChildren; }
135 			void			DeviceRemoved();
136 
137 			status_t		Register(device_node* parent);
138 			status_t		Probe(const char* devicePath, uint32 updateCycle);
139 			status_t		Reprobe();
140 			status_t		Rescan();
141 
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; }
146 
147 			void			Acquire();
148 			bool			Release();
149 
150 			const DeviceList& Devices() const { return fDevices; }
151 			void			AddDevice(Device* device);
152 			void			RemoveDevice(Device* device);
153 
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;
157 
158 			int32			Priority();
159 
160 			void			Dump(int32 level = 0);
161 
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();
180 
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;
189 
190 	const char*				fModuleName;
191 
192 	driver_module_info*		fDriver;
193 	void*					fDriverData;
194 
195 	DeviceList				fDevices;
196 	AttributeList			fAttributes;
197 	ResourceList			fResources;
198 };
199 
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,
206 
207 	NODE_FLAG_PUBLIC_MASK			= 0x0000ffff
208 };
209 
210 
211 static device_node *sRootNode;
212 static recursive_lock sLock;
213 static const char* sGenericContextPath;
214 
215 
216 //	#pragma mark -
217 
218 
219 static device_attr_private*
220 find_attr(const device_node* node, const char* name, bool recursive,
221 	type_code type)
222 {
223 	do {
224 		AttributeList::ConstIterator iterator
225 			= node->Attributes().GetIterator();
226 
227 		while (iterator.HasNext()) {
228 			device_attr_private* attr = iterator.Next();
229 
230 			if (type != B_ANY_TYPE && attr->type != type)
231 				continue;
232 
233 			if (!strcmp(attr->name, name))
234 				return attr;
235 		}
236 
237 		node = node->Parent();
238 	} while (node != NULL && recursive);
239 
240 	return NULL;
241 }
242 
243 
244 static void
245 put_level(int32 level)
246 {
247 	while (level-- > 0)
248 		kprintf("   ");
249 }
250 
251 
252 static void
253 dump_attribute(device_attr* attr, int32 level)
254 {
255 	if (attr == NULL)
256 		return;
257 
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");
286 	}
287 	kprintf("\n");
288 }
289 
290 
291 static int
292 dump_io_scheduler(int argc, char** argv)
293 {
294 	if (argc != 2) {
295 		print_debugger_command_usage(argv[0]);
296 		return 0;
297 	}
298 
299 	IOScheduler* scheduler = (IOScheduler*)parse_expression(argv[1]);
300 	scheduler->Dump();
301 	return 0;
302 }
303 
304 
305 static int
306 dump_io_request_owner(int argc, char** argv)
307 {
308 	if (argc != 2) {
309 		print_debugger_command_usage(argv[0]);
310 		return 0;
311 	}
312 
313 	IORequestOwner* owner = (IORequestOwner*)parse_expression(argv[1]);
314 	owner->Dump();
315 	return 0;
316 }
317 
318 
319 static int
320 dump_io_request(int argc, char** argv)
321 {
322 	if (argc != 2 || !strcmp(argv[1], "--help")) {
323 		kprintf("usage: %s <ptr-to-io-request>\n", argv[0]);
324 		return 0;
325 	}
326 
327 	IORequest* request = (IORequest*)parse_expression(argv[1]);
328 	request->Dump();
329 	return 0;
330 }
331 
332 
333 static int
334 dump_io_operation(int argc, char** argv)
335 {
336 	if (argc != 2 || !strcmp(argv[1], "--help")) {
337 		kprintf("usage: %s <ptr-to-io-operation>\n", argv[0]);
338 		return 0;
339 	}
340 
341 	IOOperation* operation = (IOOperation*)parse_expression(argv[1]);
342 	operation->Dump();
343 	return 0;
344 }
345 
346 
347 static int
348 dump_io_buffer(int argc, char** argv)
349 {
350 	if (argc != 2 || !strcmp(argv[1], "--help")) {
351 		kprintf("usage: %s <ptr-to-io-buffer>\n", argv[0]);
352 		return 0;
353 	}
354 
355 	IOBuffer* buffer = (IOBuffer*)parse_expression(argv[1]);
356 	buffer->Dump();
357 	return 0;
358 }
359 
360 
361 static int
362 dump_dma_buffer(int argc, char** argv)
363 {
364 	if (argc != 2 || !strcmp(argv[1], "--help")) {
365 		kprintf("usage: %s <ptr-to-dma-buffer>\n", argv[0]);
366 		return 0;
367 	}
368 
369 	DMABuffer* buffer = (DMABuffer*)parse_expression(argv[1]);
370 	buffer->Dump();
371 	return 0;
372 }
373 
374 
375 static int
376 dump_device_nodes(int argc, char** argv)
377 {
378 	sRootNode->Dump();
379 	return 0;
380 }
381 
382 
383 static void
384 publish_directories(const char* subPath)
385 {
386 	if (gBootDevice < 0) {
387 		if (subPath[0]) {
388 			// we only support the top-level directory for modules
389 			return;
390 		}
391 
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;
396 
397 		size_t length = strlen(path.Path()) + 1;
398 			// account for the separating '/'
399 
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;
406 
407 			char* leaf = name + length;
408 			char* end = strchr(leaf, '/');
409 			if (end != NULL)
410 				end[0] = '\0';
411 
412 			path.SetTo(subPath);
413 			path.Append(leaf);
414 
415 			devfs_publish_directory(path.Path());
416 		}
417 		close_module_list(list);
418 	} else {
419 		// TODO: implement module directory traversal!
420 	}
421 }
422 
423 
424 static status_t
425 control_device_manager(const char* subsystem, uint32 function, void* buffer,
426 	size_t bufferSize)
427 {
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:
433 		{
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;
440 
441 			// copy back to user space
442 			return user_memcpy(buffer, &cookie, sizeof(device_node_cookie));
443 		}
444 
445 		case DM_GET_CHILD:
446 		{
447 			if (!IS_USER_ADDRESS(buffer))
448 				return B_BAD_ADDRESS;
449 			if (bufferSize != sizeof(device_node_cookie))
450 				return B_BAD_VALUE;
451 
452 			device_node_cookie cookie;
453 			if (user_memcpy(&cookie, buffer, sizeof(device_node_cookie)) < B_OK)
454 				return B_BAD_ADDRESS;
455 
456 			device_node* node = (device_node*)cookie;
457 			NodeList::ConstIterator iterator = node->Children().GetIterator();
458 
459 			if (!iterator.HasNext()) {
460 				return B_ENTRY_NOT_FOUND;
461 			}
462 			node = iterator.Next();
463 			cookie = (device_node_cookie)node;
464 
465 			// copy back to user space
466 			return user_memcpy(buffer, &cookie, sizeof(device_node_cookie));
467 		}
468 
469 		case DM_GET_NEXT_CHILD:
470 		{
471 			if (!IS_USER_ADDRESS(buffer))
472 				return B_BAD_ADDRESS;
473 			if (bufferSize != sizeof(device_node_cookie))
474 				return B_BAD_VALUE;
475 
476 			device_node_cookie cookie;
477 			if (user_memcpy(&cookie, buffer, sizeof(device_node_cookie)) < B_OK)
478 				return B_BAD_ADDRESS;
479 
480 			device_node* last = (device_node*)cookie;
481 			if (!last->Parent())
482 				return B_ENTRY_NOT_FOUND;
483 
484 			NodeList::ConstIterator iterator
485 				= last->Parent()->Children().GetIterator();
486 
487 			// skip those we already traversed
488 			while (iterator.HasNext()) {
489 				device_node* node = iterator.Next();
490 
491 				if (node == last)
492 					break;
493 			}
494 
495 			if (!iterator.HasNext())
496 				return B_ENTRY_NOT_FOUND;
497 			device_node* node = iterator.Next();
498 			cookie = (device_node_cookie)node;
499 
500 			// copy back to user space
501 			return user_memcpy(buffer, &cookie, sizeof(device_node_cookie));
502 		}
503 
504 		case DM_GET_NEXT_ATTRIBUTE:
505 		{
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;
513 
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();
520 
521 				if (attr == last)
522 					break;
523 			}
524 
525 			if (!iterator.HasNext()) {
526 				attrInfo.cookie = 0;
527 				return B_ENTRY_NOT_FOUND;
528 			}
529 
530 			device_attr* attr = iterator.Next();
531 			attrInfo.cookie = (device_node_cookie)attr;
532 			if (attr->name != NULL)
533 				strlcpy(attrInfo.name, attr->name, 254);
534 			else
535 				attrInfo.name[0] = '\0';
536 			attrInfo.type = attr->type;
537 			switch (attrInfo.type) {
538 				case B_UINT8_TYPE:
539 					attrInfo.value.ui8 = attr->value.ui8;
540 					break;
541 				case B_UINT16_TYPE:
542 					attrInfo.value.ui16 = attr->value.ui16;
543 					break;
544 				case B_UINT32_TYPE:
545 					attrInfo.value.ui32 = attr->value.ui32;
546 					break;
547 				case B_UINT64_TYPE:
548 					attrInfo.value.ui64 = attr->value.ui64;
549 					break;
550 				case B_STRING_TYPE:
551 					if (attr->value.string != NULL)
552 						strlcpy(attrInfo.value.string, attr->value.string, 254);
553 					else
554 						attrInfo.value.string[0] = '\0';
555 					break;
556 				/*case B_RAW_TYPE:
557 					if (attr.value.raw.length > attr_info->attr.value.raw.length)
558 						attr.value.raw.length = attr_info->attr.value.raw.length;
559 					user_memcpy(attr.value.raw.data, attr_info->attr.value.raw.data,
560 						attr.value.raw.length);
561 					break;*/
562 			}
563 
564 			// copy back to user space
565 			return user_memcpy(buffer, &attrInfo, sizeof(device_attr_info));
566 		}
567 	}
568 
569 	return B_BAD_HANDLER;
570 }
571 
572 
573 //	#pragma mark - Device Manager module API
574 
575 
576 static status_t
577 rescan_node(device_node* node)
578 {
579 	RecursiveLocker _(sLock);
580 	return node->Rescan();
581 }
582 
583 
584 static status_t
585 register_node(device_node* parent, const char* moduleName,
586 	const device_attr* attrs, const io_resource* ioResources,
587 	device_node** _node)
588 {
589 	if ((parent == NULL && sRootNode != NULL) || moduleName == NULL)
590 		return B_BAD_VALUE;
591 
592 	if (parent != NULL && parent->FindChild(attrs) != NULL) {
593 		// A node like this one already exists for this parent
594 		return B_NAME_IN_USE;
595 	}
596 
597 	RecursiveLocker _(sLock);
598 
599 	device_node* newNode = new(std::nothrow) device_node(moduleName, attrs);
600 	if (newNode == NULL)
601 		return B_NO_MEMORY;
602 
603 	TRACE(("%p: register node \"%s\", parent %p\n", newNode, moduleName,
604 		parent));
605 
606 	status_t status = newNode->InitCheck();
607 	if (status == B_OK)
608 		status = newNode->AcquireResources(ioResources);
609 	if (status == B_OK)
610 		status = newNode->Register(parent);
611 
612 	if (status != B_OK) {
613 		newNode->Release();
614 		return status;
615 	}
616 
617 	if (_node)
618 		*_node = newNode;
619 
620 	return B_OK;
621 }
622 
623 
624 /*!	Unregisters the device \a node.
625 
626 	If the node is currently in use, this function will return B_BUSY to
627 	indicate that the node hasn't been removed yet - it will still remove
628 	the node as soon as possible.
629 */
630 static status_t
631 unregister_node(device_node* node)
632 {
633 	TRACE(("unregister_node(node %p)\n", node));
634 	RecursiveLocker _(sLock);
635 
636 	bool initialized = node->IsInitialized();
637 
638 	node->DeviceRemoved();
639 
640 	return initialized ? B_BUSY : B_OK;
641 }
642 
643 
644 static status_t
645 get_driver(device_node* node, driver_module_info** _module, void** _data)
646 {
647 	if (node->DriverModule() == NULL)
648 		return B_NO_INIT;
649 
650 	if (_module != NULL)
651 		*_module = node->DriverModule();
652 	if (_data != NULL)
653 		*_data = node->DriverData();
654 
655 	return B_OK;
656 }
657 
658 
659 static device_node*
660 get_root_node(void)
661 {
662 	if (sRootNode != NULL)
663 		sRootNode->Acquire();
664 
665 	return sRootNode;
666 }
667 
668 
669 static status_t
670 get_next_child_node(device_node* parent, const device_attr* attributes,
671 	device_node** _node)
672 {
673 	RecursiveLocker _(sLock);
674 
675 	NodeList::ConstIterator iterator = parent->Children().GetIterator();
676 	device_node* last = *_node;
677 
678 	// skip those we already traversed
679 	while (iterator.HasNext() && last != NULL) {
680 		device_node* node = iterator.Next();
681 
682 		if (node != last)
683 			continue;
684 	}
685 
686 	// find the next one that fits
687 	while (iterator.HasNext()) {
688 		device_node* node = iterator.Next();
689 
690 		if (!node->IsRegistered())
691 			continue;
692 
693 		if (!node->CompareTo(attributes)) {
694 			if (last != NULL)
695 				last->Release();
696 
697 			node->Acquire();
698 			*_node = node;
699 			return B_OK;
700 		}
701 	}
702 
703 	if (last != NULL)
704 		last->Release();
705 
706 	return B_ENTRY_NOT_FOUND;
707 }
708 
709 
710 static device_node*
711 get_parent_node(device_node* node)
712 {
713 	if (node == NULL)
714 		return NULL;
715 
716 	RecursiveLocker _(sLock);
717 
718 	device_node* parent = node->Parent();
719 	parent->Acquire();
720 
721 	return parent;
722 }
723 
724 
725 static void
726 put_node(device_node* node)
727 {
728 	RecursiveLocker _(sLock);
729 	node->Release();
730 }
731 
732 
733 static status_t
734 publish_device(device_node *node, const char *path, const char *moduleName)
735 {
736 	if (path == NULL || !path[0] || moduleName == NULL || !moduleName[0])
737 		return B_BAD_VALUE;
738 
739 	RecursiveLocker _(sLock);
740 	dprintf("publish device: node %p, path %s, module %s\n", node, path,
741 		moduleName);
742 
743 	Device* device = new(std::nothrow) Device(node, moduleName);
744 	if (device == NULL)
745 		return B_NO_MEMORY;
746 
747 	status_t status = device->InitCheck();
748 	if (status == B_OK)
749 		status = devfs_publish_device(path, device);
750 	if (status != B_OK) {
751 		delete device;
752 		return status;
753 	}
754 
755 	node->AddDevice(device);
756 	return B_OK;
757 }
758 
759 
760 static status_t
761 unpublish_device(device_node *node, const char *path)
762 {
763 	if (path == NULL)
764 		return B_BAD_VALUE;
765 
766 	BaseDevice* baseDevice;
767 	status_t error = devfs_get_device(path, baseDevice);
768 	if (error != B_OK)
769 		return error;
770 	CObjectDeleter<BaseDevice, void, devfs_put_device>
771 		baseDevicePutter(baseDevice);
772 
773 	Device* device = dynamic_cast<Device*>(baseDevice);
774 	if (device == NULL || device->Node() != node)
775 		return B_BAD_VALUE;
776 
777 	return devfs_unpublish_device(device, true);
778 }
779 
780 
781 static status_t
782 get_attr_uint8(const device_node* node, const char* name, uint8* _value,
783 	bool recursive)
784 {
785 	if (node == NULL || name == NULL || _value == NULL)
786 		return B_BAD_VALUE;
787 
788 	device_attr_private* attr = find_attr(node, name, recursive, B_UINT8_TYPE);
789 	if (attr == NULL)
790 		return B_NAME_NOT_FOUND;
791 
792 	*_value = attr->value.ui8;
793 	return B_OK;
794 }
795 
796 
797 static status_t
798 get_attr_uint16(const device_node* node, const char* name, uint16* _value,
799 	bool recursive)
800 {
801 	if (node == NULL || name == NULL || _value == NULL)
802 		return B_BAD_VALUE;
803 
804 	device_attr_private* attr = find_attr(node, name, recursive, B_UINT16_TYPE);
805 	if (attr == NULL)
806 		return B_NAME_NOT_FOUND;
807 
808 	*_value = attr->value.ui16;
809 	return B_OK;
810 }
811 
812 
813 static status_t
814 get_attr_uint32(const device_node* node, const char* name, uint32* _value,
815 	bool recursive)
816 {
817 	if (node == NULL || name == NULL || _value == NULL)
818 		return B_BAD_VALUE;
819 
820 	device_attr_private* attr = find_attr(node, name, recursive, B_UINT32_TYPE);
821 	if (attr == NULL)
822 		return B_NAME_NOT_FOUND;
823 
824 	*_value = attr->value.ui32;
825 	return B_OK;
826 }
827 
828 
829 static status_t
830 get_attr_uint64(const device_node* node, const char* name,
831 	uint64* _value, bool recursive)
832 {
833 	if (node == NULL || name == NULL || _value == NULL)
834 		return B_BAD_VALUE;
835 
836 	device_attr_private* attr = find_attr(node, name, recursive, B_UINT64_TYPE);
837 	if (attr == NULL)
838 		return B_NAME_NOT_FOUND;
839 
840 	*_value = attr->value.ui64;
841 	return B_OK;
842 }
843 
844 
845 static status_t
846 get_attr_string(const device_node* node, const char* name,
847 	const char** _value, bool recursive)
848 {
849 	if (node == NULL || name == NULL || _value == NULL)
850 		return B_BAD_VALUE;
851 
852 	device_attr_private* attr = find_attr(node, name, recursive, B_STRING_TYPE);
853 	if (attr == NULL)
854 		return B_NAME_NOT_FOUND;
855 
856 	*_value = attr->value.string;
857 	return B_OK;
858 }
859 
860 
861 static status_t
862 get_attr_raw(const device_node* node, const char* name, const void** _data,
863 	size_t* _length, bool recursive)
864 {
865 	if (node == NULL || name == NULL || (_data == NULL && _length == NULL))
866 		return B_BAD_VALUE;
867 
868 	device_attr_private* attr = find_attr(node, name, recursive, B_RAW_TYPE);
869 	if (attr == NULL)
870 		return B_NAME_NOT_FOUND;
871 
872 	if (_data != NULL)
873 		*_data = attr->value.raw.data;
874 	if (_length != NULL)
875 		*_length = attr->value.raw.length;
876 	return B_OK;
877 }
878 
879 
880 static status_t
881 get_next_attr(device_node* node, device_attr** _attr)
882 {
883 	if (node == NULL)
884 		return B_BAD_VALUE;
885 
886 	device_attr_private* next;
887 	device_attr_private* attr = *(device_attr_private**)_attr;
888 
889 	if (attr != NULL) {
890 		// next attribute
891 		next = attr->GetDoublyLinkedListLink()->next;
892 	} else {
893 		// first attribute
894 		next = node->Attributes().First();
895 	}
896 
897 	*_attr = next;
898 
899 	return next ? B_OK : B_ENTRY_NOT_FOUND;
900 }
901 
902 
903 static status_t
904 find_child_node(device_node* parent, const device_attr* attributes,
905 	device_node** _node, bool *_lastFound)
906 {
907 	RecursiveLocker _(sLock);
908 
909 	NodeList::ConstIterator iterator = parent->Children().GetIterator();
910 	device_node* last = *_node;
911 
912 	// find the next one that fits
913 	while (iterator.HasNext()) {
914 		device_node* node = iterator.Next();
915 
916 		if (!node->IsRegistered())
917 			continue;
918 
919 		if (node == last)
920 			*_lastFound = true;
921 		else if (!node->CompareTo(attributes) && *_lastFound) {
922 			if (last != NULL)
923 				last->Release();
924 
925 			node->Acquire();
926 			*_node = node;
927 			return B_OK;
928 		}
929 		if (find_child_node(node, attributes, _node, _lastFound) == B_OK)
930 			return B_OK;
931 	}
932 
933 	return B_ENTRY_NOT_FOUND;
934 }
935 
936 
937 static status_t
938 find_child_node(device_node* parent, const device_attr* attributes,
939 	device_node** _node)
940 {
941 	device_node* last = *_node;
942 	bool lastFound = last == NULL;
943 	status_t status = find_child_node(parent, attributes, _node, &lastFound);
944 	if (status == B_ENTRY_NOT_FOUND && last != NULL && lastFound)
945 		last->Release();
946 	return status;
947 }
948 
949 
950 struct device_manager_info gDeviceManagerModule = {
951 	{
952 		B_DEVICE_MANAGER_MODULE_NAME,
953 		0,
954 		NULL
955 	},
956 
957 	// device nodes
958 	rescan_node,
959 	register_node,
960 	unregister_node,
961 	get_driver,
962 	get_root_node,
963 	get_next_child_node,
964 	get_parent_node,
965 	put_node,
966 
967 	// devices
968 	publish_device,
969 	unpublish_device,
970 
971 	// I/O resources
972 
973 	// ID generator
974 	dm_create_id,
975 	dm_free_id,
976 
977 	// attributes
978 	get_attr_uint8,
979 	get_attr_uint16,
980 	get_attr_uint32,
981 	get_attr_uint64,
982 	get_attr_string,
983 	get_attr_raw,
984 	get_next_attr,
985 	find_child_node
986 };
987 
988 
989 //	#pragma mark - device_attr
990 
991 
992 device_attr_private::device_attr_private()
993 {
994 	name = NULL;
995 	type = 0;
996 	value.raw.data = NULL;
997 	value.raw.length = 0;
998 }
999 
1000 
1001 device_attr_private::device_attr_private(const device_attr& attr)
1002 {
1003 	CopyFrom(attr);
1004 }
1005 
1006 
1007 device_attr_private::~device_attr_private()
1008 {
1009 	_Unset();
1010 }
1011 
1012 
1013 status_t
1014 device_attr_private::InitCheck()
1015 {
1016 	return name != NULL ? B_OK : B_NO_INIT;
1017 }
1018 
1019 
1020 status_t
1021 device_attr_private::CopyFrom(const device_attr& attr)
1022 {
1023 	name = strdup(attr.name);
1024 	if (name == NULL)
1025 		return B_NO_MEMORY;
1026 
1027 	type = attr.type;
1028 
1029 	switch (type) {
1030 		case B_UINT8_TYPE:
1031 		case B_UINT16_TYPE:
1032 		case B_UINT32_TYPE:
1033 		case B_UINT64_TYPE:
1034 			value.ui64 = attr.value.ui64;
1035 			break;
1036 
1037 		case B_STRING_TYPE:
1038 			if (attr.value.string != NULL) {
1039 				value.string = strdup(attr.value.string);
1040 				if (value.string == NULL) {
1041 					_Unset();
1042 					return B_NO_MEMORY;
1043 				}
1044 			} else
1045 				value.string = NULL;
1046 			break;
1047 
1048 		case B_RAW_TYPE:
1049 			value.raw.data = malloc(attr.value.raw.length);
1050 			if (value.raw.data == NULL) {
1051 				_Unset();
1052 				return B_NO_MEMORY;
1053 			}
1054 
1055 			value.raw.length = attr.value.raw.length;
1056 			memcpy((void*)value.raw.data, attr.value.raw.data,
1057 				attr.value.raw.length);
1058 			break;
1059 
1060 		default:
1061 			return B_BAD_VALUE;
1062 	}
1063 
1064 	return B_OK;
1065 }
1066 
1067 
1068 void
1069 device_attr_private::_Unset()
1070 {
1071 	if (type == B_STRING_TYPE)
1072 		free((char*)value.string);
1073 	else if (type == B_RAW_TYPE)
1074 		free((void*)value.raw.data);
1075 
1076 	free((char*)name);
1077 
1078 	name = NULL;
1079 	value.raw.data = NULL;
1080 	value.raw.length = 0;
1081 }
1082 
1083 
1084 /*static*/ int
1085 device_attr_private::Compare(const device_attr* attrA, const device_attr *attrB)
1086 {
1087 	if (attrA->type != attrB->type)
1088 		return -1;
1089 
1090 	switch (attrA->type) {
1091 		case B_UINT8_TYPE:
1092 			return (int)attrA->value.ui8 - (int)attrB->value.ui8;
1093 
1094 		case B_UINT16_TYPE:
1095 			return (int)attrA->value.ui16 - (int)attrB->value.ui16;
1096 
1097 		case B_UINT32_TYPE:
1098 			if (attrA->value.ui32 > attrB->value.ui32)
1099 				return 1;
1100 			if (attrA->value.ui32 < attrB->value.ui32)
1101 				return -1;
1102 			return 0;
1103 
1104 		case B_UINT64_TYPE:
1105 			if (attrA->value.ui64 > attrB->value.ui64)
1106 				return 1;
1107 			if (attrA->value.ui64 < attrB->value.ui64)
1108 				return -1;
1109 			return 0;
1110 
1111 		case B_STRING_TYPE:
1112 			return strcmp(attrA->value.string, attrB->value.string);
1113 
1114 		case B_RAW_TYPE:
1115 			if (attrA->value.raw.length != attrB->value.raw.length)
1116 				return -1;
1117 
1118 			return memcmp(attrA->value.raw.data, attrB->value.raw.data,
1119 				attrA->value.raw.length);
1120 	}
1121 
1122 	return -1;
1123 }
1124 
1125 
1126 //	#pragma mark - Device
1127 
1128 
1129 Device::Device(device_node* node, const char* moduleName)
1130 	:
1131 	fModuleName(strdup(moduleName)),
1132 	fRemovedFromParent(false)
1133 {
1134 	fNode = node;
1135 }
1136 
1137 
1138 Device::~Device()
1139 {
1140 	free((char*)fModuleName);
1141 }
1142 
1143 
1144 status_t
1145 Device::InitCheck() const
1146 {
1147 	return fModuleName != NULL ? B_OK : B_NO_MEMORY;
1148 }
1149 
1150 
1151 status_t
1152 Device::InitDevice()
1153 {
1154 	RecursiveLocker _(sLock);
1155 
1156 	if ((fNode->Flags() & NODE_FLAG_DEVICE_REMOVED) != 0) {
1157 		// TODO: maybe the device should be unlinked in devfs, too
1158 		return ENODEV;
1159 	}
1160 	if ((fNode->Flags() & NODE_FLAG_WAITING_FOR_DRIVER) != 0)
1161 		return B_BUSY;
1162 
1163 	if (fInitialized++ > 0) {
1164 		fNode->InitDriver();
1165 			// acquire another reference to our parent as well
1166 		return B_OK;
1167 	}
1168 
1169 	status_t status = get_module(ModuleName(), (module_info**)&fDeviceModule);
1170 	if (status == B_OK) {
1171 		// our parent always has to be initialized
1172 		status = fNode->InitDriver();
1173 	}
1174 	if (status < B_OK) {
1175 		fInitialized--;
1176 		return status;
1177 	}
1178 
1179 	if (Module()->init_device != NULL)
1180 		status = Module()->init_device(fNode->DriverData(), &fDeviceData);
1181 
1182 	if (status < B_OK) {
1183 		fNode->UninitDriver();
1184 		fInitialized--;
1185 
1186 		put_module(ModuleName());
1187 		fDeviceModule = NULL;
1188 		fDeviceData = NULL;
1189 	}
1190 
1191 	return status;
1192 }
1193 
1194 
1195 void
1196 Device::UninitDevice()
1197 {
1198 	RecursiveLocker _(sLock);
1199 
1200 	if (fInitialized-- > 1) {
1201 		fNode->UninitDriver();
1202 		return;
1203 	}
1204 
1205 	TRACE(("uninit driver for node %p\n", this));
1206 
1207 	if (Module()->uninit_device != NULL)
1208 		Module()->uninit_device(fDeviceData);
1209 
1210 	fDeviceModule = NULL;
1211 	fDeviceData = NULL;
1212 
1213 	put_module(ModuleName());
1214 
1215 	fNode->UninitDriver();
1216 }
1217 
1218 
1219 void
1220 Device::Removed()
1221 {
1222 	RecursiveLocker _(sLock);
1223 
1224 	if (!fRemovedFromParent)
1225 		fNode->RemoveDevice(this);
1226 
1227 	delete this;
1228 }
1229 
1230 
1231 //	#pragma mark - device_node
1232 
1233 
1234 device_node::device_node(const char* moduleName, const device_attr* attrs)
1235 {
1236 	fModuleName = strdup(moduleName);
1237 	if (fModuleName == NULL)
1238 		return;
1239 
1240 	fParent = NULL;
1241 	fRefCount = 1;
1242 	fInitialized = 0;
1243 	fRegistered = false;
1244 	fFlags = 0;
1245 	fSupportsParent = 0.0;
1246 	fLastUpdateCycle = 0;
1247 	fDriver = NULL;
1248 	fDriverData = NULL;
1249 
1250 	// copy attributes
1251 
1252 	while (attrs != NULL && attrs->name != NULL) {
1253 		device_attr_private* attr
1254 			= new(std::nothrow) device_attr_private(*attrs);
1255 		if (attr == NULL)
1256 			break;
1257 
1258 		fAttributes.Add(attr);
1259 		attrs++;
1260 	}
1261 
1262 	get_attr_uint32(this, B_DEVICE_FLAGS, &fFlags, false);
1263 	fFlags &= NODE_FLAG_PUBLIC_MASK;
1264 }
1265 
1266 
1267 device_node::~device_node()
1268 {
1269 	TRACE(("delete node %p\n", this));
1270 	ASSERT(DriverModule() == NULL);
1271 
1272 	if (Parent() != NULL) {
1273 		if ((fFlags & NODE_FLAG_OBSOLETE_DRIVER) != 0) {
1274 			// This driver has been obsoleted; another driver has been waiting
1275 			// for us - make it available
1276 			Parent()->_ReleaseWaiting();
1277 		}
1278 		Parent()->RemoveChild(this);
1279 	}
1280 
1281 	// Delete children
1282 	while (device_node* child = fChildren.RemoveHead()) {
1283 		delete child;
1284 	}
1285 
1286 	// Delete devices
1287 	while (Device* device = fDevices.RemoveHead()) {
1288 		device->SetRemovedFromParent(true);
1289 		devfs_unpublish_device(device, true);
1290 	}
1291 
1292 	// Delete attributes
1293 	while (device_attr_private* attr = fAttributes.RemoveHead()) {
1294 		delete attr;
1295 	}
1296 
1297 	// Delete resources
1298 	while (io_resource_private* resource = fResources.RemoveHead()) {
1299 		delete resource;
1300 	}
1301 
1302 	free((char*)fModuleName);
1303 }
1304 
1305 
1306 status_t
1307 device_node::InitCheck() const
1308 {
1309 	return fModuleName != NULL ? B_OK : B_NO_MEMORY;
1310 }
1311 
1312 
1313 status_t
1314 device_node::AcquireResources(const io_resource* resources)
1315 {
1316 	if (resources == NULL)
1317 		return B_OK;
1318 
1319 	for (uint32 i = 0; resources[i].type != 0; i++) {
1320 		io_resource_private* resource = new(std::nothrow) io_resource_private;
1321 		if (resource == NULL)
1322 			return B_NO_MEMORY;
1323 
1324 		status_t status = resource->Acquire(resources[i]);
1325 		if (status != B_OK) {
1326 			delete resource;
1327 			return status;
1328 		}
1329 
1330 		fResources.Add(resource);
1331 	}
1332 
1333 	return B_OK;
1334 }
1335 
1336 
1337 status_t
1338 device_node::InitDriver()
1339 {
1340 	if (fInitialized++ > 0) {
1341 		if (Parent() != NULL) {
1342 			Parent()->InitDriver();
1343 				// acquire another reference to our parent as well
1344 		}
1345 		Acquire();
1346 		return B_OK;
1347 	}
1348 
1349 	status_t status = get_module(ModuleName(), (module_info**)&fDriver);
1350 	if (status == B_OK && Parent() != NULL) {
1351 		// our parent always has to be initialized
1352 		status = Parent()->InitDriver();
1353 	}
1354 	if (status < B_OK) {
1355 		fInitialized--;
1356 		return status;
1357 	}
1358 
1359 	if (fDriver->init_driver != NULL) {
1360 		status = fDriver->init_driver(this, &fDriverData);
1361 		if (status != B_OK) {
1362 			dprintf("driver %s init failed: %s\n", ModuleName(),
1363 				strerror(status));
1364 		}
1365 	}
1366 
1367 	if (status < B_OK) {
1368 		if (Parent() != NULL)
1369 			Parent()->UninitDriver();
1370 		fInitialized--;
1371 
1372 		put_module(ModuleName());
1373 		fDriver = NULL;
1374 		fDriverData = NULL;
1375 		return status;
1376 	}
1377 
1378 	Acquire();
1379 	return B_OK;
1380 }
1381 
1382 
1383 bool
1384 device_node::UninitDriver()
1385 {
1386 	if (fInitialized-- > 1) {
1387 		if (Parent() != NULL)
1388 			Parent()->UninitDriver();
1389 		Release();
1390 		return false;
1391 	}
1392 
1393 	TRACE(("uninit driver for node %p\n", this));
1394 
1395 	if (fDriver->uninit_driver != NULL)
1396 		fDriver->uninit_driver(fDriverData);
1397 
1398 	fDriver = NULL;
1399 	fDriverData = NULL;
1400 
1401 	put_module(ModuleName());
1402 
1403 	if (Parent() != NULL)
1404 		Parent()->UninitDriver();
1405 	Release();
1406 
1407 	return true;
1408 }
1409 
1410 
1411 void
1412 device_node::AddChild(device_node* node)
1413 {
1414 	// we must not be destroyed	as long as we have children
1415 	Acquire();
1416 	node->fParent = this;
1417 
1418 	int32 priority = node->Priority();
1419 
1420 	// Enforce an order in which the children are traversed - from most
1421 	// specific to least specific child.
1422 	NodeList::Iterator iterator = fChildren.GetIterator();
1423 	device_node* before = NULL;
1424 	while (iterator.HasNext()) {
1425 		device_node* child = iterator.Next();
1426 		if (child->Priority() <= priority) {
1427 			before = child;
1428 			break;
1429 		}
1430 	}
1431 
1432 	fChildren.Insert(before, node);
1433 }
1434 
1435 
1436 void
1437 device_node::RemoveChild(device_node* node)
1438 {
1439 	node->fParent = NULL;
1440 	fChildren.Remove(node);
1441 	Release();
1442 }
1443 
1444 
1445 /*!	Registers this node, and all of its children that have to be registered.
1446 	Also initializes the driver and keeps it that way on return in case
1447 	it returns successfully.
1448 */
1449 status_t
1450 device_node::Register(device_node* parent)
1451 {
1452 	// make it public
1453 	if (parent != NULL)
1454 		parent->AddChild(this);
1455 	else
1456 		sRootNode = this;
1457 
1458 	status_t status = InitDriver();
1459 	if (status != B_OK)
1460 		return status;
1461 
1462 	if ((fFlags & B_KEEP_DRIVER_LOADED) != 0) {
1463 		// We keep this driver loaded by having it always initialized
1464 		InitDriver();
1465 	}
1466 
1467 	fFlags |= NODE_FLAG_REGISTER_INITIALIZED;
1468 		// We don't uninitialize the driver - this is done by the caller
1469 		// in order to save reinitializing during driver loading.
1470 
1471 	uint32 registeredFixedCount;
1472 	status = _RegisterFixed(registeredFixedCount);
1473 	if (status != B_OK) {
1474 		UninitUnusedDriver();
1475 		return status;
1476 	}
1477 
1478 	// Register the children the driver wants
1479 
1480 	if (DriverModule()->register_child_devices != NULL) {
1481 		status = DriverModule()->register_child_devices(DriverData());
1482 		if (status != B_OK) {
1483 			UninitUnusedDriver();
1484 			return status;
1485 		}
1486 
1487 		if (!fChildren.IsEmpty()) {
1488 			fRegistered = true;
1489 			return B_OK;
1490 		}
1491 	}
1492 
1493 	if (registeredFixedCount > 0) {
1494 		// Nodes with fixed children cannot have any dynamic children, so bail
1495 		// out here
1496 		fRegistered = true;
1497 		return B_OK;
1498 	}
1499 
1500 	// Register all possible child device nodes
1501 
1502 	status = _RegisterDynamic();
1503 	if (status == B_OK)
1504 		fRegistered = true;
1505 	else
1506 		UninitUnusedDriver();
1507 
1508 	return status;
1509 }
1510 
1511 
1512 /*!	Registers any children that are identified via the B_DEVICE_FIXED_CHILD
1513 	attribute.
1514 	If any of these children cannot be registered, this call will fail (we
1515 	don't remove children we already registered up to this point in this case).
1516 */
1517 status_t
1518 device_node::_RegisterFixed(uint32& registered)
1519 {
1520 	AttributeList::Iterator iterator = fAttributes.GetIterator();
1521 	registered = 0;
1522 
1523 	while (iterator.HasNext()) {
1524 		device_attr_private* attr = iterator.Next();
1525 		if (strcmp(attr->name, B_DEVICE_FIXED_CHILD))
1526 			continue;
1527 
1528 		driver_module_info* driver;
1529 		status_t status = get_module(attr->value.string,
1530 			(module_info**)&driver);
1531 		if (status != B_OK) {
1532 			TRACE(("register fixed child %s failed: %s\n", attr->value.string,
1533 				strerror(status)));
1534 			return status;
1535 		}
1536 
1537 		if (driver->register_device != NULL) {
1538 			status = driver->register_device(this);
1539 			if (status == B_OK)
1540 				registered++;
1541 		}
1542 
1543 		put_module(attr->value.string);
1544 
1545 		if (status != B_OK)
1546 			return status;
1547 	}
1548 
1549 	return B_OK;
1550 }
1551 
1552 
1553 status_t
1554 device_node::_AddPath(Stack<KPath*>& stack, const char* basePath,
1555 	const char* subPath)
1556 {
1557 	KPath* path = new(std::nothrow) KPath;
1558 	if (path == NULL)
1559 		return B_NO_MEMORY;
1560 
1561 	status_t status = path->SetTo(basePath);
1562 	if (status == B_OK && subPath != NULL && subPath[0])
1563 		status = path->Append(subPath);
1564 	if (status == B_OK)
1565 		status = stack.Push(path);
1566 
1567 	TRACE(("  add path: \"%s\", %" B_PRId32 "\n", path->Path(), status));
1568 
1569 	if (status != B_OK)
1570 		delete path;
1571 
1572 	return status;
1573 }
1574 
1575 
1576 status_t
1577 device_node::_GetNextDriverPath(void*& cookie, KPath& _path)
1578 {
1579 	Stack<KPath*>* stack = NULL;
1580 
1581 	if (cookie == NULL) {
1582 		// find all paths and add them
1583 		stack = new(std::nothrow) Stack<KPath*>();
1584 		if (stack == NULL)
1585 			return B_NO_MEMORY;
1586 
1587 		StackDeleter<KPath*> stackDeleter(stack);
1588 
1589 		bool generic = false;
1590 		uint16 type = 0;
1591 		uint16 subType = 0;
1592 		uint16 interface = 0;
1593 		if (get_attr_uint16(this, B_DEVICE_TYPE, &type, false) != B_OK
1594 			|| get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false)
1595 					!= B_OK)
1596 			generic = true;
1597 
1598 		get_attr_uint16(this, B_DEVICE_INTERFACE, &interface, false);
1599 
1600 		// TODO: maybe make this extendible via settings file?
1601 		switch (type) {
1602 			case PCI_mass_storage:
1603 				switch (subType) {
1604 					case PCI_scsi:
1605 						_AddPath(*stack, "busses", "scsi");
1606 						_AddPath(*stack, "busses", "virtio");
1607 						break;
1608 					case PCI_ide:
1609 						_AddPath(*stack, "busses", "ata");
1610 						_AddPath(*stack, "busses", "ide");
1611 						break;
1612 					case PCI_sata:
1613 						// TODO: check for ahci interface
1614 						_AddPath(*stack, "busses", "scsi");
1615 						_AddPath(*stack, "busses", "ata");
1616 						_AddPath(*stack, "busses", "ide");
1617 						break;
1618 					case PCI_nvm:
1619 						_AddPath(*stack, "drivers", "disk");
1620 						break;
1621 					default:
1622 						_AddPath(*stack, "busses");
1623 						break;
1624 				}
1625 				break;
1626 			case PCI_serial_bus:
1627 				switch (subType) {
1628 					case PCI_firewire:
1629 						_AddPath(*stack, "busses", "firewire");
1630 						break;
1631 					case PCI_usb:
1632 						_AddPath(*stack, "busses", "usb");
1633 						break;
1634 					default:
1635 						_AddPath(*stack, "busses");
1636 						break;
1637 				}
1638 				break;
1639 			case PCI_network:
1640 				_AddPath(*stack, "drivers", "net");
1641 				_AddPath(*stack, "busses", "virtio");
1642 				break;
1643 			case PCI_display:
1644 				_AddPath(*stack, "drivers", "graphics");
1645 				break;
1646 			case PCI_multimedia:
1647 				switch (subType) {
1648 					case PCI_audio:
1649 					case PCI_hd_audio:
1650 						_AddPath(*stack, "drivers", "audio");
1651 						break;
1652 					case PCI_video:
1653 						_AddPath(*stack, "drivers", "video");
1654 						break;
1655 					default:
1656 						_AddPath(*stack, "drivers");
1657 						break;
1658 				}
1659 				break;
1660 			case PCI_base_peripheral:
1661 				switch (subType) {
1662 					case PCI_sd_host:
1663 						_AddPath(*stack, "busses", "mmc");
1664 						break;
1665 					case PCI_system_peripheral_other:
1666 						_AddPath(*stack, "busses", "mmc");
1667 						_AddPath(*stack, "drivers");
1668 						break;
1669 					default:
1670 						_AddPath(*stack, "drivers");
1671 						break;
1672 				}
1673 				break;
1674 			case PCI_data_acquisition:
1675 				switch (subType) {
1676 					case PCI_data_acquisition_other:
1677 						_AddPath(*stack, "busses", "i2c");
1678 						break;
1679 					default:
1680 						_AddPath(*stack, "drivers");
1681 						break;
1682 				}
1683 				break;
1684 			default:
1685 				if (sRootNode == this) {
1686 					_AddPath(*stack, "busses/pci");
1687 					_AddPath(*stack, "bus_managers");
1688 				} else if (!generic) {
1689 					_AddPath(*stack, "busses", "virtio");
1690 					_AddPath(*stack, "drivers");
1691 				} else {
1692 					// For generic drivers, we only allow busses when the
1693 					// request is more specified
1694 					if (sGenericContextPath != NULL
1695 						&& (!strcmp(sGenericContextPath, "disk")
1696 							|| !strcmp(sGenericContextPath, "ports")
1697 							|| !strcmp(sGenericContextPath, "bus"))) {
1698 						_AddPath(*stack, "busses");
1699 					}
1700 					_AddPath(*stack, "drivers", sGenericContextPath);
1701 					_AddPath(*stack, "busses/i2c");
1702 					_AddPath(*stack, "busses/scsi");
1703 					_AddPath(*stack, "busses/random");
1704 				}
1705 				break;
1706 		}
1707 
1708 		stackDeleter.Detach();
1709 
1710 		cookie = (void*)stack;
1711 	} else
1712 		stack = static_cast<Stack<KPath*>*>(cookie);
1713 
1714 	KPath* path;
1715 	if (stack->Pop(&path)) {
1716 		_path.Adopt(*path);
1717 		delete path;
1718 		return B_OK;
1719 	}
1720 
1721 	delete stack;
1722 	return B_ENTRY_NOT_FOUND;
1723 }
1724 
1725 
1726 status_t
1727 device_node::_GetNextDriver(void* list, driver_module_info*& driver)
1728 {
1729 	while (true) {
1730 		char name[B_FILE_NAME_LENGTH];
1731 		size_t nameLength = sizeof(name);
1732 
1733 		status_t status = read_next_module_name(list, name, &nameLength);
1734 		if (status != B_OK)
1735 			return status;
1736 
1737 		if (!strcmp(fModuleName, name))
1738 			continue;
1739 
1740 		if (get_module(name, (module_info**)&driver) != B_OK)
1741 			continue;
1742 
1743 		if (driver->supports_device == NULL
1744 			|| driver->register_device == NULL) {
1745 			put_module(name);
1746 			continue;
1747 		}
1748 
1749 		return B_OK;
1750 	}
1751 }
1752 
1753 
1754 status_t
1755 device_node::_FindBestDriver(const char* path, driver_module_info*& bestDriver,
1756 	float& bestSupport, device_node* previous)
1757 {
1758 	if (bestDriver == NULL)
1759 		bestSupport = previous != NULL ? previous->fSupportsParent : 0.0f;
1760 
1761 	void* list = open_module_list_etc(path, "driver_v1");
1762 	driver_module_info* driver;
1763 	while (_GetNextDriver(list, driver) == B_OK) {
1764 		if (previous != NULL && driver == previous->DriverModule()) {
1765 			put_module(driver->info.name);
1766 			continue;
1767 		}
1768 
1769 		float support = driver->supports_device(this);
1770 		if (support > bestSupport) {
1771 			if (bestDriver != NULL)
1772 				put_module(bestDriver->info.name);
1773 
1774 			bestDriver = driver;
1775 			bestSupport = support;
1776 			continue;
1777 				// keep reference to best module around
1778 		}
1779 
1780 		put_module(driver->info.name);
1781 	}
1782 	close_module_list(list);
1783 
1784 	return bestDriver != NULL ? B_OK : B_ENTRY_NOT_FOUND;
1785 }
1786 
1787 
1788 status_t
1789 device_node::_RegisterPath(const char* path)
1790 {
1791 	void* list = open_module_list_etc(path, "driver_v1");
1792 	driver_module_info* driver;
1793 	uint32 count = 0;
1794 
1795 	while (_GetNextDriver(list, driver) == B_OK) {
1796 		float support = driver->supports_device(this);
1797 		if (support > 0.0) {
1798 			TRACE(("  register module \"%s\", support %f\n", driver->info.name,
1799 				support));
1800 			if (driver->register_device(this) == B_OK)
1801 				count++;
1802 		}
1803 
1804 		put_module(driver->info.name);
1805 	}
1806 	close_module_list(list);
1807 
1808 	return count > 0 ? B_OK : B_ENTRY_NOT_FOUND;
1809 }
1810 
1811 
1812 bool
1813 device_node::_AlwaysRegisterDynamic()
1814 {
1815 	uint16 type = 0;
1816 	uint16 subType = 0;
1817 	get_attr_uint16(this, B_DEVICE_TYPE, &type, false);
1818 	get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false);
1819 
1820 	return type == PCI_serial_bus || type == PCI_bridge || type == 0;
1821 		// TODO: we may want to be a bit more specific in the future
1822 }
1823 
1824 
1825 status_t
1826 device_node::_RegisterDynamic(device_node* previous)
1827 {
1828 	// If this is not a bus, we don't have to scan it
1829 	if (find_attr(this, B_DEVICE_BUS, false, B_STRING_TYPE) == NULL)
1830 		return B_OK;
1831 
1832 	// If we're not being probed, we honour the B_FIND_CHILD_ON_DEMAND
1833 	// requirements
1834 	if (!IsProbed() && (fFlags & B_FIND_CHILD_ON_DEMAND) != 0
1835 		&& !_AlwaysRegisterDynamic())
1836 		return B_OK;
1837 
1838 	KPath path;
1839 
1840 	if ((fFlags & B_FIND_MULTIPLE_CHILDREN) == 0) {
1841 		// find the one driver
1842 		driver_module_info* bestDriver = NULL;
1843 		float bestSupport = 0.0;
1844 		void* cookie = NULL;
1845 
1846 		while (_GetNextDriverPath(cookie, path) == B_OK) {
1847 			_FindBestDriver(path.Path(), bestDriver, bestSupport, previous);
1848 		}
1849 
1850 		if (bestDriver != NULL) {
1851 			TRACE(("  register best module \"%s\", support %f\n",
1852 				bestDriver->info.name, bestSupport));
1853 			if (bestDriver->register_device(this) == B_OK) {
1854 				// There can only be one node of this driver
1855 				// (usually only one at all, but there might be a new driver
1856 				// "waiting" for its turn)
1857 				device_node* child = FindChild(bestDriver->info.name);
1858 				if (child != NULL) {
1859 					child->fSupportsParent = bestSupport;
1860 					if (previous != NULL) {
1861 						previous->fFlags |= NODE_FLAG_OBSOLETE_DRIVER;
1862 						previous->Release();
1863 						child->fFlags |= NODE_FLAG_WAITING_FOR_DRIVER;
1864 					}
1865 				}
1866 				// TODO: if this fails, we could try the second best driver,
1867 				// and so on...
1868 			}
1869 			put_module(bestDriver->info.name);
1870 		}
1871 	} else {
1872 		// register all drivers that match
1873 		void* cookie = NULL;
1874 		while (_GetNextDriverPath(cookie, path) == B_OK) {
1875 			_RegisterPath(path.Path());
1876 		}
1877 	}
1878 
1879 	return B_OK;
1880 }
1881 
1882 
1883 void
1884 device_node::_ReleaseWaiting()
1885 {
1886 	NodeList::Iterator iterator = fChildren.GetIterator();
1887 	while (iterator.HasNext()) {
1888 		device_node* child = iterator.Next();
1889 
1890 		child->fFlags &= ~NODE_FLAG_WAITING_FOR_DRIVER;
1891 	}
1892 }
1893 
1894 
1895 status_t
1896 device_node::_RemoveChildren()
1897 {
1898 	NodeList::Iterator iterator = fChildren.GetIterator();
1899 	while (iterator.HasNext()) {
1900 		device_node* child = iterator.Next();
1901 		child->Release();
1902 	}
1903 
1904 	return fChildren.IsEmpty() ? B_OK : B_BUSY;
1905 }
1906 
1907 
1908 device_node*
1909 device_node::_FindCurrentChild()
1910 {
1911 	NodeList::Iterator iterator = fChildren.GetIterator();
1912 	while (iterator.HasNext()) {
1913 		device_node* child = iterator.Next();
1914 
1915 		if ((child->Flags() & NODE_FLAG_WAITING_FOR_DRIVER) == 0)
1916 			return child;
1917 	}
1918 
1919 	return NULL;
1920 }
1921 
1922 
1923 status_t
1924 device_node::_Probe()
1925 {
1926 	device_node* previous = NULL;
1927 
1928 	if (IsProbed() && !fChildren.IsEmpty()
1929 		&& (fFlags & (B_FIND_CHILD_ON_DEMAND | B_FIND_MULTIPLE_CHILDREN))
1930 				== B_FIND_CHILD_ON_DEMAND) {
1931 		// We already have a driver that claims this node; remove all
1932 		// (unused) nodes, and evaluate it again
1933 		_RemoveChildren();
1934 
1935 		previous = _FindCurrentChild();
1936 		if (previous != NULL) {
1937 			// This driver is still active - give it back the reference
1938 			// that was stolen by _RemoveChildren() - _RegisterDynamic()
1939 			// will release it, if it really isn't needed anymore
1940 			previous->Acquire();
1941 		}
1942 	}
1943 
1944 	return _RegisterDynamic(previous);
1945 }
1946 
1947 
1948 status_t
1949 device_node::Probe(const char* devicePath, uint32 updateCycle)
1950 {
1951 	if ((fFlags & NODE_FLAG_DEVICE_REMOVED) != 0
1952 		|| updateCycle == fLastUpdateCycle)
1953 		return B_OK;
1954 
1955 	status_t status = InitDriver();
1956 	if (status < B_OK)
1957 		return status;
1958 
1959 	MethodDeleter<device_node, bool, &device_node::UninitDriver> uninit(this);
1960 
1961 	if ((fFlags & B_FIND_CHILD_ON_DEMAND) != 0) {
1962 		bool matches = false;
1963 		uint16 type = 0;
1964 		uint16 subType = 0;
1965 		if (get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false) == B_OK
1966 			&& get_attr_uint16(this, B_DEVICE_TYPE, &type, false) == B_OK) {
1967 			// Check if this node matches the device path
1968 			// TODO: maybe make this extendible via settings file?
1969 			if (!strcmp(devicePath, "disk")) {
1970 				matches = type == PCI_mass_storage
1971 					|| (type == PCI_base_peripheral
1972 						&& (subType == PCI_sd_host
1973 							|| subType == PCI_system_peripheral_other));
1974 			} else if (!strcmp(devicePath, "audio")) {
1975 				matches = type == PCI_multimedia
1976 					&& (subType == PCI_audio || subType == PCI_hd_audio);
1977 			} else if (!strcmp(devicePath, "net")) {
1978 				matches = type == PCI_network;
1979 			} else if (!strcmp(devicePath, "graphics")) {
1980 				matches = type == PCI_display;
1981 			} else if (!strcmp(devicePath, "video")) {
1982 				matches = type == PCI_multimedia && subType == PCI_video;
1983 			} else if (!strcmp(devicePath, "power")) {
1984 				matches = type == PCI_data_acquisition;
1985 			} else if (!strcmp(devicePath, "input")) {
1986 				matches = type == PCI_data_acquisition
1987 					&& subType == PCI_data_acquisition_other;
1988 			}
1989 		} else {
1990 			// This driver does not support types, but still wants to its
1991 			// children explored on demand only.
1992 			matches = true;
1993 			sGenericContextPath = devicePath;
1994 		}
1995 
1996 		if (matches) {
1997 			fLastUpdateCycle = updateCycle;
1998 				// This node will be probed in this update cycle
1999 
2000 			status = _Probe();
2001 
2002 			sGenericContextPath = NULL;
2003 			return status;
2004 		}
2005 
2006 		return B_OK;
2007 	}
2008 
2009 	NodeList::Iterator iterator = fChildren.GetIterator();
2010 	while (iterator.HasNext()) {
2011 		device_node* child = iterator.Next();
2012 
2013 		status = child->Probe(devicePath, updateCycle);
2014 		if (status != B_OK)
2015 			return status;
2016 	}
2017 
2018 	return B_OK;
2019 }
2020 
2021 
2022 status_t
2023 device_node::Reprobe()
2024 {
2025 	status_t status = InitDriver();
2026 	if (status < B_OK)
2027 		return status;
2028 
2029 	MethodDeleter<device_node, bool, &device_node::UninitDriver> uninit(this);
2030 
2031 	// If this child has been probed already, probe it again
2032 	status = _Probe();
2033 	if (status != B_OK)
2034 		return status;
2035 
2036 	NodeList::Iterator iterator = fChildren.GetIterator();
2037 	while (iterator.HasNext()) {
2038 		device_node* child = iterator.Next();
2039 
2040 		status = child->Reprobe();
2041 		if (status != B_OK)
2042 			return status;
2043 	}
2044 
2045 	return B_OK;
2046 }
2047 
2048 
2049 status_t
2050 device_node::Rescan()
2051 {
2052 	status_t status = InitDriver();
2053 	if (status < B_OK)
2054 		return status;
2055 
2056 	MethodDeleter<device_node, bool, &device_node::UninitDriver> uninit(this);
2057 
2058 	if (DriverModule()->rescan_child_devices != NULL) {
2059 		status = DriverModule()->rescan_child_devices(DriverData());
2060 		if (status != B_OK)
2061 			return status;
2062 	}
2063 
2064 	NodeList::Iterator iterator = fChildren.GetIterator();
2065 	while (iterator.HasNext()) {
2066 		device_node* child = iterator.Next();
2067 
2068 		status = child->Rescan();
2069 		if (status != B_OK)
2070 			return status;
2071 	}
2072 
2073 	return B_OK;
2074 }
2075 
2076 
2077 /*!	Uninitializes all temporary references to the driver. The registration
2078 	process keeps the driver initialized to optimize the startup procedure;
2079 	this function gives this reference away again.
2080 */
2081 void
2082 device_node::UninitUnusedDriver()
2083 {
2084 	// First, we need to go to the leaf, and go back from there
2085 
2086 	NodeList::Iterator iterator = fChildren.GetIterator();
2087 	while (iterator.HasNext()) {
2088 		device_node* child = iterator.Next();
2089 
2090 		child->UninitUnusedDriver();
2091 	}
2092 
2093 	if (!IsInitialized()
2094 		|| (fFlags & NODE_FLAG_REGISTER_INITIALIZED) == 0)
2095 		return;
2096 
2097 	fFlags &= ~NODE_FLAG_REGISTER_INITIALIZED;
2098 
2099 	UninitDriver();
2100 }
2101 
2102 
2103 /*!	Calls device_removed() on this node and all of its children - starting
2104 	with the deepest and last child.
2105 	It will also remove the one reference that every node gets on its creation.
2106 */
2107 void
2108 device_node::DeviceRemoved()
2109 {
2110 	// notify children
2111 	NodeList::ConstIterator iterator = Children().GetIterator();
2112 	while (iterator.HasNext()) {
2113 		device_node* child = iterator.Next();
2114 
2115 		child->DeviceRemoved();
2116 	}
2117 
2118 	// notify devices
2119 	DeviceList::ConstIterator deviceIterator = Devices().GetIterator();
2120 	while (deviceIterator.HasNext()) {
2121 		Device* device = deviceIterator.Next();
2122 
2123 		if (device->Module() != NULL
2124 			&& device->Module()->device_removed != NULL)
2125 			device->Module()->device_removed(device->Data());
2126 	}
2127 
2128 	fFlags |= NODE_FLAG_DEVICE_REMOVED;
2129 
2130 	if (IsInitialized() && DriverModule()->device_removed != NULL)
2131 		DriverModule()->device_removed(this);
2132 
2133 	if ((fFlags & B_KEEP_DRIVER_LOADED) != 0) {
2134 		// There is no point in keeping this driver loaded when its device
2135 		// is gone
2136 		UninitDriver();
2137 	}
2138 
2139 	UninitUnusedDriver();
2140 	Release();
2141 }
2142 
2143 
2144 void
2145 device_node::Acquire()
2146 {
2147 	atomic_add(&fRefCount, 1);
2148 }
2149 
2150 
2151 bool
2152 device_node::Release()
2153 {
2154 	if (atomic_add(&fRefCount, -1) > 1)
2155 		return false;
2156 
2157 	delete this;
2158 	return true;
2159 }
2160 
2161 
2162 void
2163 device_node::AddDevice(Device* device)
2164 {
2165 	fDevices.Add(device);
2166 }
2167 
2168 
2169 void
2170 device_node::RemoveDevice(Device* device)
2171 {
2172 	fDevices.Remove(device);
2173 }
2174 
2175 
2176 int
2177 device_node::CompareTo(const device_attr* attributes) const
2178 {
2179 	if (attributes == NULL)
2180 		return -1;
2181 
2182 	for (; attributes->name != NULL; attributes++) {
2183 		// find corresponding attribute
2184 		AttributeList::ConstIterator iterator = Attributes().GetIterator();
2185 		device_attr_private* attr = NULL;
2186 		bool found = false;
2187 
2188 		while (iterator.HasNext()) {
2189 			attr = iterator.Next();
2190 
2191 			if (!strcmp(attr->name, attributes->name)) {
2192 				found = true;
2193 				break;
2194 			}
2195 		}
2196 		if (!found)
2197 			return -1;
2198 
2199 		int compare = device_attr_private::Compare(attr, attributes);
2200 		if (compare != 0)
2201 			return compare;
2202 	}
2203 
2204 	return 0;
2205 }
2206 
2207 
2208 device_node*
2209 device_node::FindChild(const device_attr* attributes) const
2210 {
2211 	if (attributes == NULL)
2212 		return NULL;
2213 
2214 	NodeList::ConstIterator iterator = Children().GetIterator();
2215 	while (iterator.HasNext()) {
2216 		device_node* child = iterator.Next();
2217 
2218 		// ignore nodes that are pending to be removed
2219 		if ((child->Flags() & NODE_FLAG_DEVICE_REMOVED) == 0
2220 			&& !child->CompareTo(attributes))
2221 			return child;
2222 	}
2223 
2224 	return NULL;
2225 }
2226 
2227 
2228 device_node*
2229 device_node::FindChild(const char* moduleName) const
2230 {
2231 	if (moduleName == NULL)
2232 		return NULL;
2233 
2234 	NodeList::ConstIterator iterator = Children().GetIterator();
2235 	while (iterator.HasNext()) {
2236 		device_node* child = iterator.Next();
2237 
2238 		if (!strcmp(child->ModuleName(), moduleName))
2239 			return child;
2240 	}
2241 
2242 	return NULL;
2243 }
2244 
2245 
2246 /*!	This returns the priority or importance of this node. Nodes with higher
2247 	priority are registered/probed first.
2248 	Currently, only the B_FIND_MULTIPLE_CHILDREN flag alters the priority;
2249 	it might make sense to be able to directly set the priority via an
2250 	attribute.
2251 */
2252 int32
2253 device_node::Priority()
2254 {
2255 	return (fFlags & B_FIND_MULTIPLE_CHILDREN) != 0 ? 0 : 100;
2256 }
2257 
2258 
2259 void
2260 device_node::Dump(int32 level)
2261 {
2262 	put_level(level);
2263 	kprintf("(%" B_PRId32 ") @%p \"%s\" (ref %" B_PRId32 ", init %" B_PRId32
2264 		", module %p, data %p)\n", level, this, ModuleName(), fRefCount,
2265 		fInitialized, DriverModule(), DriverData());
2266 
2267 	AttributeList::Iterator attribute = Attributes().GetIterator();
2268 	while (attribute.HasNext()) {
2269 		dump_attribute(attribute.Next(), level);
2270 	}
2271 
2272 	DeviceList::Iterator deviceIterator = fDevices.GetIterator();
2273 	while (deviceIterator.HasNext()) {
2274 		Device* device = deviceIterator.Next();
2275 		put_level(level);
2276 		kprintf("device: %s, %p\n", device->ModuleName(), device->Data());
2277 	}
2278 
2279 	NodeList::ConstIterator iterator = Children().GetIterator();
2280 	while (iterator.HasNext()) {
2281 		iterator.Next()->Dump(level + 1);
2282 	}
2283 }
2284 
2285 
2286 //	#pragma mark - root node
2287 
2288 
2289 static void
2290 init_node_tree(void)
2291 {
2292 	device_attr attrs[] = {
2293 		{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "Devices Root"}},
2294 		{B_DEVICE_BUS, B_STRING_TYPE, {string: "root"}},
2295 		{B_DEVICE_FLAGS, B_UINT32_TYPE,
2296 			{ui32: B_FIND_MULTIPLE_CHILDREN | B_KEEP_DRIVER_LOADED }},
2297 		{NULL}
2298 	};
2299 
2300 	device_node* node = NULL;
2301 	if (register_node(NULL, DEVICE_MANAGER_ROOT_NAME, attrs, NULL, &node)
2302 			!= B_OK) {
2303 		dprintf("Cannot register Devices Root Node\n");
2304 	}
2305 
2306 	device_attr genericAttrs[] = {
2307 		{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "Generic"}},
2308 		{B_DEVICE_BUS, B_STRING_TYPE, {string: "generic"}},
2309 		{B_DEVICE_FLAGS, B_UINT32_TYPE, {ui32: B_FIND_MULTIPLE_CHILDREN
2310 			| B_KEEP_DRIVER_LOADED | B_FIND_CHILD_ON_DEMAND}},
2311 		{NULL}
2312 	};
2313 
2314 	if (register_node(node, DEVICE_MANAGER_GENERIC_NAME, genericAttrs, NULL,
2315 			NULL) != B_OK) {
2316 		dprintf("Cannot register Generic Devices Node\n");
2317 	}
2318 }
2319 
2320 
2321 driver_module_info gDeviceRootModule = {
2322 	{
2323 		DEVICE_MANAGER_ROOT_NAME,
2324 		0,
2325 		NULL,
2326 	},
2327 };
2328 
2329 
2330 driver_module_info gDeviceGenericModule = {
2331 	{
2332 		DEVICE_MANAGER_GENERIC_NAME,
2333 		0,
2334 		NULL,
2335 	},
2336 	NULL
2337 };
2338 
2339 
2340 //	#pragma mark - private kernel API
2341 
2342 
2343 status_t
2344 device_manager_probe(const char* path, uint32 updateCycle)
2345 {
2346 	TRACE(("device_manager_probe(\"%s\")\n", path));
2347 	RecursiveLocker _(sLock);
2348 
2349 	// first, publish directories in the driver directory
2350 	publish_directories(path);
2351 
2352 	return sRootNode->Probe(path, updateCycle);
2353 }
2354 
2355 
2356 status_t
2357 device_manager_init(struct kernel_args* args)
2358 {
2359 	TRACE(("device manager init\n"));
2360 
2361 	IOSchedulerRoster::Init();
2362 
2363 	dm_init_id_generator();
2364 	dm_init_io_resources();
2365 
2366 	recursive_lock_init(&sLock, "device manager");
2367 
2368 	register_generic_syscall(DEVICE_MANAGER_SYSCALLS, control_device_manager,
2369 		1, 0);
2370 
2371 	add_debugger_command("dm_tree", &dump_device_nodes,
2372 		"dump device node tree");
2373 	add_debugger_command_etc("io_scheduler", &dump_io_scheduler,
2374 		"Dump an I/O scheduler",
2375 		"<scheduler>\n"
2376 		"Dumps I/O scheduler at address <scheduler>.\n", 0);
2377 	add_debugger_command_etc("io_request_owner", &dump_io_request_owner,
2378 		"Dump an I/O request owner",
2379 		"<owner>\n"
2380 		"Dumps I/O request owner at address <owner>.\n", 0);
2381 	add_debugger_command("io_request", &dump_io_request, "dump an I/O request");
2382 	add_debugger_command("io_operation", &dump_io_operation,
2383 		"dump an I/O operation");
2384 	add_debugger_command("io_buffer", &dump_io_buffer, "dump an I/O buffer");
2385 	add_debugger_command("dma_buffer", &dump_dma_buffer, "dump a DMA buffer");
2386 
2387 	init_node_tree();
2388 
2389 	return B_OK;
2390 }
2391 
2392 
2393 status_t
2394 device_manager_init_post_modules(struct kernel_args* args)
2395 {
2396 	RecursiveLocker _(sLock);
2397 	return sRootNode->Reprobe();
2398 }
2399