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