xref: /haiku/src/system/kernel/device_manager/device_manager.cpp (revision d12bb8b14803d030b4a8fba91131e4bb96c4f406)
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 					case PCI_nvm:
1564 						_AddPath(*stack, "drivers", "disk");
1565 						break;
1566 					default:
1567 						_AddPath(*stack, "busses");
1568 						break;
1569 				}
1570 				break;
1571 			case PCI_serial_bus:
1572 				switch (subType) {
1573 					case PCI_firewire:
1574 						_AddPath(*stack, "busses", "firewire");
1575 						break;
1576 					case PCI_usb:
1577 						_AddPath(*stack, "busses", "usb");
1578 						break;
1579 					default:
1580 						_AddPath(*stack, "busses");
1581 						break;
1582 				}
1583 				break;
1584 			case PCI_network:
1585 				_AddPath(*stack, "drivers", "net");
1586 				_AddPath(*stack, "busses", "virtio");
1587 				break;
1588 			case PCI_display:
1589 				_AddPath(*stack, "drivers", "graphics");
1590 				break;
1591 			case PCI_multimedia:
1592 				switch (subType) {
1593 					case PCI_audio:
1594 					case PCI_hd_audio:
1595 						_AddPath(*stack, "drivers", "audio");
1596 						break;
1597 					case PCI_video:
1598 						_AddPath(*stack, "drivers", "video");
1599 						break;
1600 					default:
1601 						_AddPath(*stack, "drivers");
1602 						break;
1603 				}
1604 				break;
1605 			case PCI_base_peripheral:
1606 				switch (subType) {
1607 					case PCI_sd_host:
1608 						_AddPath(*stack, "busses", "mmc");
1609 						break;
1610 					default:
1611 						_AddPath(*stack, "drivers");
1612 						break;
1613 				}
1614 				break;
1615 			default:
1616 				if (sRootNode == this) {
1617 					_AddPath(*stack, "busses/pci");
1618 					_AddPath(*stack, "bus_managers");
1619 				} else if (!generic) {
1620 					_AddPath(*stack, "busses", "virtio");
1621 					_AddPath(*stack, "drivers");
1622 				} else {
1623 					// For generic drivers, we only allow busses when the
1624 					// request is more specified
1625 					if (sGenericContextPath != NULL
1626 						&& (!strcmp(sGenericContextPath, "disk")
1627 							|| !strcmp(sGenericContextPath, "ports")
1628 							|| !strcmp(sGenericContextPath, "bus"))) {
1629 						_AddPath(*stack, "busses");
1630 					}
1631 					_AddPath(*stack, "drivers", sGenericContextPath);
1632 					_AddPath(*stack, "busses/scsi");
1633 					_AddPath(*stack, "busses/random");
1634 				}
1635 				break;
1636 		}
1637 
1638 		stackDeleter.Detach();
1639 
1640 		cookie = (void*)stack;
1641 	} else
1642 		stack = static_cast<Stack<KPath*>*>(cookie);
1643 
1644 	KPath* path;
1645 	if (stack->Pop(&path)) {
1646 		_path.Adopt(*path);
1647 		delete path;
1648 		return B_OK;
1649 	}
1650 
1651 	delete stack;
1652 	return B_ENTRY_NOT_FOUND;
1653 }
1654 
1655 
1656 status_t
1657 device_node::_GetNextDriver(void* list, driver_module_info*& driver)
1658 {
1659 	while (true) {
1660 		char name[B_FILE_NAME_LENGTH];
1661 		size_t nameLength = sizeof(name);
1662 
1663 		status_t status = read_next_module_name(list, name, &nameLength);
1664 		if (status != B_OK)
1665 			return status;
1666 
1667 		if (!strcmp(fModuleName, name))
1668 			continue;
1669 
1670 		if (get_module(name, (module_info**)&driver) != B_OK)
1671 			continue;
1672 
1673 		if (driver->supports_device == NULL
1674 			|| driver->register_device == NULL) {
1675 			put_module(name);
1676 			continue;
1677 		}
1678 
1679 		return B_OK;
1680 	}
1681 }
1682 
1683 
1684 status_t
1685 device_node::_FindBestDriver(const char* path, driver_module_info*& bestDriver,
1686 	float& bestSupport, device_node* previous)
1687 {
1688 	if (bestDriver == NULL)
1689 		bestSupport = previous != NULL ? previous->fSupportsParent : 0.0f;
1690 
1691 	void* list = open_module_list_etc(path, "driver_v1");
1692 	driver_module_info* driver;
1693 	while (_GetNextDriver(list, driver) == B_OK) {
1694 		if (previous != NULL && driver == previous->DriverModule()) {
1695 			put_module(driver->info.name);
1696 			continue;
1697 		}
1698 
1699 		float support = driver->supports_device(this);
1700 		if (support > bestSupport) {
1701 			if (bestDriver != NULL)
1702 				put_module(bestDriver->info.name);
1703 
1704 			bestDriver = driver;
1705 			bestSupport = support;
1706 			continue;
1707 				// keep reference to best module around
1708 		}
1709 
1710 		put_module(driver->info.name);
1711 	}
1712 	close_module_list(list);
1713 
1714 	return bestDriver != NULL ? B_OK : B_ENTRY_NOT_FOUND;
1715 }
1716 
1717 
1718 status_t
1719 device_node::_RegisterPath(const char* path)
1720 {
1721 	void* list = open_module_list_etc(path, "driver_v1");
1722 	driver_module_info* driver;
1723 	uint32 count = 0;
1724 
1725 	while (_GetNextDriver(list, driver) == B_OK) {
1726 		float support = driver->supports_device(this);
1727 		if (support > 0.0) {
1728 			TRACE(("  register module \"%s\", support %f\n", driver->info.name,
1729 				support));
1730 			if (driver->register_device(this) == B_OK)
1731 				count++;
1732 		}
1733 
1734 		put_module(driver->info.name);
1735 	}
1736 	close_module_list(list);
1737 
1738 	return count > 0 ? B_OK : B_ENTRY_NOT_FOUND;
1739 }
1740 
1741 
1742 bool
1743 device_node::_AlwaysRegisterDynamic()
1744 {
1745 	uint16 type = 0;
1746 	uint16 subType = 0;
1747 	get_attr_uint16(this, B_DEVICE_TYPE, &type, false);
1748 	get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false);
1749 
1750 	return type == PCI_serial_bus || type == PCI_bridge || type == 0;
1751 		// TODO: we may want to be a bit more specific in the future
1752 }
1753 
1754 
1755 status_t
1756 device_node::_RegisterDynamic(device_node* previous)
1757 {
1758 	// If this is not a bus, we don't have to scan it
1759 	if (find_attr(this, B_DEVICE_BUS, false, B_STRING_TYPE) == NULL)
1760 		return B_OK;
1761 
1762 	// If we're not being probed, we honour the B_FIND_CHILD_ON_DEMAND
1763 	// requirements
1764 	if (!IsProbed() && (fFlags & B_FIND_CHILD_ON_DEMAND) != 0
1765 		&& !_AlwaysRegisterDynamic())
1766 		return B_OK;
1767 
1768 	KPath path;
1769 
1770 	if ((fFlags & B_FIND_MULTIPLE_CHILDREN) == 0) {
1771 		// find the one driver
1772 		driver_module_info* bestDriver = NULL;
1773 		float bestSupport = 0.0;
1774 		void* cookie = NULL;
1775 
1776 		while (_GetNextDriverPath(cookie, path) == B_OK) {
1777 			_FindBestDriver(path.Path(), bestDriver, bestSupport, previous);
1778 		}
1779 
1780 		if (bestDriver != NULL) {
1781 			TRACE(("  register best module \"%s\", support %f\n",
1782 				bestDriver->info.name, bestSupport));
1783 			if (bestDriver->register_device(this) == B_OK) {
1784 				// There can only be one node of this driver
1785 				// (usually only one at all, but there might be a new driver
1786 				// "waiting" for its turn)
1787 				device_node* child = FindChild(bestDriver->info.name);
1788 				if (child != NULL) {
1789 					child->fSupportsParent = bestSupport;
1790 					if (previous != NULL) {
1791 						previous->fFlags |= NODE_FLAG_OBSOLETE_DRIVER;
1792 						previous->Release();
1793 						child->fFlags |= NODE_FLAG_WAITING_FOR_DRIVER;
1794 					}
1795 				}
1796 				// TODO: if this fails, we could try the second best driver,
1797 				// and so on...
1798 			}
1799 			put_module(bestDriver->info.name);
1800 		}
1801 	} else {
1802 		// register all drivers that match
1803 		void* cookie = NULL;
1804 		while (_GetNextDriverPath(cookie, path) == B_OK) {
1805 			_RegisterPath(path.Path());
1806 		}
1807 	}
1808 
1809 	return B_OK;
1810 }
1811 
1812 
1813 void
1814 device_node::_ReleaseWaiting()
1815 {
1816 	NodeList::Iterator iterator = fChildren.GetIterator();
1817 	while (iterator.HasNext()) {
1818 		device_node* child = iterator.Next();
1819 
1820 		child->fFlags &= ~NODE_FLAG_WAITING_FOR_DRIVER;
1821 	}
1822 }
1823 
1824 
1825 status_t
1826 device_node::_RemoveChildren()
1827 {
1828 	NodeList::Iterator iterator = fChildren.GetIterator();
1829 	while (iterator.HasNext()) {
1830 		device_node* child = iterator.Next();
1831 		child->Release();
1832 	}
1833 
1834 	return fChildren.IsEmpty() ? B_OK : B_BUSY;
1835 }
1836 
1837 
1838 device_node*
1839 device_node::_FindCurrentChild()
1840 {
1841 	NodeList::Iterator iterator = fChildren.GetIterator();
1842 	while (iterator.HasNext()) {
1843 		device_node* child = iterator.Next();
1844 
1845 		if ((child->Flags() & NODE_FLAG_WAITING_FOR_DRIVER) == 0)
1846 			return child;
1847 	}
1848 
1849 	return NULL;
1850 }
1851 
1852 
1853 status_t
1854 device_node::_Probe()
1855 {
1856 	device_node* previous = NULL;
1857 
1858 	if (IsProbed() && !fChildren.IsEmpty()
1859 		&& (fFlags & (B_FIND_CHILD_ON_DEMAND | B_FIND_MULTIPLE_CHILDREN))
1860 				== B_FIND_CHILD_ON_DEMAND) {
1861 		// We already have a driver that claims this node; remove all
1862 		// (unused) nodes, and evaluate it again
1863 		_RemoveChildren();
1864 
1865 		previous = _FindCurrentChild();
1866 		if (previous != NULL) {
1867 			// This driver is still active - give it back the reference
1868 			// that was stolen by _RemoveChildren() - _RegisterDynamic()
1869 			// will release it, if it really isn't needed anymore
1870 			previous->Acquire();
1871 		}
1872 	}
1873 
1874 	return _RegisterDynamic(previous);
1875 }
1876 
1877 
1878 status_t
1879 device_node::Probe(const char* devicePath, uint32 updateCycle)
1880 {
1881 	if ((fFlags & NODE_FLAG_DEVICE_REMOVED) != 0
1882 		|| updateCycle == fLastUpdateCycle)
1883 		return B_OK;
1884 
1885 	status_t status = InitDriver();
1886 	if (status < B_OK)
1887 		return status;
1888 
1889 	MethodDeleter<device_node, bool> uninit(this,
1890 		&device_node::UninitDriver);
1891 
1892 	if ((fFlags & B_FIND_CHILD_ON_DEMAND) != 0) {
1893 		bool matches = false;
1894 		uint16 type = 0;
1895 		uint16 subType = 0;
1896 		if (get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false) == B_OK
1897 			&& get_attr_uint16(this, B_DEVICE_TYPE, &type, false) == B_OK) {
1898 			// Check if this node matches the device path
1899 			// TODO: maybe make this extendible via settings file?
1900 			if (!strcmp(devicePath, "disk")) {
1901 				matches = type == PCI_mass_storage
1902 					|| (type == PCI_base_peripheral && subType == PCI_sd_host);
1903 			} else if (!strcmp(devicePath, "audio")) {
1904 				matches = type == PCI_multimedia
1905 					&& (subType == PCI_audio || subType == PCI_hd_audio);
1906 			} else if (!strcmp(devicePath, "net")) {
1907 				matches = type == PCI_network;
1908 			} else if (!strcmp(devicePath, "graphics")) {
1909 				matches = type == PCI_display;
1910 			} else if (!strcmp(devicePath, "video")) {
1911 				matches = type == PCI_multimedia && subType == PCI_video;
1912 			} else if (!strcmp(devicePath, "power")) {
1913 				matches = type == PCI_data_acquisition;
1914 			}
1915 		} else {
1916 			// This driver does not support types, but still wants to its
1917 			// children explored on demand only.
1918 			matches = true;
1919 			sGenericContextPath = devicePath;
1920 		}
1921 
1922 		if (matches) {
1923 			fLastUpdateCycle = updateCycle;
1924 				// This node will be probed in this update cycle
1925 
1926 			status = _Probe();
1927 
1928 			sGenericContextPath = NULL;
1929 			return status;
1930 		}
1931 
1932 		return B_OK;
1933 	}
1934 
1935 	NodeList::Iterator iterator = fChildren.GetIterator();
1936 	while (iterator.HasNext()) {
1937 		device_node* child = iterator.Next();
1938 
1939 		status = child->Probe(devicePath, updateCycle);
1940 		if (status != B_OK)
1941 			return status;
1942 	}
1943 
1944 	return B_OK;
1945 }
1946 
1947 
1948 status_t
1949 device_node::Reprobe()
1950 {
1951 	status_t status = InitDriver();
1952 	if (status < B_OK)
1953 		return status;
1954 
1955 	MethodDeleter<device_node, bool> uninit(this,
1956 		&device_node::UninitDriver);
1957 
1958 	// If this child has been probed already, probe it again
1959 	status = _Probe();
1960 	if (status != B_OK)
1961 		return status;
1962 
1963 	NodeList::Iterator iterator = fChildren.GetIterator();
1964 	while (iterator.HasNext()) {
1965 		device_node* child = iterator.Next();
1966 
1967 		status = child->Reprobe();
1968 		if (status != B_OK)
1969 			return status;
1970 	}
1971 
1972 	return B_OK;
1973 }
1974 
1975 
1976 status_t
1977 device_node::Rescan()
1978 {
1979 	status_t status = InitDriver();
1980 	if (status < B_OK)
1981 		return status;
1982 
1983 	MethodDeleter<device_node, bool> uninit(this,
1984 		&device_node::UninitDriver);
1985 
1986 	if (DriverModule()->rescan_child_devices != NULL) {
1987 		status = DriverModule()->rescan_child_devices(DriverData());
1988 		if (status != B_OK)
1989 			return status;
1990 	}
1991 
1992 	NodeList::Iterator iterator = fChildren.GetIterator();
1993 	while (iterator.HasNext()) {
1994 		device_node* child = iterator.Next();
1995 
1996 		status = child->Rescan();
1997 		if (status != B_OK)
1998 			return status;
1999 	}
2000 
2001 	return B_OK;
2002 }
2003 
2004 
2005 /*!	Uninitializes all temporary references to the driver. The registration
2006 	process keeps the driver initialized to optimize the startup procedure;
2007 	this function gives this reference away again.
2008 */
2009 void
2010 device_node::UninitUnusedDriver()
2011 {
2012 	// First, we need to go to the leaf, and go back from there
2013 
2014 	NodeList::Iterator iterator = fChildren.GetIterator();
2015 	while (iterator.HasNext()) {
2016 		device_node* child = iterator.Next();
2017 
2018 		child->UninitUnusedDriver();
2019 	}
2020 
2021 	if (!IsInitialized()
2022 		|| (fFlags & NODE_FLAG_REGISTER_INITIALIZED) == 0)
2023 		return;
2024 
2025 	fFlags &= ~NODE_FLAG_REGISTER_INITIALIZED;
2026 
2027 	UninitDriver();
2028 }
2029 
2030 
2031 /*!	Calls device_removed() on this node and all of its children - starting
2032 	with the deepest and last child.
2033 	It will also remove the one reference that every node gets on its creation.
2034 */
2035 void
2036 device_node::DeviceRemoved()
2037 {
2038 	// notify children
2039 	NodeList::ConstIterator iterator = Children().GetIterator();
2040 	while (iterator.HasNext()) {
2041 		device_node* child = iterator.Next();
2042 
2043 		child->DeviceRemoved();
2044 	}
2045 
2046 	// notify devices
2047 	DeviceList::ConstIterator deviceIterator = Devices().GetIterator();
2048 	while (deviceIterator.HasNext()) {
2049 		Device* device = deviceIterator.Next();
2050 
2051 		if (device->Module() != NULL
2052 			&& device->Module()->device_removed != NULL)
2053 			device->Module()->device_removed(device->Data());
2054 	}
2055 
2056 	fFlags |= NODE_FLAG_DEVICE_REMOVED;
2057 
2058 	if (IsInitialized() && DriverModule()->device_removed != NULL)
2059 		DriverModule()->device_removed(this);
2060 
2061 	if ((fFlags & B_KEEP_DRIVER_LOADED) != 0) {
2062 		// There is no point in keeping this driver loaded when its device
2063 		// is gone
2064 		UninitDriver();
2065 	}
2066 
2067 	UninitUnusedDriver();
2068 	Release();
2069 }
2070 
2071 
2072 void
2073 device_node::Acquire()
2074 {
2075 	atomic_add(&fRefCount, 1);
2076 }
2077 
2078 
2079 bool
2080 device_node::Release()
2081 {
2082 	if (atomic_add(&fRefCount, -1) > 1)
2083 		return false;
2084 
2085 	delete this;
2086 	return true;
2087 }
2088 
2089 
2090 void
2091 device_node::AddDevice(Device* device)
2092 {
2093 	fDevices.Add(device);
2094 }
2095 
2096 
2097 void
2098 device_node::RemoveDevice(Device* device)
2099 {
2100 	fDevices.Remove(device);
2101 }
2102 
2103 
2104 int
2105 device_node::CompareTo(const device_attr* attributes) const
2106 {
2107 	if (attributes == NULL)
2108 		return -1;
2109 
2110 	for (; attributes->name != NULL; attributes++) {
2111 		// find corresponding attribute
2112 		AttributeList::ConstIterator iterator = Attributes().GetIterator();
2113 		device_attr_private* attr = NULL;
2114 		bool found = false;
2115 
2116 		while (iterator.HasNext()) {
2117 			attr = iterator.Next();
2118 
2119 			if (!strcmp(attr->name, attributes->name)) {
2120 				found = true;
2121 				break;
2122 			}
2123 		}
2124 		if (!found)
2125 			return -1;
2126 
2127 		int compare = device_attr_private::Compare(attr, attributes);
2128 		if (compare != 0)
2129 			return compare;
2130 	}
2131 
2132 	return 0;
2133 }
2134 
2135 
2136 device_node*
2137 device_node::FindChild(const device_attr* attributes) const
2138 {
2139 	if (attributes == NULL)
2140 		return NULL;
2141 
2142 	NodeList::ConstIterator iterator = Children().GetIterator();
2143 	while (iterator.HasNext()) {
2144 		device_node* child = iterator.Next();
2145 
2146 		// ignore nodes that are pending to be removed
2147 		if ((child->Flags() & NODE_FLAG_DEVICE_REMOVED) == 0
2148 			&& !child->CompareTo(attributes))
2149 			return child;
2150 	}
2151 
2152 	return NULL;
2153 }
2154 
2155 
2156 device_node*
2157 device_node::FindChild(const char* moduleName) const
2158 {
2159 	if (moduleName == NULL)
2160 		return NULL;
2161 
2162 	NodeList::ConstIterator iterator = Children().GetIterator();
2163 	while (iterator.HasNext()) {
2164 		device_node* child = iterator.Next();
2165 
2166 		if (!strcmp(child->ModuleName(), moduleName))
2167 			return child;
2168 	}
2169 
2170 	return NULL;
2171 }
2172 
2173 
2174 /*!	This returns the priority or importance of this node. Nodes with higher
2175 	priority are registered/probed first.
2176 	Currently, only the B_FIND_MULTIPLE_CHILDREN flag alters the priority;
2177 	it might make sense to be able to directly set the priority via an
2178 	attribute.
2179 */
2180 int32
2181 device_node::Priority()
2182 {
2183 	return (fFlags & B_FIND_MULTIPLE_CHILDREN) != 0 ? 0 : 100;
2184 }
2185 
2186 
2187 void
2188 device_node::Dump(int32 level)
2189 {
2190 	put_level(level);
2191 	kprintf("(%" B_PRId32 ") @%p \"%s\" (ref %" B_PRId32 ", init %" B_PRId32
2192 		", module %p, data %p)\n", level, this, ModuleName(), fRefCount,
2193 		fInitialized, DriverModule(), DriverData());
2194 
2195 	AttributeList::Iterator attribute = Attributes().GetIterator();
2196 	while (attribute.HasNext()) {
2197 		dump_attribute(attribute.Next(), level);
2198 	}
2199 
2200 	DeviceList::Iterator deviceIterator = fDevices.GetIterator();
2201 	while (deviceIterator.HasNext()) {
2202 		Device* device = deviceIterator.Next();
2203 		put_level(level);
2204 		kprintf("device: %s, %p\n", device->ModuleName(), device->Data());
2205 	}
2206 
2207 	NodeList::ConstIterator iterator = Children().GetIterator();
2208 	while (iterator.HasNext()) {
2209 		iterator.Next()->Dump(level + 1);
2210 	}
2211 }
2212 
2213 
2214 //	#pragma mark - root node
2215 
2216 
2217 static void
2218 init_node_tree(void)
2219 {
2220 	device_attr attrs[] = {
2221 		{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "Devices Root"}},
2222 		{B_DEVICE_BUS, B_STRING_TYPE, {string: "root"}},
2223 		{B_DEVICE_FLAGS, B_UINT32_TYPE,
2224 			{ui32: B_FIND_MULTIPLE_CHILDREN | B_KEEP_DRIVER_LOADED }},
2225 		{NULL}
2226 	};
2227 
2228 	device_node* node = NULL;
2229 	if (register_node(NULL, DEVICE_MANAGER_ROOT_NAME, attrs, NULL, &node)
2230 			!= B_OK) {
2231 		dprintf("Cannot register Devices Root Node\n");
2232 	}
2233 
2234 	device_attr genericAttrs[] = {
2235 		{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "Generic"}},
2236 		{B_DEVICE_BUS, B_STRING_TYPE, {string: "generic"}},
2237 		{B_DEVICE_FLAGS, B_UINT32_TYPE, {ui32: B_FIND_MULTIPLE_CHILDREN
2238 			| B_KEEP_DRIVER_LOADED | B_FIND_CHILD_ON_DEMAND}},
2239 		{NULL}
2240 	};
2241 
2242 	if (register_node(node, DEVICE_MANAGER_GENERIC_NAME, genericAttrs, NULL,
2243 			NULL) != B_OK) {
2244 		dprintf("Cannot register Generic Devices Node\n");
2245 	}
2246 }
2247 
2248 
2249 driver_module_info gDeviceRootModule = {
2250 	{
2251 		DEVICE_MANAGER_ROOT_NAME,
2252 		0,
2253 		NULL,
2254 	},
2255 };
2256 
2257 
2258 driver_module_info gDeviceGenericModule = {
2259 	{
2260 		DEVICE_MANAGER_GENERIC_NAME,
2261 		0,
2262 		NULL,
2263 	},
2264 	NULL
2265 };
2266 
2267 
2268 //	#pragma mark - private kernel API
2269 
2270 
2271 status_t
2272 device_manager_probe(const char* path, uint32 updateCycle)
2273 {
2274 	TRACE(("device_manager_probe(\"%s\")\n", path));
2275 	RecursiveLocker _(sLock);
2276 
2277 	// first, publish directories in the driver directory
2278 	publish_directories(path);
2279 
2280 	return sRootNode->Probe(path, updateCycle);
2281 }
2282 
2283 
2284 status_t
2285 device_manager_init(struct kernel_args* args)
2286 {
2287 	TRACE(("device manager init\n"));
2288 
2289 	IOSchedulerRoster::Init();
2290 
2291 	dm_init_id_generator();
2292 	dm_init_io_resources();
2293 
2294 	recursive_lock_init(&sLock, "device manager");
2295 
2296 	register_generic_syscall(DEVICE_MANAGER_SYSCALLS, control_device_manager,
2297 		1, 0);
2298 
2299 	add_debugger_command("dm_tree", &dump_device_nodes,
2300 		"dump device node tree");
2301 	add_debugger_command_etc("io_scheduler", &dump_io_scheduler,
2302 		"Dump an I/O scheduler",
2303 		"<scheduler>\n"
2304 		"Dumps I/O scheduler at address <scheduler>.\n", 0);
2305 	add_debugger_command_etc("io_request_owner", &dump_io_request_owner,
2306 		"Dump an I/O request owner",
2307 		"<owner>\n"
2308 		"Dumps I/O request owner at address <owner>.\n", 0);
2309 	add_debugger_command("io_request", &dump_io_request, "dump an I/O request");
2310 	add_debugger_command("io_operation", &dump_io_operation,
2311 		"dump an I/O operation");
2312 	add_debugger_command("io_buffer", &dump_io_buffer, "dump an I/O buffer");
2313 	add_debugger_command("dma_buffer", &dump_dma_buffer, "dump a DMA buffer");
2314 
2315 	init_node_tree();
2316 
2317 	return B_OK;
2318 }
2319 
2320 
2321 status_t
2322 device_manager_init_post_modules(struct kernel_args* args)
2323 {
2324 	RecursiveLocker _(sLock);
2325 	return sRootNode->Reprobe();
2326 }
2327