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