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