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