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