Changeset 25406
- Timestamp:
- 05/09/08 17:05:50 (3 days ago)
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
haiku/trunk/src/tests/system/kernel/device_manager/playground/device_manager.cpp
r25394 r25406 97 97 98 98 status_t InitDriver(); 99 voidUninitDriver();99 bool UninitDriver(); 100 100 101 101 // The following two are only valid, if the node's driver is … … 107 107 void RemoveChild(device_node *node); 108 108 const NodeList& Children() const { return fChildren; } 109 void UninitUnusedChildren(); 109 110 110 111 status_t Register(); 112 status_t Probe(const char* devicePath); 111 113 bool IsRegistered() const { return fRegistered; } 114 bool IsInitialized() const { return fInitialized > 0; } 112 115 113 116 private: … … 124 127 status_t _RegisterPath(const char* path); 125 128 status_t _RegisterDynamic(); 129 status_t _RemoveChildren(); 130 bool _UninitUnusedChildren(); 126 131 127 132 device_node* fParent; … … 130 135 int32 fInitialized; 131 136 bool fRegistered; 137 uint32 fFlags; 132 138 133 139 const char* fModuleName; … … 138 144 }; 139 145 146 enum node_flags { 147 NODE_FLAG_REMOVE_ON_UNINIT = 0x01 148 }; 149 140 150 device_manager_info *gDeviceManager; 141 151 142 152 static device_node *sRootNode; 153 static recursive_lock sLock; 143 154 144 155 … … 372 383 373 384 385 static void 386 uninit_unused() 387 { 388 RecursiveLocker _(sLock); 389 sRootNode->UninitUnusedChildren(); 390 } 391 392 393 static status_t 394 probe_path(const char* path) 395 { 396 RecursiveLocker _(sLock); 397 return sRootNode->Probe(path); 398 } 399 400 374 401 // #pragma mark - device_node 375 402 … … 408 435 device_node::~device_node() 409 436 { 410 AttributeList::Iterator iterator = fAttributes.GetIterator(); 411 while (iterator.HasNext()) { 412 device_attr_private* attr = iterator.Next(); 413 iterator.Remove(); 437 // Delete children 438 NodeList::Iterator nodeIterator = fChildren.GetIterator(); 439 while (nodeIterator.HasNext()) { 440 device_node* child = nodeIterator.Next(); 441 nodeIterator.Remove(); 442 delete child; 443 } 444 445 // Delete attributes 446 AttributeList::Iterator attrIterator = fAttributes.GetIterator(); 447 while (attrIterator.HasNext()) { 448 device_attr_private* attr = attrIterator.Next(); 449 attrIterator.Remove(); 414 450 delete attr; 415 451 } 452 416 453 free((char*)fModuleName); 417 454 } … … 449 486 450 487 451 void 488 bool 452 489 device_node::UninitDriver() 453 490 { 454 491 if (fInitialized-- > 1) 455 return ;492 return false; 456 493 457 494 if (fDriver->uninit_driver != NULL) 458 495 fDriver->uninit_driver(this); 496 497 fDriver = NULL; 459 498 fDriverData = NULL; 460 499 461 500 put_module(ModuleName()); 501 502 if ((fFlags & NODE_FLAG_REMOVE_ON_UNINIT) != 0) 503 delete this; 504 505 return true; 462 506 } 463 507 … … 808 852 809 853 810 // #pragma mark - 854 status_t 855 device_node::_RemoveChildren() 856 { 857 NodeList::Iterator iterator = fChildren.GetIterator(); 858 while (iterator.HasNext()) { 859 device_node* child = iterator.Next(); 860 861 if (!child->IsInitialized()) { 862 // this child is not used currently, and can be removed safely 863 iterator.Remove(); 864 fRefCount--; 865 child->fParent = NULL; 866 delete child; 867 } else 868 child->fFlags |= NODE_FLAG_REMOVE_ON_UNINIT; 869 } 870 871 return fChildren.IsEmpty() ? B_OK : B_BUSY; 872 } 873 874 875 status_t 876 device_node::Probe(const char* devicePath) 877 { 878 uint16 type = 0; 879 uint16 subType = 0; 880 if (dm_get_attr_uint16(this, B_DEVICE_TYPE, &type, false) == B_OK 881 && dm_get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false) 882 == B_OK) { 883 // Check if this node matches the device path 884 // TODO: maybe make this extendible via settings file? 885 bool matches = false; 886 if (!strcmp(devicePath, "disk")) { 887 matches = type == PCI_mass_storage; 888 } else if (!strcmp(devicePath, "audio")) { 889 matches = type == PCI_multimedia 890 && (subType == PCI_audio || subType == PCI_hd_audio); 891 } else if (!strcmp(devicePath, "net")) { 892 matches = type == PCI_network; 893 } else if (!strcmp(devicePath, "graphics")) { 894 matches = type == PCI_display; 895 } else if (!strcmp(devicePath, "video")) { 896 matches = type == PCI_multimedia && subType == PCI_video; 897 } 898 899 if (matches) { 900 if (!fChildren.IsEmpty()) { 901 // We already have a driver that claims this node. 902 // Try to remove uninitialized children, so that this node 903 // can be re-evaluated 904 // TODO: try first if there is a better child! 905 // TODO: publish both devices, make new one busy as long 906 // as the old one is in use! 907 if (_RemoveChildren() != B_OK) 908 return B_OK; 909 } 910 return _RegisterDynamic(); 911 } 912 913 return B_OK; 914 } 915 916 NodeList::Iterator iterator = fChildren.GetIterator(); 917 while (iterator.HasNext()) { 918 device_node* child = iterator.Next(); 919 920 status_t status = child->Probe(devicePath); 921 if (status != B_OK) 922 return status; 923 } 924 925 return B_OK; 926 } 927 928 929 bool 930 device_node::_UninitUnusedChildren() 931 { 932 // First, we need to go to the leaf, and go back from there 933 934 bool uninit = true; 935 936 NodeList::Iterator iterator = fChildren.GetIterator(); 937 938 while (iterator.HasNext()) { 939 device_node* child = iterator.Next(); 940 941 if (!child->_UninitUnusedChildren()) 942 uninit = false; 943 } 944 945 // Not all of our children could be uninitialized 946 if (!uninit) 947 return false; 948 949 if (!IsInitialized()) 950 return true; 951 952 if ((DriverModule()->info.flags & B_KEEP_LOADED) != 0) { 953 // We must not get unloaded 954 return false; 955 } 956 957 return UninitDriver(); 958 } 959 960 961 void 962 device_node::UninitUnusedChildren() 963 { 964 _UninitUnusedChildren(); 965 } 811 966 812 967 … … 838 993 TRACE(("%p: register device \"%s\", parent %p\n", newNode, moduleName, 839 994 parent)); 995 996 RecursiveLocker _(sLock); 840 997 841 998 status_t status = newNode->InitCheck(); … … 891 1048 892 1049 893 static void1050 static status_t 894 1051 get_driver(device_node* node, driver_module_info** _module, void** _data) 895 1052 { 1053 if (node->DriverModule() == NULL) 1054 return B_NO_INIT; 1055 896 1056 if (_module != NULL) 897 1057 *_module = node->DriverModule(); 898 1058 if (_data != NULL) 899 1059 *_data = node->DriverData(); 1060 1061 return B_OK; 900 1062 } 901 1063 … … 1137 1299 } 1138 1300 1301 recursive_lock_init(&sLock, "device manager"); 1302 1139 1303 dm_init_root_node(); 1140 1304 dm_dump_node(sRootNode, 0); 1141 1305 1306 probe_path("net"); 1307 uninit_unused(); 1308 1309 recursive_lock_destroy(&sLock); 1142 1310 return 0; 1143 1311 } haiku/trunk/src/tests/system/kernel/device_manager/playground/device_manager.h
r25394 r25406 70 70 status_t (*unregister_device)(device_node *node); 71 71 72 void(*get_driver)(device_node *node, driver_module_info **_module,72 status_t (*get_driver)(device_node *node, driver_module_info **_module, 73 73 void **_cookie); 74 74
