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