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