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