1 /* 2 * Copyright 2006-2007, Marcus Overhagen. All rights reserved. 3 * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 4 * Copyright 2003, Marcus Overhagen. All rights reserved. 5 * 6 * Distributed under the terms of the MIT License. 7 */ 8 9 10 #include <string.h> 11 #include <KernelExport.h> 12 #define __HAIKU_PCI_BUS_MANAGER_TESTING 1 13 #include <PCI.h> 14 15 #include "util/kernel_cpp.h" 16 #include "pci_fixup.h" 17 #include "pci_priv.h" 18 #include "pci.h" 19 20 #define TRACE_CAP(x...) dprintf(x) 21 #define FLOW(x...) 22 //#define FLOW(x...) dprintf(x) 23 24 static PCI *sPCI; 25 26 // #pragma mark bus manager exports 27 28 29 status_t 30 pci_controller_add(pci_controller *controller, void *cookie) 31 { 32 return sPCI->AddController(controller, cookie); 33 } 34 35 36 long 37 pci_get_nth_pci_info(long index, pci_info *outInfo) 38 { 39 return sPCI->GetNthPciInfo(index, outInfo); 40 } 41 42 43 uint32 44 pci_read_config(uint8 virt_bus, uint8 device, uint8 function, uint8 offset, uint8 size) 45 { 46 uint8 bus; 47 int domain; 48 uint32 value; 49 50 if (sPCI->GetVirtBus(virt_bus, &domain, &bus) != B_OK) 51 return 0xffffffff; 52 53 if (sPCI->ReadPciConfig(domain, bus, device, function, offset, size, &value) != B_OK) 54 return 0xffffffff; 55 56 return value; 57 } 58 59 60 void 61 pci_write_config(uint8 virt_bus, uint8 device, uint8 function, uint8 offset, uint8 size, uint32 value) 62 { 63 uint8 bus; 64 int domain; 65 66 if (sPCI->GetVirtBus(virt_bus, &domain, &bus) != B_OK) 67 return; 68 69 sPCI->WritePciConfig(domain, bus, device, function, offset, size, value); 70 } 71 72 73 status_t 74 pci_find_capability(uchar bus, uchar device, uchar function, uchar cap_id, uchar *offset) 75 { 76 uint16 status; 77 uint8 header_type; 78 uint8 cap_ptr; 79 int i; 80 81 if (!offset) { 82 TRACE_CAP("PCI: find_pci_capability ERROR %u:%u:%u capability %#02x offset NULL pointer\n", bus, device, function, cap_id); 83 return B_BAD_VALUE; 84 } 85 86 status = pci_read_config(bus, device, function, PCI_status, 2); 87 if (!(status & PCI_status_capabilities)) { 88 TRACE_CAP("PCI: find_pci_capability ERROR %u:%u:%u capability %#02x not supported\n", bus, device, function, cap_id); 89 return B_ERROR; 90 } 91 92 header_type = pci_read_config(bus, device, function, PCI_header_type, 1); 93 switch (header_type & PCI_header_type_mask) { 94 case PCI_header_type_generic: 95 case PCI_header_type_PCI_to_PCI_bridge: 96 cap_ptr = pci_read_config(bus, device, function, PCI_capabilities_ptr, 1); 97 break; 98 case PCI_header_type_cardbus: 99 cap_ptr = pci_read_config(bus, device, function, PCI_capabilities_ptr_2, 1); 100 break; 101 default: 102 TRACE_CAP("PCI: find_pci_capability ERROR %u:%u:%u capability %#02x unknown header type\n", bus, device, function, cap_id); 103 return B_ERROR; 104 } 105 106 cap_ptr &= ~3; 107 if (!cap_ptr) { 108 TRACE_CAP("PCI: find_pci_capability ERROR %u:%u:%u capability %#02x empty list\n", bus, device, function, cap_id); 109 return B_NAME_NOT_FOUND; 110 } 111 112 for (i = 0; i < 48; i++) { 113 uint8 this_cap_id = pci_read_config(bus, device, function, cap_ptr, 1); 114 if (this_cap_id == cap_id) { 115 *offset = cap_ptr; 116 return B_OK; 117 } 118 119 cap_ptr = pci_read_config(bus, device, function, cap_ptr + 1, 1); 120 cap_ptr &= ~3; 121 122 if (!cap_ptr) 123 return B_NAME_NOT_FOUND; 124 } 125 126 TRACE_CAP("PCI: find_pci_capability ERROR %u:%u:%u capability %#02x circular list\n", bus, device, function, cap_id); 127 return B_ERROR; 128 } 129 130 131 // #pragma mark kernel debugger commands 132 133 static int 134 display_io(int argc, char **argv) 135 { 136 int32 displayWidth; 137 int32 itemSize; 138 int32 num = 1; 139 int address; 140 int i = 1, j; 141 142 switch (argc) { 143 case 3: 144 num = atoi(argv[2]); 145 case 2: 146 address = strtoul(argv[1], NULL, 0); 147 break; 148 default: 149 kprintf("usage: %s <address> [num]\n", argv[0]); 150 return 0; 151 } 152 153 // build the format string 154 if (strcmp(argv[0], "inb") == 0 || strcmp(argv[0], "in8") == 0) { 155 itemSize = 1; 156 displayWidth = 16; 157 } else if (strcmp(argv[0], "ins") == 0 || strcmp(argv[0], "in16") == 0) { 158 itemSize = 2; 159 displayWidth = 8; 160 } else if (strcmp(argv[0], "inw") == 0 || strcmp(argv[0], "in32") == 0) { 161 itemSize = 4; 162 displayWidth = 4; 163 } else { 164 kprintf("display_io called in an invalid way!\n"); 165 return 0; 166 } 167 168 for (i = 0; i < num; i++) { 169 if ((i % displayWidth) == 0) { 170 int32 displayed = min_c(displayWidth, (num-i)) * itemSize; 171 if (i != 0) 172 kprintf("\n"); 173 174 kprintf("[0x%lx] ", address + i * itemSize); 175 176 if (num > displayWidth) { 177 // make sure the spacing in the last line is correct 178 for (j = displayed; j < displayWidth * itemSize; j++) 179 kprintf(" "); 180 } 181 kprintf(" "); 182 } 183 184 switch (itemSize) { 185 case 1: 186 kprintf(" %02x", pci_read_io_8(address + i * itemSize)); 187 break; 188 case 2: 189 kprintf(" %04x", pci_read_io_16(address + i * itemSize)); 190 break; 191 case 4: 192 kprintf(" %08lx", pci_read_io_32(address + i * itemSize)); 193 break; 194 } 195 } 196 197 kprintf("\n"); 198 return 0; 199 } 200 201 202 static int 203 write_io(int argc, char **argv) 204 { 205 int32 itemSize; 206 uint32 value; 207 int address; 208 int i = 1; 209 210 if (argc < 3) { 211 kprintf("usage: %s <address> <value> [value [...]]\n", argv[0]); 212 return 0; 213 } 214 215 address = strtoul(argv[1], NULL, 0); 216 217 if (strcmp(argv[0], "outb") == 0 || strcmp(argv[0], "out8") == 0) { 218 itemSize = 1; 219 } else if (strcmp(argv[0], "outs") == 0 || strcmp(argv[0], "out16") == 0) { 220 itemSize = 2; 221 } else if (strcmp(argv[0], "outw") == 0 || strcmp(argv[0], "out32") == 0) { 222 itemSize = 4; 223 } else { 224 kprintf("write_io called in an invalid way!\n"); 225 return 0; 226 } 227 228 // skip cmd name and address 229 argv += 2; 230 argc -= 2; 231 232 for (i = 0; i < argc; i++) { 233 value = strtoul(argv[i], NULL, 0); 234 switch (itemSize) { 235 case 1: 236 pci_write_io_8(address + i * itemSize, value); 237 break; 238 case 2: 239 pci_write_io_16(address + i * itemSize, value); 240 break; 241 case 4: 242 pci_write_io_32(address + i * itemSize, value); 243 break; 244 } 245 } 246 247 return 0; 248 } 249 250 251 // #pragma mark bus manager init/uninit 252 253 status_t 254 pci_init(void) 255 { 256 sPCI = new PCI; 257 258 if (pci_io_init() != B_OK) { 259 TRACE(("PCI: pci_io_init failed\n")); 260 return B_ERROR; 261 } 262 263 add_debugger_command("inw", &display_io, "dump io words (32-bit)"); 264 add_debugger_command("in32", &display_io, "dump io words (32-bit)"); 265 add_debugger_command("ins", &display_io, "dump io shorts (16-bit)"); 266 add_debugger_command("in16", &display_io, "dump io shorts (16-bit)"); 267 add_debugger_command("inb", &display_io, "dump io bytes (8-bit)"); 268 add_debugger_command("in8", &display_io, "dump io bytes (8-bit)"); 269 270 add_debugger_command("outw", &write_io, "write io words (32-bit)"); 271 add_debugger_command("out32", &write_io, "write io words (32-bit)"); 272 add_debugger_command("outs", &write_io, "write io shorts (16-bit)"); 273 add_debugger_command("out16", &write_io, "write io shorts (16-bit)"); 274 add_debugger_command("outb", &write_io, "write io bytes (8-bit)"); 275 add_debugger_command("out8", &write_io, "write io bytes (8-bit)"); 276 277 if (pci_controller_init() != B_OK) { 278 TRACE(("PCI: pci_controller_init failed\n")); 279 return B_ERROR; 280 } 281 282 sPCI->InitDomainData(); 283 sPCI->InitBus(); 284 285 return B_OK; 286 } 287 288 289 void 290 pci_uninit(void) 291 { 292 remove_debugger_command("outw", &write_io); 293 remove_debugger_command("out32", &write_io); 294 remove_debugger_command("outs", &write_io); 295 remove_debugger_command("out16", &write_io); 296 remove_debugger_command("outb", &write_io); 297 remove_debugger_command("out8", &write_io); 298 299 remove_debugger_command("inw", &display_io); 300 remove_debugger_command("in32", &display_io); 301 remove_debugger_command("ins", &display_io); 302 remove_debugger_command("in16", &display_io); 303 remove_debugger_command("inb", &display_io); 304 remove_debugger_command("in8", &display_io); 305 306 delete sPCI; 307 } 308 309 310 // #pragma mark PCI class 311 312 PCI::PCI() 313 : fRootBus(0) 314 , fDomainCount(0) 315 , fBusEnumeration(false) 316 { 317 #if defined(__POWERPC__) || defined(__M68K__) 318 fBusEnumeration = true; 319 #endif 320 } 321 322 323 void 324 PCI::InitBus() 325 { 326 PCIBus **ppnext = &fRootBus; 327 for (int i = 0; i < fDomainCount; i++) { 328 PCIBus *bus = new PCIBus; 329 bus->next = NULL; 330 bus->parent = NULL; 331 bus->child = NULL; 332 bus->domain = i; 333 bus->bus = 0; 334 *ppnext = bus; 335 ppnext = &bus->next; 336 } 337 338 if (fBusEnumeration) { 339 for (int i = 0; i < fDomainCount; i++) { 340 EnumerateBus(i, 0); 341 } 342 } 343 344 if (1) { 345 for (int i = 0; i < fDomainCount; i++) { 346 FixupDevices(i, 0); 347 } 348 } 349 350 if (fRootBus) { 351 DiscoverBus(fRootBus); 352 RefreshDeviceInfo(fRootBus); 353 } 354 } 355 356 357 PCI::~PCI() 358 { 359 } 360 361 362 status_t 363 PCI::AddVirtBus(int domain, uint8 bus, uint8 *virt_bus) 364 { 365 if (MAX_PCI_DOMAINS != 8) 366 panic("PCI::AddVirtBus only 8 controllers supported"); 367 368 if (domain > 7) 369 panic("PCI::AddVirtBus domain %d too large", domain); 370 371 if (bus > 31) 372 panic("PCI::AddVirtBus bus %d too large", bus); 373 374 *virt_bus = (domain << 5) | bus; 375 return B_OK; 376 } 377 378 379 status_t 380 PCI::GetVirtBus(uint8 virt_bus, int *domain, uint8 *bus) 381 { 382 // XXX if you modify this, also change pci_info.cpp print_info_basic() !! 383 *domain = virt_bus >> 5; 384 *bus = virt_bus & 0x1f; 385 return B_OK; 386 } 387 388 status_t 389 PCI::AddController(pci_controller *controller, void *controller_cookie) 390 { 391 if (fDomainCount == MAX_PCI_DOMAINS) 392 return B_ERROR; 393 394 fDomainData[fDomainCount].controller = controller; 395 fDomainData[fDomainCount].controller_cookie = controller_cookie; 396 397 // initialized later to avoid call back into controller at this point 398 fDomainData[fDomainCount].max_bus_devices = -1; 399 400 fDomainCount++; 401 return B_OK; 402 } 403 404 void 405 PCI::InitDomainData() 406 { 407 for (int i = 0; i < fDomainCount; i++) { 408 int32 count; 409 status_t status; 410 411 status = (*fDomainData[i].controller->get_max_bus_devices)(fDomainData[i].controller_cookie, &count); 412 fDomainData[i].max_bus_devices = (status == B_OK) ? count : 0; 413 } 414 } 415 416 417 domain_data * 418 PCI::GetDomainData(int domain) 419 { 420 if (domain < 0 || domain >= fDomainCount) 421 return NULL; 422 423 return &fDomainData[domain]; 424 } 425 426 427 status_t 428 PCI::GetNthPciInfo(long index, pci_info *outInfo) 429 { 430 long curindex = 0; 431 if (!fRootBus) 432 return B_ERROR; 433 return GetNthPciInfo(fRootBus, &curindex, index, outInfo); 434 } 435 436 437 status_t 438 PCI::GetNthPciInfo(PCIBus *bus, long *curindex, long wantindex, pci_info *outInfo) 439 { 440 // maps tree structure to linear indexed view 441 PCIDev *dev = bus->child; 442 while (dev) { 443 if (*curindex == wantindex) { 444 *outInfo = dev->info; 445 return B_OK; 446 } 447 *curindex += 1; 448 if (dev->child && B_OK == GetNthPciInfo(dev->child, curindex, wantindex, outInfo)) 449 return B_OK; 450 dev = dev->next; 451 } 452 453 if (bus->next) 454 return GetNthPciInfo(bus->next, curindex, wantindex, outInfo); 455 456 return B_ERROR; 457 } 458 459 void 460 PCI::EnumerateBus(int domain, uint8 bus, uint8 *subordinate_bus) 461 { 462 TRACE(("PCI: EnumerateBus: domain %u, bus %u\n", domain, bus)); 463 464 int max_bus_devices = GetDomainData(domain)->max_bus_devices; 465 466 // step 1: disable all bridges on this bus 467 for (int dev = 0; dev < max_bus_devices; dev++) { 468 uint16 vendor_id = ReadPciConfig(domain, bus, dev, 0, PCI_vendor_id, 2); 469 if (vendor_id == 0xffff) 470 continue; 471 472 uint8 type = ReadPciConfig(domain, bus, dev, 0, PCI_header_type, 1); 473 int nfunc = (type & PCI_multifunction) ? 8 : 1; 474 for (int func = 0; func < nfunc; func++) { 475 uint16 device_id = ReadPciConfig(domain, bus, dev, func, PCI_device_id, 2); 476 if (device_id == 0xffff) 477 continue; 478 479 uint8 base_class = ReadPciConfig(domain, bus, dev, func, PCI_class_base, 1); 480 uint8 sub_class = ReadPciConfig(domain, bus, dev, func, PCI_class_sub, 1); 481 if (base_class != PCI_bridge || sub_class != PCI_pci) 482 continue; 483 484 TRACE(("PCI: found PCI-PCI bridge: domain %u, bus %u, dev %u, func %u\n", domain, bus, dev, func)); 485 TRACE(("PCI: original settings: pcicmd %04lx, primary-bus %lu, secondary-bus %lu, subordinate-bus %lu\n", 486 ReadPciConfig(domain, bus, dev, func, PCI_command, 2), 487 ReadPciConfig(domain, bus, dev, func, PCI_primary_bus, 1), 488 ReadPciConfig(domain, bus, dev, func, PCI_secondary_bus, 1), 489 ReadPciConfig(domain, bus, dev, func, PCI_subordinate_bus, 1))); 490 491 // disable decoding 492 uint16 pcicmd; 493 pcicmd = ReadPciConfig(domain, bus, dev, func, PCI_command, 2); 494 pcicmd &= ~(PCI_command_io | PCI_command_memory | PCI_command_master); 495 WritePciConfig(domain, bus, dev, func, PCI_command, 2, pcicmd); 496 497 // disable busses 498 WritePciConfig(domain, bus, dev, func, PCI_primary_bus, 1, 0); 499 WritePciConfig(domain, bus, dev, func, PCI_secondary_bus, 1, 0); 500 WritePciConfig(domain, bus, dev, func, PCI_subordinate_bus, 1, 0); 501 502 TRACE(("PCI: disabled settings: pcicmd %04lx, primary-bus %lu, secondary-bus %lu, subordinate-bus %lu\n", 503 ReadPciConfig(domain, bus, dev, func, PCI_command, 2), 504 ReadPciConfig(domain, bus, dev, func, PCI_primary_bus, 1), 505 ReadPciConfig(domain, bus, dev, func, PCI_secondary_bus, 1), 506 ReadPciConfig(domain, bus, dev, func, PCI_subordinate_bus, 1))); 507 } 508 } 509 510 uint8 last_used_bus_number = bus; 511 512 // step 2: assign busses to all bridges, and enable them again 513 for (int dev = 0; dev < max_bus_devices; dev++) { 514 uint16 vendor_id = ReadPciConfig(domain, bus, dev, 0, PCI_vendor_id, 2); 515 if (vendor_id == 0xffff) 516 continue; 517 518 uint8 type = ReadPciConfig(domain, bus, dev, 0, PCI_header_type, 1); 519 int nfunc = (type & PCI_multifunction) ? 8 : 1; 520 for (int func = 0; func < nfunc; func++) { 521 uint16 device_id = ReadPciConfig(domain, bus, dev, func, PCI_device_id, 2); 522 if (device_id == 0xffff) 523 continue; 524 525 uint8 base_class = ReadPciConfig(domain, bus, dev, func, PCI_class_base, 1); 526 uint8 sub_class = ReadPciConfig(domain, bus, dev, func, PCI_class_sub, 1); 527 if (base_class != PCI_bridge || sub_class != PCI_pci) 528 continue; 529 530 TRACE(("PCI: configuring PCI-PCI bridge: domain %u, bus %u, dev %u, func %u\n", 531 domain, bus, dev, func)); 532 533 // open Scheunentor for enumerating the bus behind the bridge 534 WritePciConfig(domain, bus, dev, func, PCI_primary_bus, 1, bus); 535 WritePciConfig(domain, bus, dev, func, PCI_secondary_bus, 1, last_used_bus_number + 1); 536 WritePciConfig(domain, bus, dev, func, PCI_subordinate_bus, 1, 255); 537 538 // enable decoding (too early here?) 539 uint16 pcicmd; 540 pcicmd = ReadPciConfig(domain, bus, dev, func, PCI_command, 2); 541 pcicmd |= PCI_command_io | PCI_command_memory | PCI_command_master; 542 WritePciConfig(domain, bus, dev, func, PCI_command, 2, pcicmd); 543 544 TRACE(("PCI: probing settings: pcicmd %04lx, primary-bus %lu, secondary-bus %lu, subordinate-bus %lu\n", 545 ReadPciConfig(domain, bus, dev, func, PCI_command, 2), 546 ReadPciConfig(domain, bus, dev, func, PCI_primary_bus, 1), 547 ReadPciConfig(domain, bus, dev, func, PCI_secondary_bus, 1), 548 ReadPciConfig(domain, bus, dev, func, PCI_subordinate_bus, 1))); 549 550 // enumerate bus 551 EnumerateBus(domain, last_used_bus_number + 1, &last_used_bus_number); 552 553 // close Scheunentor 554 WritePciConfig(domain, bus, dev, func, PCI_subordinate_bus, 1, last_used_bus_number); 555 556 TRACE(("PCI: configured settings: pcicmd %04lx, primary-bus %lu, secondary-bus %lu, subordinate-bus %lu\n", 557 ReadPciConfig(domain, bus, dev, func, PCI_command, 2), 558 ReadPciConfig(domain, bus, dev, func, PCI_primary_bus, 1), 559 ReadPciConfig(domain, bus, dev, func, PCI_secondary_bus, 1), 560 ReadPciConfig(domain, bus, dev, func, PCI_subordinate_bus, 1))); 561 } 562 } 563 if (subordinate_bus) 564 *subordinate_bus = last_used_bus_number; 565 566 TRACE(("PCI: EnumerateBus done: domain %u, bus %u, last used bus number %u\n", domain, bus, last_used_bus_number)); 567 } 568 569 570 void 571 PCI::FixupDevices(int domain, uint8 bus) 572 { 573 FLOW("PCI: FixupDevices domain %u, bus %u\n", domain, bus); 574 575 int maxBusDevices = GetDomainData(domain)->max_bus_devices; 576 577 for (int dev = 0; dev < maxBusDevices; dev++) { 578 uint16 vendorId = ReadPciConfig(domain, bus, dev, 0, PCI_vendor_id, 2); 579 if (vendorId == 0xffff) 580 continue; 581 582 uint8 type = ReadPciConfig(domain, bus, dev, 0, PCI_header_type, 1); 583 int nfunc = (type & PCI_multifunction) ? 8 : 1; 584 for (int func = 0; func < nfunc; func++) { 585 uint16 deviceId = ReadPciConfig(domain, bus, dev, func, PCI_device_id, 2); 586 if (deviceId == 0xffff) 587 continue; 588 589 pci_fixup_device(this, domain, bus, dev, func); 590 591 uint8 base_class = ReadPciConfig(domain, bus, dev, func, PCI_class_base, 1); 592 if (base_class != PCI_bridge) 593 continue; 594 uint8 sub_class = ReadPciConfig(domain, bus, dev, func, PCI_class_sub, 1); 595 if (sub_class != PCI_pci) 596 continue; 597 598 int busBehindBridge = ReadPciConfig(domain, bus, dev, func, PCI_secondary_bus, 1); 599 600 FixupDevices(domain, busBehindBridge); 601 } 602 } 603 } 604 605 606 void 607 PCI::DiscoverBus(PCIBus *bus) 608 { 609 FLOW("PCI: DiscoverBus, domain %u, bus %u\n", bus->domain, bus->bus); 610 611 int max_bus_devices = GetDomainData(bus->domain)->max_bus_devices; 612 613 for (int dev = 0; dev < max_bus_devices; dev++) { 614 uint16 vendor_id = ReadPciConfig(bus->domain, bus->bus, dev, 0, PCI_vendor_id, 2); 615 if (vendor_id == 0xffff) 616 continue; 617 618 uint8 type = ReadPciConfig(bus->domain, bus->bus, dev, 0, PCI_header_type, 1); 619 int nfunc = (type & PCI_multifunction) ? 8 : 1; 620 for (int func = 0; func < nfunc; func++) 621 DiscoverDevice(bus, dev, func); 622 } 623 624 if (bus->next) 625 DiscoverBus(bus->next); 626 } 627 628 629 void 630 PCI::DiscoverDevice(PCIBus *bus, uint8 dev, uint8 func) 631 { 632 FLOW("PCI: DiscoverDevice, domain %u, bus %u, dev %u, func %u\n", bus->domain, bus->bus, dev, func); 633 634 uint16 device_id = ReadPciConfig(bus->domain, bus->bus, dev, func, PCI_device_id, 2); 635 if (device_id == 0xffff) 636 return; 637 638 PCIDev *newdev = CreateDevice(bus, dev, func); 639 640 uint8 base_class = ReadPciConfig(bus->domain, bus->bus, dev, func, PCI_class_base, 1); 641 uint8 sub_class = ReadPciConfig(bus->domain, bus->bus, dev, func, PCI_class_sub, 1); 642 if (base_class == PCI_bridge && sub_class == PCI_pci) { 643 uint8 secondary_bus = ReadPciConfig(bus->domain, bus->bus, dev, func, PCI_secondary_bus, 1); 644 PCIBus *newbus = CreateBus(newdev, bus->domain, secondary_bus); 645 DiscoverBus(newbus); 646 } 647 } 648 649 650 PCIBus * 651 PCI::CreateBus(PCIDev *parent, int domain, uint8 bus) 652 { 653 PCIBus *newbus = new PCIBus; 654 newbus->next = NULL; 655 newbus->parent = parent; 656 newbus->child = NULL; 657 newbus->domain = domain; 658 newbus->bus = bus; 659 660 // append 661 parent->child = newbus; 662 663 return newbus; 664 } 665 666 667 PCIDev * 668 PCI::CreateDevice(PCIBus *parent, uint8 dev, uint8 func) 669 { 670 FLOW("PCI: CreateDevice, domain %u, bus %u, dev %u, func %u:\n", parent->domain, parent->bus, dev, func); 671 672 PCIDev *newdev = new PCIDev; 673 newdev->next = NULL; 674 newdev->parent = parent; 675 newdev->child = NULL; 676 newdev->domain = parent->domain; 677 newdev->bus = parent->bus; 678 newdev->dev = dev; 679 newdev->func = func; 680 681 ReadPciBasicInfo(newdev); 682 683 FLOW("PCI: CreateDevice, vendor 0x%04x, device 0x%04x, class_base 0x%02x, class_sub 0x%02x\n", 684 newdev->info.vendor_id, newdev->info.device_id, newdev->info.class_base, newdev->info.class_sub); 685 686 // append 687 if (parent->child == 0) { 688 parent->child = newdev; 689 } else { 690 PCIDev *sub = parent->child; 691 while (sub->next) 692 sub = sub->next; 693 sub->next = newdev; 694 } 695 696 return newdev; 697 } 698 699 700 uint32 701 PCI::BarSize(uint32 bits, uint32 mask) 702 { 703 bits &= mask; 704 if (!bits) 705 return 0; 706 uint32 size = 1; 707 while (!(bits & size)) 708 size <<= 1; 709 return size; 710 } 711 712 713 void 714 PCI::GetBarInfo(PCIDev *dev, uint8 offset, uint32 *address, uint32 *size, uint8 *flags) 715 { 716 uint32 oldvalue = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4); 717 WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4, 0xffffffff); 718 uint32 newvalue = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4); 719 WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4, oldvalue); 720 721 *address = oldvalue & PCI_address_memory_32_mask; 722 if (size) 723 *size = BarSize(newvalue, PCI_address_memory_32_mask); 724 if (flags) 725 *flags = newvalue & 0xf; 726 } 727 728 729 void 730 PCI::GetRomBarInfo(PCIDev *dev, uint8 offset, uint32 *address, uint32 *size, uint8 *flags) 731 { 732 uint32 oldvalue = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4); 733 WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4, 0xfffffffe); // LSB must be 0 734 uint32 newvalue = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4); 735 WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4, oldvalue); 736 737 *address = oldvalue & PCI_rom_address_mask; 738 if (size) 739 *size = BarSize(newvalue, PCI_rom_address_mask); 740 if (flags) 741 *flags = newvalue & 0xf; 742 } 743 744 745 void 746 PCI::ReadPciBasicInfo(PCIDev *dev) 747 { 748 uint8 virt_bus; 749 750 if (AddVirtBus(dev->domain, dev->bus, &virt_bus) != B_OK) { 751 dprintf("PCI: AddVirtBus failed, domain %u, bus %u\n", dev->domain, dev->bus); 752 return; 753 } 754 755 dev->info.vendor_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_vendor_id, 2); 756 dev->info.device_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_device_id, 2); 757 dev->info.bus = virt_bus; 758 dev->info.device = dev->dev; 759 dev->info.function = dev->func; 760 dev->info.revision = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_revision, 1); 761 dev->info.class_api = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_class_api, 1); 762 dev->info.class_sub = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_class_sub, 1); 763 dev->info.class_base = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_class_base, 1); 764 dev->info.line_size = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_line_size, 1); 765 dev->info.latency = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_latency, 1); 766 // BeOS does not mask off the multifunction bit, developer must use (header_type & PCI_header_type_mask) 767 dev->info.header_type = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_header_type, 1); 768 dev->info.bist = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_bist, 1); 769 dev->info.reserved = 0; 770 } 771 772 773 void 774 PCI::ReadPciHeaderInfo(PCIDev *dev) 775 { 776 switch (dev->info.header_type & PCI_header_type_mask) { 777 case PCI_header_type_generic: 778 { 779 // disable PCI device address decoding (io and memory) while BARs are modified 780 uint16 pcicmd = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_command, 2); 781 WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_command, 2, pcicmd & ~(PCI_command_io | PCI_command_memory)); 782 783 // get BAR size infos 784 GetRomBarInfo(dev, PCI_rom_base, &dev->info.u.h0.rom_base_pci, &dev->info.u.h0.rom_size); 785 for (int i = 0; i < 6; i++) { 786 GetBarInfo(dev, PCI_base_registers + 4*i, 787 &dev->info.u.h0.base_registers_pci[i], 788 &dev->info.u.h0.base_register_sizes[i], 789 &dev->info.u.h0.base_register_flags[i]); 790 } 791 792 // restore PCI device address decoding 793 WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_command, 2, pcicmd); 794 795 dev->info.u.h0.rom_base = (ulong)pci_ram_address((void *)dev->info.u.h0.rom_base_pci); 796 for (int i = 0; i < 6; i++) { 797 dev->info.u.h0.base_registers[i] = (ulong)pci_ram_address((void *)dev->info.u.h0.base_registers_pci[i]); 798 } 799 800 dev->info.u.h0.cardbus_cis = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_cardbus_cis, 4); 801 dev->info.u.h0.subsystem_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_subsystem_id, 2); 802 dev->info.u.h0.subsystem_vendor_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_subsystem_vendor_id, 2); 803 dev->info.u.h0.interrupt_line = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_interrupt_line, 1); 804 dev->info.u.h0.interrupt_pin = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_interrupt_pin, 1); 805 dev->info.u.h0.min_grant = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_min_grant, 1); 806 dev->info.u.h0.max_latency = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_max_latency, 1); 807 break; 808 } 809 810 case PCI_header_type_PCI_to_PCI_bridge: 811 { 812 // disable PCI device address decoding (io and memory) while BARs are modified 813 uint16 pcicmd = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_command, 2); 814 WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_command, 2, pcicmd & ~(PCI_command_io | PCI_command_memory)); 815 816 GetRomBarInfo(dev, PCI_bridge_rom_base, &dev->info.u.h1.rom_base_pci); 817 for (int i = 0; i < 2; i++) { 818 GetBarInfo(dev, PCI_base_registers + 4*i, 819 &dev->info.u.h1.base_registers_pci[i], 820 &dev->info.u.h1.base_register_sizes[i], 821 &dev->info.u.h1.base_register_flags[i]); 822 } 823 824 // restore PCI device address decoding 825 WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_command, 2, pcicmd); 826 827 dev->info.u.h1.rom_base = (ulong)pci_ram_address((void *)dev->info.u.h1.rom_base_pci); 828 for (int i = 0; i < 2; i++) { 829 dev->info.u.h1.base_registers[i] = (ulong)pci_ram_address((void *)dev->info.u.h1.base_registers_pci[i]); 830 } 831 832 dev->info.u.h1.primary_bus = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_primary_bus, 1); 833 dev->info.u.h1.secondary_bus = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_secondary_bus, 1); 834 dev->info.u.h1.subordinate_bus = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_subordinate_bus, 1); 835 dev->info.u.h1.secondary_latency = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_secondary_latency, 1); 836 dev->info.u.h1.io_base = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_io_base, 1); 837 dev->info.u.h1.io_limit = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_io_limit, 1); 838 dev->info.u.h1.secondary_status = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_secondary_status, 2); 839 dev->info.u.h1.memory_base = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_memory_base, 2); 840 dev->info.u.h1.memory_limit = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_memory_limit, 2); 841 dev->info.u.h1.prefetchable_memory_base = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_prefetchable_memory_base, 2); 842 dev->info.u.h1.prefetchable_memory_limit = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_prefetchable_memory_limit, 2); 843 dev->info.u.h1.prefetchable_memory_base_upper32 = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_prefetchable_memory_base_upper32, 4); 844 dev->info.u.h1.prefetchable_memory_limit_upper32 = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_prefetchable_memory_limit_upper32, 4); 845 dev->info.u.h1.io_base_upper16 = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_io_base_upper16, 2); 846 dev->info.u.h1.io_limit_upper16 = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_io_limit_upper16, 2); 847 dev->info.u.h1.interrupt_line = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_interrupt_line, 1); 848 dev->info.u.h1.interrupt_pin = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_interrupt_pin, 1); 849 dev->info.u.h1.bridge_control = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_bridge_control, 2); 850 dev->info.u.h1.subsystem_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_sub_device_id_1, 2); 851 dev->info.u.h1.subsystem_vendor_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_sub_vendor_id_1, 2); 852 break; 853 } 854 855 case PCI_header_type_cardbus: 856 { 857 // for testing only, not final: 858 dev->info.u.h2.subsystem_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_sub_device_id_2, 2); 859 dev->info.u.h2.subsystem_vendor_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_sub_vendor_id_2, 2); 860 dev->info.u.h2.primary_bus = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_primary_bus_2, 1); 861 dev->info.u.h2.secondary_bus = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_secondary_bus_2, 1); 862 dev->info.u.h2.subordinate_bus = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_subordinate_bus_2, 1); 863 dev->info.u.h2.secondary_latency = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_secondary_latency_2, 1); 864 dev->info.u.h2.reserved = 0; 865 dev->info.u.h2.memory_base = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_memory_base0_2, 4); 866 dev->info.u.h2.memory_limit = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_memory_limit0_2, 4); 867 dev->info.u.h2.memory_base_upper32 = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_memory_base1_2, 4); 868 dev->info.u.h2.memory_limit_upper32 = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_memory_limit1_2, 4); 869 dev->info.u.h2.io_base = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_io_base0_2, 4); 870 dev->info.u.h2.io_limit = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_io_limit0_2, 4); 871 dev->info.u.h2.io_base_upper32 = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_io_base1_2, 4); 872 dev->info.u.h2.io_limit_upper32 = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_io_limit1_2, 4); 873 dev->info.u.h2.secondary_status = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_secondary_status_2, 2); 874 dev->info.u.h2.bridge_control = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_bridge_control_2, 1); 875 break; 876 } 877 878 default: 879 TRACE(("PCI: Header type unknown (0x%02x)\n", dev->info.header_type)); 880 break; 881 } 882 } 883 884 885 void 886 PCI::RefreshDeviceInfo(PCIBus *bus) 887 { 888 for (PCIDev *dev = bus->child; dev; dev = dev->next) { 889 ReadPciBasicInfo(dev); 890 ReadPciHeaderInfo(dev); 891 if (dev->child) 892 RefreshDeviceInfo(dev->child); 893 } 894 895 if (bus->next) 896 RefreshDeviceInfo(bus->next); 897 } 898 899 900 status_t 901 PCI::ReadPciConfig(int domain, uint8 bus, uint8 device, uint8 function, 902 uint8 offset, uint8 size, uint32 *value) 903 { 904 domain_data *info; 905 info = GetDomainData(domain); 906 if (!info) 907 return B_ERROR; 908 909 if (device > (info->max_bus_devices - 1) 910 || function > 7 911 || (size != 1 && size != 2 && size != 4) 912 || (size == 2 && (offset & 3) == 3) 913 || (size == 4 && (offset & 3) != 0)) { 914 dprintf("PCI: can't read config for domain %d, bus %u, device %u, function %u, offset %u, size %u\n", 915 domain, bus, device, function, offset, size); 916 return B_ERROR; 917 } 918 919 status_t status; 920 status = (*info->controller->read_pci_config)(info->controller_cookie, 921 bus, device, function, 922 offset, size, value); 923 return status; 924 } 925 926 927 uint32 928 PCI::ReadPciConfig(int domain, uint8 bus, uint8 device, uint8 function, 929 uint8 offset, uint8 size) 930 { 931 uint32 value; 932 933 if (ReadPciConfig(domain, bus, device, function, offset, size, &value) != B_OK) 934 return 0xffffffff; 935 936 return value; 937 } 938 939 940 status_t 941 PCI::WritePciConfig(int domain, uint8 bus, uint8 device, uint8 function, 942 uint8 offset, uint8 size, uint32 value) 943 { 944 domain_data *info; 945 info = GetDomainData(domain); 946 if (!info) 947 return B_ERROR; 948 949 if (device > (info->max_bus_devices - 1) 950 || function > 7 951 || (size != 1 && size != 2 && size != 4) 952 || (size == 2 && (offset & 3) == 3) 953 || (size == 4 && (offset & 3) != 0)) { 954 dprintf("PCI: can't write config for domain %d, bus %u, device %u, function %u, offset %u, size %u\n", 955 domain, bus, device, function, offset, size); 956 return B_ERROR; 957 } 958 959 status_t status; 960 status = (*info->controller->write_pci_config)(info->controller_cookie, 961 bus, device, function, 962 offset, size, value); 963 return status; 964 } 965 966