1 /* 2 * Copyright 2003-2008, Marcus Overhagen. All rights reserved. 3 * Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 4 * 5 * Distributed under the terms of the MIT License. 6 */ 7 8 9 #include <string.h> 10 #include <KernelExport.h> 11 #define __HAIKU_PCI_BUS_MANAGER_TESTING 1 12 #include <PCI.h> 13 14 #include "util/kernel_cpp.h" 15 #include "pci_fixup.h" 16 #include "pci_private.h" 17 #include "pci.h" 18 19 #define TRACE_CAP(x...) dprintf(x) 20 #define FLOW(x...) 21 //#define FLOW(x...) dprintf(x) 22 23 24 PCI *gPCI; 25 26 27 // #pragma mark bus manager exports 28 29 30 status_t 31 pci_controller_add(pci_controller *controller, void *cookie) 32 { 33 return gPCI->AddController(controller, cookie); 34 } 35 36 37 long 38 pci_get_nth_pci_info(long index, pci_info *outInfo) 39 { 40 return gPCI->GetNthInfo(index, outInfo); 41 } 42 43 44 uint32 45 pci_read_config(uint8 virtualBus, uint8 device, uint8 function, uint8 offset, 46 uint8 size) 47 { 48 uint8 bus; 49 int domain; 50 uint32 value; 51 52 if (gPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK) 53 return 0xffffffff; 54 55 if (gPCI->ReadConfig(domain, bus, device, function, offset, size, 56 &value) != B_OK) 57 return 0xffffffff; 58 59 return value; 60 } 61 62 63 void 64 pci_write_config(uint8 virtualBus, uint8 device, uint8 function, uint8 offset, 65 uint8 size, uint32 value) 66 { 67 uint8 bus; 68 int domain; 69 if (gPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK) 70 return; 71 72 gPCI->WriteConfig(domain, bus, device, function, offset, size, value); 73 } 74 75 76 status_t 77 pci_find_capability(uchar virtualBus, uchar device, uchar function, 78 uchar capID, uchar *offset) 79 { 80 uint8 bus; 81 int domain; 82 if (gPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK) 83 return B_ERROR; 84 85 return gPCI->FindCapability(domain, bus, device, function, capID, offset); 86 } 87 88 89 status_t 90 pci_reserve_device(uchar virtualBus, uchar device, uchar function, 91 const char *driverName, void *nodeCookie) 92 { 93 status_t status; 94 uint8 bus; 95 int domain; 96 97 /* 98 * we add 2 nodes to the PCI devices, one with constant attributes, 99 * so adding for another driver fails, and a subnode with the 100 * driver-provided informations. 101 */ 102 103 if (gPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK) 104 return B_ERROR; 105 106 //TRACE(("%s(%d [%d:%d], %d, %d, %s, %p)\n", __FUNCTION__, virtualBus, 107 // domain, bus, device, function, driverName, nodeCookie)); 108 109 device_attr matchPCIRoot[] = { 110 {B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "PCI"}}, 111 {NULL} 112 }; 113 device_attr matchThis[] = { 114 // info about device 115 {B_DEVICE_BUS, B_STRING_TYPE, {string: "pci"}}, 116 117 // location on PCI bus 118 {B_PCI_DEVICE_DOMAIN, B_UINT32_TYPE, {ui32: domain}}, 119 {B_PCI_DEVICE_BUS, B_UINT8_TYPE, {ui8: bus}}, 120 {B_PCI_DEVICE_DEVICE, B_UINT8_TYPE, {ui8: device}}, 121 {B_PCI_DEVICE_FUNCTION, B_UINT8_TYPE, {ui8: function}}, 122 {NULL} 123 }; 124 device_attr legacyAttrs[] = { 125 // info about device 126 {B_DEVICE_BUS, B_STRING_TYPE, {string: "legacy_driver"}}, 127 {B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "Legacy Driver Reservation"}}, 128 {NULL} 129 }; 130 device_attr drvAttrs[] = { 131 // info about device 132 {B_DEVICE_BUS, B_STRING_TYPE, {string: "legacy_driver"}}, 133 {"legacy_driver", B_STRING_TYPE, {string: driverName}}, 134 {"legacy_driver_cookie", B_UINT64_TYPE, {ui64: (uint64)nodeCookie}}, 135 {NULL} 136 }; 137 device_node *root, *pci, *node, *legacy; 138 139 status = B_DEVICE_NOT_FOUND; 140 root = gDeviceManager->get_root_node(); 141 if (!root) 142 return status; 143 144 pci = NULL; 145 if (gDeviceManager->get_next_child_node(root, matchPCIRoot, &pci) < B_OK) 146 goto err0; 147 148 node = NULL; 149 if (gDeviceManager->get_next_child_node(pci, matchThis, &node) < B_OK) 150 goto err1; 151 152 // common API for all legacy modules ? 153 //status = legacy_driver_register(node, driverName, nodeCookie, PCI_LEGACY_DRIVER_MODULE_NAME); 154 155 status = gDeviceManager->register_node(node, PCI_LEGACY_DRIVER_MODULE_NAME, 156 legacyAttrs, NULL, &legacy); 157 if (status < B_OK) 158 goto err2; 159 160 status = gDeviceManager->register_node(legacy, PCI_LEGACY_DRIVER_MODULE_NAME, 161 drvAttrs, NULL, NULL); 162 if (status < B_OK) 163 goto err3; 164 165 gDeviceManager->put_node(node); 166 gDeviceManager->put_node(pci); 167 gDeviceManager->put_node(root); 168 169 return B_OK; 170 171 err3: 172 gDeviceManager->unregister_node(legacy); 173 err2: 174 gDeviceManager->put_node(node); 175 err1: 176 gDeviceManager->put_node(pci); 177 err0: 178 gDeviceManager->put_node(root); 179 TRACE(("pci_reserve_device for driver %s failed: %s\n", driverName, strerror(status))); 180 return status; 181 } 182 183 184 status_t 185 pci_unreserve_device(uchar virtualBus, uchar device, uchar function, 186 const char *driverName, void *nodeCookie) 187 { 188 status_t status; 189 uint8 bus; 190 int domain; 191 192 if (gPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK) 193 return B_ERROR; 194 195 //TRACE(("%s(%d [%d:%d], %d, %d, %s, %p)\n", __FUNCTION__, virtualBus, 196 // domain, bus, device, function, driverName, nodeCookie)); 197 198 device_attr matchPCIRoot[] = { 199 {B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "PCI"}}, 200 {NULL} 201 }; 202 device_attr matchThis[] = { 203 // info about device 204 {B_DEVICE_BUS, B_STRING_TYPE, {string: "pci"}}, 205 206 // location on PCI bus 207 {B_PCI_DEVICE_DOMAIN, B_UINT32_TYPE, {ui32: domain}}, 208 {B_PCI_DEVICE_BUS, B_UINT8_TYPE, {ui8: bus}}, 209 {B_PCI_DEVICE_DEVICE, B_UINT8_TYPE, {ui8: device}}, 210 {B_PCI_DEVICE_FUNCTION, B_UINT8_TYPE, {ui8: function}}, 211 {NULL} 212 }; 213 device_attr legacyAttrs[] = { 214 // info about device 215 {B_DEVICE_BUS, B_STRING_TYPE, {string: "legacy_driver"}}, 216 {B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "Legacy Driver Reservation"}}, 217 {NULL} 218 }; 219 device_attr drvAttrs[] = { 220 // info about device 221 {B_DEVICE_BUS, B_STRING_TYPE, {string: "legacy_driver"}}, 222 {"legacy_driver", B_STRING_TYPE, {string: driverName}}, 223 {"legacy_driver_cookie", B_UINT64_TYPE, {ui64: (uint64)nodeCookie}}, 224 {NULL} 225 }; 226 device_node *root, *pci, *node, *legacy, *drv; 227 228 status = B_DEVICE_NOT_FOUND; 229 root = gDeviceManager->get_root_node(); 230 if (!root) 231 return status; 232 233 pci = NULL; 234 if (gDeviceManager->get_next_child_node(root, matchPCIRoot, &pci) < B_OK) 235 goto err0; 236 237 node = NULL; 238 if (gDeviceManager->get_next_child_node(pci, matchThis, &node) < B_OK) 239 goto err1; 240 241 // common API for all legacy modules ? 242 //status = legacy_driver_unregister(node, driverName, nodeCookie); 243 244 legacy = NULL; 245 if (gDeviceManager->get_next_child_node(node, legacyAttrs, &legacy) < B_OK) 246 goto err2; 247 248 drv = NULL; 249 if (gDeviceManager->get_next_child_node(legacy, drvAttrs, &drv) < B_OK) 250 goto err3; 251 252 gDeviceManager->put_node(drv); 253 status = gDeviceManager->unregister_node(drv); 254 //dprintf("unreg:drv:%s\n", strerror(status)); 255 256 gDeviceManager->put_node(legacy); 257 status = gDeviceManager->unregister_node(legacy); 258 //dprintf("unreg:legacy:%s\n", strerror(status)); 259 // we'll get EBUSY here anyway... 260 261 gDeviceManager->put_node(node); 262 gDeviceManager->put_node(pci); 263 gDeviceManager->put_node(root); 264 return B_OK; 265 266 err3: 267 gDeviceManager->put_node(legacy); 268 err2: 269 gDeviceManager->put_node(node); 270 err1: 271 gDeviceManager->put_node(pci); 272 err0: 273 gDeviceManager->put_node(root); 274 TRACE(("pci_unreserve_device for driver %s failed: %s\n", driverName, strerror(status))); 275 return status; 276 } 277 278 279 // used by pci_info.cpp print_info_basic() 280 void 281 __pci_resolve_virtual_bus(uint8 virtualBus, int *domain, uint8 *bus) 282 { 283 if (gPCI->ResolveVirtualBus(virtualBus, domain, bus) < B_OK) 284 panic("ResolveVirtualBus failed"); 285 } 286 287 288 // #pragma mark kernel debugger commands 289 290 291 static int 292 display_io(int argc, char **argv) 293 { 294 int32 displayWidth; 295 int32 itemSize; 296 int32 num = 1; 297 int address; 298 int i = 1, j; 299 300 switch (argc) { 301 case 3: 302 num = atoi(argv[2]); 303 case 2: 304 address = strtoul(argv[1], NULL, 0); 305 break; 306 default: 307 kprintf("usage: %s <address> [num]\n", argv[0]); 308 return 0; 309 } 310 311 // build the format string 312 if (strcmp(argv[0], "inb") == 0 || strcmp(argv[0], "in8") == 0) { 313 itemSize = 1; 314 displayWidth = 16; 315 } else if (strcmp(argv[0], "ins") == 0 || strcmp(argv[0], "in16") == 0) { 316 itemSize = 2; 317 displayWidth = 8; 318 } else if (strcmp(argv[0], "inw") == 0 || strcmp(argv[0], "in32") == 0) { 319 itemSize = 4; 320 displayWidth = 4; 321 } else { 322 kprintf("display_io called in an invalid way!\n"); 323 return 0; 324 } 325 326 for (i = 0; i < num; i++) { 327 if ((i % displayWidth) == 0) { 328 int32 displayed = min_c(displayWidth, (num-i)) * itemSize; 329 if (i != 0) 330 kprintf("\n"); 331 332 kprintf("[0x%lx] ", address + i * itemSize); 333 334 if (num > displayWidth) { 335 // make sure the spacing in the last line is correct 336 for (j = displayed; j < displayWidth * itemSize; j++) 337 kprintf(" "); 338 } 339 kprintf(" "); 340 } 341 342 switch (itemSize) { 343 case 1: 344 kprintf(" %02x", pci_read_io_8(address + i * itemSize)); 345 break; 346 case 2: 347 kprintf(" %04x", pci_read_io_16(address + i * itemSize)); 348 break; 349 case 4: 350 kprintf(" %08lx", pci_read_io_32(address + i * itemSize)); 351 break; 352 } 353 } 354 355 kprintf("\n"); 356 return 0; 357 } 358 359 360 static int 361 write_io(int argc, char **argv) 362 { 363 int32 itemSize; 364 uint32 value; 365 int address; 366 int i = 1; 367 368 if (argc < 3) { 369 kprintf("usage: %s <address> <value> [value [...]]\n", argv[0]); 370 return 0; 371 } 372 373 address = strtoul(argv[1], NULL, 0); 374 375 if (strcmp(argv[0], "outb") == 0 || strcmp(argv[0], "out8") == 0) { 376 itemSize = 1; 377 } else if (strcmp(argv[0], "outs") == 0 || strcmp(argv[0], "out16") == 0) { 378 itemSize = 2; 379 } else if (strcmp(argv[0], "outw") == 0 || strcmp(argv[0], "out32") == 0) { 380 itemSize = 4; 381 } else { 382 kprintf("write_io called in an invalid way!\n"); 383 return 0; 384 } 385 386 // skip cmd name and address 387 argv += 2; 388 argc -= 2; 389 390 for (i = 0; i < argc; i++) { 391 value = strtoul(argv[i], NULL, 0); 392 switch (itemSize) { 393 case 1: 394 pci_write_io_8(address + i * itemSize, value); 395 break; 396 case 2: 397 pci_write_io_16(address + i * itemSize, value); 398 break; 399 case 4: 400 pci_write_io_32(address + i * itemSize, value); 401 break; 402 } 403 } 404 405 return 0; 406 } 407 408 409 static int 410 pcistatus(int argc, char **argv) 411 { 412 gPCI->ClearDeviceStatus(NULL, true); 413 return 0; 414 } 415 416 417 // #pragma mark bus manager init/uninit 418 419 420 status_t 421 pci_init(void) 422 { 423 gPCI = new PCI; 424 425 if (pci_io_init() != B_OK) { 426 TRACE(("PCI: pci_io_init failed\n")); 427 return B_ERROR; 428 } 429 430 add_debugger_command("inw", &display_io, "dump io words (32-bit)"); 431 add_debugger_command("in32", &display_io, "dump io words (32-bit)"); 432 add_debugger_command("ins", &display_io, "dump io shorts (16-bit)"); 433 add_debugger_command("in16", &display_io, "dump io shorts (16-bit)"); 434 add_debugger_command("inb", &display_io, "dump io bytes (8-bit)"); 435 add_debugger_command("in8", &display_io, "dump io bytes (8-bit)"); 436 437 add_debugger_command("outw", &write_io, "write io words (32-bit)"); 438 add_debugger_command("out32", &write_io, "write io words (32-bit)"); 439 add_debugger_command("outs", &write_io, "write io shorts (16-bit)"); 440 add_debugger_command("out16", &write_io, "write io shorts (16-bit)"); 441 add_debugger_command("outb", &write_io, "write io bytes (8-bit)"); 442 add_debugger_command("out8", &write_io, "write io bytes (8-bit)"); 443 444 if (pci_controller_init() != B_OK) { 445 TRACE(("PCI: pci_controller_init failed\n")); 446 return B_ERROR; 447 } 448 449 gPCI->InitDomainData(); 450 gPCI->InitBus(); 451 452 add_debugger_command("pcistatus", &pcistatus, "dump and clear pci device status registers"); 453 454 return B_OK; 455 } 456 457 458 void 459 pci_uninit(void) 460 { 461 remove_debugger_command("outw", &write_io); 462 remove_debugger_command("out32", &write_io); 463 remove_debugger_command("outs", &write_io); 464 remove_debugger_command("out16", &write_io); 465 remove_debugger_command("outb", &write_io); 466 remove_debugger_command("out8", &write_io); 467 468 remove_debugger_command("inw", &display_io); 469 remove_debugger_command("in32", &display_io); 470 remove_debugger_command("ins", &display_io); 471 remove_debugger_command("in16", &display_io); 472 remove_debugger_command("inb", &display_io); 473 remove_debugger_command("in8", &display_io); 474 475 delete gPCI; 476 } 477 478 479 // #pragma mark PCI class 480 481 482 PCI::PCI() 483 : 484 fRootBus(0), 485 fDomainCount(0), 486 fBusEnumeration(false), 487 fVirtualBusMap(), 488 fNextVirtualBus(0) 489 { 490 #if defined(__POWERPC__) || defined(__M68K__) 491 fBusEnumeration = true; 492 #endif 493 } 494 495 496 void 497 PCI::InitBus() 498 { 499 PCIBus **nextBus = &fRootBus; 500 for (int i = 0; i < fDomainCount; i++) { 501 PCIBus *bus = new PCIBus; 502 bus->next = NULL; 503 bus->parent = NULL; 504 bus->child = NULL; 505 bus->domain = i; 506 bus->bus = 0; 507 *nextBus = bus; 508 nextBus = &bus->next; 509 } 510 511 if (fBusEnumeration) { 512 for (int i = 0; i < fDomainCount; i++) { 513 _EnumerateBus(i, 0); 514 } 515 } 516 517 if (1) { 518 for (int i = 0; i < fDomainCount; i++) { 519 _FixupDevices(i, 0); 520 } 521 } 522 523 if (fRootBus) { 524 _DiscoverBus(fRootBus); 525 _ConfigureBridges(fRootBus); 526 ClearDeviceStatus(fRootBus, false); 527 _RefreshDeviceInfo(fRootBus); 528 } 529 } 530 531 532 PCI::~PCI() 533 { 534 } 535 536 537 status_t 538 PCI::_CreateVirtualBus(int domain, uint8 bus, uint8 *virtualBus) 539 { 540 #if defined(__INTEL__) 541 542 // IA32 doesn't use domains 543 if (domain) 544 panic("PCI::CreateVirtualBus domain != 0"); 545 *virtualBus = bus; 546 return B_OK; 547 548 #else 549 550 if (fNextVirtualBus > 0xff) 551 panic("PCI::CreateVirtualBus: virtual bus number space exhausted"); 552 if (unsigned(domain) > 0xff) 553 panic("PCI::CreateVirtualBus: domain %d too large", domain); 554 555 uint16 value = domain << 8 | bus; 556 557 for (VirtualBusMap::Iterator it = fVirtualBusMap.Begin(); it != fVirtualBusMap.End(); ++it) { 558 if (it->Value() == value) { 559 *virtualBus = it->Key(); 560 FLOW("PCI::CreateVirtualBus: domain %d, bus %d already in map => virtualBus %d\n", domain, bus, *virtualBus); 561 return B_OK; 562 } 563 } 564 565 *virtualBus = fNextVirtualBus++; 566 567 FLOW("PCI::CreateVirtualBus: domain %d, bus %d => virtualBus %d\n", domain, bus, *virtualBus); 568 569 return fVirtualBusMap.Insert(*virtualBus, value); 570 571 #endif 572 } 573 574 575 status_t 576 PCI::ResolveVirtualBus(uint8 virtualBus, int *domain, uint8 *bus) 577 { 578 #if defined(__INTEL__) 579 580 // IA32 doesn't use domains 581 *bus = virtualBus; 582 *domain = 0; 583 return B_OK; 584 585 #else 586 587 if (virtualBus >= fNextVirtualBus) 588 return B_ERROR; 589 590 uint16 value = fVirtualBusMap.Get(virtualBus); 591 *domain = value >> 8; 592 *bus = value & 0xff; 593 return B_OK; 594 595 #endif 596 } 597 598 599 status_t 600 PCI::AddController(pci_controller *controller, void *controller_cookie) 601 { 602 if (fDomainCount == MAX_PCI_DOMAINS) 603 return B_ERROR; 604 605 fDomainData[fDomainCount].controller = controller; 606 fDomainData[fDomainCount].controller_cookie = controller_cookie; 607 608 // initialized later to avoid call back into controller at this point 609 fDomainData[fDomainCount].max_bus_devices = -1; 610 611 fDomainCount++; 612 return B_OK; 613 } 614 615 void 616 PCI::InitDomainData() 617 { 618 for (int i = 0; i < fDomainCount; i++) { 619 int32 count; 620 status_t status; 621 622 status = (*fDomainData[i].controller->get_max_bus_devices)(fDomainData[i].controller_cookie, &count); 623 fDomainData[i].max_bus_devices = (status == B_OK) ? count : 0; 624 } 625 } 626 627 628 domain_data * 629 PCI::_GetDomainData(int domain) 630 { 631 if (domain < 0 || domain >= fDomainCount) 632 return NULL; 633 634 return &fDomainData[domain]; 635 } 636 637 638 inline int 639 PCI::_NumFunctions(int domain, uint8 bus, uint8 device) 640 { 641 uint8 type = ReadConfig(domain, bus, device, 642 0, PCI_header_type, 1); 643 return (type & PCI_multifunction) != 0 ? 8 : 1; 644 } 645 646 647 status_t 648 PCI::GetNthInfo(long index, pci_info *outInfo) 649 { 650 long currentIndex = 0; 651 if (!fRootBus) 652 return B_ERROR; 653 654 return _GetNthInfo(fRootBus, ¤tIndex, index, outInfo); 655 } 656 657 658 status_t 659 PCI::_GetNthInfo(PCIBus *bus, long *currentIndex, long wantIndex, 660 pci_info *outInfo) 661 { 662 // maps tree structure to linear indexed view 663 PCIDev *dev = bus->child; 664 while (dev) { 665 if (*currentIndex == wantIndex) { 666 *outInfo = dev->info; 667 return B_OK; 668 } 669 *currentIndex += 1; 670 if (dev->child && B_OK == _GetNthInfo(dev->child, currentIndex, 671 wantIndex, outInfo)) 672 return B_OK; 673 dev = dev->next; 674 } 675 676 if (bus->next) 677 return _GetNthInfo(bus->next, currentIndex, wantIndex, outInfo); 678 679 return B_ERROR; 680 } 681 682 683 void 684 PCI::_EnumerateBus(int domain, uint8 bus, uint8 *subordinateBus) 685 { 686 TRACE(("PCI: EnumerateBus: domain %u, bus %u\n", domain, bus)); 687 688 int maxBusDevices = _GetDomainData(domain)->max_bus_devices; 689 690 // step 1: disable all bridges on this bus 691 for (int dev = 0; dev < maxBusDevices; dev++) { 692 uint16 vendor_id = ReadConfig(domain, bus, dev, 0, PCI_vendor_id, 2); 693 if (vendor_id == 0xffff) 694 continue; 695 696 int numFunctions = _NumFunctions(domain, bus, dev); 697 for (int function = 0; function < numFunctions; function++) { 698 uint16 device_id = ReadConfig(domain, bus, dev, function, 699 PCI_device_id, 2); 700 if (device_id == 0xffff) 701 continue; 702 703 uint8 baseClass = ReadConfig(domain, bus, dev, function, 704 PCI_class_base, 1); 705 uint8 subClass = ReadConfig(domain, bus, dev, function, 706 PCI_class_sub, 1); 707 if (baseClass != PCI_bridge || subClass != PCI_pci) 708 continue; 709 710 TRACE(("PCI: found PCI-PCI bridge: domain %u, bus %u, dev %u, func %u\n", domain, bus, dev, function)); 711 TRACE(("PCI: original settings: pcicmd %04lx, primary-bus %lu, secondary-bus %lu, subordinate-bus %lu\n", 712 ReadConfig(domain, bus, dev, function, PCI_command, 2), 713 ReadConfig(domain, bus, dev, function, PCI_primary_bus, 1), 714 ReadConfig(domain, bus, dev, function, PCI_secondary_bus, 1), 715 ReadConfig(domain, bus, dev, function, PCI_subordinate_bus, 1))); 716 717 // disable decoding 718 uint16 pcicmd; 719 pcicmd = ReadConfig(domain, bus, dev, function, PCI_command, 2); 720 pcicmd &= ~(PCI_command_io | PCI_command_memory 721 | PCI_command_master); 722 WriteConfig(domain, bus, dev, function, PCI_command, 2, pcicmd); 723 724 // disable busses 725 WriteConfig(domain, bus, dev, function, PCI_primary_bus, 1, 0); 726 WriteConfig(domain, bus, dev, function, PCI_secondary_bus, 1, 0); 727 WriteConfig(domain, bus, dev, function, PCI_subordinate_bus, 1, 0); 728 729 TRACE(("PCI: disabled settings: pcicmd %04lx, primary-bus %lu, secondary-bus %lu, subordinate-bus %lu\n", 730 ReadConfig(domain, bus, dev, function, PCI_command, 2), 731 ReadConfig(domain, bus, dev, function, PCI_primary_bus, 1), 732 ReadConfig(domain, bus, dev, function, PCI_secondary_bus, 1), 733 ReadConfig(domain, bus, dev, function, PCI_subordinate_bus, 1))); 734 } 735 } 736 737 uint8 lastUsedBusNumber = bus; 738 739 // step 2: assign busses to all bridges, and enable them again 740 for (int dev = 0; dev < maxBusDevices; dev++) { 741 uint16 vendor_id = ReadConfig(domain, bus, dev, 0, PCI_vendor_id, 2); 742 if (vendor_id == 0xffff) 743 continue; 744 745 int numFunctions = _NumFunctions(domain, bus, dev); 746 for (int function = 0; function < numFunctions; function++) { 747 uint16 deviceID = ReadConfig(domain, bus, dev, function, 748 PCI_device_id, 2); 749 if (deviceID == 0xffff) 750 continue; 751 752 uint8 baseClass = ReadConfig(domain, bus, dev, function, 753 PCI_class_base, 1); 754 uint8 subClass = ReadConfig(domain, bus, dev, function, 755 PCI_class_sub, 1); 756 if (baseClass != PCI_bridge || subClass != PCI_pci) 757 continue; 758 759 TRACE(("PCI: configuring PCI-PCI bridge: domain %u, bus %u, dev %u, func %u\n", 760 domain, bus, dev, function)); 761 762 // open Scheunentor for enumerating the bus behind the bridge 763 WriteConfig(domain, bus, dev, function, PCI_primary_bus, 1, bus); 764 WriteConfig(domain, bus, dev, function, PCI_secondary_bus, 1, 765 lastUsedBusNumber + 1); 766 WriteConfig(domain, bus, dev, function, PCI_subordinate_bus, 1, 255); 767 768 // enable decoding (too early here?) 769 uint16 pcicmd; 770 pcicmd = ReadConfig(domain, bus, dev, function, PCI_command, 2); 771 pcicmd |= PCI_command_io | PCI_command_memory | PCI_command_master; 772 WriteConfig(domain, bus, dev, function, PCI_command, 2, pcicmd); 773 774 TRACE(("PCI: probing settings: pcicmd %04lx, primary-bus %lu, secondary-bus %lu, subordinate-bus %lu\n", 775 ReadConfig(domain, bus, dev, function, PCI_command, 2), 776 ReadConfig(domain, bus, dev, function, PCI_primary_bus, 1), 777 ReadConfig(domain, bus, dev, function, PCI_secondary_bus, 1), 778 ReadConfig(domain, bus, dev, function, PCI_subordinate_bus, 1))); 779 780 // enumerate bus 781 _EnumerateBus(domain, lastUsedBusNumber + 1, &lastUsedBusNumber); 782 783 // close Scheunentor 784 WriteConfig(domain, bus, dev, function, PCI_subordinate_bus, 1, lastUsedBusNumber); 785 786 TRACE(("PCI: configured settings: pcicmd %04lx, primary-bus %lu, secondary-bus %lu, subordinate-bus %lu\n", 787 ReadConfig(domain, bus, dev, function, PCI_command, 2), 788 ReadConfig(domain, bus, dev, function, PCI_primary_bus, 1), 789 ReadConfig(domain, bus, dev, function, PCI_secondary_bus, 1), 790 ReadConfig(domain, bus, dev, function, PCI_subordinate_bus, 1))); 791 } 792 } 793 if (subordinateBus) 794 *subordinateBus = lastUsedBusNumber; 795 796 TRACE(("PCI: EnumerateBus done: domain %u, bus %u, last used bus number %u\n", domain, bus, lastUsedBusNumber)); 797 } 798 799 800 void 801 PCI::_FixupDevices(int domain, uint8 bus) 802 { 803 FLOW("PCI: FixupDevices domain %u, bus %u\n", domain, bus); 804 805 int maxBusDevices = _GetDomainData(domain)->max_bus_devices; 806 807 for (int dev = 0; dev < maxBusDevices; dev++) { 808 uint16 vendorId = ReadConfig(domain, bus, dev, 0, PCI_vendor_id, 2); 809 if (vendorId == 0xffff) 810 continue; 811 812 int numFunctions = _NumFunctions(domain, bus, dev); 813 for (int function = 0; function < numFunctions; function++) { 814 uint16 deviceId = ReadConfig(domain, bus, dev, function, 815 PCI_device_id, 2); 816 if (deviceId == 0xffff) 817 continue; 818 819 pci_fixup_device(this, domain, bus, dev, function); 820 821 uint8 baseClass = ReadConfig(domain, bus, dev, function, 822 PCI_class_base, 1); 823 if (baseClass != PCI_bridge) 824 continue; 825 uint8 subClass = ReadConfig(domain, bus, dev, function, 826 PCI_class_sub, 1); 827 if (subClass != PCI_pci) 828 continue; 829 830 int busBehindBridge = ReadConfig(domain, bus, dev, function, 831 PCI_secondary_bus, 1); 832 833 _FixupDevices(domain, busBehindBridge); 834 } 835 } 836 } 837 838 839 void 840 PCI::_ConfigureBridges(PCIBus *bus) 841 { 842 for (PCIDev *dev = bus->child; dev; dev = dev->next) { 843 if (dev->info.class_base == PCI_bridge 844 && dev->info.class_sub == PCI_pci) { 845 uint16 bridgeControlOld = ReadConfig(dev->domain, dev->bus, 846 dev->device, dev->function, PCI_bridge_control, 2); 847 uint16 bridgeControlNew = bridgeControlOld; 848 // Enable: Parity Error Response, SERR, Master Abort Mode, Discard 849 // Timer SERR 850 // Clear: Discard Timer Status 851 bridgeControlNew |= (1 << 0) | (1 << 1) | (1 << 5) | (1 << 10) 852 | (1 << 11); 853 // Set discard timer to 2^15 PCI clocks 854 bridgeControlNew &= ~((1 << 8) | (1 << 9)); 855 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, 856 PCI_bridge_control, 2, bridgeControlNew); 857 bridgeControlNew = ReadConfig(dev->domain, dev->bus, dev->device, 858 dev->function, PCI_bridge_control, 2); 859 dprintf("PCI: dom %u, bus %u, dev %2u, func %u, changed PCI bridge control from 0x%04x to 0x%04x\n", 860 dev->domain, dev->bus, dev->device, dev->function, bridgeControlOld, bridgeControlNew); 861 } 862 863 if (dev->child) 864 _ConfigureBridges(dev->child); 865 } 866 867 if (bus->next) 868 _ConfigureBridges(bus->next); 869 } 870 871 872 void 873 PCI::ClearDeviceStatus(PCIBus *bus, bool dumpStatus) 874 { 875 if (!bus) { 876 if (!fRootBus) 877 return; 878 bus = fRootBus; 879 } 880 881 for (PCIDev *dev = bus->child; dev; dev = dev->next) { 882 // Clear and dump PCI device status 883 uint16 status = ReadConfig(dev->domain, dev->bus, dev->device, 884 dev->function, PCI_status, 2); 885 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, PCI_status, 886 2, status); 887 if (dumpStatus) { 888 kprintf("domain %u, bus %u, dev %2u, func %u, PCI device status 0x%04x\n", 889 dev->domain, dev->bus, dev->device, dev->function, status); 890 if (status & (1 << 15)) 891 kprintf(" Detected Parity Error\n"); 892 if (status & (1 << 14)) 893 kprintf(" Signalled System Error\n"); 894 if (status & (1 << 13)) 895 kprintf(" Received Master-Abort\n"); 896 if (status & (1 << 12)) 897 kprintf(" Received Target-Abort\n"); 898 if (status & (1 << 11)) 899 kprintf(" Signalled Target-Abort\n"); 900 if (status & (1 << 8)) 901 kprintf(" Master Data Parity Error\n"); 902 } 903 904 if (dev->info.class_base == PCI_bridge 905 && dev->info.class_sub == PCI_pci) { 906 // Clear and dump PCI bridge secondary status 907 uint16 secondaryStatus = ReadConfig(dev->domain, dev->bus, 908 dev->device, dev->function, PCI_secondary_status, 2); 909 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, 910 PCI_secondary_status, 2, secondaryStatus); 911 if (dumpStatus) { 912 kprintf("domain %u, bus %u, dev %2u, func %u, PCI bridge secondary status 0x%04x\n", 913 dev->domain, dev->bus, dev->device, dev->function, secondaryStatus); 914 if (secondaryStatus & (1 << 15)) 915 kprintf(" Detected Parity Error\n"); 916 if (secondaryStatus & (1 << 14)) 917 kprintf(" Received System Error\n"); 918 if (secondaryStatus & (1 << 13)) 919 kprintf(" Received Master-Abort\n"); 920 if (secondaryStatus & (1 << 12)) 921 kprintf(" Received Target-Abort\n"); 922 if (secondaryStatus & (1 << 11)) 923 kprintf(" Signalled Target-Abort\n"); 924 if (secondaryStatus & (1 << 8)) 925 kprintf(" Data Parity Reported\n"); 926 } 927 928 // Clear and dump the discard-timer error bit located in bridge-control register 929 uint16 bridgeControl = ReadConfig(dev->domain, dev->bus, 930 dev->device, dev->function, PCI_bridge_control, 2); 931 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, 932 PCI_bridge_control, 2, bridgeControl); 933 if (dumpStatus) { 934 kprintf("domain %u, bus %u, dev %2u, func %u, PCI bridge control 0x%04x\n", 935 dev->domain, dev->bus, dev->device, dev->function, bridgeControl); 936 if (bridgeControl & (1 << 10)) { 937 kprintf(" bridge-control: Discard Timer Error\n"); 938 } 939 } 940 } 941 942 if (dev->child) 943 ClearDeviceStatus(dev->child, dumpStatus); 944 } 945 946 if (bus->next) 947 ClearDeviceStatus(bus->next, dumpStatus); 948 } 949 950 951 void 952 PCI::_DiscoverBus(PCIBus *bus) 953 { 954 FLOW("PCI: DiscoverBus, domain %u, bus %u\n", bus->domain, bus->bus); 955 956 int maxBusDevices = _GetDomainData(bus->domain)->max_bus_devices; 957 958 for (int dev = 0; dev < maxBusDevices; dev++) { 959 uint16 vendorID = ReadConfig(bus->domain, bus->bus, dev, 0, 960 PCI_vendor_id, 2); 961 if (vendorID == 0xffff) 962 continue; 963 964 int numFunctions = _NumFunctions(bus->domain, bus->bus, dev); 965 for (int function = 0; function < numFunctions; function++) 966 _DiscoverDevice(bus, dev, function); 967 } 968 969 if (bus->next) 970 _DiscoverBus(bus->next); 971 } 972 973 974 void 975 PCI::_DiscoverDevice(PCIBus *bus, uint8 dev, uint8 function) 976 { 977 FLOW("PCI: DiscoverDevice, domain %u, bus %u, dev %u, func %u\n", bus->domain, bus->bus, dev, function); 978 979 uint16 deviceID = ReadConfig(bus->domain, bus->bus, dev, function, 980 PCI_device_id, 2); 981 if (deviceID == 0xffff) 982 return; 983 984 PCIDev *newDev = _CreateDevice(bus, dev, function); 985 986 uint8 baseClass = ReadConfig(bus->domain, bus->bus, dev, function, 987 PCI_class_base, 1); 988 uint8 subClass = ReadConfig(bus->domain, bus->bus, dev, function, 989 PCI_class_sub, 1); 990 if (baseClass == PCI_bridge && subClass == PCI_pci) { 991 uint8 secondaryBus = ReadConfig(bus->domain, bus->bus, dev, function, 992 PCI_secondary_bus, 1); 993 PCIBus *newBus = _CreateBus(newDev, bus->domain, secondaryBus); 994 _DiscoverBus(newBus); 995 } 996 } 997 998 999 PCIBus * 1000 PCI::_CreateBus(PCIDev *parent, int domain, uint8 bus) 1001 { 1002 PCIBus *newBus = new(std::nothrow) PCIBus; 1003 if (newBus == NULL) 1004 return NULL; 1005 1006 newBus->next = NULL; 1007 newBus->parent = parent; 1008 newBus->child = NULL; 1009 newBus->domain = domain; 1010 newBus->bus = bus; 1011 1012 // append 1013 parent->child = newBus; 1014 1015 return newBus; 1016 } 1017 1018 1019 PCIDev * 1020 PCI::_CreateDevice(PCIBus *parent, uint8 device, uint8 function) 1021 { 1022 FLOW("PCI: CreateDevice, domain %u, bus %u, dev %u, func %u:\n", parent->domain, parent->bus, device, function); 1023 1024 PCIDev *newDev = new(std::nothrow) PCIDev; 1025 if (newDev == NULL) 1026 return NULL; 1027 1028 newDev->next = NULL; 1029 newDev->parent = parent; 1030 newDev->child = NULL; 1031 newDev->domain = parent->domain; 1032 newDev->bus = parent->bus; 1033 newDev->device = device; 1034 newDev->function = function; 1035 1036 _ReadBasicInfo(newDev); 1037 1038 FLOW("PCI: CreateDevice, vendor 0x%04x, device 0x%04x, class_base 0x%02x, class_sub 0x%02x\n", 1039 newDev->info.vendor_id, newDev->info.device_id, newDev->info.class_base, newDev->info.class_sub); 1040 1041 // append 1042 if (parent->child == NULL) { 1043 parent->child = newDev; 1044 } else { 1045 PCIDev *sub = parent->child; 1046 while (sub->next) 1047 sub = sub->next; 1048 sub->next = newDev; 1049 } 1050 1051 return newDev; 1052 } 1053 1054 1055 uint32 1056 PCI::_BarSize(uint32 bits, uint32 mask) 1057 { 1058 bits &= mask; 1059 if (!bits) 1060 return 0; 1061 uint32 size = 1; 1062 while (!(bits & size)) 1063 size <<= 1; 1064 return size; 1065 } 1066 1067 1068 void 1069 PCI::_GetBarInfo(PCIDev *dev, uint8 offset, uint32 *_address, uint32 *_size, 1070 uint8 *_flags) 1071 { 1072 uint32 oldValue = ReadConfig(dev->domain, dev->bus, dev->device, dev->function, 1073 offset, 4); 1074 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, offset, 4, 1075 0xffffffff); 1076 uint32 newValue = ReadConfig(dev->domain, dev->bus, dev->device, dev->function, 1077 offset, 4); 1078 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, offset, 4, 1079 oldValue); 1080 1081 *_address = oldValue & PCI_address_memory_32_mask; 1082 if (_size != NULL) 1083 *_size = _BarSize(newValue, PCI_address_memory_32_mask); 1084 if (_flags != NULL) 1085 *_flags = newValue & 0xf; 1086 } 1087 1088 1089 void 1090 PCI::_GetRomBarInfo(PCIDev *dev, uint8 offset, uint32 *_address, uint32 *_size, 1091 uint8 *_flags) 1092 { 1093 uint32 oldValue = ReadConfig(dev->domain, dev->bus, dev->device, dev->function, 1094 offset, 4); 1095 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, offset, 4, 1096 0xfffffffe); // LSB must be 0 1097 uint32 newValue = ReadConfig(dev->domain, dev->bus, dev->device, dev->function, 1098 offset, 4); 1099 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, offset, 4, 1100 oldValue); 1101 1102 *_address = oldValue & PCI_rom_address_mask; 1103 if (_size != NULL) 1104 *_size = _BarSize(newValue, PCI_rom_address_mask); 1105 if (_flags != NULL) 1106 *_flags = newValue & 0xf; 1107 } 1108 1109 1110 void 1111 PCI::_ReadBasicInfo(PCIDev *dev) 1112 { 1113 uint8 virtualBus; 1114 1115 if (_CreateVirtualBus(dev->domain, dev->bus, &virtualBus) != B_OK) { 1116 dprintf("PCI: CreateVirtualBus failed, domain %u, bus %u\n", dev->domain, dev->bus); 1117 return; 1118 } 1119 1120 dev->info.vendor_id = ReadConfig(dev->domain, dev->bus, dev->device, 1121 dev->function, PCI_vendor_id, 2); 1122 dev->info.device_id = ReadConfig(dev->domain, dev->bus, dev->device, 1123 dev->function, PCI_device_id, 2); 1124 dev->info.bus = virtualBus; 1125 dev->info.device = dev->device; 1126 dev->info.function = dev->function; 1127 dev->info.revision = ReadConfig(dev->domain, dev->bus, dev->device, 1128 dev->function, PCI_revision, 1); 1129 dev->info.class_api = ReadConfig(dev->domain, dev->bus, dev->device, 1130 dev->function, PCI_class_api, 1); 1131 dev->info.class_sub = ReadConfig(dev->domain, dev->bus, dev->device, 1132 dev->function, PCI_class_sub, 1); 1133 dev->info.class_base = ReadConfig(dev->domain, dev->bus, dev->device, 1134 dev->function, PCI_class_base, 1); 1135 dev->info.line_size = ReadConfig(dev->domain, dev->bus, dev->device, 1136 dev->function, PCI_line_size, 1); 1137 dev->info.latency = ReadConfig(dev->domain, dev->bus, dev->device, 1138 dev->function, PCI_latency, 1); 1139 // BeOS does not mask off the multifunction bit, developer must use 1140 // (header_type & PCI_header_type_mask) 1141 dev->info.header_type = ReadConfig(dev->domain, dev->bus, dev->device, 1142 dev->function, PCI_header_type, 1); 1143 dev->info.bist = ReadConfig(dev->domain, dev->bus, dev->device, 1144 dev->function, PCI_bist, 1); 1145 dev->info.reserved = 0; 1146 } 1147 1148 1149 void 1150 PCI::_ReadHeaderInfo(PCIDev *dev) 1151 { 1152 switch (dev->info.header_type & PCI_header_type_mask) { 1153 case PCI_header_type_generic: 1154 { 1155 // disable PCI device address decoding (io and memory) while BARs 1156 // are modified 1157 uint16 pcicmd = ReadConfig(dev->domain, dev->bus, dev->device, 1158 dev->function, PCI_command, 2); 1159 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, 1160 PCI_command, 2, 1161 pcicmd & ~(PCI_command_io | PCI_command_memory)); 1162 1163 // get BAR size infos 1164 _GetRomBarInfo(dev, PCI_rom_base, &dev->info.u.h0.rom_base_pci, 1165 &dev->info.u.h0.rom_size); 1166 for (int i = 0; i < 6; i++) { 1167 _GetBarInfo(dev, PCI_base_registers + 4*i, 1168 &dev->info.u.h0.base_registers_pci[i], 1169 &dev->info.u.h0.base_register_sizes[i], 1170 &dev->info.u.h0.base_register_flags[i]); 1171 } 1172 1173 // restore PCI device address decoding 1174 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, 1175 PCI_command, 2, pcicmd); 1176 1177 dev->info.u.h0.rom_base = (ulong)pci_ram_address( 1178 (void *)dev->info.u.h0.rom_base_pci); 1179 for (int i = 0; i < 6; i++) { 1180 dev->info.u.h0.base_registers[i] = (ulong)pci_ram_address( 1181 (void *)dev->info.u.h0.base_registers_pci[i]); 1182 } 1183 1184 dev->info.u.h0.cardbus_cis = ReadConfig(dev->domain, dev->bus, 1185 dev->device, dev->function, PCI_cardbus_cis, 4); 1186 dev->info.u.h0.subsystem_id = ReadConfig(dev->domain, dev->bus, 1187 dev->device, dev->function, PCI_subsystem_id, 2); 1188 dev->info.u.h0.subsystem_vendor_id = ReadConfig(dev->domain, 1189 dev->bus, dev->device, dev->function, PCI_subsystem_vendor_id, 2); 1190 dev->info.u.h0.interrupt_line = ReadConfig(dev->domain, dev->bus, 1191 dev->device, dev->function, PCI_interrupt_line, 1); 1192 dev->info.u.h0.interrupt_pin = ReadConfig(dev->domain, dev->bus, 1193 dev->device, dev->function, PCI_interrupt_pin, 1); 1194 dev->info.u.h0.min_grant = ReadConfig(dev->domain, dev->bus, 1195 dev->device, dev->function, PCI_min_grant, 1); 1196 dev->info.u.h0.max_latency = ReadConfig(dev->domain, dev->bus, 1197 dev->device, dev->function, PCI_max_latency, 1); 1198 break; 1199 } 1200 1201 case PCI_header_type_PCI_to_PCI_bridge: 1202 { 1203 // disable PCI device address decoding (io and memory) while BARs are modified 1204 uint16 pcicmd = ReadConfig(dev->domain, dev->bus, dev->device, 1205 dev->function, PCI_command, 2); 1206 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, 1207 PCI_command, 2, 1208 pcicmd & ~(PCI_command_io | PCI_command_memory)); 1209 1210 _GetRomBarInfo(dev, PCI_bridge_rom_base, 1211 &dev->info.u.h1.rom_base_pci); 1212 for (int i = 0; i < 2; i++) { 1213 _GetBarInfo(dev, PCI_base_registers + 4*i, 1214 &dev->info.u.h1.base_registers_pci[i], 1215 &dev->info.u.h1.base_register_sizes[i], 1216 &dev->info.u.h1.base_register_flags[i]); 1217 } 1218 1219 // restore PCI device address decoding 1220 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, 1221 PCI_command, 2, pcicmd); 1222 1223 dev->info.u.h1.rom_base = (ulong)pci_ram_address( 1224 (void *)dev->info.u.h1.rom_base_pci); 1225 for (int i = 0; i < 2; i++) { 1226 dev->info.u.h1.base_registers[i] = (ulong)pci_ram_address( 1227 (void *)dev->info.u.h1.base_registers_pci[i]); 1228 } 1229 1230 dev->info.u.h1.primary_bus = ReadConfig(dev->domain, dev->bus, 1231 dev->device, dev->function, PCI_primary_bus, 1); 1232 dev->info.u.h1.secondary_bus = ReadConfig(dev->domain, dev->bus, 1233 dev->device, dev->function, PCI_secondary_bus, 1); 1234 dev->info.u.h1.subordinate_bus = ReadConfig(dev->domain, 1235 dev->bus, dev->device, dev->function, PCI_subordinate_bus, 1); 1236 dev->info.u.h1.secondary_latency = ReadConfig(dev->domain, 1237 dev->bus, dev->device, dev->function, PCI_secondary_latency, 1); 1238 dev->info.u.h1.io_base = ReadConfig(dev->domain, dev->bus, 1239 dev->device, dev->function, PCI_io_base, 1); 1240 dev->info.u.h1.io_limit = ReadConfig(dev->domain, dev->bus, 1241 dev->device, dev->function, PCI_io_limit, 1); 1242 dev->info.u.h1.secondary_status = ReadConfig(dev->domain, 1243 dev->bus, dev->device, dev->function, PCI_secondary_status, 2); 1244 dev->info.u.h1.memory_base = ReadConfig(dev->domain, dev->bus, 1245 dev->device, dev->function, PCI_memory_base, 2); 1246 dev->info.u.h1.memory_limit = ReadConfig(dev->domain, dev->bus, 1247 dev->device, dev->function, PCI_memory_limit, 2); 1248 dev->info.u.h1.prefetchable_memory_base = ReadConfig(dev->domain, 1249 dev->bus, dev->device, dev->function, PCI_prefetchable_memory_base, 2); 1250 dev->info.u.h1.prefetchable_memory_limit = ReadConfig( 1251 dev->domain, dev->bus, dev->device, dev->function, 1252 PCI_prefetchable_memory_limit, 2); 1253 dev->info.u.h1.prefetchable_memory_base_upper32 = ReadConfig( 1254 dev->domain, dev->bus, dev->device, dev->function, 1255 PCI_prefetchable_memory_base_upper32, 4); 1256 dev->info.u.h1.prefetchable_memory_limit_upper32 = ReadConfig( 1257 dev->domain, dev->bus, dev->device, dev->function, 1258 PCI_prefetchable_memory_limit_upper32, 4); 1259 dev->info.u.h1.io_base_upper16 = ReadConfig(dev->domain, 1260 dev->bus, dev->device, dev->function, PCI_io_base_upper16, 2); 1261 dev->info.u.h1.io_limit_upper16 = ReadConfig(dev->domain, 1262 dev->bus, dev->device, dev->function, PCI_io_limit_upper16, 2); 1263 dev->info.u.h1.interrupt_line = ReadConfig(dev->domain, dev->bus, 1264 dev->device, dev->function, PCI_interrupt_line, 1); 1265 dev->info.u.h1.interrupt_pin = ReadConfig(dev->domain, dev->bus, 1266 dev->device, dev->function, PCI_interrupt_pin, 1); 1267 dev->info.u.h1.bridge_control = ReadConfig(dev->domain, dev->bus, 1268 dev->device, dev->function, PCI_bridge_control, 2); 1269 dev->info.u.h1.subsystem_id = ReadConfig(dev->domain, dev->bus, 1270 dev->device, dev->function, PCI_sub_device_id_1, 2); 1271 dev->info.u.h1.subsystem_vendor_id = ReadConfig(dev->domain, 1272 dev->bus, dev->device, dev->function, PCI_sub_vendor_id_1, 2); 1273 break; 1274 } 1275 1276 case PCI_header_type_cardbus: 1277 { 1278 // for testing only, not final: 1279 dev->info.u.h2.subsystem_id = ReadConfig(dev->domain, dev->bus, 1280 dev->device, dev->function, PCI_sub_device_id_2, 2); 1281 dev->info.u.h2.subsystem_vendor_id = ReadConfig(dev->domain, 1282 dev->bus, dev->device, dev->function, PCI_sub_vendor_id_2, 2); 1283 dev->info.u.h2.primary_bus = ReadConfig(dev->domain, dev->bus, 1284 dev->device, dev->function, PCI_primary_bus_2, 1); 1285 dev->info.u.h2.secondary_bus = ReadConfig(dev->domain, dev->bus, 1286 dev->device, dev->function, PCI_secondary_bus_2, 1); 1287 dev->info.u.h2.subordinate_bus = ReadConfig(dev->domain, 1288 dev->bus, dev->device, dev->function, PCI_subordinate_bus_2, 1); 1289 dev->info.u.h2.secondary_latency = ReadConfig(dev->domain, 1290 dev->bus, dev->device, dev->function, PCI_secondary_latency_2, 1); 1291 dev->info.u.h2.reserved = 0; 1292 dev->info.u.h2.memory_base = ReadConfig(dev->domain, dev->bus, 1293 dev->device, dev->function, PCI_memory_base0_2, 4); 1294 dev->info.u.h2.memory_limit = ReadConfig(dev->domain, dev->bus, 1295 dev->device, dev->function, PCI_memory_limit0_2, 4); 1296 dev->info.u.h2.memory_base_upper32 = ReadConfig(dev->domain, 1297 dev->bus, dev->device, dev->function, PCI_memory_base1_2, 4); 1298 dev->info.u.h2.memory_limit_upper32 = ReadConfig(dev->domain, 1299 dev->bus, dev->device, dev->function, PCI_memory_limit1_2, 4); 1300 dev->info.u.h2.io_base = ReadConfig(dev->domain, dev->bus, 1301 dev->device, dev->function, PCI_io_base0_2, 4); 1302 dev->info.u.h2.io_limit = ReadConfig(dev->domain, dev->bus, 1303 dev->device, dev->function, PCI_io_limit0_2, 4); 1304 dev->info.u.h2.io_base_upper32 = ReadConfig(dev->domain, 1305 dev->bus, dev->device, dev->function, PCI_io_base1_2, 4); 1306 dev->info.u.h2.io_limit_upper32 = ReadConfig(dev->domain, 1307 dev->bus, dev->device, dev->function, PCI_io_limit1_2, 4); 1308 dev->info.u.h2.secondary_status = ReadConfig(dev->domain, 1309 dev->bus, dev->device, dev->function, PCI_secondary_status_2, 2); 1310 dev->info.u.h2.bridge_control = ReadConfig(dev->domain, 1311 dev->bus, dev->device, dev->function, PCI_bridge_control_2, 2); 1312 break; 1313 } 1314 1315 default: 1316 TRACE(("PCI: Header type unknown (0x%02x)\n", dev->info.header_type)); 1317 break; 1318 } 1319 } 1320 1321 1322 void 1323 PCI::_RefreshDeviceInfo(PCIBus *bus) 1324 { 1325 for (PCIDev *dev = bus->child; dev; dev = dev->next) { 1326 _ReadBasicInfo(dev); 1327 _ReadHeaderInfo(dev); 1328 #ifdef __INTEL__ 1329 pci_read_arch_info(dev); 1330 #endif 1331 if (dev->child) 1332 _RefreshDeviceInfo(dev->child); 1333 } 1334 1335 if (bus->next) 1336 _RefreshDeviceInfo(bus->next); 1337 } 1338 1339 1340 status_t 1341 PCI::ReadConfig(int domain, uint8 bus, uint8 device, uint8 function, 1342 uint8 offset, uint8 size, uint32 *value) 1343 { 1344 domain_data *info = _GetDomainData(domain); 1345 if (!info) 1346 return B_ERROR; 1347 1348 if (device > (info->max_bus_devices - 1) 1349 || function > 7 1350 || (size != 1 && size != 2 && size != 4) 1351 || (size == 2 && (offset & 3) == 3) 1352 || (size == 4 && (offset & 3) != 0)) { 1353 dprintf("PCI: can't read config for domain %d, bus %u, device %u, function %u, offset %u, size %u\n", 1354 domain, bus, device, function, offset, size); 1355 return B_ERROR; 1356 } 1357 1358 return (*info->controller->read_pci_config)(info->controller_cookie, bus, 1359 device, function, offset, size, value); 1360 } 1361 1362 1363 uint32 1364 PCI::ReadConfig(int domain, uint8 bus, uint8 device, uint8 function, 1365 uint8 offset, uint8 size) 1366 { 1367 uint32 value; 1368 if (ReadConfig(domain, bus, device, function, offset, size, &value) 1369 != B_OK) 1370 return 0xffffffff; 1371 1372 return value; 1373 } 1374 1375 1376 uint32 1377 PCI::ReadConfig(PCIDev *device, uint8 offset, uint8 size) 1378 { 1379 uint32 value; 1380 if (ReadConfig(device->domain, device->bus, device->device, 1381 device->function, offset, size, &value) != B_OK) 1382 return 0xffffffff; 1383 1384 return value; 1385 } 1386 1387 1388 status_t 1389 PCI::WriteConfig(int domain, uint8 bus, uint8 device, uint8 function, 1390 uint8 offset, uint8 size, uint32 value) 1391 { 1392 domain_data *info = _GetDomainData(domain); 1393 if (!info) 1394 return B_ERROR; 1395 1396 if (device > (info->max_bus_devices - 1) 1397 || function > 7 1398 || (size != 1 && size != 2 && size != 4) 1399 || (size == 2 && (offset & 3) == 3) 1400 || (size == 4 && (offset & 3) != 0)) { 1401 dprintf("PCI: can't write config for domain %d, bus %u, device %u, function %u, offset %u, size %u\n", 1402 domain, bus, device, function, offset, size); 1403 return B_ERROR; 1404 } 1405 1406 return (*info->controller->write_pci_config)(info->controller_cookie, bus, 1407 device, function, offset, size, value); 1408 } 1409 1410 1411 status_t 1412 PCI::WriteConfig(PCIDev *device, uint8 offset, uint8 size, uint32 value) 1413 { 1414 return WriteConfig(device->domain, device->bus, device->device, 1415 device->function, offset, size, value); 1416 } 1417 1418 1419 status_t 1420 PCI::FindCapability(int domain, uint8 bus, uint8 device, uint8 function, 1421 uint8 capID, uint8 *offset) 1422 { 1423 if (offset == NULL) { 1424 TRACE_CAP("PCI: FindCapability() ERROR %u:%u:%u capability %#02x offset NULL pointer\n", bus, device, function, capID); 1425 return B_BAD_VALUE; 1426 } 1427 1428 uint16 status = ReadConfig(domain, bus, device, function, PCI_status, 2); 1429 if (!(status & PCI_status_capabilities)) { 1430 TRACE_CAP("PCI: find_pci_capability ERROR %u:%u:%u capability %#02x not supported\n", bus, device, function, capID); 1431 return B_ERROR; 1432 } 1433 1434 uint8 headerType = ReadConfig(domain, bus, device, function, 1435 PCI_header_type, 1); 1436 uint8 capPointer; 1437 1438 switch (headerType & PCI_header_type_mask) { 1439 case PCI_header_type_generic: 1440 case PCI_header_type_PCI_to_PCI_bridge: 1441 capPointer = ReadConfig(domain, bus, device, function, 1442 PCI_capabilities_ptr, 1); 1443 break; 1444 case PCI_header_type_cardbus: 1445 capPointer = ReadConfig(domain, bus, device, function, 1446 PCI_capabilities_ptr_2, 1); 1447 break; 1448 default: 1449 TRACE_CAP("PCI: find_pci_capability ERROR %u:%u:%u capability %#02x unknown header type\n", bus, device, function, capID); 1450 return B_ERROR; 1451 } 1452 1453 capPointer &= ~3; 1454 if (capPointer == 0) { 1455 TRACE_CAP("PCI: find_pci_capability ERROR %u:%u:%u capability %#02x empty list\n", bus, device, function, capID); 1456 return B_NAME_NOT_FOUND; 1457 } 1458 1459 for (int i = 0; i < 48; i++) { 1460 if (ReadConfig(domain, bus, device, function, capPointer, 1) == capID) { 1461 *offset = capPointer; 1462 return B_OK; 1463 } 1464 1465 capPointer = ReadConfig(domain, bus, device, function, capPointer + 1, 1466 1); 1467 capPointer &= ~3; 1468 1469 if (capPointer == 0) 1470 return B_NAME_NOT_FOUND; 1471 } 1472 1473 TRACE_CAP("PCI: find_pci_capability ERROR %u:%u:%u capability %#02x circular list\n", bus, device, function, capID); 1474 return B_ERROR; 1475 } 1476 1477 1478 status_t 1479 PCI::FindCapability(PCIDev *device, uint8 capID, uint8 *offset) 1480 { 1481 return FindCapability(device->domain, device->bus, device->device, 1482 device->function, capID, offset); 1483 } 1484 1485 1486 PCIDev * 1487 PCI::FindDevice(int domain, uint8 bus, uint8 device, uint8 function) 1488 { 1489 return _FindDevice(fRootBus, domain, bus, device, function); 1490 } 1491 1492 1493 PCIDev * 1494 PCI::_FindDevice(PCIBus *current, int domain, uint8 bus, uint8 device, 1495 uint8 function) 1496 { 1497 if (current->domain == domain) { 1498 // search device on this bus 1499 1500 for (PCIDev *child = current->child; child != NULL; 1501 child = child->next) { 1502 if (child->bus == bus && child->device == device 1503 && child->function == function) 1504 return child; 1505 1506 if (child->child != NULL) { 1507 // search child busses 1508 PCIDev *found = _FindDevice(child->child, domain, bus, device, 1509 function); 1510 if (found != NULL) 1511 return found; 1512 } 1513 } 1514 } 1515 1516 // search other busses 1517 if (current->next != NULL) 1518 return _FindDevice(current->next, domain, bus, device, function); 1519 1520 return NULL; 1521 } 1522