xref: /haiku/src/system/kernel/device_manager/device_manager.cpp (revision 1e60bdeab63fa7a57bc9a55b032052e95a18bd2c)
1 /*
2  * Copyright 2008-2009, Axel Dörfler, axeld@pinc-software.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <kdevice_manager.h>
8 
9 #include <new>
10 #include <set>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include <KernelExport.h>
16 #include <Locker.h>
17 #include <module.h>
18 #include <PCI.h>
19 
20 #include <boot_device.h>
21 #include <device_manager_defs.h>
22 #include <fs/devfs.h>
23 #include <fs/KPath.h>
24 #include <kernel.h>
25 #include <generic_syscall.h>
26 #include <util/AutoLock.h>
27 #include <util/DoublyLinkedList.h>
28 #include <util/Stack.h>
29 
30 #include "AbstractModuleDevice.h"
31 #include "devfs_private.h"
32 #include "id_generator.h"
33 #include "IORequest.h"
34 #include "io_resources.h"
35 #include "IOSchedulerRoster.h"
36 
37 
38 //#define TRACE_DEVICE_MANAGER
39 #ifdef TRACE_DEVICE_MANAGER
40 #	define TRACE(a) dprintf a
41 #else
42 #	define TRACE(a) ;
43 #endif
44 
45 
46 #define DEVICE_MANAGER_ROOT_NAME "system/devices_root/driver_v1"
47 #define DEVICE_MANAGER_GENERIC_NAME "system/devices_generic/driver_v1"
48 
49 
50 struct device_attr_private : device_attr,
51 		DoublyLinkedListLinkImpl<device_attr_private> {
52 						device_attr_private();
53 						device_attr_private(const device_attr& attr);
54 						~device_attr_private();
55 
56 			status_t	InitCheck();
57 			status_t	CopyFrom(const device_attr& attr);
58 
59 	static	int			Compare(const device_attr* attrA,
60 							const device_attr *attrB);
61 
62 private:
63 			void		_Unset();
64 };
65 
66 typedef DoublyLinkedList<device_attr_private> AttributeList;
67 
68 // I/O resource
69 typedef struct io_resource_info {
70 	struct io_resource_info *prev, *next;
71 	device_node*		owner;			// associated node; NULL for temporary allocation
72 	io_resource			resource;		// info about actual resource
73 } io_resource_info;
74 
75 
76 namespace {
77 
78 
79 class Device : public AbstractModuleDevice,
80 	public DoublyLinkedListLinkImpl<Device> {
81 public:
82 							Device(device_node* node, const char* moduleName);
83 	virtual					~Device();
84 
85 			status_t		InitCheck() const;
86 
87 			const char*		ModuleName() const { return fModuleName; }
88 
89 	virtual	status_t		InitDevice();
90 	virtual	void			UninitDevice();
91 
92 	virtual void			Removed();
93 
94 			void			SetRemovedFromParent(bool removed)
95 								{ fRemovedFromParent = removed; }
96 
97 private:
98 	const char*				fModuleName;
99 	bool					fRemovedFromParent;
100 };
101 
102 
103 } // unnamed namespace
104 
105 
106 typedef DoublyLinkedList<Device> DeviceList;
107 typedef DoublyLinkedList<device_node> NodeList;
108 
109 struct device_node : DoublyLinkedListLinkImpl<device_node> {
110 							device_node(const char* moduleName,
111 								const device_attr* attrs);
112 							~device_node();
113 
114 			status_t		InitCheck() const;
115 
116 			status_t		AcquireResources(const io_resource* resources);
117 
118 			const char*		ModuleName() const { return fModuleName; }
119 			device_node*	Parent() const { return fParent; }
120 			AttributeList&	Attributes() { return fAttributes; }
121 			const AttributeList& Attributes() const { return fAttributes; }
122 
123 			status_t		InitDriver();
124 			bool			UninitDriver();
125 			void			UninitUnusedDriver();
126 
127 			// The following two are only valid, if the node's driver is
128 			// initialized
129 			driver_module_info* DriverModule() const { return fDriver; }
130 			void*			DriverData() const { return fDriverData; }
131 
132 			void			AddChild(device_node *node);
133 			void			RemoveChild(device_node *node);
134 			const NodeList&	Children() const { return fChildren; }
135 			void			DeviceRemoved();
136 
137 			status_t		Register(device_node* parent);
138 			status_t		Probe(const char* devicePath, uint32 updateCycle);
139 			status_t		Reprobe();
140 			status_t		Rescan();
141 
142 			bool			IsRegistered() const { return fRegistered; }
143 			bool			IsInitialized() const { return fInitialized > 0; }
144 			bool			IsProbed() const { return fLastUpdateCycle != 0; }
145 			uint32			Flags() const { return fFlags; }
146 
147 			void			Acquire();
148 			bool			Release();
149 
150 			const DeviceList& Devices() const { return fDevices; }
151 			void			AddDevice(Device* device);
152 			void			RemoveDevice(Device* device);
153 
154 			int				CompareTo(const device_attr* attributes) const;
155 			device_node*	FindChild(const device_attr* attributes) const;
156 			device_node*	FindChild(const char* moduleName) const;
157 
158 			int32			Priority();
159 
160 			void			Dump(int32 level = 0);
161 
162 private:
163 			status_t		_RegisterFixed(uint32& registered);
164 			bool			_AlwaysRegisterDynamic();
165 			status_t		_AddPath(Stack<KPath*>& stack, const char* path,
166 								const char* subPath = NULL);
167 			status_t		_GetNextDriverPath(void*& cookie, KPath& _path);
168 			status_t		_GetNextDriver(void* list,
169 								driver_module_info*& driver);
170 			status_t		_FindBestDriver(const char* path,
171 								driver_module_info*& bestDriver,
172 								float& bestSupport,
173 								device_node* previous = NULL);
174 			status_t		_RegisterPath(const char* path);
175 			status_t		_RegisterDynamic(device_node* previous = NULL);
176 			status_t		_RemoveChildren();
177 			device_node*	_FindCurrentChild();
178 			status_t		_Probe();
179 			void			_ReleaseWaiting();
180 
181 	device_node*			fParent;
182 	NodeList				fChildren;
183 	int32					fRefCount;
184 	int32					fInitialized;
185 	bool					fRegistered;
186 	uint32					fFlags;
187 	float					fSupportsParent;
188 	uint32					fLastUpdateCycle;
189 
190 	const char*				fModuleName;
191 
192 	driver_module_info*		fDriver;
193 	void*					fDriverData;
194 
195 	DeviceList				fDevices;
196 	AttributeList			fAttributes;
197 	ResourceList			fResources;
198 };
199 
200 // flags in addition to those specified by B_DEVICE_FLAGS
201 enum node_flags {
202 	NODE_FLAG_REGISTER_INITIALIZED	= 0x00010000,
203 	NODE_FLAG_DEVICE_REMOVED		= 0x00020000,
204 	NODE_FLAG_OBSOLETE_DRIVER		= 0x00040000,
205 	NODE_FLAG_WAITING_FOR_DRIVER	= 0x00080000,
206 
207 	NODE_FLAG_PUBLIC_MASK			= 0x0000ffff
208 };
209 
210 
211 static device_node *sRootNode;
212 static recursive_lock sLock;
213 static const char* sGenericContextPath;
214 
215 
216 //	#pragma mark -
217 
218 
219 static device_attr_private*
220 find_attr(const device_node* node, const char* name, bool recursive,
221 	type_code type)
222 {
223 	do {
224 		AttributeList::ConstIterator iterator
225 			= node->Attributes().GetIterator();
226 
227 		while (iterator.HasNext()) {
228 			device_attr_private* attr = iterator.Next();
229 
230 			if (type != B_ANY_TYPE && attr->type != type)
231 				continue;
232 
233 			if (!strcmp(attr->name, name))
234 				return attr;
235 		}
236 
237 		node = node->Parent();
238 	} while (node != NULL && recursive);
239 
240 	return NULL;
241 }
242 
243 
244 static void
245 put_level(int32 level)
246 {
247 	while (level-- > 0)
248 		kprintf("   ");
249 }
250 
251 
252 static void
253 dump_attribute(device_attr* attr, int32 level)
254 {
255 	if (attr == NULL)
256 		return;
257 
258 	put_level(level + 2);
259 	kprintf("\"%s\" : ", attr->name);
260 	switch (attr->type) {
261 		case B_STRING_TYPE:
262 			kprintf("string : \"%s\"", attr->value.string);
263 			break;
264 		case B_INT8_TYPE:
265 		case B_UINT8_TYPE:
266 			kprintf("uint8 : %" B_PRIu8 " (%#" B_PRIx8 ")", attr->value.ui8,
267 				attr->value.ui8);
268 			break;
269 		case B_INT16_TYPE:
270 		case B_UINT16_TYPE:
271 			kprintf("uint16 : %" B_PRIu16 " (%#" B_PRIx16 ")", attr->value.ui16,
272 				attr->value.ui16);
273 			break;
274 		case B_INT32_TYPE:
275 		case B_UINT32_TYPE:
276 			kprintf("uint32 : %" B_PRIu32 " (%#" B_PRIx32 ")", attr->value.ui32,
277 				attr->value.ui32);
278 			break;
279 		case B_INT64_TYPE:
280 		case B_UINT64_TYPE:
281 			kprintf("uint64 : %" B_PRIu64 " (%#" B_PRIx64 ")", attr->value.ui64,
282 				attr->value.ui64);
283 			break;
284 		default:
285 			kprintf("raw data");
286 	}
287 	kprintf("\n");
288 }
289 
290 
291 static int
292 dump_io_scheduler(int argc, char** argv)
293 {
294 	if (argc != 2) {
295 		print_debugger_command_usage(argv[0]);
296 		return 0;
297 	}
298 
299 	IOScheduler* scheduler = (IOScheduler*)parse_expression(argv[1]);
300 	scheduler->Dump();
301 	return 0;
302 }
303 
304 
305 static int
306 dump_io_request_owner(int argc, char** argv)
307 {
308 	if (argc != 2) {
309 		print_debugger_command_usage(argv[0]);
310 		return 0;
311 	}
312 
313 	IORequestOwner* owner = (IORequestOwner*)parse_expression(argv[1]);
314 	owner->Dump();
315 	return 0;
316 }
317 
318 
319 static int
320 dump_io_request(int argc, char** argv)
321 {
322 	if (argc != 2 || !strcmp(argv[1], "--help")) {
323 		kprintf("usage: %s <ptr-to-io-request>\n", argv[0]);
324 		return 0;
325 	}
326 
327 	IORequest* request = (IORequest*)parse_expression(argv[1]);
328 	request->Dump();
329 	return 0;
330 }
331 
332 
333 static int
334 dump_io_operation(int argc, char** argv)
335 {
336 	if (argc != 2 || !strcmp(argv[1], "--help")) {
337 		kprintf("usage: %s <ptr-to-io-operation>\n", argv[0]);
338 		return 0;
339 	}
340 
341 	IOOperation* operation = (IOOperation*)parse_expression(argv[1]);
342 	operation->Dump();
343 	return 0;
344 }
345 
346 
347 static int
348 dump_io_buffer(int argc, char** argv)
349 {
350 	if (argc != 2 || !strcmp(argv[1], "--help")) {
351 		kprintf("usage: %s <ptr-to-io-buffer>\n", argv[0]);
352 		return 0;
353 	}
354 
355 	IOBuffer* buffer = (IOBuffer*)parse_expression(argv[1]);
356 	buffer->Dump();
357 	return 0;
358 }
359 
360 
361 static int
362 dump_dma_buffer(int argc, char** argv)
363 {
364 	if (argc != 2 || !strcmp(argv[1], "--help")) {
365 		kprintf("usage: %s <ptr-to-dma-buffer>\n", argv[0]);
366 		return 0;
367 	}
368 
369 	DMABuffer* buffer = (DMABuffer*)parse_expression(argv[1]);
370 	buffer->Dump();
371 	return 0;
372 }
373 
374 
375 static int
376 dump_device_nodes(int argc, char** argv)
377 {
378 	sRootNode->Dump();
379 	return 0;
380 }
381 
382 
383 static void
384 publish_directories(const char* subPath)
385 {
386 	if (gBootDevice < 0) {
387 		if (subPath[0]) {
388 			// we only support the top-level directory for modules
389 			return;
390 		}
391 
392 		// we can only iterate over the known modules to find all directories
393 		KPath path("drivers");
394 		if (path.Append(subPath) != B_OK)
395 			return;
396 
397 		size_t length = strlen(path.Path()) + 1;
398 			// account for the separating '/'
399 
400 		void* list = open_module_list_etc(path.Path(), "driver_v1");
401 		char name[B_FILE_NAME_LENGTH];
402 		size_t nameLength = sizeof(name);
403 		while (read_next_module_name(list, name, &nameLength) == B_OK) {
404 			if (nameLength == length)
405 				continue;
406 
407 			char* leaf = name + length;
408 			char* end = strchr(leaf, '/');
409 			if (end != NULL)
410 				end[0] = '\0';
411 
412 			path.SetTo(subPath);
413 			path.Append(leaf);
414 
415 			devfs_publish_directory(path.Path());
416 		}
417 		close_module_list(list);
418 	} else {
419 		// TODO: implement module directory traversal!
420 	}
421 }
422 
423 
424 static status_t
425 control_device_manager(const char* subsystem, uint32 function, void* buffer,
426 	size_t bufferSize)
427 {
428 	// TODO: this function passes pointers to userland, and uses pointers
429 	// to device nodes that came from userland - this is completely unsafe
430 	// and should be changed.
431 	switch (function) {
432 		case DM_GET_ROOT:
433 		{
434 			device_node_cookie cookie;
435 			if (!IS_USER_ADDRESS(buffer))
436 				return B_BAD_ADDRESS;
437 			if (bufferSize != sizeof(device_node_cookie))
438 				return B_BAD_VALUE;
439 			cookie = (device_node_cookie)sRootNode;
440 
441 			// copy back to user space
442 			return user_memcpy(buffer, &cookie, sizeof(device_node_cookie));
443 		}
444 
445 		case DM_GET_CHILD:
446 		{
447 			if (!IS_USER_ADDRESS(buffer))
448 				return B_BAD_ADDRESS;
449 			if (bufferSize != sizeof(device_node_cookie))
450 				return B_BAD_VALUE;
451 
452 			device_node_cookie cookie;
453 			if (user_memcpy(&cookie, buffer, sizeof(device_node_cookie)) < B_OK)
454 				return B_BAD_ADDRESS;
455 
456 			device_node* node = (device_node*)cookie;
457 			NodeList::ConstIterator iterator = node->Children().GetIterator();
458 
459 			if (!iterator.HasNext()) {
460 				return B_ENTRY_NOT_FOUND;
461 			}
462 			node = iterator.Next();
463 			cookie = (device_node_cookie)node;
464 
465 			// copy back to user space
466 			return user_memcpy(buffer, &cookie, sizeof(device_node_cookie));
467 		}
468 
469 		case DM_GET_NEXT_CHILD:
470 		{
471 			if (!IS_USER_ADDRESS(buffer))
472 				return B_BAD_ADDRESS;
473 			if (bufferSize != sizeof(device_node_cookie))
474 				return B_BAD_VALUE;
475 
476 			device_node_cookie cookie;
477 			if (user_memcpy(&cookie, buffer, sizeof(device_node_cookie)) < B_OK)
478 				return B_BAD_ADDRESS;
479 
480 			device_node* last = (device_node*)cookie;
481 			if (!last->Parent())
482 				return B_ENTRY_NOT_FOUND;
483 
484 			NodeList::ConstIterator iterator
485 				= last->Parent()->Children().GetIterator();
486 
487 			// skip those we already traversed
488 			while (iterator.HasNext()) {
489 				device_node* node = iterator.Next();
490 
491 				if (node == last)
492 					break;
493 			}
494 
495 			if (!iterator.HasNext())
496 				return B_ENTRY_NOT_FOUND;
497 			device_node* node = iterator.Next();
498 			cookie = (device_node_cookie)node;
499 
500 			// copy back to user space
501 			return user_memcpy(buffer, &cookie, sizeof(device_node_cookie));
502 		}
503 
504 		case DM_GET_NEXT_ATTRIBUTE:
505 		{
506 			struct device_attr_info attrInfo;
507 			if (!IS_USER_ADDRESS(buffer))
508 				return B_BAD_ADDRESS;
509 			if (bufferSize != sizeof(device_attr_info))
510 				return B_BAD_VALUE;
511 			if (user_memcpy(&attrInfo, buffer, sizeof(device_attr_info)) < B_OK)
512 				return B_BAD_ADDRESS;
513 
514 			device_node* node = (device_node*)attrInfo.node_cookie;
515 			device_attr* last = (device_attr*)attrInfo.cookie;
516 			AttributeList::Iterator iterator = node->Attributes().GetIterator();
517 			// skip those we already traversed
518 			while (iterator.HasNext() && last != NULL) {
519 				device_attr* attr = iterator.Next();
520 
521 				if (attr == last)
522 					break;
523 			}
524 
525 			if (!iterator.HasNext()) {
526 				attrInfo.cookie = 0;
527 				return B_ENTRY_NOT_FOUND;
528 			}
529 
530 			device_attr* attr = iterator.Next();
531 			attrInfo.cookie = (device_node_cookie)attr;
532 			strlcpy(attrInfo.name, attr->name, 254);
533 			attrInfo.type = attr->type;
534 			switch (attrInfo.type) {
535 				case B_UINT8_TYPE:
536 					attrInfo.value.ui8 = attr->value.ui8;
537 					break;
538 				case B_UINT16_TYPE:
539 					attrInfo.value.ui16 = attr->value.ui16;
540 					break;
541 				case B_UINT32_TYPE:
542 					attrInfo.value.ui32 = attr->value.ui32;
543 					break;
544 				case B_UINT64_TYPE:
545 					attrInfo.value.ui64 = attr->value.ui64;
546 					break;
547 				case B_STRING_TYPE:
548 					strlcpy(attrInfo.value.string, attr->value.string, 254);
549 					break;
550 				/*case B_RAW_TYPE:
551 					if (attr.value.raw.length > attr_info->attr.value.raw.length)
552 						attr.value.raw.length = attr_info->attr.value.raw.length;
553 					user_memcpy(attr.value.raw.data, attr_info->attr.value.raw.data,
554 						attr.value.raw.length);
555 					break;*/
556 			}
557 
558 			// copy back to user space
559 			return user_memcpy(buffer, &attrInfo, sizeof(device_attr_info));
560 		}
561 	}
562 
563 	return B_BAD_HANDLER;
564 }
565 
566 
567 //	#pragma mark - Device Manager module API
568 
569 
570 static status_t
571 rescan_node(device_node* node)
572 {
573 	RecursiveLocker _(sLock);
574 	return node->Rescan();
575 }
576 
577 
578 static status_t
579 register_node(device_node* parent, const char* moduleName,
580 	const device_attr* attrs, const io_resource* ioResources,
581 	device_node** _node)
582 {
583 	if ((parent == NULL && sRootNode != NULL) || moduleName == NULL)
584 		return B_BAD_VALUE;
585 
586 	if (parent != NULL && parent->FindChild(attrs) != NULL) {
587 		// A node like this one already exists for this parent
588 		return B_NAME_IN_USE;
589 	}
590 
591 	RecursiveLocker _(sLock);
592 
593 	device_node* newNode = new(std::nothrow) device_node(moduleName, attrs);
594 	if (newNode == NULL)
595 		return B_NO_MEMORY;
596 
597 	TRACE(("%p: register node \"%s\", parent %p\n", newNode, moduleName,
598 		parent));
599 
600 	status_t status = newNode->InitCheck();
601 	if (status == B_OK)
602 		status = newNode->AcquireResources(ioResources);
603 	if (status == B_OK)
604 		status = newNode->Register(parent);
605 
606 	if (status != B_OK) {
607 		newNode->Release();
608 		return status;
609 	}
610 
611 	if (_node)
612 		*_node = newNode;
613 
614 	return B_OK;
615 }
616 
617 
618 /*!	Unregisters the device \a node.
619 
620 	If the node is currently in use, this function will return B_BUSY to
621 	indicate that the node hasn't been removed yet - it will still remove
622 	the node as soon as possible.
623 */
624 static status_t
625 unregister_node(device_node* node)
626 {
627 	TRACE(("unregister_node(node %p)\n", node));
628 	RecursiveLocker _(sLock);
629 
630 	bool initialized = node->IsInitialized();
631 
632 	node->DeviceRemoved();
633 
634 	return initialized ? B_BUSY : B_OK;
635 }
636 
637 
638 static status_t
639 get_driver(device_node* node, driver_module_info** _module, void** _data)
640 {
641 	if (node->DriverModule() == NULL)
642 		return B_NO_INIT;
643 
644 	if (_module != NULL)
645 		*_module = node->DriverModule();
646 	if (_data != NULL)
647 		*_data = node->DriverData();
648 
649 	return B_OK;
650 }
651 
652 
653 static device_node*
654 get_root_node(void)
655 {
656 	if (sRootNode != NULL)
657 		sRootNode->Acquire();
658 
659 	return sRootNode;
660 }
661 
662 
663 static status_t
664 get_next_child_node(device_node* parent, const device_attr* attributes,
665 	device_node** _node)
666 {
667 	RecursiveLocker _(sLock);
668 
669 	NodeList::ConstIterator iterator = parent->Children().GetIterator();
670 	device_node* last = *_node;
671 
672 	// skip those we already traversed
673 	while (iterator.HasNext() && last != NULL) {
674 		device_node* node = iterator.Next();
675 
676 		if (node != last)
677 			continue;
678 	}
679 
680 	// find the next one that fits
681 	while (iterator.HasNext()) {
682 		device_node* node = iterator.Next();
683 
684 		if (!node->IsRegistered())
685 			continue;
686 
687 		if (!node->CompareTo(attributes)) {
688 			if (last != NULL)
689 				last->Release();
690 
691 			node->Acquire();
692 			*_node = node;
693 			return B_OK;
694 		}
695 	}
696 
697 	if (last != NULL)
698 		last->Release();
699 
700 	return B_ENTRY_NOT_FOUND;
701 }
702 
703 
704 static device_node*
705 get_parent_node(device_node* node)
706 {
707 	if (node == NULL)
708 		return NULL;
709 
710 	RecursiveLocker _(sLock);
711 
712 	device_node* parent = node->Parent();
713 	parent->Acquire();
714 
715 	return parent;
716 }
717 
718 
719 static void
720 put_node(device_node* node)
721 {
722 	RecursiveLocker _(sLock);
723 	node->Release();
724 }
725 
726 
727 static status_t
728 publish_device(device_node *node, const char *path, const char *moduleName)
729 {
730 	if (path == NULL || !path[0] || moduleName == NULL || !moduleName[0])
731 		return B_BAD_VALUE;
732 
733 	RecursiveLocker _(sLock);
734 	dprintf("publish device: node %p, path %s, module %s\n", node, path,
735 		moduleName);
736 
737 	Device* device = new(std::nothrow) Device(node, moduleName);
738 	if (device == NULL)
739 		return B_NO_MEMORY;
740 
741 	status_t status = device->InitCheck();
742 	if (status == B_OK)
743 		status = devfs_publish_device(path, device);
744 	if (status != B_OK) {
745 		delete device;
746 		return status;
747 	}
748 
749 	node->AddDevice(device);
750 	return B_OK;
751 }
752 
753 
754 static status_t
755 unpublish_device(device_node *node, const char *path)
756 {
757 	if (path == NULL)
758 		return B_BAD_VALUE;
759 
760 	BaseDevice* baseDevice;
761 	status_t error = devfs_get_device(path, baseDevice);
762 	if (error != B_OK)
763 		return error;
764 	CObjectDeleter<BaseDevice> baseDevicePutter(baseDevice, &devfs_put_device);
765 
766 	Device* device = dynamic_cast<Device*>(baseDevice);
767 	if (device == NULL || device->Node() != node)
768 		return B_BAD_VALUE;
769 
770 	return devfs_unpublish_device(device, true);
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\", %" B_PRId32 "\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 						_AddPath(*stack, "busses", "virtio");
1552 						break;
1553 					case PCI_ide:
1554 						_AddPath(*stack, "busses", "ata");
1555 						_AddPath(*stack, "busses", "ide");
1556 						break;
1557 					case PCI_sata:
1558 						// TODO: check for ahci interface
1559 						_AddPath(*stack, "busses", "scsi");
1560 						_AddPath(*stack, "busses", "ata");
1561 						_AddPath(*stack, "busses", "ide");
1562 						break;
1563 					default:
1564 						_AddPath(*stack, "busses");
1565 						break;
1566 				}
1567 				break;
1568 			case PCI_serial_bus:
1569 				switch (subType) {
1570 					case PCI_firewire:
1571 						_AddPath(*stack, "busses", "firewire");
1572 						break;
1573 					case PCI_usb:
1574 						_AddPath(*stack, "busses", "usb");
1575 						break;
1576 					default:
1577 						_AddPath(*stack, "busses");
1578 						break;
1579 				}
1580 				break;
1581 			case PCI_network:
1582 				_AddPath(*stack, "drivers", "net");
1583 				_AddPath(*stack, "busses", "virtio");
1584 				break;
1585 			case PCI_display:
1586 				_AddPath(*stack, "drivers", "graphics");
1587 				break;
1588 			case PCI_multimedia:
1589 				switch (subType) {
1590 					case PCI_audio:
1591 					case PCI_hd_audio:
1592 						_AddPath(*stack, "drivers", "audio");
1593 						break;
1594 					case PCI_video:
1595 						_AddPath(*stack, "drivers", "video");
1596 						break;
1597 					default:
1598 						_AddPath(*stack, "drivers");
1599 						break;
1600 				}
1601 				break;
1602 			default:
1603 				if (sRootNode == this) {
1604 					_AddPath(*stack, "busses/pci");
1605 					_AddPath(*stack, "bus_managers");
1606 				} else if (!generic) {
1607 					_AddPath(*stack, "busses", "virtio");
1608 					_AddPath(*stack, "drivers");
1609 				} else {
1610 					// For generic drivers, we only allow busses when the
1611 					// request is more specified
1612 					if (sGenericContextPath != NULL
1613 						&& (!strcmp(sGenericContextPath, "disk")
1614 							|| !strcmp(sGenericContextPath, "ports")
1615 							|| !strcmp(sGenericContextPath, "bus"))) {
1616 						_AddPath(*stack, "busses");
1617 					}
1618 					_AddPath(*stack, "drivers", sGenericContextPath);
1619 					_AddPath(*stack, "busses/scsi");
1620 					_AddPath(*stack, "busses/random");
1621 				}
1622 				break;
1623 		}
1624 
1625 		stackDeleter.Detach();
1626 
1627 		cookie = (void*)stack;
1628 	} else
1629 		stack = static_cast<Stack<KPath*>*>(cookie);
1630 
1631 	KPath* path;
1632 	if (stack->Pop(&path)) {
1633 		_path.Adopt(*path);
1634 		delete path;
1635 		return B_OK;
1636 	}
1637 
1638 	delete stack;
1639 	return B_ENTRY_NOT_FOUND;
1640 }
1641 
1642 
1643 status_t
1644 device_node::_GetNextDriver(void* list, driver_module_info*& driver)
1645 {
1646 	while (true) {
1647 		char name[B_FILE_NAME_LENGTH];
1648 		size_t nameLength = sizeof(name);
1649 
1650 		status_t status = read_next_module_name(list, name, &nameLength);
1651 		if (status != B_OK)
1652 			return status;
1653 
1654 		if (!strcmp(fModuleName, name))
1655 			continue;
1656 
1657 		if (get_module(name, (module_info**)&driver) != B_OK)
1658 			continue;
1659 
1660 		if (driver->supports_device == NULL
1661 			|| driver->register_device == NULL) {
1662 			put_module(name);
1663 			continue;
1664 		}
1665 
1666 		return B_OK;
1667 	}
1668 }
1669 
1670 
1671 status_t
1672 device_node::_FindBestDriver(const char* path, driver_module_info*& bestDriver,
1673 	float& bestSupport, device_node* previous)
1674 {
1675 	if (bestDriver == NULL)
1676 		bestSupport = previous != NULL ? previous->fSupportsParent : 0.0f;
1677 
1678 	void* list = open_module_list_etc(path, "driver_v1");
1679 	driver_module_info* driver;
1680 	while (_GetNextDriver(list, driver) == B_OK) {
1681 		if (previous != NULL && driver == previous->DriverModule()) {
1682 			put_module(driver->info.name);
1683 			continue;
1684 		}
1685 
1686 		float support = driver->supports_device(this);
1687 		if (support > bestSupport) {
1688 			if (bestDriver != NULL)
1689 				put_module(bestDriver->info.name);
1690 
1691 			bestDriver = driver;
1692 			bestSupport = support;
1693 			continue;
1694 				// keep reference to best module around
1695 		}
1696 
1697 		put_module(driver->info.name);
1698 	}
1699 	close_module_list(list);
1700 
1701 	return bestDriver != NULL ? B_OK : B_ENTRY_NOT_FOUND;
1702 }
1703 
1704 
1705 status_t
1706 device_node::_RegisterPath(const char* path)
1707 {
1708 	void* list = open_module_list_etc(path, "driver_v1");
1709 	driver_module_info* driver;
1710 	uint32 count = 0;
1711 
1712 	while (_GetNextDriver(list, driver) == B_OK) {
1713 		float support = driver->supports_device(this);
1714 		if (support > 0.0) {
1715 			TRACE(("  register module \"%s\", support %f\n", driver->info.name,
1716 				support));
1717 			if (driver->register_device(this) == B_OK)
1718 				count++;
1719 		}
1720 
1721 		put_module(driver->info.name);
1722 	}
1723 	close_module_list(list);
1724 
1725 	return count > 0 ? B_OK : B_ENTRY_NOT_FOUND;
1726 }
1727 
1728 
1729 bool
1730 device_node::_AlwaysRegisterDynamic()
1731 {
1732 	uint16 type = 0;
1733 	uint16 subType = 0;
1734 	get_attr_uint16(this, B_DEVICE_TYPE, &type, false);
1735 	get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false);
1736 
1737 	return type == PCI_serial_bus || type == PCI_bridge || type == 0;
1738 		// TODO: we may want to be a bit more specific in the future
1739 }
1740 
1741 
1742 status_t
1743 device_node::_RegisterDynamic(device_node* previous)
1744 {
1745 	// If this is not a bus, we don't have to scan it
1746 	if (find_attr(this, B_DEVICE_BUS, false, B_STRING_TYPE) == NULL)
1747 		return B_OK;
1748 
1749 	// If we're not being probed, we honour the B_FIND_CHILD_ON_DEMAND
1750 	// requirements
1751 	if (!IsProbed() && (fFlags & B_FIND_CHILD_ON_DEMAND) != 0
1752 		&& !_AlwaysRegisterDynamic())
1753 		return B_OK;
1754 
1755 	KPath path;
1756 
1757 	if ((fFlags & B_FIND_MULTIPLE_CHILDREN) == 0) {
1758 		// find the one driver
1759 		driver_module_info* bestDriver = NULL;
1760 		float bestSupport = 0.0;
1761 		void* cookie = NULL;
1762 
1763 		while (_GetNextDriverPath(cookie, path) == B_OK) {
1764 			_FindBestDriver(path.Path(), bestDriver, bestSupport, previous);
1765 		}
1766 
1767 		if (bestDriver != NULL) {
1768 			TRACE(("  register best module \"%s\", support %f\n",
1769 				bestDriver->info.name, bestSupport));
1770 			if (bestDriver->register_device(this) == B_OK) {
1771 				// There can only be one node of this driver
1772 				// (usually only one at all, but there might be a new driver
1773 				// "waiting" for its turn)
1774 				device_node* child = FindChild(bestDriver->info.name);
1775 				if (child != NULL) {
1776 					child->fSupportsParent = bestSupport;
1777 					if (previous != NULL) {
1778 						previous->fFlags |= NODE_FLAG_OBSOLETE_DRIVER;
1779 						previous->Release();
1780 						child->fFlags |= NODE_FLAG_WAITING_FOR_DRIVER;
1781 					}
1782 				}
1783 				// TODO: if this fails, we could try the second best driver,
1784 				// and so on...
1785 			}
1786 			put_module(bestDriver->info.name);
1787 		}
1788 	} else {
1789 		// register all drivers that match
1790 		void* cookie = NULL;
1791 		while (_GetNextDriverPath(cookie, path) == B_OK) {
1792 			_RegisterPath(path.Path());
1793 		}
1794 	}
1795 
1796 	return B_OK;
1797 }
1798 
1799 
1800 void
1801 device_node::_ReleaseWaiting()
1802 {
1803 	NodeList::Iterator iterator = fChildren.GetIterator();
1804 	while (iterator.HasNext()) {
1805 		device_node* child = iterator.Next();
1806 
1807 		child->fFlags &= ~NODE_FLAG_WAITING_FOR_DRIVER;
1808 	}
1809 }
1810 
1811 
1812 status_t
1813 device_node::_RemoveChildren()
1814 {
1815 	NodeList::Iterator iterator = fChildren.GetIterator();
1816 	while (iterator.HasNext()) {
1817 		device_node* child = iterator.Next();
1818 		child->Release();
1819 	}
1820 
1821 	return fChildren.IsEmpty() ? B_OK : B_BUSY;
1822 }
1823 
1824 
1825 device_node*
1826 device_node::_FindCurrentChild()
1827 {
1828 	NodeList::Iterator iterator = fChildren.GetIterator();
1829 	while (iterator.HasNext()) {
1830 		device_node* child = iterator.Next();
1831 
1832 		if ((child->Flags() & NODE_FLAG_WAITING_FOR_DRIVER) == 0)
1833 			return child;
1834 	}
1835 
1836 	return NULL;
1837 }
1838 
1839 
1840 status_t
1841 device_node::_Probe()
1842 {
1843 	device_node* previous = NULL;
1844 
1845 	if (IsProbed() && !fChildren.IsEmpty()
1846 		&& (fFlags & (B_FIND_CHILD_ON_DEMAND | B_FIND_MULTIPLE_CHILDREN))
1847 				== B_FIND_CHILD_ON_DEMAND) {
1848 		// We already have a driver that claims this node; remove all
1849 		// (unused) nodes, and evaluate it again
1850 		_RemoveChildren();
1851 
1852 		previous = _FindCurrentChild();
1853 		if (previous != NULL) {
1854 			// This driver is still active - give it back the reference
1855 			// that was stolen by _RemoveChildren() - _RegisterDynamic()
1856 			// will release it, if it really isn't needed anymore
1857 			previous->Acquire();
1858 		}
1859 	}
1860 
1861 	return _RegisterDynamic(previous);
1862 }
1863 
1864 
1865 status_t
1866 device_node::Probe(const char* devicePath, uint32 updateCycle)
1867 {
1868 	if ((fFlags & NODE_FLAG_DEVICE_REMOVED) != 0
1869 		|| updateCycle == fLastUpdateCycle)
1870 		return B_OK;
1871 
1872 	status_t status = InitDriver();
1873 	if (status < B_OK)
1874 		return status;
1875 
1876 	MethodDeleter<device_node, bool> uninit(this,
1877 		&device_node::UninitDriver);
1878 
1879 	if ((fFlags & B_FIND_CHILD_ON_DEMAND) != 0) {
1880 		bool matches = false;
1881 		uint16 type = 0;
1882 		uint16 subType = 0;
1883 		if (get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false) == B_OK
1884 			&& get_attr_uint16(this, B_DEVICE_TYPE, &type, false) == B_OK) {
1885 			// Check if this node matches the device path
1886 			// TODO: maybe make this extendible via settings file?
1887 			if (!strcmp(devicePath, "disk")) {
1888 				matches = type == PCI_mass_storage;
1889 			} else if (!strcmp(devicePath, "audio")) {
1890 				matches = type == PCI_multimedia
1891 					&& (subType == PCI_audio || subType == PCI_hd_audio);
1892 			} else if (!strcmp(devicePath, "net")) {
1893 				matches = type == PCI_network;
1894 			} else if (!strcmp(devicePath, "graphics")) {
1895 				matches = type == PCI_display;
1896 			} else if (!strcmp(devicePath, "video")) {
1897 				matches = type == PCI_multimedia && subType == PCI_video;
1898 			}
1899 		} else {
1900 			// This driver does not support types, but still wants to its
1901 			// children explored on demand only.
1902 			matches = true;
1903 			sGenericContextPath = devicePath;
1904 		}
1905 
1906 		if (matches) {
1907 			fLastUpdateCycle = updateCycle;
1908 				// This node will be probed in this update cycle
1909 
1910 			status = _Probe();
1911 
1912 			sGenericContextPath = NULL;
1913 			return status;
1914 		}
1915 
1916 		return B_OK;
1917 	}
1918 
1919 	NodeList::Iterator iterator = fChildren.GetIterator();
1920 	while (iterator.HasNext()) {
1921 		device_node* child = iterator.Next();
1922 
1923 		status = child->Probe(devicePath, updateCycle);
1924 		if (status != B_OK)
1925 			return status;
1926 	}
1927 
1928 	return B_OK;
1929 }
1930 
1931 
1932 status_t
1933 device_node::Reprobe()
1934 {
1935 	status_t status = InitDriver();
1936 	if (status < B_OK)
1937 		return status;
1938 
1939 	MethodDeleter<device_node, bool> uninit(this,
1940 		&device_node::UninitDriver);
1941 
1942 	// If this child has been probed already, probe it again
1943 	status = _Probe();
1944 	if (status != B_OK)
1945 		return status;
1946 
1947 	NodeList::Iterator iterator = fChildren.GetIterator();
1948 	while (iterator.HasNext()) {
1949 		device_node* child = iterator.Next();
1950 
1951 		status = child->Reprobe();
1952 		if (status != B_OK)
1953 			return status;
1954 	}
1955 
1956 	return B_OK;
1957 }
1958 
1959 
1960 status_t
1961 device_node::Rescan()
1962 {
1963 	status_t status = InitDriver();
1964 	if (status < B_OK)
1965 		return status;
1966 
1967 	MethodDeleter<device_node, bool> uninit(this,
1968 		&device_node::UninitDriver);
1969 
1970 	if (DriverModule()->rescan_child_devices != NULL) {
1971 		status = DriverModule()->rescan_child_devices(DriverData());
1972 		if (status != B_OK)
1973 			return status;
1974 	}
1975 
1976 	NodeList::Iterator iterator = fChildren.GetIterator();
1977 	while (iterator.HasNext()) {
1978 		device_node* child = iterator.Next();
1979 
1980 		status = child->Rescan();
1981 		if (status != B_OK)
1982 			return status;
1983 	}
1984 
1985 	return B_OK;
1986 }
1987 
1988 
1989 /*!	Uninitializes all temporary references to the driver. The registration
1990 	process keeps the driver initialized to optimize the startup procedure;
1991 	this function gives this reference away again.
1992 */
1993 void
1994 device_node::UninitUnusedDriver()
1995 {
1996 	// First, we need to go to the leaf, and go back from there
1997 
1998 	NodeList::Iterator iterator = fChildren.GetIterator();
1999 	while (iterator.HasNext()) {
2000 		device_node* child = iterator.Next();
2001 
2002 		child->UninitUnusedDriver();
2003 	}
2004 
2005 	if (!IsInitialized()
2006 		|| (fFlags & NODE_FLAG_REGISTER_INITIALIZED) == 0)
2007 		return;
2008 
2009 	fFlags &= ~NODE_FLAG_REGISTER_INITIALIZED;
2010 
2011 	UninitDriver();
2012 }
2013 
2014 
2015 /*!	Calls device_removed() on this node and all of its children - starting
2016 	with the deepest and last child.
2017 	It will also remove the one reference that every node gets on its creation.
2018 */
2019 void
2020 device_node::DeviceRemoved()
2021 {
2022 	// notify children
2023 	NodeList::ConstIterator iterator = Children().GetIterator();
2024 	while (iterator.HasNext()) {
2025 		device_node* child = iterator.Next();
2026 
2027 		child->DeviceRemoved();
2028 	}
2029 
2030 	// notify devices
2031 	DeviceList::ConstIterator deviceIterator = Devices().GetIterator();
2032 	while (deviceIterator.HasNext()) {
2033 		Device* device = deviceIterator.Next();
2034 
2035 		if (device->Module() != NULL
2036 			&& device->Module()->device_removed != NULL)
2037 			device->Module()->device_removed(device->Data());
2038 	}
2039 
2040 	fFlags |= NODE_FLAG_DEVICE_REMOVED;
2041 
2042 	if (IsInitialized() && DriverModule()->device_removed != NULL)
2043 		DriverModule()->device_removed(this);
2044 
2045 	if ((fFlags & B_KEEP_DRIVER_LOADED) != 0) {
2046 		// There is no point in keeping this driver loaded when its device
2047 		// is gone
2048 		UninitDriver();
2049 	}
2050 
2051 	UninitUnusedDriver();
2052 	Release();
2053 }
2054 
2055 
2056 void
2057 device_node::Acquire()
2058 {
2059 	atomic_add(&fRefCount, 1);
2060 }
2061 
2062 
2063 bool
2064 device_node::Release()
2065 {
2066 	if (atomic_add(&fRefCount, -1) > 1)
2067 		return false;
2068 
2069 	delete this;
2070 	return true;
2071 }
2072 
2073 
2074 void
2075 device_node::AddDevice(Device* device)
2076 {
2077 	fDevices.Add(device);
2078 }
2079 
2080 
2081 void
2082 device_node::RemoveDevice(Device* device)
2083 {
2084 	fDevices.Remove(device);
2085 }
2086 
2087 
2088 int
2089 device_node::CompareTo(const device_attr* attributes) const
2090 {
2091 	if (attributes == NULL)
2092 		return -1;
2093 
2094 	for (; attributes->name != NULL; attributes++) {
2095 		// find corresponding attribute
2096 		AttributeList::ConstIterator iterator = Attributes().GetIterator();
2097 		device_attr_private* attr = NULL;
2098 		bool found = false;
2099 
2100 		while (iterator.HasNext()) {
2101 			attr = iterator.Next();
2102 
2103 			if (!strcmp(attr->name, attributes->name)) {
2104 				found = true;
2105 				break;
2106 			}
2107 		}
2108 		if (!found)
2109 			return -1;
2110 
2111 		int compare = device_attr_private::Compare(attr, attributes);
2112 		if (compare != 0)
2113 			return compare;
2114 	}
2115 
2116 	return 0;
2117 }
2118 
2119 
2120 device_node*
2121 device_node::FindChild(const device_attr* attributes) const
2122 {
2123 	if (attributes == NULL)
2124 		return NULL;
2125 
2126 	NodeList::ConstIterator iterator = Children().GetIterator();
2127 	while (iterator.HasNext()) {
2128 		device_node* child = iterator.Next();
2129 
2130 		// ignore nodes that are pending to be removed
2131 		if ((child->Flags() & NODE_FLAG_DEVICE_REMOVED) == 0
2132 			&& !child->CompareTo(attributes))
2133 			return child;
2134 	}
2135 
2136 	return NULL;
2137 }
2138 
2139 
2140 device_node*
2141 device_node::FindChild(const char* moduleName) const
2142 {
2143 	if (moduleName == NULL)
2144 		return NULL;
2145 
2146 	NodeList::ConstIterator iterator = Children().GetIterator();
2147 	while (iterator.HasNext()) {
2148 		device_node* child = iterator.Next();
2149 
2150 		if (!strcmp(child->ModuleName(), moduleName))
2151 			return child;
2152 	}
2153 
2154 	return NULL;
2155 }
2156 
2157 
2158 /*!	This returns the priority or importance of this node. Nodes with higher
2159 	priority are registered/probed first.
2160 	Currently, only the B_FIND_MULTIPLE_CHILDREN flag alters the priority;
2161 	it might make sense to be able to directly set the priority via an
2162 	attribute.
2163 */
2164 int32
2165 device_node::Priority()
2166 {
2167 	return (fFlags & B_FIND_MULTIPLE_CHILDREN) != 0 ? 0 : 100;
2168 }
2169 
2170 
2171 void
2172 device_node::Dump(int32 level)
2173 {
2174 	put_level(level);
2175 	kprintf("(%" B_PRId32 ") @%p \"%s\" (ref %" B_PRId32 ", init %" B_PRId32
2176 		", module %p, data %p)\n", level, this, ModuleName(), fRefCount,
2177 		fInitialized, DriverModule(), DriverData());
2178 
2179 	AttributeList::Iterator attribute = Attributes().GetIterator();
2180 	while (attribute.HasNext()) {
2181 		dump_attribute(attribute.Next(), level);
2182 	}
2183 
2184 	DeviceList::Iterator deviceIterator = fDevices.GetIterator();
2185 	while (deviceIterator.HasNext()) {
2186 		Device* device = deviceIterator.Next();
2187 		put_level(level);
2188 		kprintf("device: %s, %p\n", device->ModuleName(), device->Data());
2189 	}
2190 
2191 	NodeList::ConstIterator iterator = Children().GetIterator();
2192 	while (iterator.HasNext()) {
2193 		iterator.Next()->Dump(level + 1);
2194 	}
2195 }
2196 
2197 
2198 //	#pragma mark - root node
2199 
2200 
2201 static void
2202 init_node_tree(void)
2203 {
2204 	device_attr attrs[] = {
2205 		{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "Devices Root"}},
2206 		{B_DEVICE_BUS, B_STRING_TYPE, {string: "root"}},
2207 		{B_DEVICE_FLAGS, B_UINT32_TYPE,
2208 			{ui32: B_FIND_MULTIPLE_CHILDREN | B_KEEP_DRIVER_LOADED }},
2209 		{NULL}
2210 	};
2211 
2212 	device_node* node = NULL;
2213 	if (register_node(NULL, DEVICE_MANAGER_ROOT_NAME, attrs, NULL, &node)
2214 			!= B_OK) {
2215 		dprintf("Cannot register Devices Root Node\n");
2216 	}
2217 
2218 	device_attr genericAttrs[] = {
2219 		{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "Generic"}},
2220 		{B_DEVICE_BUS, B_STRING_TYPE, {string: "generic"}},
2221 		{B_DEVICE_FLAGS, B_UINT32_TYPE, {ui32: B_FIND_MULTIPLE_CHILDREN
2222 			| B_KEEP_DRIVER_LOADED | B_FIND_CHILD_ON_DEMAND}},
2223 		{NULL}
2224 	};
2225 
2226 	if (register_node(node, DEVICE_MANAGER_GENERIC_NAME, genericAttrs, NULL,
2227 			NULL) != B_OK) {
2228 		dprintf("Cannot register Generic Devices Node\n");
2229 	}
2230 }
2231 
2232 
2233 driver_module_info gDeviceRootModule = {
2234 	{
2235 		DEVICE_MANAGER_ROOT_NAME,
2236 		0,
2237 		NULL,
2238 	},
2239 };
2240 
2241 
2242 driver_module_info gDeviceGenericModule = {
2243 	{
2244 		DEVICE_MANAGER_GENERIC_NAME,
2245 		0,
2246 		NULL,
2247 	},
2248 	NULL
2249 };
2250 
2251 
2252 //	#pragma mark - private kernel API
2253 
2254 
2255 status_t
2256 device_manager_probe(const char* path, uint32 updateCycle)
2257 {
2258 	TRACE(("device_manager_probe(\"%s\")\n", path));
2259 	RecursiveLocker _(sLock);
2260 
2261 	// first, publish directories in the driver directory
2262 	publish_directories(path);
2263 
2264 	return sRootNode->Probe(path, updateCycle);
2265 }
2266 
2267 
2268 status_t
2269 device_manager_init(struct kernel_args* args)
2270 {
2271 	TRACE(("device manager init\n"));
2272 
2273 	IOSchedulerRoster::Init();
2274 
2275 	dm_init_id_generator();
2276 	dm_init_io_resources();
2277 
2278 	recursive_lock_init(&sLock, "device manager");
2279 
2280 	register_generic_syscall(DEVICE_MANAGER_SYSCALLS, control_device_manager,
2281 		1, 0);
2282 
2283 	add_debugger_command("dm_tree", &dump_device_nodes,
2284 		"dump device node tree");
2285 	add_debugger_command_etc("io_scheduler", &dump_io_scheduler,
2286 		"Dump an I/O scheduler",
2287 		"<scheduler>\n"
2288 		"Dumps I/O scheduler at address <scheduler>.\n", 0);
2289 	add_debugger_command_etc("io_request_owner", &dump_io_request_owner,
2290 		"Dump an I/O request owner",
2291 		"<owner>\n"
2292 		"Dumps I/O request owner at address <owner>.\n", 0);
2293 	add_debugger_command("io_request", &dump_io_request, "dump an I/O request");
2294 	add_debugger_command("io_operation", &dump_io_operation,
2295 		"dump an I/O operation");
2296 	add_debugger_command("io_buffer", &dump_io_buffer, "dump an I/O buffer");
2297 	add_debugger_command("dma_buffer", &dump_dma_buffer, "dump a DMA buffer");
2298 
2299 	init_node_tree();
2300 
2301 	return B_OK;
2302 }
2303 
2304 
2305 status_t
2306 device_manager_init_post_modules(struct kernel_args* args)
2307 {
2308 	RecursiveLocker _(sLock);
2309 	return sRootNode->Reprobe();
2310 }
2311