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