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