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