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