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