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