1 /* 2 * Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "device_manager.h" 8 9 #include <util/AutoLock.h> 10 #include <util/DoublyLinkedList.h> 11 12 #include <KernelExport.h> 13 #include <module.h> 14 #include <Locker.h> 15 16 #include <new> 17 #include <set> 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <string.h> 21 22 23 #define TRACE(a) dprintf a 24 25 #define DEVICE_MANAGER_ROOT_NAME "system/devices_root/driver_v1" 26 27 extern struct device_module_info gDeviceModuleInfo; 28 extern struct driver_module_info gDriverModuleInfo; 29 extern struct driver_module_info gBusModuleInfo; 30 extern struct driver_module_info gBusDriverModuleInfo; 31 32 extern "C" status_t _add_builtin_module(module_info *info); 33 extern "C" status_t _get_builtin_dependencies(void); 34 extern bool gDebugOutputEnabled; 35 // from libkernelland_emu.so 36 37 status_t dm_get_attr_uint8(const device_node* node, const char* name, uint8* _value, 38 bool recursive); 39 status_t dm_get_attr_uint32(device_node* node, const char* name, uint32* _value, 40 bool recursive); 41 status_t dm_get_attr_string(device_node* node, const char* name, 42 const char** _value, bool recursive); 43 44 45 struct device_attr_private : device_attr, 46 DoublyLinkedListLinkImpl<device_attr_private> { 47 device_attr_private(); 48 device_attr_private(const device_attr& attr); 49 ~device_attr_private(); 50 51 status_t InitCheck(); 52 status_t CopyFrom(const device_attr& attr); 53 54 static int Compare(const device_attr* attrA, 55 const device_attr *attrB); 56 57 private: 58 void _Unset(); 59 }; 60 61 typedef DoublyLinkedList<device_attr_private> AttributeList; 62 63 64 // I/O resource 65 typedef struct io_resource_info { 66 struct io_resource_info *prev, *next; 67 device_node* owner; // associated node; NULL for temporary allocation 68 io_resource resource; // info about actual resource 69 } io_resource_info; 70 71 72 // a structure to put nodes into lists 73 struct node_entry { 74 struct list_link link; 75 device_node* node; 76 }; 77 78 typedef DoublyLinkedList<device_node> NodeList; 79 80 struct device_node : DoublyLinkedListLinkImpl<device_node> { 81 device_node(const char *moduleName, 82 const device_attr *attrs, 83 const io_resource *resources); 84 ~device_node(); 85 86 status_t InitCheck(); 87 88 const char* ModuleName() const { return fModuleName; } 89 device_node* Parent() const { return fParent; } 90 AttributeList& Attributes() { return fAttributes; } 91 const AttributeList& Attributes() const { return fAttributes; } 92 93 status_t InitDriver(); 94 void UninitDriver(); 95 96 // The following two are only valid, if the node's driver is 97 // initialized 98 driver_module_info* DriverModule() const { return fDriver; } 99 void* DriverData() const { return fDriverData; } 100 101 void AddChild(device_node *node); 102 void RemoveChild(device_node *node); 103 const NodeList& Children() const { return fChildren; } 104 105 status_t Register(); 106 bool IsRegistered() const { return fRegistered; } 107 108 private: 109 status_t _RegisterFixed(uint32& registered); 110 status_t _RegisterDynamic(); 111 bool _IsBus() const; 112 113 device_node* fParent; 114 NodeList fChildren; 115 int32 fRefCount; 116 int32 fInitialized; 117 bool fRegistered; 118 119 const char* fModuleName; 120 driver_module_info* fDriver; 121 void* fDriverData; 122 123 AttributeList fAttributes; 124 }; 125 126 127 device_manager_info *gDeviceManager; 128 129 static device_node *sRootNode; 130 131 132 device_attr_private::device_attr_private() 133 { 134 name = NULL; 135 type = 0; 136 value.raw.data = NULL; 137 value.raw.length = 0; 138 } 139 140 141 device_attr_private::device_attr_private(const device_attr& attr) 142 { 143 CopyFrom(attr); 144 } 145 146 147 device_attr_private::~device_attr_private() 148 { 149 _Unset(); 150 } 151 152 153 status_t 154 device_attr_private::InitCheck() 155 { 156 return name != NULL ? B_OK : B_NO_INIT; 157 } 158 159 160 status_t 161 device_attr_private::CopyFrom(const device_attr& attr) 162 { 163 name = strdup(attr.name); 164 if (name == NULL) 165 return B_NO_MEMORY; 166 167 type = attr.type; 168 169 switch (type) { 170 case B_UINT8_TYPE: 171 case B_UINT16_TYPE: 172 case B_UINT32_TYPE: 173 case B_UINT64_TYPE: 174 value.ui64 = attr.value.ui64; 175 break; 176 177 case B_STRING_TYPE: 178 if (attr.value.string != NULL) { 179 value.string = strdup(attr.value.string); 180 if (value.string == NULL) { 181 _Unset(); 182 return B_NO_MEMORY; 183 } 184 } else 185 value.string = NULL; 186 break; 187 188 case B_RAW_TYPE: 189 value.raw.data = malloc(attr.value.raw.length); 190 if (value.raw.data == NULL) { 191 _Unset(); 192 return B_NO_MEMORY; 193 } 194 195 value.raw.length = attr.value.raw.length; 196 memcpy((void*)value.raw.data, attr.value.raw.data, 197 attr.value.raw.length); 198 break; 199 200 default: 201 return B_BAD_VALUE; 202 } 203 204 return B_OK; 205 } 206 207 208 void 209 device_attr_private::_Unset() 210 { 211 if (type == B_STRING_TYPE) 212 free((char*)value.string); 213 else if (type == B_RAW_TYPE) 214 free((void*)value.raw.data); 215 216 free((char*)name); 217 218 name = NULL; 219 value.raw.data = NULL; 220 value.raw.length = 0; 221 } 222 223 224 /*static*/ int 225 device_attr_private::Compare(const device_attr* attrA, const device_attr *attrB) 226 { 227 if (attrA->type != attrB->type) 228 return -1; 229 230 switch (attrA->type) { 231 case B_UINT8_TYPE: 232 return (int)attrA->value.ui8 - (int)attrB->value.ui8; 233 234 case B_UINT16_TYPE: 235 return (int)attrA->value.ui16 - (int)attrB->value.ui16; 236 237 case B_UINT32_TYPE: 238 if (attrA->value.ui32 > attrB->value.ui32) 239 return 1; 240 if (attrA->value.ui32 < attrB->value.ui32) 241 return -1; 242 return 0; 243 244 case B_UINT64_TYPE: 245 if (attrA->value.ui64 > attrB->value.ui64) 246 return 1; 247 if (attrA->value.ui64 < attrB->value.ui64) 248 return -1; 249 return 0; 250 251 case B_STRING_TYPE: 252 return strcmp(attrA->value.string, attrB->value.string); 253 254 case B_RAW_TYPE: 255 if (attrA->value.raw.length != attrB->value.raw.length) 256 return -1; 257 258 return memcmp(attrA->value.raw.data, attrB->value.raw.data, 259 attrA->value.raw.length); 260 } 261 262 return -1; 263 } 264 265 266 // #pragma mark - 267 268 269 device_attr_private* 270 dm_find_attr(const device_node* node, const char* name, bool recursive, 271 type_code type) 272 { 273 do { 274 AttributeList::ConstIterator iterator 275 = node->Attributes().GetIterator(); 276 277 while (iterator.HasNext()) { 278 device_attr_private* attr = iterator.Next(); 279 280 if (type != B_ANY_TYPE && attr->type != type) 281 continue; 282 283 if (!strcmp(attr->name, name)) 284 return attr; 285 } 286 287 node = node->Parent(); 288 } while (node != NULL && recursive); 289 290 return NULL; 291 } 292 293 294 static void 295 put_level(int32 level) 296 { 297 while (level-- > 0) 298 dprintf(" "); 299 } 300 301 302 static void 303 dump_attribute(device_attr* attr, int32 level) 304 { 305 if (attr == NULL) 306 return; 307 308 put_level(level + 2); 309 dprintf("\"%s\" : ", attr->name); 310 switch (attr->type) { 311 case B_STRING_TYPE: 312 dprintf("string : \"%s\"", attr->value.string); 313 break; 314 case B_INT8_TYPE: 315 case B_UINT8_TYPE: 316 dprintf("uint8 : %u (%#x)", attr->value.ui8, attr->value.ui8); 317 break; 318 case B_INT16_TYPE: 319 case B_UINT16_TYPE: 320 dprintf("uint16 : %u (%#x)", attr->value.ui16, attr->value.ui16); 321 break; 322 case B_INT32_TYPE: 323 case B_UINT32_TYPE: 324 dprintf("uint32 : %lu (%#lx)", attr->value.ui32, attr->value.ui32); 325 break; 326 case B_INT64_TYPE: 327 case B_UINT64_TYPE: 328 dprintf("uint64 : %Lu (%#Lx)", attr->value.ui64, attr->value.ui64); 329 break; 330 default: 331 dprintf("raw data"); 332 } 333 dprintf("\n"); 334 } 335 336 337 void 338 dm_dump_node(device_node* node, int32 level) 339 { 340 if (node == NULL) 341 return; 342 343 put_level(level); 344 dprintf("(%ld) @%p \"%s\"\n", level, node, node->ModuleName()); 345 346 AttributeList::Iterator attribute = node->Attributes().GetIterator(); 347 while (attribute.HasNext()) { 348 dump_attribute(attribute.Next(), level); 349 } 350 351 NodeList::ConstIterator iterator = node->Children().GetIterator(); 352 while (iterator.HasNext()) { 353 dm_dump_node(iterator.Next(), level + 1); 354 } 355 } 356 357 358 // #pragma mark - 359 360 361 /*! Allocate device node info structure; 362 initially, ref_count is one to make sure node won't get destroyed by mistake 363 */ 364 device_node::device_node(const char* moduleName, const device_attr* attrs, 365 const io_resource* resources) 366 { 367 fModuleName = strdup(moduleName); 368 if (fModuleName == NULL) 369 return; 370 371 fParent = NULL; 372 fRefCount = 1; 373 fInitialized = 0; 374 fRegistered = false; 375 fDriver = NULL; 376 fDriverData = NULL; 377 378 // copy attributes 379 380 while (attrs != NULL && attrs->name != NULL) { 381 device_attr_private* attr 382 = new(std::nothrow) device_attr_private(*attrs); 383 if (attr == NULL) 384 break; 385 386 fAttributes.Add(attr); 387 attrs++; 388 } 389 } 390 391 392 device_node::~device_node() 393 { 394 AttributeList::Iterator iterator = fAttributes.GetIterator(); 395 while (iterator.HasNext()) { 396 device_attr_private* attr = iterator.Next(); 397 iterator.Remove(); 398 delete attr; 399 } 400 free((char*)fModuleName); 401 } 402 403 404 status_t 405 device_node::InitCheck() 406 { 407 return fModuleName != NULL ? B_OK : B_NO_MEMORY; 408 } 409 410 411 status_t 412 device_node::InitDriver() 413 { 414 if (fInitialized++ > 0) 415 return B_OK; 416 417 status_t status = get_module(ModuleName(), (module_info**)&fDriver); 418 if (status < B_OK) { 419 fInitialized--; 420 return status; 421 } 422 423 if (fDriver->init_driver != NULL) 424 status = fDriver->init_driver(this, &fDriverData); 425 if (status < B_OK) { 426 fInitialized--; 427 put_module(ModuleName()); 428 return status; 429 } 430 431 return B_OK; 432 } 433 434 435 void 436 device_node::UninitDriver() 437 { 438 if (fInitialized-- > 1) 439 return; 440 441 if (fDriver->uninit_driver != NULL) 442 fDriver->uninit_driver(this); 443 fDriverData = NULL; 444 445 put_module(ModuleName()); 446 } 447 448 449 void 450 device_node::AddChild(device_node* node) 451 { 452 // we must not be destroyed as long as we have children 453 fRefCount++; 454 node->fParent = this; 455 fChildren.Add(node); 456 } 457 458 459 void 460 device_node::RemoveChild(device_node* node) 461 { 462 fRefCount--; 463 // TODO: we may need to destruct ourselves here! 464 node->fParent = NULL; 465 fChildren.Remove(node); 466 } 467 468 469 status_t 470 device_node::Register() 471 { 472 uint32 registered; 473 status_t status = _RegisterFixed(registered); 474 if (status != B_OK) 475 return status; 476 if (registered > 0) { 477 fRegistered = true; 478 return B_OK; 479 } 480 481 // Register the children the driver wants 482 483 if (DriverModule()->register_child_devices != NULL) { 484 status = DriverModule()->register_child_devices(this); 485 if (status != B_OK) 486 return status; 487 488 if (!fChildren.IsEmpty()) 489 return B_OK; 490 } 491 492 // Register all possible child device nodes 493 494 uint32 findFlags = 0; 495 dm_get_attr_uint32(this, B_DRIVER_FIND_CHILD_FLAGS, &findFlags, false); 496 497 if ((findFlags & B_FIND_CHILD_ON_DEMAND) != 0) 498 return B_OK; 499 500 return _RegisterDynamic(); 501 } 502 503 504 bool 505 device_node::_IsBus() const 506 { 507 uint8 isBus; 508 if (dm_get_attr_uint8(this, B_DRIVER_IS_BUS, &isBus, false) != B_OK) 509 return false; 510 511 return isBus; 512 } 513 514 515 /*! Registers any children that are identified via the B_DRIVER_FIXED_CHILD 516 attribute. 517 If any of these children cannot be registered, this call will fail (we 518 don't remove already registered children in this case). 519 */ 520 status_t 521 device_node::_RegisterFixed(uint32& registered) 522 { 523 AttributeList::Iterator iterator = fAttributes.GetIterator(); 524 registered = 0; 525 526 while (iterator.HasNext()) { 527 device_attr_private* attr = iterator.Next(); 528 if (strcmp(attr->name, B_DRIVER_FIXED_CHILD)) 529 continue; 530 531 driver_module_info* driver; 532 status_t status = get_module(attr->value.string, 533 (module_info**)&driver); 534 if (status != B_OK) 535 return status; 536 537 if (driver->register_device != NULL) { 538 status = driver->register_device(this); 539 if (status == B_OK) 540 registered++; 541 } 542 543 put_module(attr->value.string); 544 545 if (status != B_OK) 546 return status; 547 } 548 549 return B_OK; 550 } 551 552 553 status_t 554 device_node::_RegisterDynamic() 555 { 556 uint32 findFlags; 557 if (dm_get_attr_uint32(this, B_DRIVER_FIND_CHILD_FLAGS, &findFlags, false) 558 != B_OK) 559 findFlags = 0; 560 561 driver_module_info* bestDriver = NULL; 562 float best = 0.0; 563 564 char path[64]; 565 if (!_IsBus()) { 566 strlcpy(path, "drivers", sizeof(path)); 567 568 const char *type; 569 if (dm_get_attr_string(this, B_DRIVER_DEVICE_TYPE, &type, false) 570 == B_OK) { 571 strlcat(path, "/", sizeof(path)); 572 strlcat(path, type, sizeof(path)); 573 } 574 } else { 575 // TODO: we might want to allow bus* specifiers as well, ie. 576 // busses/usb 577 strlcpy(path, "bus", sizeof(path)); 578 } 579 580 void* list = open_module_list_etc(path, "driver_v1"); 581 while (true) { 582 char name[B_FILE_NAME_LENGTH]; 583 size_t nameLength = sizeof(name); 584 585 if (read_next_module_name(list, name, &nameLength) != B_OK) 586 break; 587 588 if (!strcmp(fModuleName, name)) 589 continue; 590 591 driver_module_info* driver; 592 if (get_module(name, (module_info**)&driver) != B_OK) 593 continue; 594 595 if (driver->supports_device != NULL 596 && driver->register_device != NULL) { 597 float support = driver->supports_device(this); 598 599 if ((findFlags & B_FIND_MULTIPLE_CHILDREN) == 0) { 600 if (support > best) { 601 if (bestDriver != NULL) 602 put_module(bestDriver->info.name); 603 604 bestDriver = driver; 605 best = support; 606 continue; 607 // keep reference to best module around 608 } 609 } else if (support > 0.0) { 610 printf(" register module \"%s\", support %f\n", name, support); 611 driver->register_device(this); 612 } 613 } 614 615 put_module(name); 616 } 617 close_module_list(list); 618 619 if (bestDriver != NULL) { 620 printf(" register best module \"%s\", support %f\n", bestDriver->info.name, best); 621 bestDriver->register_device(this); 622 put_module(bestDriver->info.name); 623 } 624 625 return B_OK; 626 } 627 628 629 // #pragma mark - 630 631 632 // #pragma mark - Device Manager module API 633 634 635 static status_t 636 rescan_device(device_node* node) 637 { 638 return B_ERROR; 639 } 640 641 642 static status_t 643 register_device(device_node* parent, const char* moduleName, 644 const device_attr* attrs, const io_resource* ioResources, 645 device_node** _node) 646 { 647 if ((parent == NULL && sRootNode != NULL) || moduleName == NULL) 648 return B_BAD_VALUE; 649 650 // TODO: handle I/O resources! 651 652 device_node *newNode = new(std::nothrow) device_node(moduleName, attrs, 653 ioResources); 654 if (newNode == NULL) 655 return B_NO_MEMORY; 656 657 TRACE(("%p: register device \"%s\", parent %p\n", newNode, moduleName, 658 parent)); 659 660 status_t status = newNode->InitCheck(); 661 if (status != B_OK) 662 goto err1; 663 664 status = newNode->InitDriver(); 665 if (status != B_OK) 666 goto err1; 667 668 // make it public 669 if (parent != NULL) 670 parent->AddChild(newNode); 671 else 672 sRootNode = newNode; 673 674 #if 0 675 // The following is done to reduce the stack usage of deeply nested 676 // child device nodes. 677 // There is no other need to delay the complete registration process 678 // the way done here. This approach is also slightly different as 679 // the registration might fail later than it used in case of errors. 680 681 if (!parent->IsRegistered()) { 682 // The parent has not been registered completely yet - child 683 // registration is deferred to the parent registration 684 return B_OK; 685 } 686 #endif 687 688 status = newNode->Register(); 689 if (status < B_OK) { 690 parent->RemoveChild(newNode); 691 goto err1; 692 } 693 694 if (_node) 695 *_node = newNode; 696 697 return B_OK; 698 699 err1: 700 delete newNode; 701 return status; 702 } 703 704 705 static status_t 706 unregister_device(device_node* node) 707 { 708 return B_ERROR; 709 } 710 711 712 static driver_module_info* 713 driver_module(device_node* node) 714 { 715 return node->DriverModule(); 716 } 717 718 719 static void* 720 driver_data(device_node* node) 721 { 722 return node->DriverData(); 723 } 724 725 726 static device_node* 727 device_root(void) 728 { 729 return sRootNode; 730 } 731 732 733 static status_t 734 get_next_child_device(device_node* parent, device_node* _node, 735 const device_attr* attrs) 736 { 737 return B_ERROR; 738 } 739 740 741 static device_node* 742 get_parent(device_node* node) 743 { 744 return NULL; 745 } 746 747 748 static void 749 put_device_node(device_node* node) 750 { 751 } 752 753 754 status_t 755 dm_get_attr_uint8(const device_node* node, const char* name, uint8* _value, 756 bool recursive) 757 { 758 if (node == NULL || name == NULL || _value == NULL) 759 return B_BAD_VALUE; 760 761 device_attr_private* attr = dm_find_attr(node, name, recursive, 762 B_UINT8_TYPE); 763 if (attr == NULL) 764 return B_NAME_NOT_FOUND; 765 766 *_value = attr->value.ui8; 767 return B_OK; 768 } 769 770 771 status_t 772 dm_get_attr_uint16(device_node* node, const char* name, uint16* _value, 773 bool recursive) 774 { 775 if (node == NULL || name == NULL || _value == NULL) 776 return B_BAD_VALUE; 777 778 device_attr_private* attr = dm_find_attr(node, name, recursive, 779 B_UINT16_TYPE); 780 if (attr == NULL) 781 return B_NAME_NOT_FOUND; 782 783 *_value = attr->value.ui16; 784 return B_OK; 785 } 786 787 788 status_t 789 dm_get_attr_uint32(device_node* node, const char* name, uint32* _value, 790 bool recursive) 791 { 792 if (node == NULL || name == NULL || _value == NULL) 793 return B_BAD_VALUE; 794 795 device_attr_private* attr = dm_find_attr(node, name, recursive, 796 B_UINT32_TYPE); 797 if (attr == NULL) 798 return B_NAME_NOT_FOUND; 799 800 *_value = attr->value.ui32; 801 return B_OK; 802 } 803 804 805 status_t 806 dm_get_attr_uint64(device_node* node, const char* name, 807 uint64* _value, bool recursive) 808 { 809 if (node == NULL || name == NULL || _value == NULL) 810 return B_BAD_VALUE; 811 812 device_attr_private* attr = dm_find_attr(node, name, recursive, 813 B_UINT64_TYPE); 814 if (attr == NULL) 815 return B_NAME_NOT_FOUND; 816 817 *_value = attr->value.ui64; 818 return B_OK; 819 } 820 821 822 status_t 823 dm_get_attr_string(device_node* node, const char* name, const char** _value, 824 bool recursive) 825 { 826 if (node == NULL || name == NULL || _value == NULL) 827 return B_BAD_VALUE; 828 829 device_attr_private* attr = dm_find_attr(node, name, recursive, 830 B_STRING_TYPE); 831 if (attr == NULL) 832 return B_NAME_NOT_FOUND; 833 834 *_value = attr->value.string; 835 return B_OK; 836 } 837 838 839 status_t 840 dm_get_attr_raw(device_node* node, const char* name, const void** _data, 841 size_t* _length, bool recursive) 842 { 843 if (node == NULL || name == NULL || (_data == NULL && _length == NULL)) 844 return B_BAD_VALUE; 845 846 device_attr_private* attr = dm_find_attr(node, name, recursive, B_RAW_TYPE); 847 if (attr == NULL) 848 return B_NAME_NOT_FOUND; 849 850 if (_data != NULL) 851 *_data = attr->value.raw.data; 852 if (_length != NULL) 853 *_length = attr->value.raw.length; 854 return B_OK; 855 } 856 857 858 status_t 859 dm_get_next_attr(device_node* node, device_attr** _attr) 860 { 861 if (node == NULL) 862 return B_BAD_VALUE; 863 864 device_attr_private* next; 865 device_attr_private* attr = *(device_attr_private**)_attr; 866 867 if (attr != NULL) { 868 // next attribute 869 next = attr->GetDoublyLinkedListLink()->next; 870 } else { 871 // first attribute 872 next = node->Attributes().First(); 873 } 874 875 *_attr = next; 876 877 return next ? B_OK : B_ENTRY_NOT_FOUND; 878 } 879 880 881 static struct device_manager_info sDeviceManagerModule = { 882 { 883 B_DEVICE_MANAGER_MODULE_NAME, 884 0, 885 NULL 886 }, 887 888 // device nodes 889 rescan_device, 890 register_device, 891 unregister_device, 892 driver_module, 893 driver_data, 894 device_root, 895 get_next_child_device, 896 get_parent, 897 put_device_node, 898 899 // attributes 900 dm_get_attr_uint8, 901 dm_get_attr_uint16, 902 dm_get_attr_uint32, 903 dm_get_attr_uint64, 904 dm_get_attr_string, 905 dm_get_attr_raw, 906 dm_get_next_attr, 907 }; 908 909 910 // #pragma mark - root node 911 912 913 void 914 dm_init_root_node(void) 915 { 916 device_attr attrs[] = { 917 {B_DRIVER_PRETTY_NAME, B_STRING_TYPE, {string: "Devices Root"}}, 918 {B_DRIVER_IS_BUS, B_UINT8_TYPE, {ui8: true}}, 919 {B_DRIVER_BUS, B_STRING_TYPE, {string: "root"}}, 920 {B_DRIVER_FIND_CHILD_FLAGS, B_UINT32_TYPE, 921 {ui32: B_FIND_MULTIPLE_CHILDREN}}, 922 {NULL} 923 }; 924 925 if (register_device(NULL, DEVICE_MANAGER_ROOT_NAME, attrs, NULL, NULL) 926 != B_OK) { 927 dprintf("Cannot register Devices Root Node\n"); 928 } 929 } 930 931 932 static driver_module_info sDeviceRootModule = { 933 { 934 DEVICE_MANAGER_ROOT_NAME, 935 0, 936 NULL, 937 }, 938 NULL 939 }; 940 941 942 // #pragma mark - 943 944 945 int 946 main(int argc, char** argv) 947 { 948 _add_builtin_module((module_info*)&sDeviceManagerModule); 949 _add_builtin_module((module_info*)&sDeviceRootModule); 950 _add_builtin_module((module_info*)&gDeviceModuleInfo); 951 _add_builtin_module((module_info*)&gDriverModuleInfo); 952 _add_builtin_module((module_info*)&gBusModuleInfo); 953 _add_builtin_module((module_info*)&gBusDriverModuleInfo); 954 955 gDeviceManager = &sDeviceManagerModule; 956 957 status_t status = _get_builtin_dependencies(); 958 if (status < B_OK) { 959 fprintf(stderr, "device_manager: Could not initialize modules: %s\n", 960 strerror(status)); 961 return 1; 962 } 963 964 dm_init_root_node(); 965 dm_dump_node(sRootNode, 0); 966 967 return 0; 968 } 969