xref: /haiku/src/system/kernel/device_manager/device_manager.cpp (revision ed24eb5ff12640d052171c6a7feba37fab8a75d1)
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 <set>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include <KernelExport.h>
16 #include <Locker.h>
17 #include <module.h>
18 #include <PCI.h>
19 
20 #include <boot_device.h>
21 #include <device_manager_defs.h>
22 #include <fs/devfs.h>
23 #include <fs/KPath.h>
24 #include <generic_syscall.h>
25 #include <kernel.h>
26 #include <kmodule.h>
27 #include <util/AutoLock.h>
28 #include <util/DoublyLinkedList.h>
29 #include <util/Stack.h>
30 
31 #include "AbstractModuleDevice.h"
32 #include "devfs_private.h"
33 #include "id_generator.h"
34 #include "IORequest.h"
35 #include "io_resources.h"
36 #include "IOSchedulerRoster.h"
37 
38 
39 //#define TRACE_DEVICE_MANAGER
40 #ifdef TRACE_DEVICE_MANAGER
41 #	define TRACE(a) dprintf a
42 #else
43 #	define TRACE(a) ;
44 #endif
45 
46 
47 #define DEVICE_MANAGER_ROOT_NAME "system/devices_root/driver_v1"
48 #define DEVICE_MANAGER_GENERIC_NAME "system/devices_generic/driver_v1"
49 
50 
51 struct device_attr_private : device_attr,
52 		DoublyLinkedListLinkImpl<device_attr_private> {
53 						device_attr_private();
54 						device_attr_private(const device_attr& attr);
55 						~device_attr_private();
56 
57 			status_t	InitCheck();
58 			status_t	CopyFrom(const device_attr& attr);
59 
60 	static	int			Compare(const device_attr* attrA,
61 							const device_attr *attrB);
62 
63 private:
64 			void		_Unset();
65 };
66 
67 typedef DoublyLinkedList<device_attr_private> AttributeList;
68 
69 // I/O resource
70 typedef struct io_resource_info {
71 	struct io_resource_info *prev, *next;
72 	device_node*		owner;			// associated node; NULL for temporary allocation
73 	io_resource			resource;		// info about actual resource
74 } io_resource_info;
75 
76 
77 namespace {
78 
79 
80 class Device : public AbstractModuleDevice,
81 	public DoublyLinkedListLinkImpl<Device> {
82 public:
83 							Device(device_node* node, const char* moduleName);
84 	virtual					~Device();
85 
86 			status_t		InitCheck() const;
87 
88 			const char*		ModuleName() const { return fModuleName; }
89 
90 	virtual	status_t		InitDevice();
91 	virtual	void			UninitDevice();
92 
93 	virtual void			Removed();
94 
95 	virtual	status_t		Control(void* cookie, int32 op, void* buffer, size_t length);
96 
97 			void			SetRemovedFromParent(bool removed)
98 								{ fRemovedFromParent = removed; }
99 
100 private:
101 	const char*				fModuleName;
102 	bool					fRemovedFromParent;
103 };
104 
105 
106 } // unnamed namespace
107 
108 
109 typedef DoublyLinkedList<Device> DeviceList;
110 typedef DoublyLinkedList<device_node> NodeList;
111 
112 struct device_node : DoublyLinkedListLinkImpl<device_node> {
113 							device_node(const char* moduleName,
114 								const device_attr* attrs);
115 							~device_node();
116 
117 			status_t		InitCheck() const;
118 
119 			status_t		AcquireResources(const io_resource* resources);
120 
121 			const char*		ModuleName() const { return fModuleName; }
122 			device_node*	Parent() const { return fParent; }
123 			AttributeList&	Attributes() { return fAttributes; }
124 			const AttributeList& Attributes() const { return fAttributes; }
125 
126 			status_t		InitDriver();
127 			bool			UninitDriver();
128 			void			UninitUnusedDriver();
129 
130 			// The following two are only valid, if the node's driver is
131 			// initialized
132 			driver_module_info* DriverModule() const { return fDriver; }
133 			void*			DriverData() const { return fDriverData; }
134 
135 			void			AddChild(device_node *node);
136 			void			RemoveChild(device_node *node);
137 			const NodeList&	Children() const { return fChildren; }
138 			void			DeviceRemoved();
139 
140 			status_t		Register(device_node* parent);
141 			status_t		Probe(const char* devicePath, uint32 updateCycle);
142 			status_t		Reprobe();
143 			status_t		Rescan();
144 
145 			bool			IsRegistered() const { return fRegistered; }
146 			bool			IsInitialized() const { return fInitialized > 0; }
147 			bool			IsProbed() const { return fLastUpdateCycle != 0; }
148 			uint32			Flags() const { return fFlags; }
149 
150 			void			Acquire();
151 			bool			Release();
152 
153 			const DeviceList& Devices() const { return fDevices; }
154 			void			AddDevice(Device* device);
155 			void			RemoveDevice(Device* device);
156 
157 			int				CompareTo(const device_attr* attributes) const;
158 			device_node*	FindChild(const device_attr* attributes) const;
159 			device_node*	FindChild(const char* moduleName) const;
160 
161 			int32			Priority();
162 
163 			void			Dump(int32 level = 0);
164 
165 private:
166 			status_t		_RegisterFixed(uint32& registered);
167 			bool			_AlwaysRegisterDynamic();
168 			status_t		_AddPath(Stack<KPath*>& stack, const char* path,
169 								const char* subPath = NULL);
170 			status_t		_GetNextDriverPath(void*& cookie, KPath& _path);
171 			status_t		_GetNextDriver(void* list,
172 								driver_module_info*& driver);
173 			status_t		_FindBestDriver(const char* path,
174 								driver_module_info*& bestDriver,
175 								float& bestSupport,
176 								device_node* previous = NULL);
177 			status_t		_RegisterPath(const char* path);
178 			status_t		_RegisterDynamic(device_node* previous = NULL);
179 			status_t		_RemoveChildren();
180 			device_node*	_FindCurrentChild();
181 			status_t		_Probe();
182 			void			_ReleaseWaiting();
183 
184 	device_node*			fParent;
185 	NodeList				fChildren;
186 	int32					fRefCount;
187 	int32					fInitialized;
188 	bool					fRegistered;
189 	uint32					fFlags;
190 	float					fSupportsParent;
191 	uint32					fLastUpdateCycle;
192 
193 	const char*				fModuleName;
194 
195 	driver_module_info*		fDriver;
196 	void*					fDriverData;
197 
198 	DeviceList				fDevices;
199 	AttributeList			fAttributes;
200 	ResourceList			fResources;
201 };
202 
203 // flags in addition to those specified by B_DEVICE_FLAGS
204 enum node_flags {
205 	NODE_FLAG_REGISTER_INITIALIZED	= 0x00010000,
206 	NODE_FLAG_DEVICE_REMOVED		= 0x00020000,
207 	NODE_FLAG_OBSOLETE_DRIVER		= 0x00040000,
208 	NODE_FLAG_WAITING_FOR_DRIVER	= 0x00080000,
209 
210 	NODE_FLAG_PUBLIC_MASK			= 0x0000ffff
211 };
212 
213 
214 static device_node *sRootNode;
215 static recursive_lock sLock;
216 static const char* sGenericContextPath;
217 
218 
219 //	#pragma mark -
220 
221 
222 static device_attr_private*
223 find_attr(const device_node* node, const char* name, bool recursive,
224 	type_code type)
225 {
226 	do {
227 		AttributeList::ConstIterator iterator
228 			= node->Attributes().GetIterator();
229 
230 		while (iterator.HasNext()) {
231 			device_attr_private* attr = iterator.Next();
232 
233 			if (type != B_ANY_TYPE && attr->type != type)
234 				continue;
235 
236 			if (!strcmp(attr->name, name))
237 				return attr;
238 		}
239 
240 		node = node->Parent();
241 	} while (node != NULL && recursive);
242 
243 	return NULL;
244 }
245 
246 
247 static void
248 put_level(int32 level)
249 {
250 	while (level-- > 0)
251 		kprintf("   ");
252 }
253 
254 
255 static void
256 dump_attribute(device_attr* attr, int32 level)
257 {
258 	if (attr == NULL)
259 		return;
260 
261 	put_level(level + 2);
262 	kprintf("\"%s\" : ", attr->name);
263 	switch (attr->type) {
264 		case B_STRING_TYPE:
265 			kprintf("string : \"%s\"", attr->value.string);
266 			break;
267 		case B_INT8_TYPE:
268 		case B_UINT8_TYPE:
269 			kprintf("uint8 : %" B_PRIu8 " (%#" B_PRIx8 ")", attr->value.ui8,
270 				attr->value.ui8);
271 			break;
272 		case B_INT16_TYPE:
273 		case B_UINT16_TYPE:
274 			kprintf("uint16 : %" B_PRIu16 " (%#" B_PRIx16 ")", attr->value.ui16,
275 				attr->value.ui16);
276 			break;
277 		case B_INT32_TYPE:
278 		case B_UINT32_TYPE:
279 			kprintf("uint32 : %" B_PRIu32 " (%#" B_PRIx32 ")", attr->value.ui32,
280 				attr->value.ui32);
281 			break;
282 		case B_INT64_TYPE:
283 		case B_UINT64_TYPE:
284 			kprintf("uint64 : %" B_PRIu64 " (%#" B_PRIx64 ")", attr->value.ui64,
285 				attr->value.ui64);
286 			break;
287 		default:
288 			kprintf("raw data");
289 	}
290 	kprintf("\n");
291 }
292 
293 
294 static int
295 dump_io_scheduler(int argc, char** argv)
296 {
297 	if (argc != 2) {
298 		print_debugger_command_usage(argv[0]);
299 		return 0;
300 	}
301 
302 	IOScheduler* scheduler = (IOScheduler*)parse_expression(argv[1]);
303 	scheduler->Dump();
304 	return 0;
305 }
306 
307 
308 static int
309 dump_io_request_owner(int argc, char** argv)
310 {
311 	if (argc != 2) {
312 		print_debugger_command_usage(argv[0]);
313 		return 0;
314 	}
315 
316 	IORequestOwner* owner = (IORequestOwner*)parse_expression(argv[1]);
317 	owner->Dump();
318 	return 0;
319 }
320 
321 
322 static int
323 dump_io_request(int argc, char** argv)
324 {
325 	if (argc != 2 || !strcmp(argv[1], "--help")) {
326 		kprintf("usage: %s <ptr-to-io-request>\n", argv[0]);
327 		return 0;
328 	}
329 
330 	IORequest* request = (IORequest*)parse_expression(argv[1]);
331 	request->Dump();
332 	return 0;
333 }
334 
335 
336 static int
337 dump_io_operation(int argc, char** argv)
338 {
339 	if (argc != 2 || !strcmp(argv[1], "--help")) {
340 		kprintf("usage: %s <ptr-to-io-operation>\n", argv[0]);
341 		return 0;
342 	}
343 
344 	IOOperation* operation = (IOOperation*)parse_expression(argv[1]);
345 	operation->Dump();
346 	return 0;
347 }
348 
349 
350 static int
351 dump_io_buffer(int argc, char** argv)
352 {
353 	if (argc != 2 || !strcmp(argv[1], "--help")) {
354 		kprintf("usage: %s <ptr-to-io-buffer>\n", argv[0]);
355 		return 0;
356 	}
357 
358 	IOBuffer* buffer = (IOBuffer*)parse_expression(argv[1]);
359 	buffer->Dump();
360 	return 0;
361 }
362 
363 
364 static int
365 dump_dma_buffer(int argc, char** argv)
366 {
367 	if (argc != 2 || !strcmp(argv[1], "--help")) {
368 		kprintf("usage: %s <ptr-to-dma-buffer>\n", argv[0]);
369 		return 0;
370 	}
371 
372 	DMABuffer* buffer = (DMABuffer*)parse_expression(argv[1]);
373 	buffer->Dump();
374 	return 0;
375 }
376 
377 
378 static int
379 dump_device_nodes(int argc, char** argv)
380 {
381 	sRootNode->Dump();
382 	return 0;
383 }
384 
385 
386 static void
387 publish_directories(const char* subPath)
388 {
389 	if (gBootDevice < 0) {
390 		if (subPath[0]) {
391 			// we only support the top-level directory for modules
392 			return;
393 		}
394 
395 		// we can only iterate over the known modules to find all directories
396 		KPath path("drivers");
397 		if (path.Append(subPath) != B_OK)
398 			return;
399 
400 		size_t length = strlen(path.Path()) + 1;
401 			// account for the separating '/'
402 
403 		void* list = open_module_list_etc(path.Path(), "driver_v1");
404 		char name[B_FILE_NAME_LENGTH];
405 		size_t nameLength = sizeof(name);
406 		while (read_next_module_name(list, name, &nameLength) == B_OK) {
407 			if (nameLength == length)
408 				continue;
409 
410 			char* leaf = name + length;
411 			char* end = strchr(leaf, '/');
412 			if (end != NULL)
413 				end[0] = '\0';
414 
415 			path.SetTo(subPath);
416 			path.Append(leaf);
417 
418 			devfs_publish_directory(path.Path());
419 		}
420 		close_module_list(list);
421 	} else {
422 		// TODO: implement module directory traversal!
423 	}
424 }
425 
426 
427 static status_t
428 control_device_manager(const char* subsystem, uint32 function, void* buffer,
429 	size_t bufferSize)
430 {
431 	// TODO: this function passes pointers to userland, and uses pointers
432 	// to device nodes that came from userland - this is completely unsafe
433 	// and should be changed.
434 	switch (function) {
435 		case DM_GET_ROOT:
436 		{
437 			device_node_cookie cookie;
438 			if (!IS_USER_ADDRESS(buffer))
439 				return B_BAD_ADDRESS;
440 			if (bufferSize != sizeof(device_node_cookie))
441 				return B_BAD_VALUE;
442 			cookie = (device_node_cookie)sRootNode;
443 
444 			// copy back to user space
445 			return user_memcpy(buffer, &cookie, sizeof(device_node_cookie));
446 		}
447 
448 		case DM_GET_CHILD:
449 		{
450 			if (!IS_USER_ADDRESS(buffer))
451 				return B_BAD_ADDRESS;
452 			if (bufferSize != sizeof(device_node_cookie))
453 				return B_BAD_VALUE;
454 
455 			device_node_cookie cookie;
456 			if (user_memcpy(&cookie, buffer, sizeof(device_node_cookie)) < B_OK)
457 				return B_BAD_ADDRESS;
458 
459 			device_node* node = (device_node*)cookie;
460 			NodeList::ConstIterator iterator = node->Children().GetIterator();
461 
462 			if (!iterator.HasNext()) {
463 				return B_ENTRY_NOT_FOUND;
464 			}
465 			node = iterator.Next();
466 			cookie = (device_node_cookie)node;
467 
468 			// copy back to user space
469 			return user_memcpy(buffer, &cookie, sizeof(device_node_cookie));
470 		}
471 
472 		case DM_GET_NEXT_CHILD:
473 		{
474 			if (!IS_USER_ADDRESS(buffer))
475 				return B_BAD_ADDRESS;
476 			if (bufferSize != sizeof(device_node_cookie))
477 				return B_BAD_VALUE;
478 
479 			device_node_cookie cookie;
480 			if (user_memcpy(&cookie, buffer, sizeof(device_node_cookie)) < B_OK)
481 				return B_BAD_ADDRESS;
482 
483 			device_node* last = (device_node*)cookie;
484 			if (!last->Parent())
485 				return B_ENTRY_NOT_FOUND;
486 
487 			NodeList::ConstIterator iterator
488 				= last->Parent()->Children().GetIterator();
489 
490 			// skip those we already traversed
491 			while (iterator.HasNext()) {
492 				device_node* node = iterator.Next();
493 
494 				if (node == last)
495 					break;
496 			}
497 
498 			if (!iterator.HasNext())
499 				return B_ENTRY_NOT_FOUND;
500 			device_node* node = iterator.Next();
501 			cookie = (device_node_cookie)node;
502 
503 			// copy back to user space
504 			return user_memcpy(buffer, &cookie, sizeof(device_node_cookie));
505 		}
506 
507 		case DM_GET_NEXT_ATTRIBUTE:
508 		{
509 			struct device_attr_info attrInfo;
510 			if (!IS_USER_ADDRESS(buffer))
511 				return B_BAD_ADDRESS;
512 			if (bufferSize != sizeof(device_attr_info))
513 				return B_BAD_VALUE;
514 			if (user_memcpy(&attrInfo, buffer, sizeof(device_attr_info)) < B_OK)
515 				return B_BAD_ADDRESS;
516 
517 			device_node* node = (device_node*)attrInfo.node_cookie;
518 			device_attr* last = (device_attr*)attrInfo.cookie;
519 			AttributeList::Iterator iterator = node->Attributes().GetIterator();
520 			// skip those we already traversed
521 			while (iterator.HasNext() && last != NULL) {
522 				device_attr* attr = iterator.Next();
523 
524 				if (attr == last)
525 					break;
526 			}
527 
528 			if (!iterator.HasNext()) {
529 				attrInfo.cookie = 0;
530 				return B_ENTRY_NOT_FOUND;
531 			}
532 
533 			device_attr* attr = iterator.Next();
534 			attrInfo.cookie = (device_node_cookie)attr;
535 			if (attr->name != NULL)
536 				strlcpy(attrInfo.name, attr->name, 254);
537 			else
538 				attrInfo.name[0] = '\0';
539 			attrInfo.type = attr->type;
540 			switch (attrInfo.type) {
541 				case B_UINT8_TYPE:
542 					attrInfo.value.ui8 = attr->value.ui8;
543 					break;
544 				case B_UINT16_TYPE:
545 					attrInfo.value.ui16 = attr->value.ui16;
546 					break;
547 				case B_UINT32_TYPE:
548 					attrInfo.value.ui32 = attr->value.ui32;
549 					break;
550 				case B_UINT64_TYPE:
551 					attrInfo.value.ui64 = attr->value.ui64;
552 					break;
553 				case B_STRING_TYPE:
554 					if (attr->value.string != NULL)
555 						strlcpy(attrInfo.value.string, attr->value.string, 254);
556 					else
557 						attrInfo.value.string[0] = '\0';
558 					break;
559 				/*case B_RAW_TYPE:
560 					if (attr.value.raw.length > attr_info->attr.value.raw.length)
561 						attr.value.raw.length = attr_info->attr.value.raw.length;
562 					user_memcpy(attr.value.raw.data, attr_info->attr.value.raw.data,
563 						attr.value.raw.length);
564 					break;*/
565 			}
566 
567 			// copy back to user space
568 			return user_memcpy(buffer, &attrInfo, sizeof(device_attr_info));
569 		}
570 	}
571 
572 	return B_BAD_HANDLER;
573 }
574 
575 
576 //	#pragma mark - Device Manager module API
577 
578 
579 static status_t
580 rescan_node(device_node* node)
581 {
582 	RecursiveLocker _(sLock);
583 	return node->Rescan();
584 }
585 
586 
587 static status_t
588 register_node(device_node* parent, const char* moduleName,
589 	const device_attr* attrs, const io_resource* ioResources,
590 	device_node** _node)
591 {
592 	if ((parent == NULL && sRootNode != NULL) || moduleName == NULL)
593 		return B_BAD_VALUE;
594 
595 	if (parent != NULL && parent->FindChild(attrs) != NULL) {
596 		// A node like this one already exists for this parent
597 		return B_NAME_IN_USE;
598 	}
599 
600 	RecursiveLocker _(sLock);
601 
602 	device_node* newNode = new(std::nothrow) device_node(moduleName, attrs);
603 	if (newNode == NULL)
604 		return B_NO_MEMORY;
605 
606 	TRACE(("%p: register node \"%s\", parent %p\n", newNode, moduleName,
607 		parent));
608 
609 	status_t status = newNode->InitCheck();
610 	if (status == B_OK)
611 		status = newNode->AcquireResources(ioResources);
612 	if (status == B_OK)
613 		status = newNode->Register(parent);
614 
615 	if (status != B_OK) {
616 		newNode->Release();
617 		return status;
618 	}
619 
620 	if (_node)
621 		*_node = newNode;
622 
623 	return B_OK;
624 }
625 
626 
627 /*!	Unregisters the device \a node.
628 
629 	If the node is currently in use, this function will return B_BUSY to
630 	indicate that the node hasn't been removed yet - it will still remove
631 	the node as soon as possible.
632 */
633 static status_t
634 unregister_node(device_node* node)
635 {
636 	TRACE(("unregister_node(node %p)\n", node));
637 	RecursiveLocker _(sLock);
638 
639 	bool initialized = node->IsInitialized();
640 
641 	node->DeviceRemoved();
642 
643 	return initialized ? B_BUSY : B_OK;
644 }
645 
646 
647 static status_t
648 get_driver(device_node* node, driver_module_info** _module, void** _data)
649 {
650 	if (node->DriverModule() == NULL)
651 		return B_NO_INIT;
652 
653 	if (_module != NULL)
654 		*_module = node->DriverModule();
655 	if (_data != NULL)
656 		*_data = node->DriverData();
657 
658 	return B_OK;
659 }
660 
661 
662 static device_node*
663 get_root_node(void)
664 {
665 	if (sRootNode != NULL)
666 		sRootNode->Acquire();
667 
668 	return sRootNode;
669 }
670 
671 
672 static status_t
673 get_next_child_node(device_node* parent, const device_attr* attributes,
674 	device_node** _node)
675 {
676 	RecursiveLocker _(sLock);
677 
678 	NodeList::ConstIterator iterator = parent->Children().GetIterator();
679 	device_node* last = *_node;
680 
681 	// skip those we already traversed
682 	while (iterator.HasNext() && last != NULL) {
683 		device_node* node = iterator.Next();
684 
685 		if (node != last)
686 			continue;
687 	}
688 
689 	// find the next one that fits
690 	while (iterator.HasNext()) {
691 		device_node* node = iterator.Next();
692 
693 		if (!node->IsRegistered())
694 			continue;
695 
696 		if (!node->CompareTo(attributes)) {
697 			if (last != NULL)
698 				last->Release();
699 
700 			node->Acquire();
701 			*_node = node;
702 			return B_OK;
703 		}
704 	}
705 
706 	if (last != NULL)
707 		last->Release();
708 
709 	return B_ENTRY_NOT_FOUND;
710 }
711 
712 
713 static device_node*
714 get_parent_node(device_node* node)
715 {
716 	if (node == NULL)
717 		return NULL;
718 
719 	RecursiveLocker _(sLock);
720 
721 	device_node* parent = node->Parent();
722 	parent->Acquire();
723 
724 	return parent;
725 }
726 
727 
728 static void
729 put_node(device_node* node)
730 {
731 	RecursiveLocker _(sLock);
732 	node->Release();
733 }
734 
735 
736 static status_t
737 publish_device(device_node *node, const char *path, const char *moduleName)
738 {
739 	if (path == NULL || !path[0] || moduleName == NULL || !moduleName[0])
740 		return B_BAD_VALUE;
741 
742 	RecursiveLocker _(sLock);
743 	dprintf("publish device: node %p, path %s, module %s\n", node, path,
744 		moduleName);
745 
746 	Device* device = new(std::nothrow) Device(node, moduleName);
747 	if (device == NULL)
748 		return B_NO_MEMORY;
749 
750 	status_t status = device->InitCheck();
751 	if (status == B_OK)
752 		status = devfs_publish_device(path, device);
753 	if (status != B_OK) {
754 		delete device;
755 		return status;
756 	}
757 
758 	node->AddDevice(device);
759 
760 	device_attr_private* attr;
761 
762 	attr = new(std::nothrow) device_attr_private();
763 	if (attr != NULL) {
764 		char buf[256];
765 		sprintf(buf, "dev/%" B_PRIdINO "/path", device->ID());
766 		attr->name = strdup(buf);
767 		attr->type = B_STRING_TYPE;
768 		attr->value.string = strdup(path);
769 		node->Attributes().Add(attr);
770 	}
771 
772 	attr = new(std::nothrow) device_attr_private();
773 	if (attr != NULL) {
774 		char buf[256];
775 		sprintf(buf, "dev/%" B_PRIdINO "/driver", device->ID());
776 		attr->name = strdup(buf);
777 		attr->type = B_STRING_TYPE;
778 		attr->value.string = strdup(moduleName);
779 		node->Attributes().Add(attr);
780 	}
781 
782 	return B_OK;
783 }
784 
785 
786 static status_t
787 unpublish_device(device_node *node, const char *path)
788 {
789 	if (path == NULL)
790 		return B_BAD_VALUE;
791 
792 	BaseDevice* baseDevice;
793 	status_t error = devfs_get_device(path, baseDevice);
794 	if (error != B_OK)
795 		return error;
796 	CObjectDeleter<BaseDevice, void, devfs_put_device>
797 		baseDevicePutter(baseDevice);
798 
799 	Device* device = dynamic_cast<Device*>(baseDevice);
800 	if (device == NULL || device->Node() != node)
801 		return B_BAD_VALUE;
802 
803 	return devfs_unpublish_device(device, true);
804 }
805 
806 
807 static status_t
808 get_attr_uint8(const device_node* node, const char* name, uint8* _value,
809 	bool recursive)
810 {
811 	if (node == NULL || name == NULL || _value == NULL)
812 		return B_BAD_VALUE;
813 
814 	device_attr_private* attr = find_attr(node, name, recursive, B_UINT8_TYPE);
815 	if (attr == NULL)
816 		return B_NAME_NOT_FOUND;
817 
818 	*_value = attr->value.ui8;
819 	return B_OK;
820 }
821 
822 
823 static status_t
824 get_attr_uint16(const device_node* node, const char* name, uint16* _value,
825 	bool recursive)
826 {
827 	if (node == NULL || name == NULL || _value == NULL)
828 		return B_BAD_VALUE;
829 
830 	device_attr_private* attr = find_attr(node, name, recursive, B_UINT16_TYPE);
831 	if (attr == NULL)
832 		return B_NAME_NOT_FOUND;
833 
834 	*_value = attr->value.ui16;
835 	return B_OK;
836 }
837 
838 
839 static status_t
840 get_attr_uint32(const device_node* node, const char* name, uint32* _value,
841 	bool recursive)
842 {
843 	if (node == NULL || name == NULL || _value == NULL)
844 		return B_BAD_VALUE;
845 
846 	device_attr_private* attr = find_attr(node, name, recursive, B_UINT32_TYPE);
847 	if (attr == NULL)
848 		return B_NAME_NOT_FOUND;
849 
850 	*_value = attr->value.ui32;
851 	return B_OK;
852 }
853 
854 
855 static status_t
856 get_attr_uint64(const device_node* node, const char* name,
857 	uint64* _value, bool recursive)
858 {
859 	if (node == NULL || name == NULL || _value == NULL)
860 		return B_BAD_VALUE;
861 
862 	device_attr_private* attr = find_attr(node, name, recursive, B_UINT64_TYPE);
863 	if (attr == NULL)
864 		return B_NAME_NOT_FOUND;
865 
866 	*_value = attr->value.ui64;
867 	return B_OK;
868 }
869 
870 
871 static status_t
872 get_attr_string(const device_node* node, const char* name,
873 	const char** _value, bool recursive)
874 {
875 	if (node == NULL || name == NULL || _value == NULL)
876 		return B_BAD_VALUE;
877 
878 	device_attr_private* attr = find_attr(node, name, recursive, B_STRING_TYPE);
879 	if (attr == NULL)
880 		return B_NAME_NOT_FOUND;
881 
882 	*_value = attr->value.string;
883 	return B_OK;
884 }
885 
886 
887 static status_t
888 get_attr_raw(const device_node* node, const char* name, const void** _data,
889 	size_t* _length, bool recursive)
890 {
891 	if (node == NULL || name == NULL || (_data == NULL && _length == NULL))
892 		return B_BAD_VALUE;
893 
894 	device_attr_private* attr = find_attr(node, name, recursive, B_RAW_TYPE);
895 	if (attr == NULL)
896 		return B_NAME_NOT_FOUND;
897 
898 	if (_data != NULL)
899 		*_data = attr->value.raw.data;
900 	if (_length != NULL)
901 		*_length = attr->value.raw.length;
902 	return B_OK;
903 }
904 
905 
906 static status_t
907 get_next_attr(device_node* node, device_attr** _attr)
908 {
909 	if (node == NULL)
910 		return B_BAD_VALUE;
911 
912 	device_attr_private* next;
913 	device_attr_private* attr = *(device_attr_private**)_attr;
914 
915 	if (attr != NULL) {
916 		// next attribute
917 		next = attr->GetDoublyLinkedListLink()->next;
918 	} else {
919 		// first attribute
920 		next = node->Attributes().First();
921 	}
922 
923 	*_attr = next;
924 
925 	return next ? B_OK : B_ENTRY_NOT_FOUND;
926 }
927 
928 
929 static status_t
930 find_child_node(device_node* parent, const device_attr* attributes,
931 	device_node** _node, bool *_lastFound)
932 {
933 	RecursiveLocker _(sLock);
934 
935 	NodeList::ConstIterator iterator = parent->Children().GetIterator();
936 	device_node* last = *_node;
937 
938 	// find the next one that fits
939 	while (iterator.HasNext()) {
940 		device_node* node = iterator.Next();
941 
942 		if (!node->IsRegistered())
943 			continue;
944 
945 		if (node == last)
946 			*_lastFound = true;
947 		else if (!node->CompareTo(attributes) && *_lastFound) {
948 			if (last != NULL)
949 				last->Release();
950 
951 			node->Acquire();
952 			*_node = node;
953 			return B_OK;
954 		}
955 		if (find_child_node(node, attributes, _node, _lastFound) == B_OK)
956 			return B_OK;
957 	}
958 
959 	return B_ENTRY_NOT_FOUND;
960 }
961 
962 
963 static status_t
964 find_child_node(device_node* parent, const device_attr* attributes,
965 	device_node** _node)
966 {
967 	device_node* last = *_node;
968 	bool lastFound = last == NULL;
969 	status_t status = find_child_node(parent, attributes, _node, &lastFound);
970 	if (status == B_ENTRY_NOT_FOUND && last != NULL && lastFound)
971 		last->Release();
972 	return status;
973 }
974 
975 
976 struct device_manager_info gDeviceManagerModule = {
977 	{
978 		B_DEVICE_MANAGER_MODULE_NAME,
979 		0,
980 		NULL
981 	},
982 
983 	// device nodes
984 	rescan_node,
985 	register_node,
986 	unregister_node,
987 	get_driver,
988 	get_root_node,
989 	get_next_child_node,
990 	get_parent_node,
991 	put_node,
992 
993 	// devices
994 	publish_device,
995 	unpublish_device,
996 
997 	// I/O resources
998 
999 	// ID generator
1000 	dm_create_id,
1001 	dm_free_id,
1002 
1003 	// attributes
1004 	get_attr_uint8,
1005 	get_attr_uint16,
1006 	get_attr_uint32,
1007 	get_attr_uint64,
1008 	get_attr_string,
1009 	get_attr_raw,
1010 	get_next_attr,
1011 	find_child_node
1012 };
1013 
1014 
1015 //	#pragma mark - device_attr
1016 
1017 
1018 device_attr_private::device_attr_private()
1019 {
1020 	name = NULL;
1021 	type = 0;
1022 	value.raw.data = NULL;
1023 	value.raw.length = 0;
1024 }
1025 
1026 
1027 device_attr_private::device_attr_private(const device_attr& attr)
1028 {
1029 	CopyFrom(attr);
1030 }
1031 
1032 
1033 device_attr_private::~device_attr_private()
1034 {
1035 	_Unset();
1036 }
1037 
1038 
1039 status_t
1040 device_attr_private::InitCheck()
1041 {
1042 	return name != NULL ? B_OK : B_NO_INIT;
1043 }
1044 
1045 
1046 status_t
1047 device_attr_private::CopyFrom(const device_attr& attr)
1048 {
1049 	name = strdup(attr.name);
1050 	if (name == NULL)
1051 		return B_NO_MEMORY;
1052 
1053 	type = attr.type;
1054 
1055 	switch (type) {
1056 		case B_UINT8_TYPE:
1057 		case B_UINT16_TYPE:
1058 		case B_UINT32_TYPE:
1059 		case B_UINT64_TYPE:
1060 			value.ui64 = attr.value.ui64;
1061 			break;
1062 
1063 		case B_STRING_TYPE:
1064 			if (attr.value.string != NULL) {
1065 				value.string = strdup(attr.value.string);
1066 				if (value.string == NULL) {
1067 					_Unset();
1068 					return B_NO_MEMORY;
1069 				}
1070 			} else
1071 				value.string = NULL;
1072 			break;
1073 
1074 		case B_RAW_TYPE:
1075 			value.raw.data = malloc(attr.value.raw.length);
1076 			if (value.raw.data == NULL) {
1077 				_Unset();
1078 				return B_NO_MEMORY;
1079 			}
1080 
1081 			value.raw.length = attr.value.raw.length;
1082 			memcpy((void*)value.raw.data, attr.value.raw.data,
1083 				attr.value.raw.length);
1084 			break;
1085 
1086 		default:
1087 			return B_BAD_VALUE;
1088 	}
1089 
1090 	return B_OK;
1091 }
1092 
1093 
1094 void
1095 device_attr_private::_Unset()
1096 {
1097 	if (type == B_STRING_TYPE)
1098 		free((char*)value.string);
1099 	else if (type == B_RAW_TYPE)
1100 		free((void*)value.raw.data);
1101 
1102 	free((char*)name);
1103 
1104 	name = NULL;
1105 	value.raw.data = NULL;
1106 	value.raw.length = 0;
1107 }
1108 
1109 
1110 /*static*/ int
1111 device_attr_private::Compare(const device_attr* attrA, const device_attr *attrB)
1112 {
1113 	if (attrA->type != attrB->type)
1114 		return -1;
1115 
1116 	switch (attrA->type) {
1117 		case B_UINT8_TYPE:
1118 			return (int)attrA->value.ui8 - (int)attrB->value.ui8;
1119 
1120 		case B_UINT16_TYPE:
1121 			return (int)attrA->value.ui16 - (int)attrB->value.ui16;
1122 
1123 		case B_UINT32_TYPE:
1124 			if (attrA->value.ui32 > attrB->value.ui32)
1125 				return 1;
1126 			if (attrA->value.ui32 < attrB->value.ui32)
1127 				return -1;
1128 			return 0;
1129 
1130 		case B_UINT64_TYPE:
1131 			if (attrA->value.ui64 > attrB->value.ui64)
1132 				return 1;
1133 			if (attrA->value.ui64 < attrB->value.ui64)
1134 				return -1;
1135 			return 0;
1136 
1137 		case B_STRING_TYPE:
1138 			return strcmp(attrA->value.string, attrB->value.string);
1139 
1140 		case B_RAW_TYPE:
1141 			if (attrA->value.raw.length != attrB->value.raw.length)
1142 				return -1;
1143 
1144 			return memcmp(attrA->value.raw.data, attrB->value.raw.data,
1145 				attrA->value.raw.length);
1146 	}
1147 
1148 	return -1;
1149 }
1150 
1151 
1152 //	#pragma mark - Device
1153 
1154 
1155 Device::Device(device_node* node, const char* moduleName)
1156 	:
1157 	fModuleName(strdup(moduleName)),
1158 	fRemovedFromParent(false)
1159 {
1160 	fNode = node;
1161 }
1162 
1163 
1164 Device::~Device()
1165 {
1166 	free((char*)fModuleName);
1167 }
1168 
1169 
1170 status_t
1171 Device::InitCheck() const
1172 {
1173 	return fModuleName != NULL ? B_OK : B_NO_MEMORY;
1174 }
1175 
1176 
1177 status_t
1178 Device::InitDevice()
1179 {
1180 	RecursiveLocker _(sLock);
1181 
1182 	if ((fNode->Flags() & NODE_FLAG_DEVICE_REMOVED) != 0) {
1183 		// TODO: maybe the device should be unlinked in devfs, too
1184 		return ENODEV;
1185 	}
1186 	if ((fNode->Flags() & NODE_FLAG_WAITING_FOR_DRIVER) != 0)
1187 		return B_BUSY;
1188 
1189 	if (fInitialized++ > 0) {
1190 		fNode->InitDriver();
1191 			// acquire another reference to our parent as well
1192 		return B_OK;
1193 	}
1194 
1195 	status_t status = get_module(ModuleName(), (module_info**)&fDeviceModule);
1196 	if (status == B_OK) {
1197 		// our parent always has to be initialized
1198 		status = fNode->InitDriver();
1199 	}
1200 	if (status < B_OK) {
1201 		fInitialized--;
1202 		return status;
1203 	}
1204 
1205 	if (Module()->init_device != NULL)
1206 		status = Module()->init_device(fNode->DriverData(), &fDeviceData);
1207 
1208 	if (status < B_OK) {
1209 		fNode->UninitDriver();
1210 		fInitialized--;
1211 
1212 		put_module(ModuleName());
1213 		fDeviceModule = NULL;
1214 		fDeviceData = NULL;
1215 	}
1216 
1217 	return status;
1218 }
1219 
1220 
1221 void
1222 Device::UninitDevice()
1223 {
1224 	RecursiveLocker _(sLock);
1225 
1226 	if (fInitialized-- > 1) {
1227 		fNode->UninitDriver();
1228 		return;
1229 	}
1230 
1231 	TRACE(("uninit driver for node %p\n", this));
1232 
1233 	if (Module()->uninit_device != NULL)
1234 		Module()->uninit_device(fDeviceData);
1235 
1236 	fDeviceModule = NULL;
1237 	fDeviceData = NULL;
1238 
1239 	put_module(ModuleName());
1240 
1241 	fNode->UninitDriver();
1242 }
1243 
1244 
1245 void
1246 Device::Removed()
1247 {
1248 	RecursiveLocker _(sLock);
1249 
1250 	if (!fRemovedFromParent)
1251 		fNode->RemoveDevice(this);
1252 
1253 	delete this;
1254 }
1255 
1256 
1257 status_t
1258 Device::Control(void* _cookie, int32 op, void* buffer, size_t length)
1259 {
1260 	switch (op) {
1261 		case B_GET_DRIVER_FOR_DEVICE:
1262 		{
1263 			char* path = NULL;
1264 			status_t status = module_get_path(ModuleName(), &path);
1265 			if (status != B_OK)
1266 				return status;
1267 			if (length != 0 && length <= strlen(path))
1268 				return ERANGE;
1269 			status = user_strlcpy(static_cast<char*>(buffer), path, length);
1270 			free(path);
1271 			return status;
1272 		}
1273 		default:
1274 			return AbstractModuleDevice::Control(_cookie, op, buffer, length);;
1275 	}
1276 }
1277 
1278 
1279 //	#pragma mark - device_node
1280 
1281 
1282 device_node::device_node(const char* moduleName, const device_attr* attrs)
1283 {
1284 	fModuleName = strdup(moduleName);
1285 	if (fModuleName == NULL)
1286 		return;
1287 
1288 	fParent = NULL;
1289 	fRefCount = 1;
1290 	fInitialized = 0;
1291 	fRegistered = false;
1292 	fFlags = 0;
1293 	fSupportsParent = 0.0;
1294 	fLastUpdateCycle = 0;
1295 	fDriver = NULL;
1296 	fDriverData = NULL;
1297 
1298 	// copy attributes
1299 
1300 	while (attrs != NULL && attrs->name != NULL) {
1301 		device_attr_private* attr
1302 			= new(std::nothrow) device_attr_private(*attrs);
1303 		if (attr == NULL)
1304 			break;
1305 
1306 		fAttributes.Add(attr);
1307 		attrs++;
1308 	}
1309 
1310 	device_attr_private* attr = new(std::nothrow) device_attr_private();
1311 	if (attr != NULL) {
1312 		attr->name = strdup("device/driver");
1313 		attr->type = B_STRING_TYPE;
1314 		attr->value.string = strdup(fModuleName);
1315 		fAttributes.Add(attr);
1316 	}
1317 
1318 	get_attr_uint32(this, B_DEVICE_FLAGS, &fFlags, false);
1319 	fFlags &= NODE_FLAG_PUBLIC_MASK;
1320 }
1321 
1322 
1323 device_node::~device_node()
1324 {
1325 	TRACE(("delete node %p\n", this));
1326 	ASSERT(DriverModule() == NULL);
1327 
1328 	if (Parent() != NULL) {
1329 		if ((fFlags & NODE_FLAG_OBSOLETE_DRIVER) != 0) {
1330 			// This driver has been obsoleted; another driver has been waiting
1331 			// for us - make it available
1332 			Parent()->_ReleaseWaiting();
1333 		}
1334 		Parent()->RemoveChild(this);
1335 	}
1336 
1337 	// Delete children
1338 	while (device_node* child = fChildren.RemoveHead()) {
1339 		delete child;
1340 	}
1341 
1342 	// Delete devices
1343 	while (Device* device = fDevices.RemoveHead()) {
1344 		device->SetRemovedFromParent(true);
1345 		devfs_unpublish_device(device, true);
1346 	}
1347 
1348 	// Delete attributes
1349 	while (device_attr_private* attr = fAttributes.RemoveHead()) {
1350 		delete attr;
1351 	}
1352 
1353 	// Delete resources
1354 	while (io_resource_private* resource = fResources.RemoveHead()) {
1355 		delete resource;
1356 	}
1357 
1358 	free((char*)fModuleName);
1359 }
1360 
1361 
1362 status_t
1363 device_node::InitCheck() const
1364 {
1365 	return fModuleName != NULL ? B_OK : B_NO_MEMORY;
1366 }
1367 
1368 
1369 status_t
1370 device_node::AcquireResources(const io_resource* resources)
1371 {
1372 	if (resources == NULL)
1373 		return B_OK;
1374 
1375 	for (uint32 i = 0; resources[i].type != 0; i++) {
1376 		io_resource_private* resource = new(std::nothrow) io_resource_private;
1377 		if (resource == NULL)
1378 			return B_NO_MEMORY;
1379 
1380 		status_t status = resource->Acquire(resources[i]);
1381 		if (status != B_OK) {
1382 			delete resource;
1383 			return status;
1384 		}
1385 
1386 		fResources.Add(resource);
1387 	}
1388 
1389 	return B_OK;
1390 }
1391 
1392 
1393 status_t
1394 device_node::InitDriver()
1395 {
1396 	if (fInitialized++ > 0) {
1397 		if (Parent() != NULL) {
1398 			Parent()->InitDriver();
1399 				// acquire another reference to our parent as well
1400 		}
1401 		Acquire();
1402 		return B_OK;
1403 	}
1404 
1405 	status_t status = get_module(ModuleName(), (module_info**)&fDriver);
1406 	if (status == B_OK && Parent() != NULL) {
1407 		// our parent always has to be initialized
1408 		status = Parent()->InitDriver();
1409 	}
1410 	if (status < B_OK) {
1411 		fInitialized--;
1412 		return status;
1413 	}
1414 
1415 	if (fDriver->init_driver != NULL) {
1416 		status = fDriver->init_driver(this, &fDriverData);
1417 		if (status != B_OK) {
1418 			dprintf("driver %s init failed: %s\n", ModuleName(),
1419 				strerror(status));
1420 		}
1421 	}
1422 
1423 	if (status < B_OK) {
1424 		if (Parent() != NULL)
1425 			Parent()->UninitDriver();
1426 		fInitialized--;
1427 
1428 		put_module(ModuleName());
1429 		fDriver = NULL;
1430 		fDriverData = NULL;
1431 		return status;
1432 	}
1433 
1434 	Acquire();
1435 	return B_OK;
1436 }
1437 
1438 
1439 bool
1440 device_node::UninitDriver()
1441 {
1442 	if (fInitialized-- > 1) {
1443 		if (Parent() != NULL)
1444 			Parent()->UninitDriver();
1445 		Release();
1446 		return false;
1447 	}
1448 
1449 	TRACE(("uninit driver for node %p\n", this));
1450 
1451 	if (fDriver->uninit_driver != NULL)
1452 		fDriver->uninit_driver(fDriverData);
1453 
1454 	fDriver = NULL;
1455 	fDriverData = NULL;
1456 
1457 	put_module(ModuleName());
1458 
1459 	if (Parent() != NULL)
1460 		Parent()->UninitDriver();
1461 	Release();
1462 
1463 	return true;
1464 }
1465 
1466 
1467 void
1468 device_node::AddChild(device_node* node)
1469 {
1470 	// we must not be destroyed	as long as we have children
1471 	Acquire();
1472 	node->fParent = this;
1473 
1474 	int32 priority = node->Priority();
1475 
1476 	// Enforce an order in which the children are traversed - from most
1477 	// specific to least specific child.
1478 	NodeList::Iterator iterator = fChildren.GetIterator();
1479 	device_node* before = NULL;
1480 	while (iterator.HasNext()) {
1481 		device_node* child = iterator.Next();
1482 		if (child->Priority() < priority) {
1483 			before = child;
1484 			break;
1485 		}
1486 	}
1487 
1488 	fChildren.Insert(before, node);
1489 }
1490 
1491 
1492 void
1493 device_node::RemoveChild(device_node* node)
1494 {
1495 	node->fParent = NULL;
1496 	fChildren.Remove(node);
1497 	Release();
1498 }
1499 
1500 
1501 /*!	Registers this node, and all of its children that have to be registered.
1502 	Also initializes the driver and keeps it that way on return in case
1503 	it returns successfully.
1504 */
1505 status_t
1506 device_node::Register(device_node* parent)
1507 {
1508 	// make it public
1509 	if (parent != NULL)
1510 		parent->AddChild(this);
1511 	else
1512 		sRootNode = this;
1513 
1514 	status_t status = InitDriver();
1515 	if (status != B_OK)
1516 		return status;
1517 
1518 	if ((fFlags & B_KEEP_DRIVER_LOADED) != 0) {
1519 		// We keep this driver loaded by having it always initialized
1520 		InitDriver();
1521 	}
1522 
1523 	fFlags |= NODE_FLAG_REGISTER_INITIALIZED;
1524 		// We don't uninitialize the driver - this is done by the caller
1525 		// in order to save reinitializing during driver loading.
1526 
1527 	uint32 registeredFixedCount;
1528 	status = _RegisterFixed(registeredFixedCount);
1529 	if (status != B_OK) {
1530 		UninitUnusedDriver();
1531 		return status;
1532 	}
1533 
1534 	// Register the children the driver wants
1535 
1536 	if (DriverModule()->register_child_devices != NULL) {
1537 		status = DriverModule()->register_child_devices(DriverData());
1538 		if (status != B_OK) {
1539 			UninitUnusedDriver();
1540 			return status;
1541 		}
1542 
1543 		if (!fChildren.IsEmpty()) {
1544 			fRegistered = true;
1545 			return B_OK;
1546 		}
1547 	}
1548 
1549 	if (registeredFixedCount > 0) {
1550 		// Nodes with fixed children cannot have any dynamic children, so bail
1551 		// out here
1552 		fRegistered = true;
1553 		return B_OK;
1554 	}
1555 
1556 	// Register all possible child device nodes
1557 
1558 	status = _RegisterDynamic();
1559 	if (status == B_OK)
1560 		fRegistered = true;
1561 	else
1562 		UninitUnusedDriver();
1563 
1564 	return status;
1565 }
1566 
1567 
1568 /*!	Registers any children that are identified via the B_DEVICE_FIXED_CHILD
1569 	attribute.
1570 	If any of these children cannot be registered, this call will fail (we
1571 	don't remove children we already registered up to this point in this case).
1572 */
1573 status_t
1574 device_node::_RegisterFixed(uint32& registered)
1575 {
1576 	AttributeList::Iterator iterator = fAttributes.GetIterator();
1577 	registered = 0;
1578 
1579 	while (iterator.HasNext()) {
1580 		device_attr_private* attr = iterator.Next();
1581 		if (strcmp(attr->name, B_DEVICE_FIXED_CHILD))
1582 			continue;
1583 
1584 		driver_module_info* driver;
1585 		status_t status = get_module(attr->value.string,
1586 			(module_info**)&driver);
1587 		if (status != B_OK) {
1588 			TRACE(("register fixed child %s failed: %s\n", attr->value.string,
1589 				strerror(status)));
1590 			return status;
1591 		}
1592 
1593 		if (driver->register_device != NULL) {
1594 			status = driver->register_device(this);
1595 			if (status == B_OK)
1596 				registered++;
1597 		}
1598 
1599 		put_module(attr->value.string);
1600 
1601 		if (status != B_OK)
1602 			return status;
1603 	}
1604 
1605 	return B_OK;
1606 }
1607 
1608 
1609 status_t
1610 device_node::_AddPath(Stack<KPath*>& stack, const char* basePath,
1611 	const char* subPath)
1612 {
1613 	KPath* path = new(std::nothrow) KPath;
1614 	if (path == NULL)
1615 		return B_NO_MEMORY;
1616 
1617 	status_t status = path->SetTo(basePath);
1618 	if (status == B_OK && subPath != NULL && subPath[0])
1619 		status = path->Append(subPath);
1620 	if (status == B_OK)
1621 		status = stack.Push(path);
1622 
1623 	TRACE(("  add path: \"%s\", %" B_PRId32 "\n", path->Path(), status));
1624 
1625 	if (status != B_OK)
1626 		delete path;
1627 
1628 	return status;
1629 }
1630 
1631 
1632 status_t
1633 device_node::_GetNextDriverPath(void*& cookie, KPath& _path)
1634 {
1635 	Stack<KPath*>* stack = NULL;
1636 
1637 	if (cookie == NULL) {
1638 		// find all paths and add them
1639 		stack = new(std::nothrow) Stack<KPath*>();
1640 		if (stack == NULL)
1641 			return B_NO_MEMORY;
1642 
1643 		StackDeleter<KPath*> stackDeleter(stack);
1644 
1645 		bool generic = false;
1646 		uint16 type = 0;
1647 		uint16 subType = 0;
1648 		uint16 interface = 0;
1649 		if (get_attr_uint16(this, B_DEVICE_TYPE, &type, false) != B_OK
1650 			|| get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false)
1651 					!= B_OK)
1652 			generic = true;
1653 
1654 		get_attr_uint16(this, B_DEVICE_INTERFACE, &interface, false);
1655 
1656 		// TODO: maybe make this extendible via settings file?
1657 		switch (type) {
1658 			case PCI_mass_storage:
1659 				switch (subType) {
1660 					case PCI_scsi:
1661 						_AddPath(*stack, "busses", "scsi");
1662 						_AddPath(*stack, "busses", "virtio");
1663 						break;
1664 					case PCI_ide:
1665 						_AddPath(*stack, "busses", "ata");
1666 						_AddPath(*stack, "busses", "ide");
1667 						break;
1668 					case PCI_sata:
1669 						// TODO: check for ahci interface
1670 						_AddPath(*stack, "busses", "scsi");
1671 						_AddPath(*stack, "busses", "ata");
1672 						_AddPath(*stack, "busses", "ide");
1673 						break;
1674 					case PCI_nvm:
1675 						_AddPath(*stack, "drivers", "disk");
1676 						break;
1677 					default:
1678 						_AddPath(*stack, "busses");
1679 						break;
1680 				}
1681 				break;
1682 			case PCI_serial_bus:
1683 				switch (subType) {
1684 					case PCI_firewire:
1685 						_AddPath(*stack, "busses", "firewire");
1686 						break;
1687 					case PCI_usb:
1688 						_AddPath(*stack, "busses", "usb");
1689 						break;
1690 					default:
1691 						_AddPath(*stack, "busses");
1692 						break;
1693 				}
1694 				break;
1695 			case PCI_network:
1696 				_AddPath(*stack, "drivers", "net");
1697 				_AddPath(*stack, "busses", "virtio");
1698 				break;
1699 			case PCI_display:
1700 				_AddPath(*stack, "drivers", "graphics");
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 				}
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