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