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