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