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