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