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