xref: /haiku/src/system/kernel/device_manager/device_manager.cpp (revision 909af08f4328301fbdef1ffb41f566c3b5bec0c7)
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 		if (get_attr_uint16(this, B_DEVICE_TYPE, &type, false) != B_OK
1648 			|| get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false)
1649 					!= B_OK)
1650 			generic = true;
1651 
1652 		// TODO: maybe make this extendible via settings file?
1653 		switch (type) {
1654 			case PCI_mass_storage:
1655 				switch (subType) {
1656 					case PCI_scsi:
1657 						_AddPath(*stack, "busses", "scsi");
1658 						_AddPath(*stack, "busses", "virtio");
1659 						break;
1660 					case PCI_ide:
1661 						_AddPath(*stack, "busses", "ata");
1662 						_AddPath(*stack, "busses", "ide");
1663 						break;
1664 					case PCI_sata:
1665 						// TODO: check for ahci interface
1666 						_AddPath(*stack, "busses", "scsi");
1667 						_AddPath(*stack, "busses", "ata");
1668 						_AddPath(*stack, "busses", "ide");
1669 						break;
1670 					case PCI_nvm:
1671 						_AddPath(*stack, "drivers", "disk");
1672 						break;
1673 					default:
1674 						_AddPath(*stack, "busses");
1675 						break;
1676 				}
1677 				break;
1678 			case PCI_serial_bus:
1679 				switch (subType) {
1680 					case PCI_firewire:
1681 						_AddPath(*stack, "busses", "firewire");
1682 						break;
1683 					case PCI_usb:
1684 						_AddPath(*stack, "busses", "usb");
1685 						break;
1686 					default:
1687 						_AddPath(*stack, "busses");
1688 						break;
1689 				}
1690 				break;
1691 			case PCI_network:
1692 				_AddPath(*stack, "drivers", "net");
1693 				_AddPath(*stack, "busses", "virtio");
1694 				break;
1695 			case PCI_display:
1696 				_AddPath(*stack, "drivers", "graphics");
1697 				_AddPath(*stack, "busses", "virtio");
1698 				break;
1699 			case PCI_multimedia:
1700 				switch (subType) {
1701 					case PCI_audio:
1702 					case PCI_hd_audio:
1703 						_AddPath(*stack, "drivers", "audio");
1704 						_AddPath(*stack, "busses", "virtio");
1705 						break;
1706 					case PCI_video:
1707 						_AddPath(*stack, "drivers", "video");
1708 						break;
1709 					default:
1710 						_AddPath(*stack, "drivers");
1711 						break;
1712 				}
1713 				break;
1714 			case PCI_base_peripheral:
1715 				switch (subType) {
1716 					case PCI_sd_host:
1717 						_AddPath(*stack, "busses", "mmc");
1718 						break;
1719 					case PCI_system_peripheral_other:
1720 						_AddPath(*stack, "busses", "mmc");
1721 						_AddPath(*stack, "drivers");
1722 						break;
1723 					default:
1724 						_AddPath(*stack, "drivers");
1725 						break;
1726 				}
1727 				break;
1728 			case PCI_encryption_decryption:
1729 				switch (subType) {
1730 					case PCI_encryption_decryption_other:
1731 						_AddPath(*stack, "busses", "random");
1732 						break;
1733 					default:
1734 						_AddPath(*stack, "drivers");
1735 						break;
1736 				}
1737 				break;
1738 			case PCI_data_acquisition:
1739 				switch (subType) {
1740 					case PCI_data_acquisition_other:
1741 						_AddPath(*stack, "busses", "i2c");
1742 						break;
1743 					default:
1744 						_AddPath(*stack, "drivers");
1745 						break;
1746 				}
1747 				break;
1748 			default:
1749 				if (sRootNode == this) {
1750 					_AddPath(*stack, "busses/pci");
1751 					_AddPath(*stack, "bus_managers");
1752 				} else if (!generic) {
1753 					_AddPath(*stack, "drivers");
1754 					_AddPath(*stack, "busses/virtio");
1755 				} else {
1756 					// For generic drivers, we only allow busses when the
1757 					// request is more specified
1758 					if (sGenericContextPath != NULL
1759 						&& (!strcmp(sGenericContextPath, "disk")
1760 							|| !strcmp(sGenericContextPath, "ports")
1761 							|| !strcmp(sGenericContextPath, "bus"))) {
1762 						_AddPath(*stack, "busses");
1763 					}
1764 					const char* bus;
1765 					if (get_attr_string(this, B_DEVICE_BUS, &bus, false) == B_OK) {
1766 						if (strcmp(bus, "virtio") == 0)
1767 							_AddPath(*stack, "busses/scsi");
1768 					}
1769 					_AddPath(*stack, "drivers", sGenericContextPath);
1770 					_AddPath(*stack, "busses/i2c");
1771 					_AddPath(*stack, "busses/random");
1772 					_AddPath(*stack, "busses/virtio");
1773 					_AddPath(*stack, "bus_managers/pci");
1774 					_AddPath(*stack, "busses/pci");
1775 					_AddPath(*stack, "busses/mmc");
1776 				}
1777 				break;
1778 		}
1779 
1780 		stackDeleter.Detach();
1781 
1782 		cookie = (void*)stack;
1783 	} else
1784 		stack = static_cast<Stack<KPath*>*>(cookie);
1785 
1786 	KPath* path;
1787 	if (stack->Pop(&path)) {
1788 		_path.Adopt(*path);
1789 		delete path;
1790 		return B_OK;
1791 	}
1792 
1793 	delete stack;
1794 	return B_ENTRY_NOT_FOUND;
1795 }
1796 
1797 
1798 status_t
1799 device_node::_GetNextDriver(void* list, driver_module_info*& driver)
1800 {
1801 	while (true) {
1802 		char name[B_FILE_NAME_LENGTH];
1803 		size_t nameLength = sizeof(name);
1804 
1805 		status_t status = read_next_module_name(list, name, &nameLength);
1806 		if (status != B_OK)
1807 			return status;
1808 
1809 		if (!strcmp(fModuleName, name))
1810 			continue;
1811 
1812 		if (get_module(name, (module_info**)&driver) != B_OK)
1813 			continue;
1814 
1815 		if (driver->supports_device == NULL
1816 			|| driver->register_device == NULL) {
1817 			put_module(name);
1818 			continue;
1819 		}
1820 
1821 		return B_OK;
1822 	}
1823 }
1824 
1825 
1826 status_t
1827 device_node::_FindBestDriver(const char* path, driver_module_info*& bestDriver,
1828 	float& bestSupport, device_node* previous)
1829 {
1830 	if (bestDriver == NULL)
1831 		bestSupport = previous != NULL ? previous->fSupportsParent : 0.0f;
1832 
1833 	void* list = open_module_list_etc(path, "driver_v1");
1834 	driver_module_info* driver;
1835 	while (_GetNextDriver(list, driver) == B_OK) {
1836 		if (previous != NULL && driver == previous->DriverModule()) {
1837 			put_module(driver->info.name);
1838 			continue;
1839 		}
1840 
1841 		float support = driver->supports_device(this);
1842 		if (support > bestSupport) {
1843 			if (bestDriver != NULL)
1844 				put_module(bestDriver->info.name);
1845 
1846 			bestDriver = driver;
1847 			bestSupport = support;
1848 			continue;
1849 				// keep reference to best module around
1850 		}
1851 
1852 		put_module(driver->info.name);
1853 	}
1854 	close_module_list(list);
1855 
1856 	return bestDriver != NULL ? B_OK : B_ENTRY_NOT_FOUND;
1857 }
1858 
1859 
1860 status_t
1861 device_node::_RegisterPath(const char* path)
1862 {
1863 	void* list = open_module_list_etc(path, "driver_v1");
1864 	driver_module_info* driver;
1865 	uint32 count = 0;
1866 
1867 	while (_GetNextDriver(list, driver) == B_OK) {
1868 		float support = driver->supports_device(this);
1869 		if (support > 0.0) {
1870 			TRACE(("  register module \"%s\", support %f\n", driver->info.name,
1871 				support));
1872 			if (driver->register_device(this) == B_OK)
1873 				count++;
1874 		}
1875 
1876 		put_module(driver->info.name);
1877 	}
1878 	close_module_list(list);
1879 
1880 	return count > 0 ? B_OK : B_ENTRY_NOT_FOUND;
1881 }
1882 
1883 
1884 bool
1885 device_node::_AlwaysRegisterDynamic()
1886 {
1887 	uint16 type = 0;
1888 	uint16 subType = 0;
1889 	get_attr_uint16(this, B_DEVICE_TYPE, &type, false);
1890 	get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false);
1891 
1892 	switch (type) {
1893 		case PCI_serial_bus:
1894 		case PCI_bridge:
1895 		case PCI_encryption_decryption:
1896 		case 0:
1897 			return true;
1898 	}
1899 	return false;
1900 		// TODO: we may want to be a bit more specific in the future
1901 }
1902 
1903 
1904 status_t
1905 device_node::_RegisterDynamic(device_node* previous)
1906 {
1907 	// If this is not a bus, we don't have to scan it
1908 	if (find_attr(this, B_DEVICE_BUS, false, B_STRING_TYPE) == NULL)
1909 		return B_OK;
1910 
1911 	// If we're not being probed, we honour the B_FIND_CHILD_ON_DEMAND
1912 	// requirements
1913 	if (!IsProbed() && (fFlags & B_FIND_CHILD_ON_DEMAND) != 0
1914 		&& !_AlwaysRegisterDynamic())
1915 		return B_OK;
1916 
1917 	KPath path;
1918 
1919 	if ((fFlags & B_FIND_MULTIPLE_CHILDREN) == 0) {
1920 		// find the one driver
1921 		driver_module_info* bestDriver = NULL;
1922 		float bestSupport = 0.0;
1923 		void* cookie = NULL;
1924 
1925 		while (_GetNextDriverPath(cookie, path) == B_OK) {
1926 			_FindBestDriver(path.Path(), bestDriver, bestSupport, previous);
1927 		}
1928 
1929 		if (bestDriver != NULL) {
1930 			TRACE(("  register best module \"%s\", support %f\n",
1931 				bestDriver->info.name, bestSupport));
1932 			if (bestDriver->register_device(this) == B_OK) {
1933 				// There can only be one node of this driver
1934 				// (usually only one at all, but there might be a new driver
1935 				// "waiting" for its turn)
1936 				device_node* child = FindChild(bestDriver->info.name);
1937 				if (child != NULL) {
1938 					child->fSupportsParent = bestSupport;
1939 					if (previous != NULL) {
1940 						previous->fFlags |= NODE_FLAG_OBSOLETE_DRIVER;
1941 						previous->Release();
1942 						child->fFlags |= NODE_FLAG_WAITING_FOR_DRIVER;
1943 					}
1944 				}
1945 				// TODO: if this fails, we could try the second best driver,
1946 				// and so on...
1947 			}
1948 			put_module(bestDriver->info.name);
1949 		}
1950 	} else {
1951 		// register all drivers that match
1952 		void* cookie = NULL;
1953 		while (_GetNextDriverPath(cookie, path) == B_OK) {
1954 			_RegisterPath(path.Path());
1955 		}
1956 	}
1957 
1958 	return B_OK;
1959 }
1960 
1961 
1962 void
1963 device_node::_ReleaseWaiting()
1964 {
1965 	NodeList::Iterator iterator = fChildren.GetIterator();
1966 	while (iterator.HasNext()) {
1967 		device_node* child = iterator.Next();
1968 
1969 		child->fFlags &= ~NODE_FLAG_WAITING_FOR_DRIVER;
1970 	}
1971 }
1972 
1973 
1974 status_t
1975 device_node::_RemoveChildren()
1976 {
1977 	NodeList::Iterator iterator = fChildren.GetIterator();
1978 	while (iterator.HasNext()) {
1979 		device_node* child = iterator.Next();
1980 		child->Release();
1981 	}
1982 
1983 	return fChildren.IsEmpty() ? B_OK : B_BUSY;
1984 }
1985 
1986 
1987 device_node*
1988 device_node::_FindCurrentChild()
1989 {
1990 	NodeList::Iterator iterator = fChildren.GetIterator();
1991 	while (iterator.HasNext()) {
1992 		device_node* child = iterator.Next();
1993 
1994 		if ((child->Flags() & NODE_FLAG_WAITING_FOR_DRIVER) == 0)
1995 			return child;
1996 	}
1997 
1998 	return NULL;
1999 }
2000 
2001 
2002 status_t
2003 device_node::_Probe()
2004 {
2005 	device_node* previous = NULL;
2006 
2007 	if (IsProbed() && !fChildren.IsEmpty()
2008 		&& (fFlags & (B_FIND_CHILD_ON_DEMAND | B_FIND_MULTIPLE_CHILDREN))
2009 				== B_FIND_CHILD_ON_DEMAND) {
2010 		// We already have a driver that claims this node; remove all
2011 		// (unused) nodes, and evaluate it again
2012 		_RemoveChildren();
2013 
2014 		previous = _FindCurrentChild();
2015 		if (previous != NULL) {
2016 			// This driver is still active - give it back the reference
2017 			// that was stolen by _RemoveChildren() - _RegisterDynamic()
2018 			// will release it, if it really isn't needed anymore
2019 			previous->Acquire();
2020 		}
2021 	}
2022 
2023 	return _RegisterDynamic(previous);
2024 }
2025 
2026 
2027 status_t
2028 device_node::Probe(const char* devicePath, uint32 updateCycle)
2029 {
2030 	if ((fFlags & NODE_FLAG_DEVICE_REMOVED) != 0
2031 		|| updateCycle == fLastUpdateCycle)
2032 		return B_OK;
2033 
2034 	status_t status = InitDriver();
2035 	if (status < B_OK)
2036 		return status;
2037 
2038 	MethodDeleter<device_node, bool, &device_node::UninitDriver> uninit(this);
2039 
2040 	if ((fFlags & B_FIND_CHILD_ON_DEMAND) != 0) {
2041 		bool matches = false;
2042 		uint16 type = 0;
2043 		uint16 subType = 0;
2044 		if (get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false) == B_OK
2045 			&& get_attr_uint16(this, B_DEVICE_TYPE, &type, false) == B_OK) {
2046 			// Check if this node matches the device path
2047 			// TODO: maybe make this extendible via settings file?
2048 			if (!strcmp(devicePath, "disk")) {
2049 				matches = type == PCI_mass_storage
2050 					|| (type == PCI_base_peripheral
2051 						&& (subType == PCI_sd_host
2052 							|| subType == PCI_system_peripheral_other));
2053 			} else if (!strcmp(devicePath, "audio")) {
2054 				matches = type == PCI_multimedia
2055 					&& (subType == PCI_audio || subType == PCI_hd_audio);
2056 			} else if (!strcmp(devicePath, "net")) {
2057 				matches = type == PCI_network;
2058 			} else if (!strcmp(devicePath, "graphics")) {
2059 				matches = type == PCI_display;
2060 			} else if (!strcmp(devicePath, "video")) {
2061 				matches = type == PCI_multimedia && subType == PCI_video;
2062 			} else if (!strcmp(devicePath, "power")) {
2063 				matches = type == PCI_data_acquisition;
2064 			} else if (!strcmp(devicePath, "input")) {
2065 				matches = type == PCI_data_acquisition
2066 					&& subType == PCI_data_acquisition_other;
2067 			}
2068 		} else {
2069 			// This driver does not support types, but still wants to its
2070 			// children explored on demand only.
2071 			matches = true;
2072 			sGenericContextPath = devicePath;
2073 		}
2074 
2075 		if (matches) {
2076 			fLastUpdateCycle = updateCycle;
2077 				// This node will be probed in this update cycle
2078 
2079 			status = _Probe();
2080 
2081 			sGenericContextPath = NULL;
2082 			return status;
2083 		}
2084 
2085 		return B_OK;
2086 	}
2087 
2088 	NodeList::Iterator iterator = fChildren.GetIterator();
2089 	while (iterator.HasNext()) {
2090 		device_node* child = iterator.Next();
2091 
2092 		status = child->Probe(devicePath, updateCycle);
2093 		if (status != B_OK)
2094 			return status;
2095 	}
2096 
2097 	return B_OK;
2098 }
2099 
2100 
2101 status_t
2102 device_node::Reprobe()
2103 {
2104 	status_t status = InitDriver();
2105 	if (status < B_OK)
2106 		return status;
2107 
2108 	MethodDeleter<device_node, bool, &device_node::UninitDriver> uninit(this);
2109 
2110 	// If this child has been probed already, probe it again
2111 	status = _Probe();
2112 	if (status != B_OK)
2113 		return status;
2114 
2115 	NodeList::Iterator iterator = fChildren.GetIterator();
2116 	while (iterator.HasNext()) {
2117 		device_node* child = iterator.Next();
2118 
2119 		status = child->Reprobe();
2120 		if (status != B_OK)
2121 			return status;
2122 	}
2123 
2124 	return B_OK;
2125 }
2126 
2127 
2128 status_t
2129 device_node::Rescan()
2130 {
2131 	status_t status = InitDriver();
2132 	if (status < B_OK)
2133 		return status;
2134 
2135 	MethodDeleter<device_node, bool, &device_node::UninitDriver> uninit(this);
2136 
2137 	if (DriverModule()->rescan_child_devices != NULL) {
2138 		status = DriverModule()->rescan_child_devices(DriverData());
2139 		if (status != B_OK)
2140 			return status;
2141 	}
2142 
2143 	NodeList::Iterator iterator = fChildren.GetIterator();
2144 	while (iterator.HasNext()) {
2145 		device_node* child = iterator.Next();
2146 
2147 		status = child->Rescan();
2148 		if (status != B_OK)
2149 			return status;
2150 	}
2151 
2152 	return B_OK;
2153 }
2154 
2155 
2156 /*!	Uninitializes all temporary references to the driver. The registration
2157 	process keeps the driver initialized to optimize the startup procedure;
2158 	this function gives this reference away again.
2159 */
2160 void
2161 device_node::UninitUnusedDriver()
2162 {
2163 	// First, we need to go to the leaf, and go back from there
2164 
2165 	NodeList::Iterator iterator = fChildren.GetIterator();
2166 	while (iterator.HasNext()) {
2167 		device_node* child = iterator.Next();
2168 
2169 		child->UninitUnusedDriver();
2170 	}
2171 
2172 	if (!IsInitialized()
2173 		|| (fFlags & NODE_FLAG_REGISTER_INITIALIZED) == 0)
2174 		return;
2175 
2176 	fFlags &= ~NODE_FLAG_REGISTER_INITIALIZED;
2177 
2178 	UninitDriver();
2179 }
2180 
2181 
2182 /*!	Calls device_removed() on this node and all of its children - starting
2183 	with the deepest and last child.
2184 	It will also remove the one reference that every node gets on its creation.
2185 */
2186 void
2187 device_node::DeviceRemoved()
2188 {
2189 	// notify children
2190 	NodeList::ConstIterator iterator = Children().GetIterator();
2191 	while (iterator.HasNext()) {
2192 		device_node* child = iterator.Next();
2193 
2194 		child->DeviceRemoved();
2195 	}
2196 
2197 	// notify devices
2198 	DeviceList::ConstIterator deviceIterator = Devices().GetIterator();
2199 	while (deviceIterator.HasNext()) {
2200 		Device* device = deviceIterator.Next();
2201 
2202 		if (device->Module() != NULL
2203 			&& device->Module()->device_removed != NULL)
2204 			device->Module()->device_removed(device->Data());
2205 	}
2206 
2207 	fFlags |= NODE_FLAG_DEVICE_REMOVED;
2208 
2209 	if (IsInitialized() && DriverModule()->device_removed != NULL)
2210 		DriverModule()->device_removed(this);
2211 
2212 	if ((fFlags & B_KEEP_DRIVER_LOADED) != 0) {
2213 		// There is no point in keeping this driver loaded when its device
2214 		// is gone
2215 		UninitDriver();
2216 	}
2217 
2218 	UninitUnusedDriver();
2219 	Release();
2220 }
2221 
2222 
2223 void
2224 device_node::Acquire()
2225 {
2226 	atomic_add(&fRefCount, 1);
2227 }
2228 
2229 
2230 bool
2231 device_node::Release()
2232 {
2233 	if (atomic_add(&fRefCount, -1) > 1)
2234 		return false;
2235 
2236 	delete this;
2237 	return true;
2238 }
2239 
2240 
2241 void
2242 device_node::AddDevice(Device* device)
2243 {
2244 	fDevices.Add(device);
2245 }
2246 
2247 
2248 void
2249 device_node::RemoveDevice(Device* device)
2250 {
2251 	char attrName[256];
2252 	device_attr_private* attr;
2253 
2254 	sprintf(attrName, "dev/%" B_PRIdINO "/path", device->ID());
2255 	attr = find_attr(this, attrName, false, B_STRING_TYPE);
2256 	if (attr != NULL) {
2257 		fAttributes.Remove(attr);
2258 		delete attr;
2259 	}
2260 
2261 	sprintf(attrName, "dev/%" B_PRIdINO "/driver", device->ID());
2262 	attr = find_attr(this, attrName, false, B_STRING_TYPE);
2263 	if (attr != NULL) {
2264 		fAttributes.Remove(attr);
2265 		delete attr;
2266 	}
2267 
2268 	fDevices.Remove(device);
2269 }
2270 
2271 
2272 int
2273 device_node::CompareTo(const device_attr* attributes) const
2274 {
2275 	if (attributes == NULL)
2276 		return -1;
2277 
2278 	for (; attributes->name != NULL; attributes++) {
2279 		// find corresponding attribute
2280 		AttributeList::ConstIterator iterator = Attributes().GetIterator();
2281 		device_attr_private* attr = NULL;
2282 		bool found = false;
2283 
2284 		while (iterator.HasNext()) {
2285 			attr = iterator.Next();
2286 
2287 			if (!strcmp(attr->name, attributes->name)) {
2288 				found = true;
2289 				break;
2290 			}
2291 		}
2292 		if (!found)
2293 			return -1;
2294 
2295 		int compare = device_attr_private::Compare(attr, attributes);
2296 		if (compare != 0)
2297 			return compare;
2298 	}
2299 
2300 	return 0;
2301 }
2302 
2303 
2304 device_node*
2305 device_node::FindChild(const device_attr* attributes) const
2306 {
2307 	if (attributes == NULL)
2308 		return NULL;
2309 
2310 	NodeList::ConstIterator iterator = Children().GetIterator();
2311 	while (iterator.HasNext()) {
2312 		device_node* child = iterator.Next();
2313 
2314 		// ignore nodes that are pending to be removed
2315 		if ((child->Flags() & NODE_FLAG_DEVICE_REMOVED) == 0
2316 			&& !child->CompareTo(attributes))
2317 			return child;
2318 	}
2319 
2320 	return NULL;
2321 }
2322 
2323 
2324 device_node*
2325 device_node::FindChild(const char* moduleName) const
2326 {
2327 	if (moduleName == NULL)
2328 		return NULL;
2329 
2330 	NodeList::ConstIterator iterator = Children().GetIterator();
2331 	while (iterator.HasNext()) {
2332 		device_node* child = iterator.Next();
2333 
2334 		if (!strcmp(child->ModuleName(), moduleName))
2335 			return child;
2336 	}
2337 
2338 	return NULL;
2339 }
2340 
2341 
2342 /*!	This returns the priority or importance of this node. Nodes with higher
2343 	priority are registered/probed first.
2344 	Currently, only the B_FIND_MULTIPLE_CHILDREN flag alters the priority;
2345 	it might make sense to be able to directly set the priority via an
2346 	attribute.
2347 */
2348 int32
2349 device_node::Priority()
2350 {
2351 	return (fFlags & B_FIND_MULTIPLE_CHILDREN) != 0 ? 0 : 100;
2352 }
2353 
2354 
2355 void
2356 device_node::Dump(int32 level)
2357 {
2358 	put_level(level);
2359 	kprintf("(%" B_PRId32 ") @%p \"%s\" (ref %" B_PRId32 ", init %" B_PRId32
2360 		", module %p, data %p)\n", level, this, ModuleName(), fRefCount,
2361 		fInitialized, DriverModule(), DriverData());
2362 
2363 	AttributeList::Iterator attribute = Attributes().GetIterator();
2364 	while (attribute.HasNext()) {
2365 		dump_attribute(attribute.Next(), level);
2366 	}
2367 
2368 	DeviceList::Iterator deviceIterator = fDevices.GetIterator();
2369 	while (deviceIterator.HasNext()) {
2370 		Device* device = deviceIterator.Next();
2371 		put_level(level);
2372 		kprintf("device: %s, %p\n", device->ModuleName(), device->Data());
2373 	}
2374 
2375 	NodeList::ConstIterator iterator = Children().GetIterator();
2376 	while (iterator.HasNext()) {
2377 		iterator.Next()->Dump(level + 1);
2378 	}
2379 }
2380 
2381 
2382 //	#pragma mark - root node
2383 
2384 
2385 static void
2386 init_node_tree(void)
2387 {
2388 	device_attr attrs[] = {
2389 		{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {.string = "Devices Root"}},
2390 		{B_DEVICE_BUS, B_STRING_TYPE, {.string = "root"}},
2391 		{B_DEVICE_FLAGS, B_UINT32_TYPE,
2392 			{.ui32 = B_FIND_MULTIPLE_CHILDREN | B_KEEP_DRIVER_LOADED }},
2393 		{NULL}
2394 	};
2395 
2396 	device_node* node = NULL;
2397 	if (register_node(NULL, DEVICE_MANAGER_ROOT_NAME, attrs, NULL, &node)
2398 			!= B_OK) {
2399 		dprintf("Cannot register Devices Root Node\n");
2400 	}
2401 
2402 	device_attr genericAttrs[] = {
2403 		{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {.string = "Generic"}},
2404 		{B_DEVICE_BUS, B_STRING_TYPE, {.string = "generic"}},
2405 		{B_DEVICE_FLAGS, B_UINT32_TYPE, {.ui32 = B_FIND_MULTIPLE_CHILDREN
2406 			| B_KEEP_DRIVER_LOADED | B_FIND_CHILD_ON_DEMAND}},
2407 		{NULL}
2408 	};
2409 
2410 	if (register_node(node, DEVICE_MANAGER_GENERIC_NAME, genericAttrs, NULL,
2411 			NULL) != B_OK) {
2412 		dprintf("Cannot register Generic Devices Node\n");
2413 	}
2414 }
2415 
2416 
2417 driver_module_info gDeviceRootModule = {
2418 	{
2419 		DEVICE_MANAGER_ROOT_NAME,
2420 		0,
2421 		NULL,
2422 	},
2423 };
2424 
2425 
2426 driver_module_info gDeviceGenericModule = {
2427 	{
2428 		DEVICE_MANAGER_GENERIC_NAME,
2429 		0,
2430 		NULL,
2431 	},
2432 	NULL
2433 };
2434 
2435 
2436 //	#pragma mark - private kernel API
2437 
2438 
2439 status_t
2440 device_manager_probe(const char* path, uint32 updateCycle)
2441 {
2442 	TRACE(("device_manager_probe(\"%s\")\n", path));
2443 	RecursiveLocker _(sLock);
2444 
2445 	// first, publish directories in the driver directory
2446 	publish_directories(path);
2447 
2448 	return sRootNode->Probe(path, updateCycle);
2449 }
2450 
2451 
2452 status_t
2453 device_manager_init(struct kernel_args* args)
2454 {
2455 	TRACE(("device manager init\n"));
2456 
2457 	IOSchedulerRoster::Init();
2458 
2459 	dm_init_id_generator();
2460 	dm_init_io_resources();
2461 
2462 	recursive_lock_init(&sLock, "device manager");
2463 
2464 	register_generic_syscall(DEVICE_MANAGER_SYSCALLS, control_device_manager,
2465 		1, 0);
2466 
2467 	add_debugger_command("dm_tree", &dump_device_nodes,
2468 		"dump device node tree");
2469 	add_debugger_command_etc("io_scheduler", &dump_io_scheduler,
2470 		"Dump an I/O scheduler",
2471 		"<scheduler>\n"
2472 		"Dumps I/O scheduler at address <scheduler>.\n", 0);
2473 	add_debugger_command_etc("io_request_owner", &dump_io_request_owner,
2474 		"Dump an I/O request owner",
2475 		"<owner>\n"
2476 		"Dumps I/O request owner at address <owner>.\n", 0);
2477 	add_debugger_command("io_request", &dump_io_request, "dump an I/O request");
2478 	add_debugger_command("io_operation", &dump_io_operation,
2479 		"dump an I/O operation");
2480 	add_debugger_command("io_buffer", &dump_io_buffer, "dump an I/O buffer");
2481 	add_debugger_command("dma_buffer", &dump_dma_buffer, "dump a DMA buffer");
2482 
2483 	init_node_tree();
2484 
2485 	return B_OK;
2486 }
2487 
2488 
2489 status_t
2490 device_manager_init_post_modules(struct kernel_args* args)
2491 {
2492 	RecursiveLocker _(sLock);
2493 	return sRootNode->Reprobe();
2494 }
2495 
2496 
2497 recursive_lock*
2498 device_manager_get_lock()
2499 {
2500 	return &sLock;
2501 }
2502