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