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 if (get_attr_uint16(this, B_DEVICE_TYPE, &type, false) != B_OK 1648 || get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false) 1649 != B_OK) 1650 generic = true; 1651 1652 // TODO: maybe make this extendible via settings file? 1653 switch (type) { 1654 case PCI_mass_storage: 1655 switch (subType) { 1656 case PCI_scsi: 1657 _AddPath(*stack, "busses", "scsi"); 1658 _AddPath(*stack, "busses", "virtio"); 1659 break; 1660 case PCI_ide: 1661 _AddPath(*stack, "busses", "ata"); 1662 _AddPath(*stack, "busses", "ide"); 1663 break; 1664 case PCI_sata: 1665 // TODO: check for ahci interface 1666 _AddPath(*stack, "busses", "scsi"); 1667 _AddPath(*stack, "busses", "ata"); 1668 _AddPath(*stack, "busses", "ide"); 1669 break; 1670 case PCI_nvm: 1671 _AddPath(*stack, "drivers", "disk"); 1672 break; 1673 default: 1674 _AddPath(*stack, "busses"); 1675 break; 1676 } 1677 break; 1678 case PCI_serial_bus: 1679 switch (subType) { 1680 case PCI_firewire: 1681 _AddPath(*stack, "busses", "firewire"); 1682 break; 1683 case PCI_usb: 1684 _AddPath(*stack, "busses", "usb"); 1685 break; 1686 default: 1687 _AddPath(*stack, "busses"); 1688 break; 1689 } 1690 break; 1691 case PCI_network: 1692 _AddPath(*stack, "drivers", "net"); 1693 _AddPath(*stack, "busses", "virtio"); 1694 break; 1695 case PCI_display: 1696 _AddPath(*stack, "drivers", "graphics"); 1697 _AddPath(*stack, "busses", "virtio"); 1698 break; 1699 case PCI_multimedia: 1700 switch (subType) { 1701 case PCI_audio: 1702 case PCI_hd_audio: 1703 _AddPath(*stack, "drivers", "audio"); 1704 _AddPath(*stack, "busses", "virtio"); 1705 break; 1706 case PCI_video: 1707 _AddPath(*stack, "drivers", "video"); 1708 break; 1709 default: 1710 _AddPath(*stack, "drivers"); 1711 break; 1712 } 1713 break; 1714 case PCI_base_peripheral: 1715 switch (subType) { 1716 case PCI_sd_host: 1717 _AddPath(*stack, "busses", "mmc"); 1718 break; 1719 case PCI_system_peripheral_other: 1720 _AddPath(*stack, "busses", "mmc"); 1721 _AddPath(*stack, "drivers"); 1722 break; 1723 default: 1724 _AddPath(*stack, "drivers"); 1725 break; 1726 } 1727 break; 1728 case PCI_encryption_decryption: 1729 switch (subType) { 1730 case PCI_encryption_decryption_other: 1731 _AddPath(*stack, "busses", "random"); 1732 break; 1733 default: 1734 _AddPath(*stack, "drivers"); 1735 break; 1736 } 1737 break; 1738 case PCI_data_acquisition: 1739 switch (subType) { 1740 case PCI_data_acquisition_other: 1741 _AddPath(*stack, "busses", "i2c"); 1742 break; 1743 default: 1744 _AddPath(*stack, "drivers"); 1745 break; 1746 } 1747 break; 1748 default: 1749 if (sRootNode == this) { 1750 _AddPath(*stack, "busses/pci"); 1751 _AddPath(*stack, "bus_managers"); 1752 } else if (!generic) { 1753 _AddPath(*stack, "drivers"); 1754 _AddPath(*stack, "busses/virtio"); 1755 } else { 1756 // For generic drivers, we only allow busses when the 1757 // request is more specified 1758 if (sGenericContextPath != NULL 1759 && (!strcmp(sGenericContextPath, "disk") 1760 || !strcmp(sGenericContextPath, "ports") 1761 || !strcmp(sGenericContextPath, "bus"))) { 1762 _AddPath(*stack, "busses"); 1763 } 1764 const char* bus; 1765 if (get_attr_string(this, B_DEVICE_BUS, &bus, false) == B_OK) { 1766 if (strcmp(bus, "virtio") == 0) 1767 _AddPath(*stack, "busses/scsi"); 1768 } 1769 _AddPath(*stack, "drivers", sGenericContextPath); 1770 _AddPath(*stack, "busses/i2c"); 1771 _AddPath(*stack, "busses/random"); 1772 _AddPath(*stack, "busses/virtio"); 1773 _AddPath(*stack, "bus_managers/pci"); 1774 _AddPath(*stack, "busses/pci"); 1775 _AddPath(*stack, "busses/mmc"); 1776 } 1777 break; 1778 } 1779 1780 stackDeleter.Detach(); 1781 1782 cookie = (void*)stack; 1783 } else 1784 stack = static_cast<Stack<KPath*>*>(cookie); 1785 1786 KPath* path; 1787 if (stack->Pop(&path)) { 1788 _path.Adopt(*path); 1789 delete path; 1790 return B_OK; 1791 } 1792 1793 delete stack; 1794 return B_ENTRY_NOT_FOUND; 1795 } 1796 1797 1798 status_t 1799 device_node::_GetNextDriver(void* list, driver_module_info*& driver) 1800 { 1801 while (true) { 1802 char name[B_FILE_NAME_LENGTH]; 1803 size_t nameLength = sizeof(name); 1804 1805 status_t status = read_next_module_name(list, name, &nameLength); 1806 if (status != B_OK) 1807 return status; 1808 1809 if (!strcmp(fModuleName, name)) 1810 continue; 1811 1812 if (get_module(name, (module_info**)&driver) != B_OK) 1813 continue; 1814 1815 if (driver->supports_device == NULL 1816 || driver->register_device == NULL) { 1817 put_module(name); 1818 continue; 1819 } 1820 1821 return B_OK; 1822 } 1823 } 1824 1825 1826 status_t 1827 device_node::_FindBestDriver(const char* path, driver_module_info*& bestDriver, 1828 float& bestSupport, device_node* previous) 1829 { 1830 if (bestDriver == NULL) 1831 bestSupport = previous != NULL ? previous->fSupportsParent : 0.0f; 1832 1833 void* list = open_module_list_etc(path, "driver_v1"); 1834 driver_module_info* driver; 1835 while (_GetNextDriver(list, driver) == B_OK) { 1836 if (previous != NULL && driver == previous->DriverModule()) { 1837 put_module(driver->info.name); 1838 continue; 1839 } 1840 1841 float support = driver->supports_device(this); 1842 if (support > bestSupport) { 1843 if (bestDriver != NULL) 1844 put_module(bestDriver->info.name); 1845 1846 bestDriver = driver; 1847 bestSupport = support; 1848 continue; 1849 // keep reference to best module around 1850 } 1851 1852 put_module(driver->info.name); 1853 } 1854 close_module_list(list); 1855 1856 return bestDriver != NULL ? B_OK : B_ENTRY_NOT_FOUND; 1857 } 1858 1859 1860 status_t 1861 device_node::_RegisterPath(const char* path) 1862 { 1863 void* list = open_module_list_etc(path, "driver_v1"); 1864 driver_module_info* driver; 1865 uint32 count = 0; 1866 1867 while (_GetNextDriver(list, driver) == B_OK) { 1868 float support = driver->supports_device(this); 1869 if (support > 0.0) { 1870 TRACE((" register module \"%s\", support %f\n", driver->info.name, 1871 support)); 1872 if (driver->register_device(this) == B_OK) 1873 count++; 1874 } 1875 1876 put_module(driver->info.name); 1877 } 1878 close_module_list(list); 1879 1880 return count > 0 ? B_OK : B_ENTRY_NOT_FOUND; 1881 } 1882 1883 1884 bool 1885 device_node::_AlwaysRegisterDynamic() 1886 { 1887 uint16 type = 0; 1888 uint16 subType = 0; 1889 get_attr_uint16(this, B_DEVICE_TYPE, &type, false); 1890 get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false); 1891 1892 switch (type) { 1893 case PCI_serial_bus: 1894 case PCI_bridge: 1895 case PCI_encryption_decryption: 1896 case 0: 1897 return true; 1898 } 1899 return false; 1900 // TODO: we may want to be a bit more specific in the future 1901 } 1902 1903 1904 status_t 1905 device_node::_RegisterDynamic(device_node* previous) 1906 { 1907 // If this is not a bus, we don't have to scan it 1908 if (find_attr(this, B_DEVICE_BUS, false, B_STRING_TYPE) == NULL) 1909 return B_OK; 1910 1911 // If we're not being probed, we honour the B_FIND_CHILD_ON_DEMAND 1912 // requirements 1913 if (!IsProbed() && (fFlags & B_FIND_CHILD_ON_DEMAND) != 0 1914 && !_AlwaysRegisterDynamic()) 1915 return B_OK; 1916 1917 KPath path; 1918 1919 if ((fFlags & B_FIND_MULTIPLE_CHILDREN) == 0) { 1920 // find the one driver 1921 driver_module_info* bestDriver = NULL; 1922 float bestSupport = 0.0; 1923 void* cookie = NULL; 1924 1925 while (_GetNextDriverPath(cookie, path) == B_OK) { 1926 _FindBestDriver(path.Path(), bestDriver, bestSupport, previous); 1927 } 1928 1929 if (bestDriver != NULL) { 1930 TRACE((" register best module \"%s\", support %f\n", 1931 bestDriver->info.name, bestSupport)); 1932 if (bestDriver->register_device(this) == B_OK) { 1933 // There can only be one node of this driver 1934 // (usually only one at all, but there might be a new driver 1935 // "waiting" for its turn) 1936 device_node* child = FindChild(bestDriver->info.name); 1937 if (child != NULL) { 1938 child->fSupportsParent = bestSupport; 1939 if (previous != NULL) { 1940 previous->fFlags |= NODE_FLAG_OBSOLETE_DRIVER; 1941 previous->Release(); 1942 child->fFlags |= NODE_FLAG_WAITING_FOR_DRIVER; 1943 } 1944 } 1945 // TODO: if this fails, we could try the second best driver, 1946 // and so on... 1947 } 1948 put_module(bestDriver->info.name); 1949 } 1950 } else { 1951 // register all drivers that match 1952 void* cookie = NULL; 1953 while (_GetNextDriverPath(cookie, path) == B_OK) { 1954 _RegisterPath(path.Path()); 1955 } 1956 } 1957 1958 return B_OK; 1959 } 1960 1961 1962 void 1963 device_node::_ReleaseWaiting() 1964 { 1965 NodeList::Iterator iterator = fChildren.GetIterator(); 1966 while (iterator.HasNext()) { 1967 device_node* child = iterator.Next(); 1968 1969 child->fFlags &= ~NODE_FLAG_WAITING_FOR_DRIVER; 1970 } 1971 } 1972 1973 1974 status_t 1975 device_node::_RemoveChildren() 1976 { 1977 NodeList::Iterator iterator = fChildren.GetIterator(); 1978 while (iterator.HasNext()) { 1979 device_node* child = iterator.Next(); 1980 child->Release(); 1981 } 1982 1983 return fChildren.IsEmpty() ? B_OK : B_BUSY; 1984 } 1985 1986 1987 device_node* 1988 device_node::_FindCurrentChild() 1989 { 1990 NodeList::Iterator iterator = fChildren.GetIterator(); 1991 while (iterator.HasNext()) { 1992 device_node* child = iterator.Next(); 1993 1994 if ((child->Flags() & NODE_FLAG_WAITING_FOR_DRIVER) == 0) 1995 return child; 1996 } 1997 1998 return NULL; 1999 } 2000 2001 2002 status_t 2003 device_node::_Probe() 2004 { 2005 device_node* previous = NULL; 2006 2007 if (IsProbed() && !fChildren.IsEmpty() 2008 && (fFlags & (B_FIND_CHILD_ON_DEMAND | B_FIND_MULTIPLE_CHILDREN)) 2009 == B_FIND_CHILD_ON_DEMAND) { 2010 // We already have a driver that claims this node; remove all 2011 // (unused) nodes, and evaluate it again 2012 _RemoveChildren(); 2013 2014 previous = _FindCurrentChild(); 2015 if (previous != NULL) { 2016 // This driver is still active - give it back the reference 2017 // that was stolen by _RemoveChildren() - _RegisterDynamic() 2018 // will release it, if it really isn't needed anymore 2019 previous->Acquire(); 2020 } 2021 } 2022 2023 return _RegisterDynamic(previous); 2024 } 2025 2026 2027 status_t 2028 device_node::Probe(const char* devicePath, uint32 updateCycle) 2029 { 2030 if ((fFlags & NODE_FLAG_DEVICE_REMOVED) != 0 2031 || updateCycle == fLastUpdateCycle) 2032 return B_OK; 2033 2034 status_t status = InitDriver(); 2035 if (status < B_OK) 2036 return status; 2037 2038 MethodDeleter<device_node, bool, &device_node::UninitDriver> uninit(this); 2039 2040 if ((fFlags & B_FIND_CHILD_ON_DEMAND) != 0) { 2041 bool matches = false; 2042 uint16 type = 0; 2043 uint16 subType = 0; 2044 if (get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false) == B_OK 2045 && get_attr_uint16(this, B_DEVICE_TYPE, &type, false) == B_OK) { 2046 // Check if this node matches the device path 2047 // TODO: maybe make this extendible via settings file? 2048 if (!strcmp(devicePath, "disk")) { 2049 matches = type == PCI_mass_storage 2050 || (type == PCI_base_peripheral 2051 && (subType == PCI_sd_host 2052 || subType == PCI_system_peripheral_other)); 2053 } else if (!strcmp(devicePath, "audio")) { 2054 matches = type == PCI_multimedia 2055 && (subType == PCI_audio || subType == PCI_hd_audio); 2056 } else if (!strcmp(devicePath, "net")) { 2057 matches = type == PCI_network; 2058 } else if (!strcmp(devicePath, "graphics")) { 2059 matches = type == PCI_display; 2060 } else if (!strcmp(devicePath, "video")) { 2061 matches = type == PCI_multimedia && subType == PCI_video; 2062 } else if (!strcmp(devicePath, "power")) { 2063 matches = type == PCI_data_acquisition; 2064 } else if (!strcmp(devicePath, "input")) { 2065 matches = type == PCI_data_acquisition 2066 && subType == PCI_data_acquisition_other; 2067 } 2068 } else { 2069 // This driver does not support types, but still wants to its 2070 // children explored on demand only. 2071 matches = true; 2072 sGenericContextPath = devicePath; 2073 } 2074 2075 if (matches) { 2076 fLastUpdateCycle = updateCycle; 2077 // This node will be probed in this update cycle 2078 2079 status = _Probe(); 2080 2081 sGenericContextPath = NULL; 2082 return status; 2083 } 2084 2085 return B_OK; 2086 } 2087 2088 NodeList::Iterator iterator = fChildren.GetIterator(); 2089 while (iterator.HasNext()) { 2090 device_node* child = iterator.Next(); 2091 2092 status = child->Probe(devicePath, updateCycle); 2093 if (status != B_OK) 2094 return status; 2095 } 2096 2097 return B_OK; 2098 } 2099 2100 2101 status_t 2102 device_node::Reprobe() 2103 { 2104 status_t status = InitDriver(); 2105 if (status < B_OK) 2106 return status; 2107 2108 MethodDeleter<device_node, bool, &device_node::UninitDriver> uninit(this); 2109 2110 // If this child has been probed already, probe it again 2111 status = _Probe(); 2112 if (status != B_OK) 2113 return status; 2114 2115 NodeList::Iterator iterator = fChildren.GetIterator(); 2116 while (iterator.HasNext()) { 2117 device_node* child = iterator.Next(); 2118 2119 status = child->Reprobe(); 2120 if (status != B_OK) 2121 return status; 2122 } 2123 2124 return B_OK; 2125 } 2126 2127 2128 status_t 2129 device_node::Rescan() 2130 { 2131 status_t status = InitDriver(); 2132 if (status < B_OK) 2133 return status; 2134 2135 MethodDeleter<device_node, bool, &device_node::UninitDriver> uninit(this); 2136 2137 if (DriverModule()->rescan_child_devices != NULL) { 2138 status = DriverModule()->rescan_child_devices(DriverData()); 2139 if (status != B_OK) 2140 return status; 2141 } 2142 2143 NodeList::Iterator iterator = fChildren.GetIterator(); 2144 while (iterator.HasNext()) { 2145 device_node* child = iterator.Next(); 2146 2147 status = child->Rescan(); 2148 if (status != B_OK) 2149 return status; 2150 } 2151 2152 return B_OK; 2153 } 2154 2155 2156 /*! Uninitializes all temporary references to the driver. The registration 2157 process keeps the driver initialized to optimize the startup procedure; 2158 this function gives this reference away again. 2159 */ 2160 void 2161 device_node::UninitUnusedDriver() 2162 { 2163 // First, we need to go to the leaf, and go back from there 2164 2165 NodeList::Iterator iterator = fChildren.GetIterator(); 2166 while (iterator.HasNext()) { 2167 device_node* child = iterator.Next(); 2168 2169 child->UninitUnusedDriver(); 2170 } 2171 2172 if (!IsInitialized() 2173 || (fFlags & NODE_FLAG_REGISTER_INITIALIZED) == 0) 2174 return; 2175 2176 fFlags &= ~NODE_FLAG_REGISTER_INITIALIZED; 2177 2178 UninitDriver(); 2179 } 2180 2181 2182 /*! Calls device_removed() on this node and all of its children - starting 2183 with the deepest and last child. 2184 It will also remove the one reference that every node gets on its creation. 2185 */ 2186 void 2187 device_node::DeviceRemoved() 2188 { 2189 // notify children 2190 NodeList::ConstIterator iterator = Children().GetIterator(); 2191 while (iterator.HasNext()) { 2192 device_node* child = iterator.Next(); 2193 2194 child->DeviceRemoved(); 2195 } 2196 2197 // notify devices 2198 DeviceList::ConstIterator deviceIterator = Devices().GetIterator(); 2199 while (deviceIterator.HasNext()) { 2200 Device* device = deviceIterator.Next(); 2201 2202 if (device->Module() != NULL 2203 && device->Module()->device_removed != NULL) 2204 device->Module()->device_removed(device->Data()); 2205 } 2206 2207 fFlags |= NODE_FLAG_DEVICE_REMOVED; 2208 2209 if (IsInitialized() && DriverModule()->device_removed != NULL) 2210 DriverModule()->device_removed(this); 2211 2212 if ((fFlags & B_KEEP_DRIVER_LOADED) != 0) { 2213 // There is no point in keeping this driver loaded when its device 2214 // is gone 2215 UninitDriver(); 2216 } 2217 2218 UninitUnusedDriver(); 2219 Release(); 2220 } 2221 2222 2223 void 2224 device_node::Acquire() 2225 { 2226 atomic_add(&fRefCount, 1); 2227 } 2228 2229 2230 bool 2231 device_node::Release() 2232 { 2233 if (atomic_add(&fRefCount, -1) > 1) 2234 return false; 2235 2236 delete this; 2237 return true; 2238 } 2239 2240 2241 void 2242 device_node::AddDevice(Device* device) 2243 { 2244 fDevices.Add(device); 2245 } 2246 2247 2248 void 2249 device_node::RemoveDevice(Device* device) 2250 { 2251 char attrName[256]; 2252 device_attr_private* attr; 2253 2254 sprintf(attrName, "dev/%" B_PRIdINO "/path", device->ID()); 2255 attr = find_attr(this, attrName, false, B_STRING_TYPE); 2256 if (attr != NULL) { 2257 fAttributes.Remove(attr); 2258 delete attr; 2259 } 2260 2261 sprintf(attrName, "dev/%" B_PRIdINO "/driver", device->ID()); 2262 attr = find_attr(this, attrName, false, B_STRING_TYPE); 2263 if (attr != NULL) { 2264 fAttributes.Remove(attr); 2265 delete attr; 2266 } 2267 2268 fDevices.Remove(device); 2269 } 2270 2271 2272 int 2273 device_node::CompareTo(const device_attr* attributes) const 2274 { 2275 if (attributes == NULL) 2276 return -1; 2277 2278 for (; attributes->name != NULL; attributes++) { 2279 // find corresponding attribute 2280 AttributeList::ConstIterator iterator = Attributes().GetIterator(); 2281 device_attr_private* attr = NULL; 2282 bool found = false; 2283 2284 while (iterator.HasNext()) { 2285 attr = iterator.Next(); 2286 2287 if (!strcmp(attr->name, attributes->name)) { 2288 found = true; 2289 break; 2290 } 2291 } 2292 if (!found) 2293 return -1; 2294 2295 int compare = device_attr_private::Compare(attr, attributes); 2296 if (compare != 0) 2297 return compare; 2298 } 2299 2300 return 0; 2301 } 2302 2303 2304 device_node* 2305 device_node::FindChild(const device_attr* attributes) const 2306 { 2307 if (attributes == NULL) 2308 return NULL; 2309 2310 NodeList::ConstIterator iterator = Children().GetIterator(); 2311 while (iterator.HasNext()) { 2312 device_node* child = iterator.Next(); 2313 2314 // ignore nodes that are pending to be removed 2315 if ((child->Flags() & NODE_FLAG_DEVICE_REMOVED) == 0 2316 && !child->CompareTo(attributes)) 2317 return child; 2318 } 2319 2320 return NULL; 2321 } 2322 2323 2324 device_node* 2325 device_node::FindChild(const char* moduleName) const 2326 { 2327 if (moduleName == NULL) 2328 return NULL; 2329 2330 NodeList::ConstIterator iterator = Children().GetIterator(); 2331 while (iterator.HasNext()) { 2332 device_node* child = iterator.Next(); 2333 2334 if (!strcmp(child->ModuleName(), moduleName)) 2335 return child; 2336 } 2337 2338 return NULL; 2339 } 2340 2341 2342 /*! This returns the priority or importance of this node. Nodes with higher 2343 priority are registered/probed first. 2344 Currently, only the B_FIND_MULTIPLE_CHILDREN flag alters the priority; 2345 it might make sense to be able to directly set the priority via an 2346 attribute. 2347 */ 2348 int32 2349 device_node::Priority() 2350 { 2351 return (fFlags & B_FIND_MULTIPLE_CHILDREN) != 0 ? 0 : 100; 2352 } 2353 2354 2355 void 2356 device_node::Dump(int32 level) 2357 { 2358 put_level(level); 2359 kprintf("(%" B_PRId32 ") @%p \"%s\" (ref %" B_PRId32 ", init %" B_PRId32 2360 ", module %p, data %p)\n", level, this, ModuleName(), fRefCount, 2361 fInitialized, DriverModule(), DriverData()); 2362 2363 AttributeList::Iterator attribute = Attributes().GetIterator(); 2364 while (attribute.HasNext()) { 2365 dump_attribute(attribute.Next(), level); 2366 } 2367 2368 DeviceList::Iterator deviceIterator = fDevices.GetIterator(); 2369 while (deviceIterator.HasNext()) { 2370 Device* device = deviceIterator.Next(); 2371 put_level(level); 2372 kprintf("device: %s, %p\n", device->ModuleName(), device->Data()); 2373 } 2374 2375 NodeList::ConstIterator iterator = Children().GetIterator(); 2376 while (iterator.HasNext()) { 2377 iterator.Next()->Dump(level + 1); 2378 } 2379 } 2380 2381 2382 // #pragma mark - root node 2383 2384 2385 static void 2386 init_node_tree(void) 2387 { 2388 device_attr attrs[] = { 2389 {B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {.string = "Devices Root"}}, 2390 {B_DEVICE_BUS, B_STRING_TYPE, {.string = "root"}}, 2391 {B_DEVICE_FLAGS, B_UINT32_TYPE, 2392 {.ui32 = B_FIND_MULTIPLE_CHILDREN | B_KEEP_DRIVER_LOADED }}, 2393 {NULL} 2394 }; 2395 2396 device_node* node = NULL; 2397 if (register_node(NULL, DEVICE_MANAGER_ROOT_NAME, attrs, NULL, &node) 2398 != B_OK) { 2399 dprintf("Cannot register Devices Root Node\n"); 2400 } 2401 2402 device_attr genericAttrs[] = { 2403 {B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {.string = "Generic"}}, 2404 {B_DEVICE_BUS, B_STRING_TYPE, {.string = "generic"}}, 2405 {B_DEVICE_FLAGS, B_UINT32_TYPE, {.ui32 = B_FIND_MULTIPLE_CHILDREN 2406 | B_KEEP_DRIVER_LOADED | B_FIND_CHILD_ON_DEMAND}}, 2407 {NULL} 2408 }; 2409 2410 if (register_node(node, DEVICE_MANAGER_GENERIC_NAME, genericAttrs, NULL, 2411 NULL) != B_OK) { 2412 dprintf("Cannot register Generic Devices Node\n"); 2413 } 2414 } 2415 2416 2417 driver_module_info gDeviceRootModule = { 2418 { 2419 DEVICE_MANAGER_ROOT_NAME, 2420 0, 2421 NULL, 2422 }, 2423 }; 2424 2425 2426 driver_module_info gDeviceGenericModule = { 2427 { 2428 DEVICE_MANAGER_GENERIC_NAME, 2429 0, 2430 NULL, 2431 }, 2432 NULL 2433 }; 2434 2435 2436 // #pragma mark - private kernel API 2437 2438 2439 status_t 2440 device_manager_probe(const char* path, uint32 updateCycle) 2441 { 2442 TRACE(("device_manager_probe(\"%s\")\n", path)); 2443 RecursiveLocker _(sLock); 2444 2445 // first, publish directories in the driver directory 2446 publish_directories(path); 2447 2448 return sRootNode->Probe(path, updateCycle); 2449 } 2450 2451 2452 status_t 2453 device_manager_init(struct kernel_args* args) 2454 { 2455 TRACE(("device manager init\n")); 2456 2457 IOSchedulerRoster::Init(); 2458 2459 dm_init_id_generator(); 2460 dm_init_io_resources(); 2461 2462 recursive_lock_init(&sLock, "device manager"); 2463 2464 register_generic_syscall(DEVICE_MANAGER_SYSCALLS, control_device_manager, 2465 1, 0); 2466 2467 add_debugger_command("dm_tree", &dump_device_nodes, 2468 "dump device node tree"); 2469 add_debugger_command_etc("io_scheduler", &dump_io_scheduler, 2470 "Dump an I/O scheduler", 2471 "<scheduler>\n" 2472 "Dumps I/O scheduler at address <scheduler>.\n", 0); 2473 add_debugger_command_etc("io_request_owner", &dump_io_request_owner, 2474 "Dump an I/O request owner", 2475 "<owner>\n" 2476 "Dumps I/O request owner at address <owner>.\n", 0); 2477 add_debugger_command("io_request", &dump_io_request, "dump an I/O request"); 2478 add_debugger_command("io_operation", &dump_io_operation, 2479 "dump an I/O operation"); 2480 add_debugger_command("io_buffer", &dump_io_buffer, "dump an I/O buffer"); 2481 add_debugger_command("dma_buffer", &dump_dma_buffer, "dump a DMA buffer"); 2482 2483 init_node_tree(); 2484 2485 return B_OK; 2486 } 2487 2488 2489 status_t 2490 device_manager_init_post_modules(struct kernel_args* args) 2491 { 2492 RecursiveLocker _(sLock); 2493 return sRootNode->Reprobe(); 2494 } 2495 2496 2497 recursive_lock* 2498 device_manager_get_lock() 2499 { 2500 return &sLock; 2501 } 2502