xref: /haiku/src/system/kernel/device_manager/device_manager.cpp (revision b57470a2179ca208ea910422db1ab2881575b69d)
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 <kernel.h>
25 #include <generic_syscall.h>
26 #include <util/AutoLock.h>
27 #include <util/DoublyLinkedList.h>
28 #include <util/Stack.h>
29 
30 #include "AbstractModuleDevice.h"
31 #include "devfs_private.h"
32 #include "id_generator.h"
33 #include "IORequest.h"
34 #include "io_resources.h"
35 #include "IOSchedulerRoster.h"
36 
37 
38 //#define TRACE_DEVICE_MANAGER
39 #ifdef TRACE_DEVICE_MANAGER
40 #	define TRACE(a) dprintf a
41 #else
42 #	define TRACE(a) ;
43 #endif
44 
45 
46 #define DEVICE_MANAGER_ROOT_NAME "system/devices_root/driver_v1"
47 #define DEVICE_MANAGER_GENERIC_NAME "system/devices_generic/driver_v1"
48 
49 
50 struct device_attr_private : device_attr,
51 		DoublyLinkedListLinkImpl<device_attr_private> {
52 						device_attr_private();
53 						device_attr_private(const device_attr& attr);
54 						~device_attr_private();
55 
56 			status_t	InitCheck();
57 			status_t	CopyFrom(const device_attr& attr);
58 
59 	static	int			Compare(const device_attr* attrA,
60 							const device_attr *attrB);
61 
62 private:
63 			void		_Unset();
64 };
65 
66 typedef DoublyLinkedList<device_attr_private> AttributeList;
67 
68 // I/O resource
69 typedef struct io_resource_info {
70 	struct io_resource_info *prev, *next;
71 	device_node*		owner;			// associated node; NULL for temporary allocation
72 	io_resource			resource;		// info about actual resource
73 } io_resource_info;
74 
75 
76 namespace {
77 
78 
79 class Device : public AbstractModuleDevice,
80 	public DoublyLinkedListLinkImpl<Device> {
81 public:
82 							Device(device_node* node, const char* moduleName);
83 	virtual					~Device();
84 
85 			status_t		InitCheck() const;
86 
87 			const char*		ModuleName() const { return fModuleName; }
88 
89 	virtual	status_t		InitDevice();
90 	virtual	void			UninitDevice();
91 
92 	virtual void			Removed();
93 
94 			void			SetRemovedFromParent(bool removed)
95 								{ fRemovedFromParent = removed; }
96 
97 private:
98 	const char*				fModuleName;
99 	bool					fRemovedFromParent;
100 };
101 
102 
103 } // unnamed namespace
104 
105 
106 typedef DoublyLinkedList<Device> DeviceList;
107 typedef DoublyLinkedList<device_node> NodeList;
108 
109 struct device_node : DoublyLinkedListLinkImpl<device_node> {
110 							device_node(const char* moduleName,
111 								const device_attr* attrs);
112 							~device_node();
113 
114 			status_t		InitCheck() const;
115 
116 			status_t		AcquireResources(const io_resource* resources);
117 
118 			const char*		ModuleName() const { return fModuleName; }
119 			device_node*	Parent() const { return fParent; }
120 			AttributeList&	Attributes() { return fAttributes; }
121 			const AttributeList& Attributes() const { return fAttributes; }
122 
123 			status_t		InitDriver();
124 			bool			UninitDriver();
125 			void			UninitUnusedDriver();
126 
127 			// The following two are only valid, if the node's driver is
128 			// initialized
129 			driver_module_info* DriverModule() const { return fDriver; }
130 			void*			DriverData() const { return fDriverData; }
131 
132 			void			AddChild(device_node *node);
133 			void			RemoveChild(device_node *node);
134 			const NodeList&	Children() const { return fChildren; }
135 			void			DeviceRemoved();
136 
137 			status_t		Register(device_node* parent);
138 			status_t		Probe(const char* devicePath, uint32 updateCycle);
139 			status_t		Reprobe();
140 			status_t		Rescan();
141 
142 			bool			IsRegistered() const { return fRegistered; }
143 			bool			IsInitialized() const { return fInitialized > 0; }
144 			bool			IsProbed() const { return fLastUpdateCycle != 0; }
145 			uint32			Flags() const { return fFlags; }
146 
147 			void			Acquire();
148 			bool			Release();
149 
150 			const DeviceList& Devices() const { return fDevices; }
151 			void			AddDevice(Device* device);
152 			void			RemoveDevice(Device* device);
153 
154 			int				CompareTo(const device_attr* attributes) const;
155 			device_node*	FindChild(const device_attr* attributes) const;
156 			device_node*	FindChild(const char* moduleName) const;
157 
158 			int32			Priority();
159 
160 			void			Dump(int32 level = 0);
161 
162 private:
163 			status_t		_RegisterFixed(uint32& registered);
164 			bool			_AlwaysRegisterDynamic();
165 			status_t		_AddPath(Stack<KPath*>& stack, const char* path,
166 								const char* subPath = NULL);
167 			status_t		_GetNextDriverPath(void*& cookie, KPath& _path);
168 			status_t		_GetNextDriver(void* list,
169 								driver_module_info*& driver);
170 			status_t		_FindBestDriver(const char* path,
171 								driver_module_info*& bestDriver,
172 								float& bestSupport,
173 								device_node* previous = NULL);
174 			status_t		_RegisterPath(const char* path);
175 			status_t		_RegisterDynamic(device_node* previous = NULL);
176 			status_t		_RemoveChildren();
177 			device_node*	_FindCurrentChild();
178 			status_t		_Probe();
179 			void			_ReleaseWaiting();
180 
181 	device_node*			fParent;
182 	NodeList				fChildren;
183 	int32					fRefCount;
184 	int32					fInitialized;
185 	bool					fRegistered;
186 	uint32					fFlags;
187 	float					fSupportsParent;
188 	uint32					fLastUpdateCycle;
189 
190 	const char*				fModuleName;
191 
192 	driver_module_info*		fDriver;
193 	void*					fDriverData;
194 
195 	DeviceList				fDevices;
196 	AttributeList			fAttributes;
197 	ResourceList			fResources;
198 };
199 
200 // flags in addition to those specified by B_DEVICE_FLAGS
201 enum node_flags {
202 	NODE_FLAG_REGISTER_INITIALIZED	= 0x00010000,
203 	NODE_FLAG_DEVICE_REMOVED		= 0x00020000,
204 	NODE_FLAG_OBSOLETE_DRIVER		= 0x00040000,
205 	NODE_FLAG_WAITING_FOR_DRIVER	= 0x00080000,
206 
207 	NODE_FLAG_PUBLIC_MASK			= 0x0000ffff
208 };
209 
210 
211 static device_node *sRootNode;
212 static recursive_lock sLock;
213 static const char* sGenericContextPath;
214 
215 
216 //	#pragma mark -
217 
218 
219 static device_attr_private*
220 find_attr(const device_node* node, const char* name, bool recursive,
221 	type_code type)
222 {
223 	do {
224 		AttributeList::ConstIterator iterator
225 			= node->Attributes().GetIterator();
226 
227 		while (iterator.HasNext()) {
228 			device_attr_private* attr = iterator.Next();
229 
230 			if (type != B_ANY_TYPE && attr->type != type)
231 				continue;
232 
233 			if (!strcmp(attr->name, name))
234 				return attr;
235 		}
236 
237 		node = node->Parent();
238 	} while (node != NULL && recursive);
239 
240 	return NULL;
241 }
242 
243 
244 static void
245 put_level(int32 level)
246 {
247 	while (level-- > 0)
248 		kprintf("   ");
249 }
250 
251 
252 static void
253 dump_attribute(device_attr* attr, int32 level)
254 {
255 	if (attr == NULL)
256 		return;
257 
258 	put_level(level + 2);
259 	kprintf("\"%s\" : ", attr->name);
260 	switch (attr->type) {
261 		case B_STRING_TYPE:
262 			kprintf("string : \"%s\"", attr->value.string);
263 			break;
264 		case B_INT8_TYPE:
265 		case B_UINT8_TYPE:
266 			kprintf("uint8 : %" B_PRIu8 " (%#" B_PRIx8 ")", attr->value.ui8,
267 				attr->value.ui8);
268 			break;
269 		case B_INT16_TYPE:
270 		case B_UINT16_TYPE:
271 			kprintf("uint16 : %" B_PRIu16 " (%#" B_PRIx16 ")", attr->value.ui16,
272 				attr->value.ui16);
273 			break;
274 		case B_INT32_TYPE:
275 		case B_UINT32_TYPE:
276 			kprintf("uint32 : %" B_PRIu32 " (%#" B_PRIx32 ")", attr->value.ui32,
277 				attr->value.ui32);
278 			break;
279 		case B_INT64_TYPE:
280 		case B_UINT64_TYPE:
281 			kprintf("uint64 : %" B_PRIu64 " (%#" B_PRIx64 ")", attr->value.ui64,
282 				attr->value.ui64);
283 			break;
284 		default:
285 			kprintf("raw data");
286 	}
287 	kprintf("\n");
288 }
289 
290 
291 static int
292 dump_io_scheduler(int argc, char** argv)
293 {
294 	if (argc != 2) {
295 		print_debugger_command_usage(argv[0]);
296 		return 0;
297 	}
298 
299 	IOScheduler* scheduler = (IOScheduler*)parse_expression(argv[1]);
300 	scheduler->Dump();
301 	return 0;
302 }
303 
304 
305 static int
306 dump_io_request_owner(int argc, char** argv)
307 {
308 	if (argc != 2) {
309 		print_debugger_command_usage(argv[0]);
310 		return 0;
311 	}
312 
313 	IORequestOwner* owner = (IORequestOwner*)parse_expression(argv[1]);
314 	owner->Dump();
315 	return 0;
316 }
317 
318 
319 static int
320 dump_io_request(int argc, char** argv)
321 {
322 	if (argc != 2 || !strcmp(argv[1], "--help")) {
323 		kprintf("usage: %s <ptr-to-io-request>\n", argv[0]);
324 		return 0;
325 	}
326 
327 	IORequest* request = (IORequest*)parse_expression(argv[1]);
328 	request->Dump();
329 	return 0;
330 }
331 
332 
333 static int
334 dump_io_operation(int argc, char** argv)
335 {
336 	if (argc != 2 || !strcmp(argv[1], "--help")) {
337 		kprintf("usage: %s <ptr-to-io-operation>\n", argv[0]);
338 		return 0;
339 	}
340 
341 	IOOperation* operation = (IOOperation*)parse_expression(argv[1]);
342 	operation->Dump();
343 	return 0;
344 }
345 
346 
347 static int
348 dump_io_buffer(int argc, char** argv)
349 {
350 	if (argc != 2 || !strcmp(argv[1], "--help")) {
351 		kprintf("usage: %s <ptr-to-io-buffer>\n", argv[0]);
352 		return 0;
353 	}
354 
355 	IOBuffer* buffer = (IOBuffer*)parse_expression(argv[1]);
356 	buffer->Dump();
357 	return 0;
358 }
359 
360 
361 static int
362 dump_dma_buffer(int argc, char** argv)
363 {
364 	if (argc != 2 || !strcmp(argv[1], "--help")) {
365 		kprintf("usage: %s <ptr-to-dma-buffer>\n", argv[0]);
366 		return 0;
367 	}
368 
369 	DMABuffer* buffer = (DMABuffer*)parse_expression(argv[1]);
370 	buffer->Dump();
371 	return 0;
372 }
373 
374 
375 static int
376 dump_device_nodes(int argc, char** argv)
377 {
378 	sRootNode->Dump();
379 	return 0;
380 }
381 
382 
383 static void
384 publish_directories(const char* subPath)
385 {
386 	if (gBootDevice < 0) {
387 		if (subPath[0]) {
388 			// we only support the top-level directory for modules
389 			return;
390 		}
391 
392 		// we can only iterate over the known modules to find all directories
393 		KPath path("drivers");
394 		if (path.Append(subPath) != B_OK)
395 			return;
396 
397 		size_t length = strlen(path.Path()) + 1;
398 			// account for the separating '/'
399 
400 		void* list = open_module_list_etc(path.Path(), "driver_v1");
401 		char name[B_FILE_NAME_LENGTH];
402 		size_t nameLength = sizeof(name);
403 		while (read_next_module_name(list, name, &nameLength) == B_OK) {
404 			if (nameLength == length)
405 				continue;
406 
407 			char* leaf = name + length;
408 			char* end = strchr(leaf, '/');
409 			if (end != NULL)
410 				end[0] = '\0';
411 
412 			path.SetTo(subPath);
413 			path.Append(leaf);
414 
415 			devfs_publish_directory(path.Path());
416 		}
417 		close_module_list(list);
418 	} else {
419 		// TODO: implement module directory traversal!
420 	}
421 }
422 
423 
424 static status_t
425 control_device_manager(const char* subsystem, uint32 function, void* buffer,
426 	size_t bufferSize)
427 {
428 	// TODO: this function passes pointers to userland, and uses pointers
429 	// to device nodes that came from userland - this is completely unsafe
430 	// and should be changed.
431 	switch (function) {
432 		case DM_GET_ROOT:
433 		{
434 			device_node_cookie cookie;
435 			if (!IS_USER_ADDRESS(buffer))
436 				return B_BAD_ADDRESS;
437 			if (bufferSize != sizeof(device_node_cookie))
438 				return B_BAD_VALUE;
439 			cookie = (device_node_cookie)sRootNode;
440 
441 			// copy back to user space
442 			return user_memcpy(buffer, &cookie, sizeof(device_node_cookie));
443 		}
444 
445 		case DM_GET_CHILD:
446 		{
447 			if (!IS_USER_ADDRESS(buffer))
448 				return B_BAD_ADDRESS;
449 			if (bufferSize != sizeof(device_node_cookie))
450 				return B_BAD_VALUE;
451 
452 			device_node_cookie cookie;
453 			if (user_memcpy(&cookie, buffer, sizeof(device_node_cookie)) < B_OK)
454 				return B_BAD_ADDRESS;
455 
456 			device_node* node = (device_node*)cookie;
457 			NodeList::ConstIterator iterator = node->Children().GetIterator();
458 
459 			if (!iterator.HasNext()) {
460 				return B_ENTRY_NOT_FOUND;
461 			}
462 			node = iterator.Next();
463 			cookie = (device_node_cookie)node;
464 
465 			// copy back to user space
466 			return user_memcpy(buffer, &cookie, sizeof(device_node_cookie));
467 		}
468 
469 		case DM_GET_NEXT_CHILD:
470 		{
471 			if (!IS_USER_ADDRESS(buffer))
472 				return B_BAD_ADDRESS;
473 			if (bufferSize != sizeof(device_node_cookie))
474 				return B_BAD_VALUE;
475 
476 			device_node_cookie cookie;
477 			if (user_memcpy(&cookie, buffer, sizeof(device_node_cookie)) < B_OK)
478 				return B_BAD_ADDRESS;
479 
480 			device_node* last = (device_node*)cookie;
481 			if (!last->Parent())
482 				return B_ENTRY_NOT_FOUND;
483 
484 			NodeList::ConstIterator iterator
485 				= last->Parent()->Children().GetIterator();
486 
487 			// skip those we already traversed
488 			while (iterator.HasNext()) {
489 				device_node* node = iterator.Next();
490 
491 				if (node == last)
492 					break;
493 			}
494 
495 			if (!iterator.HasNext())
496 				return B_ENTRY_NOT_FOUND;
497 			device_node* node = iterator.Next();
498 			cookie = (device_node_cookie)node;
499 
500 			// copy back to user space
501 			return user_memcpy(buffer, &cookie, sizeof(device_node_cookie));
502 		}
503 
504 		case DM_GET_NEXT_ATTRIBUTE:
505 		{
506 			struct device_attr_info attrInfo;
507 			if (!IS_USER_ADDRESS(buffer))
508 				return B_BAD_ADDRESS;
509 			if (bufferSize != sizeof(device_attr_info))
510 				return B_BAD_VALUE;
511 			if (user_memcpy(&attrInfo, buffer, sizeof(device_attr_info)) < B_OK)
512 				return B_BAD_ADDRESS;
513 
514 			device_node* node = (device_node*)attrInfo.node_cookie;
515 			device_attr* last = (device_attr*)attrInfo.cookie;
516 			AttributeList::Iterator iterator = node->Attributes().GetIterator();
517 			// skip those we already traversed
518 			while (iterator.HasNext() && last != NULL) {
519 				device_attr* attr = iterator.Next();
520 
521 				if (attr == last)
522 					break;
523 			}
524 
525 			if (!iterator.HasNext()) {
526 				attrInfo.cookie = 0;
527 				return B_ENTRY_NOT_FOUND;
528 			}
529 
530 			device_attr* attr = iterator.Next();
531 			attrInfo.cookie = (device_node_cookie)attr;
532 			strlcpy(attrInfo.name, attr->name, 254);
533 			attrInfo.type = attr->type;
534 			switch (attrInfo.type) {
535 				case B_UINT8_TYPE:
536 					attrInfo.value.ui8 = attr->value.ui8;
537 					break;
538 				case B_UINT16_TYPE:
539 					attrInfo.value.ui16 = attr->value.ui16;
540 					break;
541 				case B_UINT32_TYPE:
542 					attrInfo.value.ui32 = attr->value.ui32;
543 					break;
544 				case B_UINT64_TYPE:
545 					attrInfo.value.ui64 = attr->value.ui64;
546 					break;
547 				case B_STRING_TYPE:
548 					strlcpy(attrInfo.value.string, attr->value.string, 254);
549 					break;
550 				/*case B_RAW_TYPE:
551 					if (attr.value.raw.length > attr_info->attr.value.raw.length)
552 						attr.value.raw.length = attr_info->attr.value.raw.length;
553 					user_memcpy(attr.value.raw.data, attr_info->attr.value.raw.data,
554 						attr.value.raw.length);
555 					break;*/
556 			}
557 
558 			// copy back to user space
559 			return user_memcpy(buffer, &attrInfo, sizeof(device_attr_info));
560 		}
561 	}
562 
563 	return B_BAD_HANDLER;
564 }
565 
566 
567 //	#pragma mark - Device Manager module API
568 
569 
570 static status_t
571 rescan_node(device_node* node)
572 {
573 	RecursiveLocker _(sLock);
574 	return node->Rescan();
575 }
576 
577 
578 static status_t
579 register_node(device_node* parent, const char* moduleName,
580 	const device_attr* attrs, const io_resource* ioResources,
581 	device_node** _node)
582 {
583 	if ((parent == NULL && sRootNode != NULL) || moduleName == NULL)
584 		return B_BAD_VALUE;
585 
586 	if (parent != NULL && parent->FindChild(attrs) != NULL) {
587 		// A node like this one already exists for this parent
588 		return B_NAME_IN_USE;
589 	}
590 
591 	RecursiveLocker _(sLock);
592 
593 	device_node* newNode = new(std::nothrow) device_node(moduleName, attrs);
594 	if (newNode == NULL)
595 		return B_NO_MEMORY;
596 
597 	TRACE(("%p: register node \"%s\", parent %p\n", newNode, moduleName,
598 		parent));
599 
600 	status_t status = newNode->InitCheck();
601 	if (status == B_OK)
602 		status = newNode->AcquireResources(ioResources);
603 	if (status == B_OK)
604 		status = newNode->Register(parent);
605 
606 	if (status != B_OK) {
607 		newNode->Release();
608 		return status;
609 	}
610 
611 	if (_node)
612 		*_node = newNode;
613 
614 	return B_OK;
615 }
616 
617 
618 /*!	Unregisters the device \a node.
619 
620 	If the node is currently in use, this function will return B_BUSY to
621 	indicate that the node hasn't been removed yet - it will still remove
622 	the node as soon as possible.
623 */
624 static status_t
625 unregister_node(device_node* node)
626 {
627 	TRACE(("unregister_node(node %p)\n", node));
628 	RecursiveLocker _(sLock);
629 
630 	bool initialized = node->IsInitialized();
631 
632 	node->DeviceRemoved();
633 
634 	return initialized ? B_BUSY : B_OK;
635 }
636 
637 
638 static status_t
639 get_driver(device_node* node, driver_module_info** _module, void** _data)
640 {
641 	if (node->DriverModule() == NULL)
642 		return B_NO_INIT;
643 
644 	if (_module != NULL)
645 		*_module = node->DriverModule();
646 	if (_data != NULL)
647 		*_data = node->DriverData();
648 
649 	return B_OK;
650 }
651 
652 
653 static device_node*
654 get_root_node(void)
655 {
656 	if (sRootNode != NULL)
657 		sRootNode->Acquire();
658 
659 	return sRootNode;
660 }
661 
662 
663 static status_t
664 get_next_child_node(device_node* parent, const device_attr* attributes,
665 	device_node** _node)
666 {
667 	RecursiveLocker _(sLock);
668 
669 	NodeList::ConstIterator iterator = parent->Children().GetIterator();
670 	device_node* last = *_node;
671 
672 	// skip those we already traversed
673 	while (iterator.HasNext() && last != NULL) {
674 		device_node* node = iterator.Next();
675 
676 		if (node != last)
677 			continue;
678 	}
679 
680 	// find the next one that fits
681 	while (iterator.HasNext()) {
682 		device_node* node = iterator.Next();
683 
684 		if (!node->IsRegistered())
685 			continue;
686 
687 		if (!node->CompareTo(attributes)) {
688 			if (last != NULL)
689 				last->Release();
690 
691 			node->Acquire();
692 			*_node = node;
693 			return B_OK;
694 		}
695 	}
696 
697 	if (last != NULL)
698 		last->Release();
699 
700 	return B_ENTRY_NOT_FOUND;
701 }
702 
703 
704 static device_node*
705 get_parent_node(device_node* node)
706 {
707 	if (node == NULL)
708 		return NULL;
709 
710 	RecursiveLocker _(sLock);
711 
712 	device_node* parent = node->Parent();
713 	parent->Acquire();
714 
715 	return parent;
716 }
717 
718 
719 static void
720 put_node(device_node* node)
721 {
722 	RecursiveLocker _(sLock);
723 	node->Release();
724 }
725 
726 
727 static status_t
728 publish_device(device_node *node, const char *path, const char *moduleName)
729 {
730 	if (path == NULL || !path[0] || moduleName == NULL || !moduleName[0])
731 		return B_BAD_VALUE;
732 
733 	RecursiveLocker _(sLock);
734 	dprintf("publish device: node %p, path %s, module %s\n", node, path,
735 		moduleName);
736 
737 	Device* device = new(std::nothrow) Device(node, moduleName);
738 	if (device == NULL)
739 		return B_NO_MEMORY;
740 
741 	status_t status = device->InitCheck();
742 	if (status == B_OK)
743 		status = devfs_publish_device(path, device);
744 	if (status != B_OK) {
745 		delete device;
746 		return status;
747 	}
748 
749 	node->AddDevice(device);
750 	return B_OK;
751 }
752 
753 
754 static status_t
755 unpublish_device(device_node *node, const char *path)
756 {
757 	if (path == NULL)
758 		return B_BAD_VALUE;
759 
760 	RecursiveLocker _(sLock);
761 
762 #if 0
763 	DeviceList::ConstIterator iterator = node->Devices().GetIterator();
764 	while (iterator.HasNext()) {
765 		Device* device = iterator.Next();
766 		if (!strcmp(device->Path(), path)) {
767 			node->RemoveDevice(device);
768 			delete device;
769 			return B_OK;
770 		}
771 	}
772 #endif
773 
774 	return B_ENTRY_NOT_FOUND;
775 }
776 
777 
778 static status_t
779 get_attr_uint8(const device_node* node, const char* name, uint8* _value,
780 	bool recursive)
781 {
782 	if (node == NULL || name == NULL || _value == NULL)
783 		return B_BAD_VALUE;
784 
785 	device_attr_private* attr = find_attr(node, name, recursive, B_UINT8_TYPE);
786 	if (attr == NULL)
787 		return B_NAME_NOT_FOUND;
788 
789 	*_value = attr->value.ui8;
790 	return B_OK;
791 }
792 
793 
794 static status_t
795 get_attr_uint16(const device_node* node, const char* name, uint16* _value,
796 	bool recursive)
797 {
798 	if (node == NULL || name == NULL || _value == NULL)
799 		return B_BAD_VALUE;
800 
801 	device_attr_private* attr = find_attr(node, name, recursive, B_UINT16_TYPE);
802 	if (attr == NULL)
803 		return B_NAME_NOT_FOUND;
804 
805 	*_value = attr->value.ui16;
806 	return B_OK;
807 }
808 
809 
810 static status_t
811 get_attr_uint32(const device_node* node, const char* name, uint32* _value,
812 	bool recursive)
813 {
814 	if (node == NULL || name == NULL || _value == NULL)
815 		return B_BAD_VALUE;
816 
817 	device_attr_private* attr = find_attr(node, name, recursive, B_UINT32_TYPE);
818 	if (attr == NULL)
819 		return B_NAME_NOT_FOUND;
820 
821 	*_value = attr->value.ui32;
822 	return B_OK;
823 }
824 
825 
826 static status_t
827 get_attr_uint64(const device_node* node, const char* name,
828 	uint64* _value, bool recursive)
829 {
830 	if (node == NULL || name == NULL || _value == NULL)
831 		return B_BAD_VALUE;
832 
833 	device_attr_private* attr = find_attr(node, name, recursive, B_UINT64_TYPE);
834 	if (attr == NULL)
835 		return B_NAME_NOT_FOUND;
836 
837 	*_value = attr->value.ui64;
838 	return B_OK;
839 }
840 
841 
842 static status_t
843 get_attr_string(const device_node* node, const char* name,
844 	const char** _value, bool recursive)
845 {
846 	if (node == NULL || name == NULL || _value == NULL)
847 		return B_BAD_VALUE;
848 
849 	device_attr_private* attr = find_attr(node, name, recursive, B_STRING_TYPE);
850 	if (attr == NULL)
851 		return B_NAME_NOT_FOUND;
852 
853 	*_value = attr->value.string;
854 	return B_OK;
855 }
856 
857 
858 static status_t
859 get_attr_raw(const device_node* node, const char* name, const void** _data,
860 	size_t* _length, bool recursive)
861 {
862 	if (node == NULL || name == NULL || (_data == NULL && _length == NULL))
863 		return B_BAD_VALUE;
864 
865 	device_attr_private* attr = find_attr(node, name, recursive, B_RAW_TYPE);
866 	if (attr == NULL)
867 		return B_NAME_NOT_FOUND;
868 
869 	if (_data != NULL)
870 		*_data = attr->value.raw.data;
871 	if (_length != NULL)
872 		*_length = attr->value.raw.length;
873 	return B_OK;
874 }
875 
876 
877 static status_t
878 get_next_attr(device_node* node, device_attr** _attr)
879 {
880 	if (node == NULL)
881 		return B_BAD_VALUE;
882 
883 	device_attr_private* next;
884 	device_attr_private* attr = *(device_attr_private**)_attr;
885 
886 	if (attr != NULL) {
887 		// next attribute
888 		next = attr->GetDoublyLinkedListLink()->next;
889 	} else {
890 		// first attribute
891 		next = node->Attributes().First();
892 	}
893 
894 	*_attr = next;
895 
896 	return next ? B_OK : B_ENTRY_NOT_FOUND;
897 }
898 
899 
900 struct device_manager_info gDeviceManagerModule = {
901 	{
902 		B_DEVICE_MANAGER_MODULE_NAME,
903 		0,
904 		NULL
905 	},
906 
907 	// device nodes
908 	rescan_node,
909 	register_node,
910 	unregister_node,
911 	get_driver,
912 	get_root_node,
913 	get_next_child_node,
914 	get_parent_node,
915 	put_node,
916 
917 	// devices
918 	publish_device,
919 	unpublish_device,
920 
921 	// I/O resources
922 
923 	// ID generator
924 	dm_create_id,
925 	dm_free_id,
926 
927 	// attributes
928 	get_attr_uint8,
929 	get_attr_uint16,
930 	get_attr_uint32,
931 	get_attr_uint64,
932 	get_attr_string,
933 	get_attr_raw,
934 	get_next_attr,
935 };
936 
937 
938 //	#pragma mark - device_attr
939 
940 
941 device_attr_private::device_attr_private()
942 {
943 	name = NULL;
944 	type = 0;
945 	value.raw.data = NULL;
946 	value.raw.length = 0;
947 }
948 
949 
950 device_attr_private::device_attr_private(const device_attr& attr)
951 {
952 	CopyFrom(attr);
953 }
954 
955 
956 device_attr_private::~device_attr_private()
957 {
958 	_Unset();
959 }
960 
961 
962 status_t
963 device_attr_private::InitCheck()
964 {
965 	return name != NULL ? B_OK : B_NO_INIT;
966 }
967 
968 
969 status_t
970 device_attr_private::CopyFrom(const device_attr& attr)
971 {
972 	name = strdup(attr.name);
973 	if (name == NULL)
974 		return B_NO_MEMORY;
975 
976 	type = attr.type;
977 
978 	switch (type) {
979 		case B_UINT8_TYPE:
980 		case B_UINT16_TYPE:
981 		case B_UINT32_TYPE:
982 		case B_UINT64_TYPE:
983 			value.ui64 = attr.value.ui64;
984 			break;
985 
986 		case B_STRING_TYPE:
987 			if (attr.value.string != NULL) {
988 				value.string = strdup(attr.value.string);
989 				if (value.string == NULL) {
990 					_Unset();
991 					return B_NO_MEMORY;
992 				}
993 			} else
994 				value.string = NULL;
995 			break;
996 
997 		case B_RAW_TYPE:
998 			value.raw.data = malloc(attr.value.raw.length);
999 			if (value.raw.data == NULL) {
1000 				_Unset();
1001 				return B_NO_MEMORY;
1002 			}
1003 
1004 			value.raw.length = attr.value.raw.length;
1005 			memcpy((void*)value.raw.data, attr.value.raw.data,
1006 				attr.value.raw.length);
1007 			break;
1008 
1009 		default:
1010 			return B_BAD_VALUE;
1011 	}
1012 
1013 	return B_OK;
1014 }
1015 
1016 
1017 void
1018 device_attr_private::_Unset()
1019 {
1020 	if (type == B_STRING_TYPE)
1021 		free((char*)value.string);
1022 	else if (type == B_RAW_TYPE)
1023 		free((void*)value.raw.data);
1024 
1025 	free((char*)name);
1026 
1027 	name = NULL;
1028 	value.raw.data = NULL;
1029 	value.raw.length = 0;
1030 }
1031 
1032 
1033 /*static*/ int
1034 device_attr_private::Compare(const device_attr* attrA, const device_attr *attrB)
1035 {
1036 	if (attrA->type != attrB->type)
1037 		return -1;
1038 
1039 	switch (attrA->type) {
1040 		case B_UINT8_TYPE:
1041 			return (int)attrA->value.ui8 - (int)attrB->value.ui8;
1042 
1043 		case B_UINT16_TYPE:
1044 			return (int)attrA->value.ui16 - (int)attrB->value.ui16;
1045 
1046 		case B_UINT32_TYPE:
1047 			if (attrA->value.ui32 > attrB->value.ui32)
1048 				return 1;
1049 			if (attrA->value.ui32 < attrB->value.ui32)
1050 				return -1;
1051 			return 0;
1052 
1053 		case B_UINT64_TYPE:
1054 			if (attrA->value.ui64 > attrB->value.ui64)
1055 				return 1;
1056 			if (attrA->value.ui64 < attrB->value.ui64)
1057 				return -1;
1058 			return 0;
1059 
1060 		case B_STRING_TYPE:
1061 			return strcmp(attrA->value.string, attrB->value.string);
1062 
1063 		case B_RAW_TYPE:
1064 			if (attrA->value.raw.length != attrB->value.raw.length)
1065 				return -1;
1066 
1067 			return memcmp(attrA->value.raw.data, attrB->value.raw.data,
1068 				attrA->value.raw.length);
1069 	}
1070 
1071 	return -1;
1072 }
1073 
1074 
1075 //	#pragma mark - Device
1076 
1077 
1078 Device::Device(device_node* node, const char* moduleName)
1079 	:
1080 	fModuleName(strdup(moduleName)),
1081 	fRemovedFromParent(false)
1082 {
1083 	fNode = node;
1084 }
1085 
1086 
1087 Device::~Device()
1088 {
1089 	free((char*)fModuleName);
1090 }
1091 
1092 
1093 status_t
1094 Device::InitCheck() const
1095 {
1096 	return fModuleName != NULL ? B_OK : B_NO_MEMORY;
1097 }
1098 
1099 
1100 status_t
1101 Device::InitDevice()
1102 {
1103 	RecursiveLocker _(sLock);
1104 
1105 	if ((fNode->Flags() & NODE_FLAG_DEVICE_REMOVED) != 0) {
1106 		// TODO: maybe the device should be unlinked in devfs, too
1107 		return ENODEV;
1108 	}
1109 	if ((fNode->Flags() & NODE_FLAG_WAITING_FOR_DRIVER) != 0)
1110 		return B_BUSY;
1111 
1112 	if (fInitialized++ > 0) {
1113 		fNode->InitDriver();
1114 			// acquire another reference to our parent as well
1115 		return B_OK;
1116 	}
1117 
1118 	status_t status = get_module(ModuleName(), (module_info**)&fDeviceModule);
1119 	if (status == B_OK) {
1120 		// our parent always has to be initialized
1121 		status = fNode->InitDriver();
1122 	}
1123 	if (status < B_OK) {
1124 		fInitialized--;
1125 		return status;
1126 	}
1127 
1128 	if (Module()->init_device != NULL)
1129 		status = Module()->init_device(fNode->DriverData(), &fDeviceData);
1130 
1131 	if (status < B_OK) {
1132 		fNode->UninitDriver();
1133 		fInitialized--;
1134 
1135 		put_module(ModuleName());
1136 		fDeviceModule = NULL;
1137 		fDeviceData = NULL;
1138 	}
1139 
1140 	return status;
1141 }
1142 
1143 
1144 void
1145 Device::UninitDevice()
1146 {
1147 	RecursiveLocker _(sLock);
1148 
1149 	if (fInitialized-- > 1) {
1150 		fNode->UninitDriver();
1151 		return;
1152 	}
1153 
1154 	TRACE(("uninit driver for node %p\n", this));
1155 
1156 	if (Module()->uninit_device != NULL)
1157 		Module()->uninit_device(fDeviceData);
1158 
1159 	fDeviceModule = NULL;
1160 	fDeviceData = NULL;
1161 
1162 	put_module(ModuleName());
1163 
1164 	fNode->UninitDriver();
1165 }
1166 
1167 
1168 void
1169 Device::Removed()
1170 {
1171 	RecursiveLocker _(sLock);
1172 
1173 	if (!fRemovedFromParent)
1174 		fNode->RemoveDevice(this);
1175 
1176 	delete this;
1177 }
1178 
1179 
1180 //	#pragma mark - device_node
1181 
1182 
1183 device_node::device_node(const char* moduleName, const device_attr* attrs)
1184 {
1185 	fModuleName = strdup(moduleName);
1186 	if (fModuleName == NULL)
1187 		return;
1188 
1189 	fParent = NULL;
1190 	fRefCount = 1;
1191 	fInitialized = 0;
1192 	fRegistered = false;
1193 	fFlags = 0;
1194 	fSupportsParent = 0.0;
1195 	fLastUpdateCycle = 0;
1196 	fDriver = NULL;
1197 	fDriverData = NULL;
1198 
1199 	// copy attributes
1200 
1201 	while (attrs != NULL && attrs->name != NULL) {
1202 		device_attr_private* attr
1203 			= new(std::nothrow) device_attr_private(*attrs);
1204 		if (attr == NULL)
1205 			break;
1206 
1207 		fAttributes.Add(attr);
1208 		attrs++;
1209 	}
1210 
1211 	get_attr_uint32(this, B_DEVICE_FLAGS, &fFlags, false);
1212 	fFlags &= NODE_FLAG_PUBLIC_MASK;
1213 }
1214 
1215 
1216 device_node::~device_node()
1217 {
1218 	TRACE(("delete node %p\n", this));
1219 	ASSERT(DriverModule() == NULL);
1220 
1221 	if (Parent() != NULL) {
1222 		if ((fFlags & NODE_FLAG_OBSOLETE_DRIVER) != 0) {
1223 			// This driver has been obsoleted; another driver has been waiting
1224 			// for us - make it available
1225 			Parent()->_ReleaseWaiting();
1226 		}
1227 		Parent()->RemoveChild(this);
1228 	}
1229 
1230 	// Delete children
1231 	while (device_node* child = fChildren.RemoveHead()) {
1232 		delete child;
1233 	}
1234 
1235 	// Delete devices
1236 	while (Device* device = fDevices.RemoveHead()) {
1237 		device->SetRemovedFromParent(true);
1238 		devfs_unpublish_device(device, true);
1239 	}
1240 
1241 	// Delete attributes
1242 	while (device_attr_private* attr = fAttributes.RemoveHead()) {
1243 		delete attr;
1244 	}
1245 
1246 	// Delete resources
1247 	while (io_resource_private* resource = fResources.RemoveHead()) {
1248 		delete resource;
1249 	}
1250 
1251 	free((char*)fModuleName);
1252 }
1253 
1254 
1255 status_t
1256 device_node::InitCheck() const
1257 {
1258 	return fModuleName != NULL ? B_OK : B_NO_MEMORY;
1259 }
1260 
1261 
1262 status_t
1263 device_node::AcquireResources(const io_resource* resources)
1264 {
1265 	if (resources == NULL)
1266 		return B_OK;
1267 
1268 	for (uint32 i = 0; resources[i].type != 0; i++) {
1269 		io_resource_private* resource = new(std::nothrow) io_resource_private;
1270 		if (resource == NULL)
1271 			return B_NO_MEMORY;
1272 
1273 		status_t status = resource->Acquire(resources[i]);
1274 		if (status != B_OK) {
1275 			delete resource;
1276 			return status;
1277 		}
1278 
1279 		fResources.Add(resource);
1280 	}
1281 
1282 	return B_OK;
1283 }
1284 
1285 
1286 status_t
1287 device_node::InitDriver()
1288 {
1289 	if (fInitialized++ > 0) {
1290 		if (Parent() != NULL) {
1291 			Parent()->InitDriver();
1292 				// acquire another reference to our parent as well
1293 		}
1294 		Acquire();
1295 		return B_OK;
1296 	}
1297 
1298 	status_t status = get_module(ModuleName(), (module_info**)&fDriver);
1299 	if (status == B_OK && Parent() != NULL) {
1300 		// our parent always has to be initialized
1301 		status = Parent()->InitDriver();
1302 	}
1303 	if (status < B_OK) {
1304 		fInitialized--;
1305 		return status;
1306 	}
1307 
1308 	if (fDriver->init_driver != NULL) {
1309 		status = fDriver->init_driver(this, &fDriverData);
1310 		if (status != B_OK) {
1311 			dprintf("driver %s init failed: %s\n", ModuleName(),
1312 				strerror(status));
1313 		}
1314 	}
1315 
1316 	if (status < B_OK) {
1317 		if (Parent() != NULL)
1318 			Parent()->UninitDriver();
1319 		fInitialized--;
1320 
1321 		put_module(ModuleName());
1322 		fDriver = NULL;
1323 		fDriverData = NULL;
1324 		return status;
1325 	}
1326 
1327 	Acquire();
1328 	return B_OK;
1329 }
1330 
1331 
1332 bool
1333 device_node::UninitDriver()
1334 {
1335 	if (fInitialized-- > 1) {
1336 		if (Parent() != NULL)
1337 			Parent()->UninitDriver();
1338 		Release();
1339 		return false;
1340 	}
1341 
1342 	TRACE(("uninit driver for node %p\n", this));
1343 
1344 	if (fDriver->uninit_driver != NULL)
1345 		fDriver->uninit_driver(fDriverData);
1346 
1347 	fDriver = NULL;
1348 	fDriverData = NULL;
1349 
1350 	put_module(ModuleName());
1351 
1352 	if (Parent() != NULL)
1353 		Parent()->UninitDriver();
1354 	Release();
1355 
1356 	return true;
1357 }
1358 
1359 
1360 void
1361 device_node::AddChild(device_node* node)
1362 {
1363 	// we must not be destroyed	as long as we have children
1364 	Acquire();
1365 	node->fParent = this;
1366 
1367 	int32 priority = node->Priority();
1368 
1369 	// Enforce an order in which the children are traversed - from most
1370 	// specific to least specific child.
1371 	NodeList::Iterator iterator = fChildren.GetIterator();
1372 	device_node* before = NULL;
1373 	while (iterator.HasNext()) {
1374 		device_node* child = iterator.Next();
1375 		if (child->Priority() <= priority) {
1376 			before = child;
1377 			break;
1378 		}
1379 	}
1380 
1381 	fChildren.Insert(before, node);
1382 }
1383 
1384 
1385 void
1386 device_node::RemoveChild(device_node* node)
1387 {
1388 	node->fParent = NULL;
1389 	fChildren.Remove(node);
1390 	Release();
1391 }
1392 
1393 
1394 /*!	Registers this node, and all of its children that have to be registered.
1395 	Also initializes the driver and keeps it that way on return in case
1396 	it returns successfully.
1397 */
1398 status_t
1399 device_node::Register(device_node* parent)
1400 {
1401 	// make it public
1402 	if (parent != NULL)
1403 		parent->AddChild(this);
1404 	else
1405 		sRootNode = this;
1406 
1407 	status_t status = InitDriver();
1408 	if (status != B_OK)
1409 		return status;
1410 
1411 	if ((fFlags & B_KEEP_DRIVER_LOADED) != 0) {
1412 		// We keep this driver loaded by having it always initialized
1413 		InitDriver();
1414 	}
1415 
1416 	fFlags |= NODE_FLAG_REGISTER_INITIALIZED;
1417 		// We don't uninitialize the driver - this is done by the caller
1418 		// in order to save reinitializing during driver loading.
1419 
1420 	uint32 registeredFixedCount;
1421 	status = _RegisterFixed(registeredFixedCount);
1422 	if (status != B_OK) {
1423 		UninitUnusedDriver();
1424 		return status;
1425 	}
1426 
1427 	// Register the children the driver wants
1428 
1429 	if (DriverModule()->register_child_devices != NULL) {
1430 		status = DriverModule()->register_child_devices(DriverData());
1431 		if (status != B_OK) {
1432 			UninitUnusedDriver();
1433 			return status;
1434 		}
1435 
1436 		if (!fChildren.IsEmpty()) {
1437 			fRegistered = true;
1438 			return B_OK;
1439 		}
1440 	}
1441 
1442 	if (registeredFixedCount > 0) {
1443 		// Nodes with fixed children cannot have any dynamic children, so bail
1444 		// out here
1445 		fRegistered = true;
1446 		return B_OK;
1447 	}
1448 
1449 	// Register all possible child device nodes
1450 
1451 	status = _RegisterDynamic();
1452 	if (status == B_OK)
1453 		fRegistered = true;
1454 	else
1455 		UninitUnusedDriver();
1456 
1457 	return status;
1458 }
1459 
1460 
1461 /*!	Registers any children that are identified via the B_DEVICE_FIXED_CHILD
1462 	attribute.
1463 	If any of these children cannot be registered, this call will fail (we
1464 	don't remove children we already registered up to this point in this case).
1465 */
1466 status_t
1467 device_node::_RegisterFixed(uint32& registered)
1468 {
1469 	AttributeList::Iterator iterator = fAttributes.GetIterator();
1470 	registered = 0;
1471 
1472 	while (iterator.HasNext()) {
1473 		device_attr_private* attr = iterator.Next();
1474 		if (strcmp(attr->name, B_DEVICE_FIXED_CHILD))
1475 			continue;
1476 
1477 		driver_module_info* driver;
1478 		status_t status = get_module(attr->value.string,
1479 			(module_info**)&driver);
1480 		if (status != B_OK) {
1481 			TRACE(("register fixed child %s failed: %s\n", attr->value.string,
1482 				strerror(status)));
1483 			return status;
1484 		}
1485 
1486 		if (driver->register_device != NULL) {
1487 			status = driver->register_device(this);
1488 			if (status == B_OK)
1489 				registered++;
1490 		}
1491 
1492 		put_module(attr->value.string);
1493 
1494 		if (status != B_OK)
1495 			return status;
1496 	}
1497 
1498 	return B_OK;
1499 }
1500 
1501 
1502 status_t
1503 device_node::_AddPath(Stack<KPath*>& stack, const char* basePath,
1504 	const char* subPath)
1505 {
1506 	KPath* path = new(std::nothrow) KPath;
1507 	if (path == NULL)
1508 		return B_NO_MEMORY;
1509 
1510 	status_t status = path->SetTo(basePath);
1511 	if (status == B_OK && subPath != NULL && subPath[0])
1512 		status = path->Append(subPath);
1513 	if (status == B_OK)
1514 		status = stack.Push(path);
1515 
1516 	TRACE(("  add path: \"%s\", %" B_PRId32 "\n", path->Path(), status));
1517 
1518 	if (status != B_OK)
1519 		delete path;
1520 
1521 	return status;
1522 }
1523 
1524 
1525 status_t
1526 device_node::_GetNextDriverPath(void*& cookie, KPath& _path)
1527 {
1528 	Stack<KPath*>* stack = NULL;
1529 
1530 	if (cookie == NULL) {
1531 		// find all paths and add them
1532 		stack = new(std::nothrow) Stack<KPath*>();
1533 		if (stack == NULL)
1534 			return B_NO_MEMORY;
1535 
1536 		StackDeleter<KPath*> stackDeleter(stack);
1537 
1538 		bool generic = false;
1539 		uint16 type = 0;
1540 		uint16 subType = 0;
1541 		uint16 interface = 0;
1542 		if (get_attr_uint16(this, B_DEVICE_TYPE, &type, false) != B_OK
1543 			|| get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false)
1544 					!= B_OK)
1545 			generic = true;
1546 
1547 		get_attr_uint16(this, B_DEVICE_INTERFACE, &interface, false);
1548 
1549 		// TODO: maybe make this extendible via settings file?
1550 		switch (type) {
1551 			case PCI_mass_storage:
1552 				switch (subType) {
1553 					case PCI_scsi:
1554 						_AddPath(*stack, "busses", "scsi");
1555 						_AddPath(*stack, "busses", "virtio");
1556 						break;
1557 					case PCI_ide:
1558 						_AddPath(*stack, "busses", "ata");
1559 						_AddPath(*stack, "busses", "ide");
1560 						break;
1561 					case PCI_sata:
1562 						// TODO: check for ahci interface
1563 						_AddPath(*stack, "busses", "scsi");
1564 						_AddPath(*stack, "busses", "ata");
1565 						_AddPath(*stack, "busses", "ide");
1566 						break;
1567 					default:
1568 						_AddPath(*stack, "busses");
1569 						break;
1570 				}
1571 				break;
1572 			case PCI_serial_bus:
1573 				switch (subType) {
1574 					case PCI_firewire:
1575 						_AddPath(*stack, "busses", "firewire");
1576 						break;
1577 					case PCI_usb:
1578 						_AddPath(*stack, "busses", "usb");
1579 						break;
1580 					default:
1581 						_AddPath(*stack, "busses");
1582 						break;
1583 				}
1584 				break;
1585 			case PCI_network:
1586 				_AddPath(*stack, "drivers", "net");
1587 				_AddPath(*stack, "busses", "virtio");
1588 				break;
1589 			case PCI_display:
1590 				_AddPath(*stack, "drivers", "graphics");
1591 				break;
1592 			case PCI_multimedia:
1593 				switch (subType) {
1594 					case PCI_audio:
1595 					case PCI_hd_audio:
1596 						_AddPath(*stack, "drivers", "audio");
1597 						break;
1598 					case PCI_video:
1599 						_AddPath(*stack, "drivers", "video");
1600 						break;
1601 					default:
1602 						_AddPath(*stack, "drivers");
1603 						break;
1604 				}
1605 				break;
1606 			default:
1607 				if (sRootNode == this) {
1608 					_AddPath(*stack, "busses/pci");
1609 					_AddPath(*stack, "bus_managers");
1610 				} else if (!generic) {
1611 					_AddPath(*stack, "drivers");
1612 				} else {
1613 					// For generic drivers, we only allow busses when the
1614 					// request is more specified
1615 					if (sGenericContextPath != NULL
1616 						&& (!strcmp(sGenericContextPath, "disk")
1617 							|| !strcmp(sGenericContextPath, "ports")
1618 							|| !strcmp(sGenericContextPath, "bus"))) {
1619 						_AddPath(*stack, "busses");
1620 					}
1621 					_AddPath(*stack, "drivers", sGenericContextPath);
1622 					_AddPath(*stack, "busses/scsi");
1623 				}
1624 				break;
1625 		}
1626 
1627 		stackDeleter.Detach();
1628 
1629 		cookie = (void*)stack;
1630 	} else
1631 		stack = static_cast<Stack<KPath*>*>(cookie);
1632 
1633 	KPath* path;
1634 	if (stack->Pop(&path)) {
1635 		_path.Adopt(*path);
1636 		delete path;
1637 		return B_OK;
1638 	}
1639 
1640 	delete stack;
1641 	return B_ENTRY_NOT_FOUND;
1642 }
1643 
1644 
1645 status_t
1646 device_node::_GetNextDriver(void* list, driver_module_info*& driver)
1647 {
1648 	while (true) {
1649 		char name[B_FILE_NAME_LENGTH];
1650 		size_t nameLength = sizeof(name);
1651 
1652 		status_t status = read_next_module_name(list, name, &nameLength);
1653 		if (status != B_OK)
1654 			return status;
1655 
1656 		if (!strcmp(fModuleName, name))
1657 			continue;
1658 
1659 		if (get_module(name, (module_info**)&driver) != B_OK)
1660 			continue;
1661 
1662 		if (driver->supports_device == NULL
1663 			|| driver->register_device == NULL) {
1664 			put_module(name);
1665 			continue;
1666 		}
1667 
1668 		return B_OK;
1669 	}
1670 }
1671 
1672 
1673 status_t
1674 device_node::_FindBestDriver(const char* path, driver_module_info*& bestDriver,
1675 	float& bestSupport, device_node* previous)
1676 {
1677 	if (bestDriver == NULL)
1678 		bestSupport = previous != NULL ? previous->fSupportsParent : 0.0f;
1679 
1680 	void* list = open_module_list_etc(path, "driver_v1");
1681 	driver_module_info* driver;
1682 	while (_GetNextDriver(list, driver) == B_OK) {
1683 		if (previous != NULL && driver == previous->DriverModule()) {
1684 			put_module(driver->info.name);
1685 			continue;
1686 		}
1687 
1688 		float support = driver->supports_device(this);
1689 		if (support > bestSupport) {
1690 			if (bestDriver != NULL)
1691 				put_module(bestDriver->info.name);
1692 
1693 			bestDriver = driver;
1694 			bestSupport = support;
1695 			continue;
1696 				// keep reference to best module around
1697 		}
1698 
1699 		put_module(driver->info.name);
1700 	}
1701 	close_module_list(list);
1702 
1703 	return bestDriver != NULL ? B_OK : B_ENTRY_NOT_FOUND;
1704 }
1705 
1706 
1707 status_t
1708 device_node::_RegisterPath(const char* path)
1709 {
1710 	void* list = open_module_list_etc(path, "driver_v1");
1711 	driver_module_info* driver;
1712 	uint32 count = 0;
1713 
1714 	while (_GetNextDriver(list, driver) == B_OK) {
1715 		float support = driver->supports_device(this);
1716 		if (support > 0.0) {
1717 			TRACE(("  register module \"%s\", support %f\n", driver->info.name,
1718 				support));
1719 			if (driver->register_device(this) == B_OK)
1720 				count++;
1721 		}
1722 
1723 		put_module(driver->info.name);
1724 	}
1725 	close_module_list(list);
1726 
1727 	return count > 0 ? B_OK : B_ENTRY_NOT_FOUND;
1728 }
1729 
1730 
1731 bool
1732 device_node::_AlwaysRegisterDynamic()
1733 {
1734 	uint16 type = 0;
1735 	uint16 subType = 0;
1736 	get_attr_uint16(this, B_DEVICE_TYPE, &type, false);
1737 	get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false);
1738 
1739 	return type == PCI_serial_bus || type == PCI_bridge;
1740 		// TODO: we may want to be a bit more specific in the future
1741 }
1742 
1743 
1744 status_t
1745 device_node::_RegisterDynamic(device_node* previous)
1746 {
1747 	// If this is not a bus, we don't have to scan it
1748 	if (find_attr(this, B_DEVICE_BUS, false, B_STRING_TYPE) == NULL)
1749 		return B_OK;
1750 
1751 	// If we're not being probed, we honour the B_FIND_CHILD_ON_DEMAND
1752 	// requirements
1753 	if (!IsProbed() && (fFlags & B_FIND_CHILD_ON_DEMAND) != 0
1754 		&& !_AlwaysRegisterDynamic())
1755 		return B_OK;
1756 
1757 	KPath path;
1758 
1759 	if ((fFlags & B_FIND_MULTIPLE_CHILDREN) == 0) {
1760 		// find the one driver
1761 		driver_module_info* bestDriver = NULL;
1762 		float bestSupport = 0.0;
1763 		void* cookie = NULL;
1764 
1765 		while (_GetNextDriverPath(cookie, path) == B_OK) {
1766 			_FindBestDriver(path.Path(), bestDriver, bestSupport, previous);
1767 		}
1768 
1769 		if (bestDriver != NULL) {
1770 			TRACE(("  register best module \"%s\", support %f\n",
1771 				bestDriver->info.name, bestSupport));
1772 			if (bestDriver->register_device(this) == B_OK) {
1773 				// There can only be one node of this driver
1774 				// (usually only one at all, but there might be a new driver
1775 				// "waiting" for its turn)
1776 				device_node* child = FindChild(bestDriver->info.name);
1777 				if (child != NULL) {
1778 					child->fSupportsParent = bestSupport;
1779 					if (previous != NULL) {
1780 						previous->fFlags |= NODE_FLAG_OBSOLETE_DRIVER;
1781 						previous->Release();
1782 						child->fFlags |= NODE_FLAG_WAITING_FOR_DRIVER;
1783 					}
1784 				}
1785 				// TODO: if this fails, we could try the second best driver,
1786 				// and so on...
1787 			}
1788 			put_module(bestDriver->info.name);
1789 		}
1790 	} else {
1791 		// register all drivers that match
1792 		void* cookie = NULL;
1793 		while (_GetNextDriverPath(cookie, path) == B_OK) {
1794 			_RegisterPath(path.Path());
1795 		}
1796 	}
1797 
1798 	return B_OK;
1799 }
1800 
1801 
1802 void
1803 device_node::_ReleaseWaiting()
1804 {
1805 	NodeList::Iterator iterator = fChildren.GetIterator();
1806 	while (iterator.HasNext()) {
1807 		device_node* child = iterator.Next();
1808 
1809 		child->fFlags &= ~NODE_FLAG_WAITING_FOR_DRIVER;
1810 	}
1811 }
1812 
1813 
1814 status_t
1815 device_node::_RemoveChildren()
1816 {
1817 	NodeList::Iterator iterator = fChildren.GetIterator();
1818 	while (iterator.HasNext()) {
1819 		device_node* child = iterator.Next();
1820 		child->Release();
1821 	}
1822 
1823 	return fChildren.IsEmpty() ? B_OK : B_BUSY;
1824 }
1825 
1826 
1827 device_node*
1828 device_node::_FindCurrentChild()
1829 {
1830 	NodeList::Iterator iterator = fChildren.GetIterator();
1831 	while (iterator.HasNext()) {
1832 		device_node* child = iterator.Next();
1833 
1834 		if ((child->Flags() & NODE_FLAG_WAITING_FOR_DRIVER) == 0)
1835 			return child;
1836 	}
1837 
1838 	return NULL;
1839 }
1840 
1841 
1842 status_t
1843 device_node::_Probe()
1844 {
1845 	device_node* previous = NULL;
1846 
1847 	if (IsProbed() && !fChildren.IsEmpty()
1848 		&& (fFlags & (B_FIND_CHILD_ON_DEMAND | B_FIND_MULTIPLE_CHILDREN))
1849 				== B_FIND_CHILD_ON_DEMAND) {
1850 		// We already have a driver that claims this node; remove all
1851 		// (unused) nodes, and evaluate it again
1852 		_RemoveChildren();
1853 
1854 		previous = _FindCurrentChild();
1855 		if (previous != NULL) {
1856 			// This driver is still active - give it back the reference
1857 			// that was stolen by _RemoveChildren() - _RegisterDynamic()
1858 			// will release it, if it really isn't needed anymore
1859 			previous->Acquire();
1860 		}
1861 	}
1862 
1863 	return _RegisterDynamic(previous);
1864 }
1865 
1866 
1867 status_t
1868 device_node::Probe(const char* devicePath, uint32 updateCycle)
1869 {
1870 	if ((fFlags & NODE_FLAG_DEVICE_REMOVED) != 0
1871 		|| updateCycle == fLastUpdateCycle)
1872 		return B_OK;
1873 
1874 	status_t status = InitDriver();
1875 	if (status < B_OK)
1876 		return status;
1877 
1878 	MethodDeleter<device_node, bool> uninit(this,
1879 		&device_node::UninitDriver);
1880 
1881 	if ((fFlags & B_FIND_CHILD_ON_DEMAND) != 0) {
1882 		bool matches = false;
1883 		uint16 type = 0;
1884 		uint16 subType = 0;
1885 		if (get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false) == B_OK
1886 			&& get_attr_uint16(this, B_DEVICE_TYPE, &type, false) == B_OK) {
1887 			// Check if this node matches the device path
1888 			// TODO: maybe make this extendible via settings file?
1889 			if (!strcmp(devicePath, "disk")) {
1890 				matches = type == PCI_mass_storage;
1891 			} else if (!strcmp(devicePath, "audio")) {
1892 				matches = type == PCI_multimedia
1893 					&& (subType == PCI_audio || subType == PCI_hd_audio);
1894 			} else if (!strcmp(devicePath, "net")) {
1895 				matches = type == PCI_network;
1896 			} else if (!strcmp(devicePath, "graphics")) {
1897 				matches = type == PCI_display;
1898 			} else if (!strcmp(devicePath, "video")) {
1899 				matches = type == PCI_multimedia && subType == PCI_video;
1900 			}
1901 		} else {
1902 			// This driver does not support types, but still wants to its
1903 			// children explored on demand only.
1904 			matches = true;
1905 			sGenericContextPath = devicePath;
1906 		}
1907 
1908 		if (matches) {
1909 			fLastUpdateCycle = updateCycle;
1910 				// This node will be probed in this update cycle
1911 
1912 			status = _Probe();
1913 
1914 			sGenericContextPath = NULL;
1915 			return status;
1916 		}
1917 
1918 		return B_OK;
1919 	}
1920 
1921 	NodeList::Iterator iterator = fChildren.GetIterator();
1922 	while (iterator.HasNext()) {
1923 		device_node* child = iterator.Next();
1924 
1925 		status = child->Probe(devicePath, updateCycle);
1926 		if (status != B_OK)
1927 			return status;
1928 	}
1929 
1930 	return B_OK;
1931 }
1932 
1933 
1934 status_t
1935 device_node::Reprobe()
1936 {
1937 	status_t status = InitDriver();
1938 	if (status < B_OK)
1939 		return status;
1940 
1941 	MethodDeleter<device_node, bool> uninit(this,
1942 		&device_node::UninitDriver);
1943 
1944 	// If this child has been probed already, probe it again
1945 	status = _Probe();
1946 	if (status != B_OK)
1947 		return status;
1948 
1949 	NodeList::Iterator iterator = fChildren.GetIterator();
1950 	while (iterator.HasNext()) {
1951 		device_node* child = iterator.Next();
1952 
1953 		status = child->Reprobe();
1954 		if (status != B_OK)
1955 			return status;
1956 	}
1957 
1958 	return B_OK;
1959 }
1960 
1961 
1962 status_t
1963 device_node::Rescan()
1964 {
1965 	status_t status = InitDriver();
1966 	if (status < B_OK)
1967 		return status;
1968 
1969 	MethodDeleter<device_node, bool> uninit(this,
1970 		&device_node::UninitDriver);
1971 
1972 	if (DriverModule()->rescan_child_devices != NULL) {
1973 		status = DriverModule()->rescan_child_devices(DriverData());
1974 		if (status != B_OK)
1975 			return status;
1976 	}
1977 
1978 	NodeList::Iterator iterator = fChildren.GetIterator();
1979 	while (iterator.HasNext()) {
1980 		device_node* child = iterator.Next();
1981 
1982 		status = child->Rescan();
1983 		if (status != B_OK)
1984 			return status;
1985 	}
1986 
1987 	return B_OK;
1988 }
1989 
1990 
1991 /*!	Uninitializes all temporary references to the driver. The registration
1992 	process keeps the driver initialized to optimize the startup procedure;
1993 	this function gives this reference away again.
1994 */
1995 void
1996 device_node::UninitUnusedDriver()
1997 {
1998 	// First, we need to go to the leaf, and go back from there
1999 
2000 	NodeList::Iterator iterator = fChildren.GetIterator();
2001 	while (iterator.HasNext()) {
2002 		device_node* child = iterator.Next();
2003 
2004 		child->UninitUnusedDriver();
2005 	}
2006 
2007 	if (!IsInitialized()
2008 		|| (fFlags & NODE_FLAG_REGISTER_INITIALIZED) == 0)
2009 		return;
2010 
2011 	fFlags &= ~NODE_FLAG_REGISTER_INITIALIZED;
2012 
2013 	UninitDriver();
2014 }
2015 
2016 
2017 /*!	Calls device_removed() on this node and all of its children - starting
2018 	with the deepest and last child.
2019 	It will also remove the one reference that every node gets on its creation.
2020 */
2021 void
2022 device_node::DeviceRemoved()
2023 {
2024 	// notify children
2025 	NodeList::ConstIterator iterator = Children().GetIterator();
2026 	while (iterator.HasNext()) {
2027 		device_node* child = iterator.Next();
2028 
2029 		child->DeviceRemoved();
2030 	}
2031 
2032 	// notify devices
2033 	DeviceList::ConstIterator deviceIterator = Devices().GetIterator();
2034 	while (deviceIterator.HasNext()) {
2035 		Device* device = deviceIterator.Next();
2036 
2037 		if (device->Module() != NULL
2038 			&& device->Module()->device_removed != NULL)
2039 			device->Module()->device_removed(device->Data());
2040 	}
2041 
2042 	fFlags |= NODE_FLAG_DEVICE_REMOVED;
2043 
2044 	if (IsInitialized() && DriverModule()->device_removed != NULL)
2045 		DriverModule()->device_removed(this);
2046 
2047 	if ((fFlags & B_KEEP_DRIVER_LOADED) != 0) {
2048 		// There is no point in keeping this driver loaded when its device
2049 		// is gone
2050 		UninitDriver();
2051 	}
2052 
2053 	UninitUnusedDriver();
2054 	Release();
2055 }
2056 
2057 
2058 void
2059 device_node::Acquire()
2060 {
2061 	atomic_add(&fRefCount, 1);
2062 }
2063 
2064 
2065 bool
2066 device_node::Release()
2067 {
2068 	if (atomic_add(&fRefCount, -1) > 1)
2069 		return false;
2070 
2071 	delete this;
2072 	return true;
2073 }
2074 
2075 
2076 void
2077 device_node::AddDevice(Device* device)
2078 {
2079 	fDevices.Add(device);
2080 }
2081 
2082 
2083 void
2084 device_node::RemoveDevice(Device* device)
2085 {
2086 	fDevices.Remove(device);
2087 }
2088 
2089 
2090 int
2091 device_node::CompareTo(const device_attr* attributes) const
2092 {
2093 	if (attributes == NULL)
2094 		return -1;
2095 
2096 	for (; attributes->name != NULL; attributes++) {
2097 		// find corresponding attribute
2098 		AttributeList::ConstIterator iterator = Attributes().GetIterator();
2099 		device_attr_private* attr = NULL;
2100 		bool found = false;
2101 
2102 		while (iterator.HasNext()) {
2103 			attr = iterator.Next();
2104 
2105 			if (!strcmp(attr->name, attributes->name)) {
2106 				found = true;
2107 				break;
2108 			}
2109 		}
2110 		if (!found)
2111 			return -1;
2112 
2113 		int compare = device_attr_private::Compare(attr, attributes);
2114 		if (compare != 0)
2115 			return compare;
2116 	}
2117 
2118 	return 0;
2119 }
2120 
2121 
2122 device_node*
2123 device_node::FindChild(const device_attr* attributes) const
2124 {
2125 	if (attributes == NULL)
2126 		return NULL;
2127 
2128 	NodeList::ConstIterator iterator = Children().GetIterator();
2129 	while (iterator.HasNext()) {
2130 		device_node* child = iterator.Next();
2131 
2132 		// ignore nodes that are pending to be removed
2133 		if ((child->Flags() & NODE_FLAG_DEVICE_REMOVED) == 0
2134 			&& !child->CompareTo(attributes))
2135 			return child;
2136 	}
2137 
2138 	return NULL;
2139 }
2140 
2141 
2142 device_node*
2143 device_node::FindChild(const char* moduleName) const
2144 {
2145 	if (moduleName == NULL)
2146 		return NULL;
2147 
2148 	NodeList::ConstIterator iterator = Children().GetIterator();
2149 	while (iterator.HasNext()) {
2150 		device_node* child = iterator.Next();
2151 
2152 		if (!strcmp(child->ModuleName(), moduleName))
2153 			return child;
2154 	}
2155 
2156 	return NULL;
2157 }
2158 
2159 
2160 /*!	This returns the priority or importance of this node. Nodes with higher
2161 	priority are registered/probed first.
2162 	Currently, only the B_FIND_MULTIPLE_CHILDREN flag alters the priority;
2163 	it might make sense to be able to directly set the priority via an
2164 	attribute.
2165 */
2166 int32
2167 device_node::Priority()
2168 {
2169 	return (fFlags & B_FIND_MULTIPLE_CHILDREN) != 0 ? 0 : 100;
2170 }
2171 
2172 
2173 void
2174 device_node::Dump(int32 level)
2175 {
2176 	put_level(level);
2177 	kprintf("(%" B_PRId32 ") @%p \"%s\" (ref %" B_PRId32 ", init %" B_PRId32
2178 		", module %p, data %p)\n", level, this, ModuleName(), fRefCount,
2179 		fInitialized, DriverModule(), DriverData());
2180 
2181 	AttributeList::Iterator attribute = Attributes().GetIterator();
2182 	while (attribute.HasNext()) {
2183 		dump_attribute(attribute.Next(), level);
2184 	}
2185 
2186 	DeviceList::Iterator deviceIterator = fDevices.GetIterator();
2187 	while (deviceIterator.HasNext()) {
2188 		Device* device = deviceIterator.Next();
2189 		put_level(level);
2190 		kprintf("device: %s, %p\n", device->ModuleName(), device->Data());
2191 	}
2192 
2193 	NodeList::ConstIterator iterator = Children().GetIterator();
2194 	while (iterator.HasNext()) {
2195 		iterator.Next()->Dump(level + 1);
2196 	}
2197 }
2198 
2199 
2200 //	#pragma mark - root node
2201 
2202 
2203 static void
2204 init_node_tree(void)
2205 {
2206 	device_attr attrs[] = {
2207 		{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "Devices Root"}},
2208 		{B_DEVICE_BUS, B_STRING_TYPE, {string: "root"}},
2209 		{B_DEVICE_FLAGS, B_UINT32_TYPE,
2210 			{ui32: B_FIND_MULTIPLE_CHILDREN | B_KEEP_DRIVER_LOADED }},
2211 		{NULL}
2212 	};
2213 
2214 	device_node* node;
2215 	if (register_node(NULL, DEVICE_MANAGER_ROOT_NAME, attrs, NULL, &node)
2216 			!= B_OK) {
2217 		dprintf("Cannot register Devices Root Node\n");
2218 	}
2219 
2220 	device_attr genericAttrs[] = {
2221 		{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "Generic"}},
2222 		{B_DEVICE_BUS, B_STRING_TYPE, {string: "generic"}},
2223 		{B_DEVICE_FLAGS, B_UINT32_TYPE, {ui32: B_FIND_MULTIPLE_CHILDREN
2224 			| B_KEEP_DRIVER_LOADED | B_FIND_CHILD_ON_DEMAND}},
2225 		{NULL}
2226 	};
2227 
2228 	if (register_node(node, DEVICE_MANAGER_GENERIC_NAME, genericAttrs, NULL,
2229 			NULL) != B_OK) {
2230 		dprintf("Cannot register Generic Devices Node\n");
2231 	}
2232 }
2233 
2234 
2235 driver_module_info gDeviceRootModule = {
2236 	{
2237 		DEVICE_MANAGER_ROOT_NAME,
2238 		0,
2239 		NULL,
2240 	},
2241 };
2242 
2243 
2244 driver_module_info gDeviceGenericModule = {
2245 	{
2246 		DEVICE_MANAGER_GENERIC_NAME,
2247 		0,
2248 		NULL,
2249 	},
2250 	NULL
2251 };
2252 
2253 
2254 //	#pragma mark - private kernel API
2255 
2256 
2257 status_t
2258 device_manager_probe(const char* path, uint32 updateCycle)
2259 {
2260 	TRACE(("device_manager_probe(\"%s\")\n", path));
2261 	RecursiveLocker _(sLock);
2262 
2263 	// first, publish directories in the driver directory
2264 	publish_directories(path);
2265 
2266 	return sRootNode->Probe(path, updateCycle);
2267 }
2268 
2269 
2270 status_t
2271 device_manager_init(struct kernel_args* args)
2272 {
2273 	TRACE(("device manager init\n"));
2274 
2275 	IOSchedulerRoster::Init();
2276 
2277 	dm_init_id_generator();
2278 	dm_init_io_resources();
2279 
2280 	recursive_lock_init(&sLock, "device manager");
2281 	init_node_tree();
2282 
2283 	register_generic_syscall(DEVICE_MANAGER_SYSCALLS, control_device_manager,
2284 		1, 0);
2285 
2286 	add_debugger_command("dm_tree", &dump_device_nodes,
2287 		"dump device node tree");
2288 	add_debugger_command_etc("io_scheduler", &dump_io_scheduler,
2289 		"Dump an I/O scheduler",
2290 		"<scheduler>\n"
2291 		"Dumps I/O scheduler at address <scheduler>.\n", 0);
2292 	add_debugger_command_etc("io_request_owner", &dump_io_request_owner,
2293 		"Dump an I/O request owner",
2294 		"<owner>\n"
2295 		"Dumps I/O request owner at address <owner>.\n", 0);
2296 	add_debugger_command("io_request", &dump_io_request, "dump an I/O request");
2297 	add_debugger_command("io_operation", &dump_io_operation,
2298 		"dump an I/O operation");
2299 	add_debugger_command("io_buffer", &dump_io_buffer, "dump an I/O buffer");
2300 	add_debugger_command("dma_buffer", &dump_dma_buffer, "dump a DMA buffer");
2301 	return B_OK;
2302 }
2303 
2304 
2305 status_t
2306 device_manager_init_post_modules(struct kernel_args* args)
2307 {
2308 	RecursiveLocker _(sLock);
2309 	return sRootNode->Reprobe();
2310 }
2311 
2312