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 26 #define TRACE(a) dprintf a 27 28 #define DEVICE_MANAGER_ROOT_NAME "system/devices_root/driver_v1" 29 30 extern struct device_module_info gDeviceModuleInfo; 31 extern struct driver_module_info gDriverModuleInfo; 32 extern struct device_module_info gGenericVideoDeviceModuleInfo; 33 extern struct driver_module_info gGenericVideoDriverModuleInfo; 34 extern struct device_module_info gSpecificVideoDeviceModuleInfo; 35 extern struct driver_module_info gSpecificVideoDriverModuleInfo; 36 extern struct driver_module_info gBusModuleInfo; 37 extern struct driver_module_info gBusDriverModuleInfo; 38 39 extern "C" status_t _add_builtin_module(module_info *info); 40 extern "C" status_t _get_builtin_dependencies(void); 41 extern bool gDebugOutputEnabled; 42 // from libkernelland_emu.so 43 44 status_t dm_get_attr_uint8(const device_node* node, const char* name, 45 uint8* _value, bool recursive); 46 status_t dm_get_attr_uint16(const device_node* node, const char* name, 47 uint16* _value, bool recursive); 48 status_t dm_get_attr_uint32(const device_node* node, const char* name, 49 uint32* _value, bool recursive); 50 status_t dm_get_attr_string(const device_node* node, const char* name, 51 const char** _value, bool recursive); 52 53 54 struct device_attr_private : device_attr, 55 DoublyLinkedListLinkImpl<device_attr_private> { 56 device_attr_private(); 57 device_attr_private(const device_attr& attr); 58 ~device_attr_private(); 59 60 status_t InitCheck(); 61 status_t CopyFrom(const device_attr& attr); 62 63 static int Compare(const device_attr* attrA, 64 const device_attr *attrB); 65 66 private: 67 void _Unset(); 68 }; 69 70 typedef DoublyLinkedList<device_attr_private> AttributeList; 71 72 73 // I/O resource 74 typedef struct io_resource_info { 75 struct io_resource_info *prev, *next; 76 device_node* owner; // associated node; NULL for temporary allocation 77 io_resource resource; // info about actual resource 78 } io_resource_info; 79 80 81 // a structure to put nodes into lists 82 struct node_entry { 83 struct list_link link; 84 device_node* node; 85 }; 86 87 typedef DoublyLinkedList<device_node> NodeList; 88 89 struct device_node : DoublyLinkedListLinkImpl<device_node> { 90 device_node(const char *moduleName, 91 const device_attr *attrs, 92 const io_resource *resources); 93 ~device_node(); 94 95 status_t InitCheck(); 96 97 const char* ModuleName() const { return fModuleName; } 98 device_node* Parent() const { return fParent; } 99 AttributeList& Attributes() { return fAttributes; } 100 const AttributeList& Attributes() const { return fAttributes; } 101 102 status_t InitDriver(); 103 bool UninitDriver(); 104 105 // The following two are only valid, if the node's driver is 106 // initialized 107 driver_module_info* DriverModule() const { return fDriver; } 108 void* DriverData() const { return fDriverData; } 109 110 void AddChild(device_node *node); 111 void RemoveChild(device_node *node); 112 const NodeList& Children() const { return fChildren; } 113 void UninitUnusedChildren(); 114 115 status_t Register(); 116 status_t Probe(const char* devicePath); 117 bool IsRegistered() const { return fRegistered; } 118 bool IsInitialized() const { return fInitialized > 0; } 119 120 void Acquire(); 121 bool Release(); 122 123 int CompareTo(const device_attr* attributes) const; 124 device_node* FindChild(const device_attr* attributes) const; 125 126 void Dump(int32 level = 0); 127 128 private: 129 status_t _RegisterFixed(uint32& registered); 130 bool _AlwaysRegisterDynamic(); 131 status_t _AddPath(Stack<KPath*>& stack, const char* path, 132 const char* subPath = NULL); 133 status_t _GetNextDriverPath(void*& cookie, KPath& _path); 134 status_t _GetNextDriver(void* list, 135 driver_module_info*& driver); 136 status_t _FindBestDriver(const char* path, 137 driver_module_info*& bestDriver, 138 float& bestSupport); 139 status_t _RegisterPath(const char* path); 140 status_t _RegisterDynamic(); 141 status_t _RemoveChildren(); 142 bool _UninitUnusedChildren(); 143 144 device_node* fParent; 145 NodeList fChildren; 146 int32 fRefCount; 147 int32 fInitialized; 148 bool fRegistered; 149 uint32 fFlags; 150 151 const char* fModuleName; 152 driver_module_info* fDriver; 153 void* fDriverData; 154 155 AttributeList fAttributes; 156 }; 157 158 enum node_flags { 159 NODE_FLAG_REMOVE_ON_UNINIT = 0x01 160 }; 161 162 device_manager_info *gDeviceManager; 163 164 static device_node *sRootNode; 165 static recursive_lock sLock; 166 167 168 // #pragma mark - device_attr 169 170 171 device_attr_private::device_attr_private() 172 { 173 name = NULL; 174 type = 0; 175 value.raw.data = NULL; 176 value.raw.length = 0; 177 } 178 179 180 device_attr_private::device_attr_private(const device_attr& attr) 181 { 182 CopyFrom(attr); 183 } 184 185 186 device_attr_private::~device_attr_private() 187 { 188 _Unset(); 189 } 190 191 192 status_t 193 device_attr_private::InitCheck() 194 { 195 return name != NULL ? B_OK : B_NO_INIT; 196 } 197 198 199 status_t 200 device_attr_private::CopyFrom(const device_attr& attr) 201 { 202 name = strdup(attr.name); 203 if (name == NULL) 204 return B_NO_MEMORY; 205 206 type = attr.type; 207 208 switch (type) { 209 case B_UINT8_TYPE: 210 case B_UINT16_TYPE: 211 case B_UINT32_TYPE: 212 case B_UINT64_TYPE: 213 value.ui64 = attr.value.ui64; 214 break; 215 216 case B_STRING_TYPE: 217 if (attr.value.string != NULL) { 218 value.string = strdup(attr.value.string); 219 if (value.string == NULL) { 220 _Unset(); 221 return B_NO_MEMORY; 222 } 223 } else 224 value.string = NULL; 225 break; 226 227 case B_RAW_TYPE: 228 value.raw.data = malloc(attr.value.raw.length); 229 if (value.raw.data == NULL) { 230 _Unset(); 231 return B_NO_MEMORY; 232 } 233 234 value.raw.length = attr.value.raw.length; 235 memcpy((void*)value.raw.data, attr.value.raw.data, 236 attr.value.raw.length); 237 break; 238 239 default: 240 return B_BAD_VALUE; 241 } 242 243 return B_OK; 244 } 245 246 247 void 248 device_attr_private::_Unset() 249 { 250 if (type == B_STRING_TYPE) 251 free((char*)value.string); 252 else if (type == B_RAW_TYPE) 253 free((void*)value.raw.data); 254 255 free((char*)name); 256 257 name = NULL; 258 value.raw.data = NULL; 259 value.raw.length = 0; 260 } 261 262 263 /*static*/ int 264 device_attr_private::Compare(const device_attr* attrA, const device_attr *attrB) 265 { 266 if (attrA->type != attrB->type) 267 return -1; 268 269 switch (attrA->type) { 270 case B_UINT8_TYPE: 271 return (int)attrA->value.ui8 - (int)attrB->value.ui8; 272 273 case B_UINT16_TYPE: 274 return (int)attrA->value.ui16 - (int)attrB->value.ui16; 275 276 case B_UINT32_TYPE: 277 if (attrA->value.ui32 > attrB->value.ui32) 278 return 1; 279 if (attrA->value.ui32 < attrB->value.ui32) 280 return -1; 281 return 0; 282 283 case B_UINT64_TYPE: 284 if (attrA->value.ui64 > attrB->value.ui64) 285 return 1; 286 if (attrA->value.ui64 < attrB->value.ui64) 287 return -1; 288 return 0; 289 290 case B_STRING_TYPE: 291 return strcmp(attrA->value.string, attrB->value.string); 292 293 case B_RAW_TYPE: 294 if (attrA->value.raw.length != attrB->value.raw.length) 295 return -1; 296 297 return memcmp(attrA->value.raw.data, attrB->value.raw.data, 298 attrA->value.raw.length); 299 } 300 301 return -1; 302 } 303 304 305 // #pragma mark - 306 307 308 device_attr_private* 309 dm_find_attr(const device_node* node, const char* name, bool recursive, 310 type_code type) 311 { 312 do { 313 AttributeList::ConstIterator iterator 314 = node->Attributes().GetIterator(); 315 316 while (iterator.HasNext()) { 317 device_attr_private* attr = iterator.Next(); 318 319 if (type != B_ANY_TYPE && attr->type != type) 320 continue; 321 322 if (!strcmp(attr->name, name)) 323 return attr; 324 } 325 326 node = node->Parent(); 327 } while (node != NULL && recursive); 328 329 return NULL; 330 } 331 332 333 static void 334 put_level(int32 level) 335 { 336 while (level-- > 0) 337 dprintf(" "); 338 } 339 340 341 static void 342 dump_attribute(device_attr* attr, int32 level) 343 { 344 if (attr == NULL) 345 return; 346 347 put_level(level + 2); 348 dprintf("\"%s\" : ", attr->name); 349 switch (attr->type) { 350 case B_STRING_TYPE: 351 dprintf("string : \"%s\"", attr->value.string); 352 break; 353 case B_INT8_TYPE: 354 case B_UINT8_TYPE: 355 dprintf("uint8 : %u (%#x)", attr->value.ui8, attr->value.ui8); 356 break; 357 case B_INT16_TYPE: 358 case B_UINT16_TYPE: 359 dprintf("uint16 : %u (%#x)", attr->value.ui16, attr->value.ui16); 360 break; 361 case B_INT32_TYPE: 362 case B_UINT32_TYPE: 363 dprintf("uint32 : %lu (%#lx)", attr->value.ui32, attr->value.ui32); 364 break; 365 case B_INT64_TYPE: 366 case B_UINT64_TYPE: 367 dprintf("uint64 : %Lu (%#Lx)", attr->value.ui64, attr->value.ui64); 368 break; 369 default: 370 dprintf("raw data"); 371 } 372 dprintf("\n"); 373 } 374 375 376 static void 377 uninit_unused() 378 { 379 RecursiveLocker _(sLock); 380 sRootNode->UninitUnusedChildren(); 381 } 382 383 384 static status_t 385 probe_path(const char* path) 386 { 387 RecursiveLocker _(sLock); 388 return sRootNode->Probe(path); 389 } 390 391 392 // #pragma mark - device_node 393 394 395 /*! Allocate device node info structure; 396 initially, ref_count is one to make sure node won't get destroyed by mistake 397 */ 398 device_node::device_node(const char* moduleName, const device_attr* attrs, 399 const io_resource* resources) 400 { 401 fModuleName = strdup(moduleName); 402 if (fModuleName == NULL) 403 return; 404 405 fParent = NULL; 406 fRefCount = 1; 407 fInitialized = 0; 408 fRegistered = false; 409 fDriver = NULL; 410 fDriverData = NULL; 411 412 // copy attributes 413 414 while (attrs != NULL && attrs->name != NULL) { 415 device_attr_private* attr 416 = new(std::nothrow) device_attr_private(*attrs); 417 if (attr == NULL) 418 break; 419 420 fAttributes.Add(attr); 421 attrs++; 422 } 423 } 424 425 426 device_node::~device_node() 427 { 428 TRACE(("delete node %p\n", this)); 429 430 // Delete children 431 NodeList::Iterator nodeIterator = fChildren.GetIterator(); 432 while (nodeIterator.HasNext()) { 433 device_node* child = nodeIterator.Next(); 434 nodeIterator.Remove(); 435 delete child; 436 } 437 438 // Delete attributes 439 AttributeList::Iterator attrIterator = fAttributes.GetIterator(); 440 while (attrIterator.HasNext()) { 441 device_attr_private* attr = attrIterator.Next(); 442 attrIterator.Remove(); 443 delete attr; 444 } 445 446 free((char*)fModuleName); 447 } 448 449 450 status_t 451 device_node::InitCheck() 452 { 453 return fModuleName != NULL ? B_OK : B_NO_MEMORY; 454 } 455 456 457 status_t 458 device_node::InitDriver() 459 { 460 if (fInitialized++ > 0) { 461 if (Parent() != NULL) { 462 Parent()->InitDriver(); 463 // acquire another reference to our parent as well 464 } 465 Acquire(); 466 return B_OK; 467 } 468 469 status_t status = get_module(ModuleName(), (module_info**)&fDriver); 470 if (status == B_OK && Parent() != NULL) { 471 // our parent always have to be initialized 472 status = Parent()->InitDriver(); 473 } 474 if (status < B_OK) { 475 fInitialized--; 476 return status; 477 } 478 479 if (fDriver->init_driver != NULL) 480 status = fDriver->init_driver(this, &fDriverData); 481 482 if (status < B_OK) { 483 fInitialized--; 484 485 put_module(ModuleName()); 486 fDriver = NULL; 487 fDriverData = NULL; 488 return status; 489 } 490 491 Acquire(); 492 return B_OK; 493 } 494 495 496 bool 497 device_node::UninitDriver() 498 { 499 if (fInitialized-- > 1) { 500 Release(); 501 return false; 502 } 503 TRACE(("uninit driver for node %p\n", this)); 504 505 if (fDriver->uninit_driver != NULL) 506 fDriver->uninit_driver(this); 507 508 fDriver = NULL; 509 fDriverData = NULL; 510 511 put_module(ModuleName()); 512 513 Release(); 514 if (Parent() != NULL) 515 Parent()->UninitDriver(); 516 517 if ((fFlags & NODE_FLAG_REMOVE_ON_UNINIT) != 0) 518 Release(); 519 520 return true; 521 } 522 523 524 void 525 device_node::AddChild(device_node* node) 526 { 527 // we must not be destroyed as long as we have children 528 Acquire(); 529 node->fParent = this; 530 fChildren.Add(node); 531 } 532 533 534 void 535 device_node::RemoveChild(device_node* node) 536 { 537 node->fParent = NULL; 538 fChildren.Remove(node); 539 Release(); 540 } 541 542 543 status_t 544 device_node::Register() 545 { 546 uint32 registered; 547 status_t status = _RegisterFixed(registered); 548 if (status != B_OK) 549 return status; 550 if (registered > 0) { 551 fRegistered = true; 552 return B_OK; 553 } 554 555 // Register the children the driver wants 556 557 if (DriverModule()->register_child_devices != NULL) { 558 status = DriverModule()->register_child_devices(this); 559 if (status != B_OK) 560 return status; 561 562 if (!fChildren.IsEmpty()) { 563 fRegistered = true; 564 return B_OK; 565 } 566 } 567 568 // Register all possible child device nodes 569 570 status = _RegisterDynamic(); 571 if (status == B_OK) 572 fRegistered = true; 573 574 return status; 575 } 576 577 578 /*! Registers any children that are identified via the B_DRIVER_FIXED_CHILD 579 attribute. 580 If any of these children cannot be registered, this call will fail (we 581 don't remove already registered children in this case). 582 */ 583 status_t 584 device_node::_RegisterFixed(uint32& registered) 585 { 586 AttributeList::Iterator iterator = fAttributes.GetIterator(); 587 registered = 0; 588 589 while (iterator.HasNext()) { 590 device_attr_private* attr = iterator.Next(); 591 if (strcmp(attr->name, B_DEVICE_FIXED_CHILD)) 592 continue; 593 594 driver_module_info* driver; 595 status_t status = get_module(attr->value.string, 596 (module_info**)&driver); 597 if (status != B_OK) 598 return status; 599 600 if (driver->register_device != NULL) { 601 status = driver->register_device(this); 602 if (status == B_OK) 603 registered++; 604 } 605 606 put_module(attr->value.string); 607 608 if (status != B_OK) 609 return status; 610 } 611 612 return B_OK; 613 } 614 615 616 status_t 617 device_node::_AddPath(Stack<KPath*>& stack, const char* basePath, 618 const char* subPath) 619 { 620 KPath* path = new(std::nothrow) KPath; 621 if (path == NULL) 622 return B_NO_MEMORY; 623 624 status_t status = path->SetTo(basePath); 625 if (status == B_OK && subPath != NULL && subPath[0]) 626 status = path->Append(subPath); 627 if (status == B_OK) 628 status = stack.Push(path); 629 630 if (status != B_OK) 631 delete path; 632 633 return status; 634 } 635 636 637 status_t 638 device_node::_GetNextDriverPath(void*& cookie, KPath& _path) 639 { 640 Stack<KPath*>* stack = NULL; 641 642 if (cookie == NULL) { 643 // find all paths and add them 644 stack = new(std::nothrow) Stack<KPath*>(); 645 if (stack == NULL) 646 return B_NO_MEMORY; 647 648 StackDeleter<KPath*> stackDeleter(stack); 649 uint16 type = 0; 650 uint16 subType = 0; 651 uint16 interface = 0; 652 dm_get_attr_uint16(this, B_DEVICE_TYPE, &type, false); 653 dm_get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false); 654 dm_get_attr_uint16(this, B_DEVICE_INTERFACE, &interface, false); 655 656 // TODO: maybe make this extendible via settings file? 657 switch (type) { 658 case PCI_mass_storage: 659 switch (subType) { 660 case PCI_scsi: 661 _AddPath(*stack, "busses", "scsi"); 662 break; 663 case PCI_ide: 664 _AddPath(*stack, "busses", "ide"); 665 break; 666 case PCI_sata: 667 _AddPath(*stack, "busses", "sata"); 668 break; 669 default: 670 _AddPath(*stack, "busses", "disk"); 671 break; 672 } 673 break; 674 case PCI_serial_bus: 675 switch (subType) { 676 case PCI_firewire: 677 _AddPath(*stack, "busses", "firewire"); 678 break; 679 case PCI_usb: 680 _AddPath(*stack, "busses", "usb"); 681 break; 682 default: 683 _AddPath(*stack, "busses"); 684 break; 685 } 686 break; 687 case PCI_network: 688 _AddPath(*stack, "drivers", "net"); 689 break; 690 case PCI_display: 691 _AddPath(*stack, "drivers", "graphics"); 692 break; 693 case PCI_multimedia: 694 switch (subType) { 695 case PCI_audio: 696 case PCI_hd_audio: 697 _AddPath(*stack, "drivers", "audio"); 698 break; 699 case PCI_video: 700 _AddPath(*stack, "drivers", "video"); 701 break; 702 default: 703 _AddPath(*stack, "drivers"); 704 break; 705 } 706 break; 707 default: 708 if (sRootNode == this) { 709 _AddPath(*stack, "busses/pci"); 710 _AddPath(*stack, "bus_managers"); 711 } else 712 _AddPath(*stack, "drivers"); 713 break; 714 } 715 716 stackDeleter.Detach(); 717 718 cookie = (void*)stack; 719 } else 720 stack = static_cast<Stack<KPath*>*>(cookie); 721 722 KPath* path; 723 if (stack->Pop(&path)) { 724 _path.Adopt(*path); 725 delete path; 726 return B_OK; 727 } 728 729 delete stack; 730 return B_ENTRY_NOT_FOUND; 731 } 732 733 734 status_t 735 device_node::_GetNextDriver(void* list, driver_module_info*& driver) 736 { 737 while (true) { 738 char name[B_FILE_NAME_LENGTH]; 739 size_t nameLength = sizeof(name); 740 741 status_t status = read_next_module_name(list, name, &nameLength); 742 if (status != B_OK) 743 return status; 744 745 if (!strcmp(fModuleName, name)) 746 continue; 747 748 if (get_module(name, (module_info**)&driver) != B_OK) 749 continue; 750 751 if (driver->supports_device == NULL 752 || driver->register_device == NULL) { 753 put_module(name); 754 continue; 755 } 756 757 return B_OK; 758 } 759 } 760 761 762 status_t 763 device_node::_FindBestDriver(const char* path, driver_module_info*& bestDriver, 764 float& bestSupport) 765 { 766 if (bestDriver == NULL) 767 bestSupport = 0.0f; 768 769 void* list = open_module_list_etc(path, "driver_v1"); 770 driver_module_info* driver; 771 while (_GetNextDriver(list, driver) == B_OK) { 772 float support = driver->supports_device(this); 773 if (support > bestSupport) { 774 if (bestDriver != NULL) 775 put_module(bestDriver->info.name); 776 777 bestDriver = driver; 778 bestSupport = support; 779 continue; 780 // keep reference to best module around 781 } 782 783 put_module(driver->info.name); 784 } 785 close_module_list(list); 786 787 return bestDriver != NULL ? B_OK : B_ENTRY_NOT_FOUND; 788 } 789 790 791 status_t 792 device_node::_RegisterPath(const char* path) 793 { 794 void* list = open_module_list_etc(path, "driver_v1"); 795 driver_module_info* driver; 796 uint32 count = 0; 797 798 while (_GetNextDriver(list, driver) == B_OK) { 799 float support = driver->supports_device(this); 800 if (support > 0.0) { 801 TRACE((" register module \"%s\", support %f\n", driver->info.name, 802 support)); 803 if (driver->register_device(this) == B_OK) 804 count++; 805 } 806 807 put_module(driver->info.name); 808 } 809 close_module_list(list); 810 811 return count > 0 ? B_OK : B_ENTRY_NOT_FOUND; 812 } 813 814 815 bool 816 device_node::_AlwaysRegisterDynamic() 817 { 818 uint16 type = 0; 819 uint16 subType = 0; 820 dm_get_attr_uint16(this, B_DEVICE_TYPE, &type, false); 821 dm_get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false); 822 823 return type == PCI_serial_bus || type == PCI_bridge; 824 // TODO: we may want to be a bit more specific in the future 825 } 826 827 828 status_t 829 device_node::_RegisterDynamic() 830 { 831 uint32 findFlags = 0; 832 dm_get_attr_uint32(this, B_DEVICE_FIND_CHILD_FLAGS, &findFlags, false); 833 834 // If this is our initial registration, we honour the B_FIND_CHILD_ON_DEMAND 835 // requirements 836 if (!fRegistered && (findFlags & B_FIND_CHILD_ON_DEMAND) != 0 837 && !_AlwaysRegisterDynamic()) 838 return B_OK; 839 840 KPath path; 841 842 if ((findFlags & B_FIND_MULTIPLE_CHILDREN) == 0) { 843 // find the one driver 844 driver_module_info* bestDriver = NULL; 845 float bestSupport = 0.0; 846 void* cookie = NULL; 847 848 while (_GetNextDriverPath(cookie, path) == B_OK) { 849 _FindBestDriver(path.Path(), bestDriver, bestSupport); 850 } 851 852 if (bestDriver != NULL) { 853 TRACE((" register best module \"%s\", support %f\n", 854 bestDriver->info.name, bestSupport)); 855 bestDriver->register_device(this); 856 put_module(bestDriver->info.name); 857 } 858 } else { 859 // register all drivers that match 860 void* cookie = NULL; 861 while (_GetNextDriverPath(cookie, path) == B_OK) { 862 _RegisterPath(path.Path()); 863 } 864 } 865 866 return B_OK; 867 } 868 869 870 status_t 871 device_node::_RemoveChildren() 872 { 873 NodeList::Iterator iterator = fChildren.GetIterator(); 874 while (iterator.HasNext()) { 875 device_node* child = iterator.Next(); 876 877 if (!child->IsInitialized()) { 878 // this child is not used currently, and can be removed safely 879 iterator.Remove(); 880 child->fParent = NULL; 881 delete child; 882 if (Release()) 883 panic("died early"); 884 } else 885 child->fFlags |= NODE_FLAG_REMOVE_ON_UNINIT; 886 } 887 888 return fChildren.IsEmpty() ? B_OK : B_BUSY; 889 } 890 891 892 status_t 893 device_node::Probe(const char* devicePath) 894 { 895 status_t status = InitDriver(); 896 if (status < B_OK) 897 return status; 898 899 MethodDeleter<device_node, bool> uninit(this, &device_node::UninitDriver); 900 901 uint16 type = 0; 902 uint16 subType = 0; 903 if (dm_get_attr_uint16(this, B_DEVICE_TYPE, &type, false) == B_OK 904 && dm_get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false) 905 == B_OK) { 906 // Check if this node matches the device path 907 // TODO: maybe make this extendible via settings file? 908 bool matches = false; 909 if (!strcmp(devicePath, "disk")) { 910 matches = type == PCI_mass_storage; 911 } else if (!strcmp(devicePath, "audio")) { 912 matches = type == PCI_multimedia 913 && (subType == PCI_audio || subType == PCI_hd_audio); 914 } else if (!strcmp(devicePath, "net")) { 915 matches = type == PCI_network; 916 } else if (!strcmp(devicePath, "graphics")) { 917 matches = type == PCI_display; 918 } else if (!strcmp(devicePath, "video")) { 919 matches = type == PCI_multimedia && subType == PCI_video; 920 } 921 922 if (matches) { 923 if (!fChildren.IsEmpty()) { 924 // We already have a driver that claims this node. 925 // Try to remove uninitialized children, so that this node 926 // can be re-evaluated 927 // TODO: try first if there is a better child! 928 // TODO: publish both devices, make new one busy as long 929 // as the old one is in use! 930 if (_RemoveChildren() != B_OK) 931 return B_OK; 932 } 933 return _RegisterDynamic(); 934 } 935 936 return B_OK; 937 } 938 939 NodeList::Iterator iterator = fChildren.GetIterator(); 940 while (iterator.HasNext()) { 941 device_node* child = iterator.Next(); 942 943 status = child->Probe(devicePath); 944 if (status != B_OK) 945 return status; 946 } 947 948 return B_OK; 949 } 950 951 952 bool 953 device_node::_UninitUnusedChildren() 954 { 955 // First, we need to go to the leaf, and go back from there 956 957 bool uninit = true; 958 959 NodeList::Iterator iterator = fChildren.GetIterator(); 960 961 while (iterator.HasNext()) { 962 device_node* child = iterator.Next(); 963 964 if (!child->_UninitUnusedChildren()) 965 uninit = false; 966 } 967 968 // Not all of our children could be uninitialized 969 if (!uninit) 970 return false; 971 972 if (!IsInitialized()) 973 return true; 974 975 if ((DriverModule()->info.flags & B_KEEP_LOADED) != 0) { 976 // We must not get unloaded 977 return false; 978 } 979 980 return UninitDriver(); 981 } 982 983 984 void 985 device_node::UninitUnusedChildren() 986 { 987 _UninitUnusedChildren(); 988 } 989 990 991 void 992 device_node::Acquire() 993 { 994 atomic_add(&fRefCount, 1); 995 } 996 997 998 bool 999 device_node::Release() 1000 { 1001 if (atomic_add(&fRefCount, -1) > 1) 1002 return false; 1003 1004 if (Parent() != NULL) 1005 Parent()->RemoveChild(this); 1006 delete this; 1007 return true; 1008 } 1009 1010 1011 int 1012 device_node::CompareTo(const device_attr* attributes) const 1013 { 1014 if (attributes == NULL) 1015 return -1; 1016 1017 for (; attributes->name != NULL; attributes++) { 1018 // find corresponding attribute 1019 AttributeList::ConstIterator iterator = Attributes().GetIterator(); 1020 device_attr_private* attr = NULL; 1021 while (iterator.HasNext()) { 1022 attr = iterator.Next(); 1023 1024 if (!strcmp(attr->name, attributes->name)) 1025 break; 1026 } 1027 if (!iterator.HasNext()) 1028 return -1; 1029 1030 int compare = device_attr_private::Compare(attr, attributes); 1031 if (compare != 0) 1032 return compare; 1033 } 1034 1035 return 0; 1036 } 1037 1038 1039 device_node* 1040 device_node::FindChild(const device_attr* attributes) const 1041 { 1042 if (attributes == NULL) 1043 return NULL; 1044 1045 NodeList::ConstIterator iterator = Children().GetIterator(); 1046 while (iterator.HasNext()) { 1047 device_node* child = iterator.Next(); 1048 1049 if (!child->CompareTo(attributes)) 1050 return child; 1051 } 1052 1053 return NULL; 1054 } 1055 1056 1057 void 1058 device_node::Dump(int32 level = 0) 1059 { 1060 put_level(level); 1061 dprintf("(%ld) @%p \"%s\" (ref %ld, init %ld)\n", level, this, ModuleName(), 1062 fRefCount, fInitialized); 1063 1064 AttributeList::Iterator attribute = Attributes().GetIterator(); 1065 while (attribute.HasNext()) { 1066 dump_attribute(attribute.Next(), level); 1067 } 1068 1069 NodeList::ConstIterator iterator = Children().GetIterator(); 1070 while (iterator.HasNext()) { 1071 iterator.Next()->Dump(level + 1); 1072 } 1073 } 1074 1075 1076 // #pragma mark - Device Manager module API 1077 1078 1079 static status_t 1080 rescan_device(device_node* node) 1081 { 1082 return B_ERROR; 1083 } 1084 1085 1086 static status_t 1087 register_device(device_node* parent, const char* moduleName, 1088 const device_attr* attrs, const io_resource* ioResources, 1089 device_node** _node) 1090 { 1091 if ((parent == NULL && sRootNode != NULL) || moduleName == NULL) 1092 return B_BAD_VALUE; 1093 1094 if (parent != NULL && parent->FindChild(attrs) != NULL) { 1095 // A node like this one already exists for this parent 1096 return B_NAME_IN_USE; 1097 } 1098 1099 // TODO: handle I/O resources! 1100 1101 device_node *newNode = new(std::nothrow) device_node(moduleName, attrs, 1102 ioResources); 1103 if (newNode == NULL) 1104 return B_NO_MEMORY; 1105 1106 TRACE(("%p: register device \"%s\", parent %p\n", newNode, moduleName, 1107 parent)); 1108 1109 RecursiveLocker _(sLock); 1110 1111 status_t status = newNode->InitCheck(); 1112 if (status != B_OK) 1113 goto err1; 1114 1115 // make it public 1116 if (parent != NULL) 1117 parent->AddChild(newNode); 1118 else 1119 sRootNode = newNode; 1120 1121 status = newNode->InitDriver(); 1122 if (status != B_OK) 1123 goto err1; 1124 1125 #if 0 1126 // The following is done to reduce the stack usage of deeply nested 1127 // child device nodes. 1128 // There is no other need to delay the complete registration process 1129 // the way done here. This approach is also slightly different as 1130 // the registration might fail later than it used in case of errors. 1131 1132 if (!parent->IsRegistered()) { 1133 // The parent has not been registered completely yet - child 1134 // registration is deferred to the parent registration 1135 return B_OK; 1136 } 1137 #endif 1138 1139 status = newNode->Register(); 1140 if (status < B_OK) { 1141 parent->RemoveChild(newNode); 1142 goto err1; 1143 } 1144 1145 if (_node) 1146 *_node = newNode; 1147 1148 return B_OK; 1149 1150 err1: 1151 delete newNode; 1152 return status; 1153 } 1154 1155 1156 static status_t 1157 unregister_device(device_node* node) 1158 { 1159 return B_ERROR; 1160 } 1161 1162 1163 static status_t 1164 get_driver(device_node* node, driver_module_info** _module, void** _data) 1165 { 1166 if (node->DriverModule() == NULL) 1167 return B_NO_INIT; 1168 1169 if (_module != NULL) 1170 *_module = node->DriverModule(); 1171 if (_data != NULL) 1172 *_data = node->DriverData(); 1173 1174 return B_OK; 1175 } 1176 1177 1178 static device_node* 1179 get_device_root(void) 1180 { 1181 if (sRootNode != NULL) 1182 sRootNode->Acquire(); 1183 1184 return sRootNode; 1185 } 1186 1187 1188 static status_t 1189 get_next_child_device(device_node* parent, device_node* _node, 1190 const device_attr* attrs) 1191 { 1192 return B_ERROR; 1193 } 1194 1195 1196 static device_node* 1197 get_parent(device_node* node) 1198 { 1199 if (node == NULL) 1200 return NULL; 1201 1202 RecursiveLocker _(sLock); 1203 1204 device_node* parent = node->Parent(); 1205 parent->Acquire(); 1206 1207 return parent; 1208 } 1209 1210 1211 static void 1212 put_device_node(device_node* node) 1213 { 1214 RecursiveLocker _(sLock); 1215 node->Release(); 1216 } 1217 1218 1219 status_t 1220 dm_get_attr_uint8(const device_node* node, const char* name, uint8* _value, 1221 bool recursive) 1222 { 1223 if (node == NULL || name == NULL || _value == NULL) 1224 return B_BAD_VALUE; 1225 1226 device_attr_private* attr = dm_find_attr(node, name, recursive, 1227 B_UINT8_TYPE); 1228 if (attr == NULL) 1229 return B_NAME_NOT_FOUND; 1230 1231 *_value = attr->value.ui8; 1232 return B_OK; 1233 } 1234 1235 1236 status_t 1237 dm_get_attr_uint16(const device_node* node, const char* name, uint16* _value, 1238 bool recursive) 1239 { 1240 if (node == NULL || name == NULL || _value == NULL) 1241 return B_BAD_VALUE; 1242 1243 device_attr_private* attr = dm_find_attr(node, name, recursive, 1244 B_UINT16_TYPE); 1245 if (attr == NULL) 1246 return B_NAME_NOT_FOUND; 1247 1248 *_value = attr->value.ui16; 1249 return B_OK; 1250 } 1251 1252 1253 status_t 1254 dm_get_attr_uint32(const device_node* node, const char* name, uint32* _value, 1255 bool recursive) 1256 { 1257 if (node == NULL || name == NULL || _value == NULL) 1258 return B_BAD_VALUE; 1259 1260 device_attr_private* attr = dm_find_attr(node, name, recursive, 1261 B_UINT32_TYPE); 1262 if (attr == NULL) 1263 return B_NAME_NOT_FOUND; 1264 1265 *_value = attr->value.ui32; 1266 return B_OK; 1267 } 1268 1269 1270 status_t 1271 dm_get_attr_uint64(const device_node* node, const char* name, 1272 uint64* _value, bool recursive) 1273 { 1274 if (node == NULL || name == NULL || _value == NULL) 1275 return B_BAD_VALUE; 1276 1277 device_attr_private* attr = dm_find_attr(node, name, recursive, 1278 B_UINT64_TYPE); 1279 if (attr == NULL) 1280 return B_NAME_NOT_FOUND; 1281 1282 *_value = attr->value.ui64; 1283 return B_OK; 1284 } 1285 1286 1287 status_t 1288 dm_get_attr_string(const device_node* node, const char* name, 1289 const char** _value, bool recursive) 1290 { 1291 if (node == NULL || name == NULL || _value == NULL) 1292 return B_BAD_VALUE; 1293 1294 device_attr_private* attr = dm_find_attr(node, name, recursive, 1295 B_STRING_TYPE); 1296 if (attr == NULL) 1297 return B_NAME_NOT_FOUND; 1298 1299 *_value = attr->value.string; 1300 return B_OK; 1301 } 1302 1303 1304 status_t 1305 dm_get_attr_raw(const device_node* node, const char* name, const void** _data, 1306 size_t* _length, bool recursive) 1307 { 1308 if (node == NULL || name == NULL || (_data == NULL && _length == NULL)) 1309 return B_BAD_VALUE; 1310 1311 device_attr_private* attr = dm_find_attr(node, name, recursive, B_RAW_TYPE); 1312 if (attr == NULL) 1313 return B_NAME_NOT_FOUND; 1314 1315 if (_data != NULL) 1316 *_data = attr->value.raw.data; 1317 if (_length != NULL) 1318 *_length = attr->value.raw.length; 1319 return B_OK; 1320 } 1321 1322 1323 status_t 1324 dm_get_next_attr(device_node* node, device_attr** _attr) 1325 { 1326 if (node == NULL) 1327 return B_BAD_VALUE; 1328 1329 device_attr_private* next; 1330 device_attr_private* attr = *(device_attr_private**)_attr; 1331 1332 if (attr != NULL) { 1333 // next attribute 1334 next = attr->GetDoublyLinkedListLink()->next; 1335 } else { 1336 // first attribute 1337 next = node->Attributes().First(); 1338 } 1339 1340 *_attr = next; 1341 1342 return next ? B_OK : B_ENTRY_NOT_FOUND; 1343 } 1344 1345 1346 static struct device_manager_info sDeviceManagerModule = { 1347 { 1348 B_DEVICE_MANAGER_MODULE_NAME, 1349 0, 1350 NULL 1351 }, 1352 1353 // device nodes 1354 rescan_device, 1355 register_device, 1356 unregister_device, 1357 get_driver, 1358 get_device_root, 1359 get_next_child_device, 1360 get_parent, 1361 put_device_node, 1362 1363 // attributes 1364 dm_get_attr_uint8, 1365 dm_get_attr_uint16, 1366 dm_get_attr_uint32, 1367 dm_get_attr_uint64, 1368 dm_get_attr_string, 1369 dm_get_attr_raw, 1370 dm_get_next_attr, 1371 }; 1372 1373 1374 // #pragma mark - root node 1375 1376 1377 void 1378 dm_init_root_node(void) 1379 { 1380 device_attr attrs[] = { 1381 {B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "Devices Root"}}, 1382 {B_DEVICE_BUS, B_STRING_TYPE, {string: "root"}}, 1383 {B_DEVICE_FIND_CHILD_FLAGS, B_UINT32_TYPE, 1384 {ui32: B_FIND_MULTIPLE_CHILDREN}}, 1385 {NULL} 1386 }; 1387 1388 if (register_device(NULL, DEVICE_MANAGER_ROOT_NAME, attrs, NULL, NULL) 1389 != B_OK) { 1390 dprintf("Cannot register Devices Root Node\n"); 1391 } 1392 } 1393 1394 1395 static driver_module_info sDeviceRootModule = { 1396 { 1397 DEVICE_MANAGER_ROOT_NAME, 1398 0, 1399 NULL, 1400 }, 1401 NULL 1402 }; 1403 1404 1405 // #pragma mark - 1406 1407 1408 int 1409 main(int argc, char** argv) 1410 { 1411 _add_builtin_module((module_info*)&sDeviceManagerModule); 1412 _add_builtin_module((module_info*)&sDeviceRootModule); 1413 1414 // bus 1415 _add_builtin_module((module_info*)&gBusModuleInfo); 1416 _add_builtin_module((module_info*)&gBusDriverModuleInfo); 1417 1418 // sample driver 1419 _add_builtin_module((module_info*)&gDriverModuleInfo); 1420 _add_builtin_module((module_info*)&gDeviceModuleInfo); 1421 1422 // generic video driver 1423 _add_builtin_module((module_info*)&gGenericVideoDriverModuleInfo); 1424 _add_builtin_module((module_info*)&gGenericVideoDeviceModuleInfo); 1425 1426 gDeviceManager = &sDeviceManagerModule; 1427 1428 status_t status = _get_builtin_dependencies(); 1429 if (status < B_OK) { 1430 fprintf(stderr, "device_manager: Could not initialize modules: %s\n", 1431 strerror(status)); 1432 return 1; 1433 } 1434 1435 recursive_lock_init(&sLock, "device manager"); 1436 1437 dm_init_root_node(); 1438 sRootNode->Dump(); 1439 1440 probe_path("net"); 1441 probe_path("graphics"); 1442 // TODO: opened devices need to keep a "initialized" reference of the 1443 // device_node 1444 1445 sRootNode->Dump(); 1446 uninit_unused(); 1447 1448 // add specific video driver - ie. simulate installing it 1449 _add_builtin_module((module_info*)&gSpecificVideoDriverModuleInfo); 1450 _add_builtin_module((module_info*)&gSpecificVideoDeviceModuleInfo); 1451 probe_path("graphics"); 1452 1453 uninit_unused(); 1454 1455 recursive_lock_destroy(&sLock); 1456 return 0; 1457 } 1458