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