1/* 2 * Copyright (c) 2004-2005 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 2.0 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22 23#include <IOKit/assert.h> 24#include <IOKit/IODeviceTreeSupport.h> 25#include <IOKit/IOPlatformExpert.h> 26#include <IOKit/pci/IOPCIPrivate.h> 27#include <IOKit/pci/IOPCIConfigurator.h> 28#if ACPI_SUPPORT 29#include <IOKit/acpi/IOACPIPlatformDevice.h> 30#endif 31#include <libkern/sysctl.h> 32 33__BEGIN_DECLS 34 35#if defined(__i386__) || defined(__x86_64__) 36 37#include <i386/cpuid.h> 38#include <i386/cpu_number.h> 39 40extern void mp_rendezvous_no_intrs( 41 void (*action_func)(void *), 42 void *arg); 43 44#else /* defined(__i386__) || defined(__x86_64__) */ 45 46#define NO_RENDEZVOUS_KERNEL 1 47#define cpu_number() (0) 48 49#define KB (1024ULL) 50#define MB (1024ULL*KB) 51#define GB (1024ULL*MB) 52 53#endif /* ! defined(__i386__) || defined(__x86_64__) */ 54 55__END_DECLS 56 57#define PFM64_SIZE (2ULL*GB) 58#define MAX_BAR_SIZE (1ULL*GB) 59// NPHYSMAP 60// #define PFM64_MAX (100ULL*GB) 61 62#define DLOGC(configurator, fmt, args...) \ 63 do { \ 64 if ((configurator->fFlags & kIOPCIConfiguratorIOLog) && !ml_at_interrupt_context()) \ 65 IOLog(fmt, ## args); \ 66 if (configurator->fFlags & kIOPCIConfiguratorKPrintf) \ 67 kprintf(fmt, ## args); \ 68 } while(0) 69 70 71#define DLOG(fmt, args...) DLOGC(this, fmt, ## args); 72#define DLOGI(fmt, args...) do { if (dolog) DLOG(fmt, ## args); } while (0); 73 74#define DLOG_RANGE(name, range) if (range) { \ 75 DLOG(name": start/size = 0x%08llx:0x%08llx,0x%08llx\n", \ 76 range->start, \ 77 range->size, \ 78 range->proposedSize) } 79 80#define DLOGI_RANGE(name, range) do { if (dolog) DLOG_RANGE(name, range); } while (0); 81 82static const char * gPCIResourceTypeName[kIOPCIResourceTypeCount] = 83{ 84 "MEM", "PFM", "I/O", "BUS" 85}; 86 87#define BRN(type) ((type) + kIOPCIRangeBridgeMemory) 88 89 90#define D() "[i%x]%u:%u:%u(0x%x:0x%x)" 91#define DEVICE_IDENT(device) \ 92 device->id, \ 93 PCI_ADDRESS_TUPLE(device), \ 94 (device->vendorProduct & 0xffff), \ 95 (device->vendorProduct >> 16) 96 97#define B() "[i%x]%u:%u:%u(%u:%u)" 98#define BRIDGE_IDENT(bridge) \ 99 bridge->id, PCI_ADDRESS_TUPLE(bridge), bridge->secBusNum, bridge->subBusNum 100 101 102static const IOPCIScalar minBridgeAlignments[kIOPCIResourceTypeCount] = { 103 kPCIBridgeMemoryAlignment, kPCIBridgeMemoryAlignment, 104 kPCIBridgeIOAlignment, kPCIBridgeBusNumberAlignment 105}; 106 107static const IOPCIScalar maxBridgeAddressDefault[kIOPCIResourceTypeCount] = { 108 0xFFFFFFFF, 0xFFFFFFFF, 109 0xFFFF, 0xFF 110}; 111 112// Never allocate ranges below 1K I/O and 1MB Memory to avoid 113// stomping on legacy ISA, and VGA ranges. 114static const IOPCIScalar minBARAddressDefault[kIOPCIResourceTypeCount] = { 115 kPCIBridgeMemoryAlignment, kPCIBridgeMemoryAlignment, 116 0x400, 0 117}; 118 119static UInt8 IOPCIIsHotplugPort(IORegistryEntry * bridgeDevice); 120#if ACPI_SUPPORT 121static IOACPIPlatformDevice * IOPCICopyACPIDevice(IORegistryEntry * device); 122#endif 123 124/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 125 126#define CLASS IOPCIConfigurator 127#define super IOService 128 129OSDefineMetaClassAndStructors( IOPCIConfigurator, IOService ) 130 131/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 132 133bool CLASS::init(IOWorkLoop * wl, uint32_t flags) 134{ 135 if (!super::init()) return false; 136 137 fWL = wl; 138 fFlags = flags; 139 140 // Fetch global resources 141 if (!createRoot()) return false; 142 143 return (true); 144} 145 146IOWorkLoop * CLASS::getWorkLoop() const 147{ 148 return (fWL); 149} 150 151/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 152 153IOPCIConfigEntry * CLASS::findEntry(IOPCIAddressSpace space) 154{ 155 IOPCIConfigEntry * child; 156 IOPCIConfigEntry * entry; 157 IOPCIConfigEntry * next; 158 uint8_t bus, dev, func; 159 160 bus = space.s.busNum; 161 dev = space.s.deviceNum; 162 func = space.s.functionNum; 163 next = fRoot; 164 child = NULL; 165 166 while ((entry = next)) 167 { 168 next = NULL; 169 for (child = entry->child; child; child = child->peer) 170 { 171 if (bus == entry->secBusNum) 172 { 173 if (dev != child->space.s.deviceNum) continue; 174 if (func != child->space.s.functionNum) continue; 175 break; 176 } 177 if (!child->isBridge) continue; 178 else if (bus < child->secBusNum) continue; 179 else if (bus > child->subBusNum) continue; 180 next = child; 181 break; 182 } 183 } 184 185 return (child); 186} 187/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 188 189IOReturn CLASS::configOp(IOService * device, uintptr_t op, void * arg, void * arg2) 190{ 191 IOReturn ret = kIOReturnUnsupported; 192 IOPCIConfigEntry * entry = NULL; 193 IOPCIDevice * pciDevice; 194 195 if ((pciDevice = OSDynamicCast(IOPCIDevice, device))) 196 entry = pciDevice->reserved->configEntry; 197 198 switch (op) 199 { 200 case kConfigOpAddHostBridge: 201 ret = addHostBridge(OSDynamicCast(IOPCIBridge, device)); 202 return (ret); 203 break; 204 205 case kConfigOpGetState: 206 if (!entry) *((uint32_t *) arg) = kPCIDeviceStateDead; 207 else 208 { 209 *((uint32_t *) arg) = entry->deviceState; 210 } 211 ret = kIOReturnSuccess; 212 return (ret); 213 break; 214 215 216 case kConfigOpFindEntry: 217 entry = findEntry(*((IOPCIAddressSpace *) arg2)); 218 *((void **) arg) = NULL; 219 if (!entry || !entry->dtNub) ret = kIOReturnNotFound; 220 else 221 { 222 entry->dtNub->retain(); 223 *((void **) arg) = entry->dtNub; 224 ret = kIOReturnSuccess; 225 } 226 return (ret); 227 break; 228 } 229 230 if (!entry) return (kIOReturnBadArgument); 231 232 switch (op) 233 { 234 case kConfigOpNeedsScan: 235 entry->deviceState &= ~kPCIDeviceStateScanned; 236 ret = kIOReturnSuccess; 237 break; 238 239 case kConfigOpShadowed: 240 entry->configShadow = (uint8_t *) arg; 241 ret = kIOReturnSuccess; 242 if (!arg) break; 243 /* fall thru */ 244 case kConfigOpPaused: 245 DLOG("kConfigOpPaused%s at "D()"\n", 246 op == kConfigOpShadowed ? "(shadowed)" : "", DEVICE_IDENT(entry)); 247 248 if (kPCIDeviceStateRequestPause & entry->deviceState) 249 { 250 entry->deviceState &= ~kPCIDeviceStateRequestPause; 251 entry->deviceState &= ~kPCIDeviceStateAllocated; 252 fWaitingPause--; 253 } 254 if (!(kPCIDeviceStatePaused & entry->deviceState)) 255 { 256#if 0 257 uint32_t reg32; 258 reg32 = entry->pausedCommand = configRead16(entry, kIOPCIConfigCommand); 259 reg32 &= ~(kIOPCICommandIOSpace 260 | kIOPCICommandMemorySpace 261 | kIOPCICommandBusMaster); 262 reg32 |= kIOPCICommandInterruptDisable; 263 configWrite16(entry, kIOPCIConfigCommand, reg32); 264 265 if (entry->isBridge) 266 { 267 entry->rangeBaseChanges |= (1 << kIOPCIRangeBridgeBusNumber); 268 reg32 = configRead32(entry, kPCI2PCIPrimaryBus); 269 reg32 &= ~0x00ffffff; 270 configWrite32(entry, kPCI2PCIPrimaryBus, reg32); 271 } 272#endif 273 entry->deviceState |= kPCIDeviceStatePaused; 274 } 275 ret = kIOReturnSuccess; 276 break; 277 278 case kConfigOpUnpaused: 279 if (kPCIDeviceStatePaused & entry->deviceState) 280 { 281 DLOG("kConfigOpUnpaused at "D()"\n", DEVICE_IDENT(entry)); 282// configWrite16(entry, kIOPCIConfigCommand, entry->pausedCommand); 283 entry->deviceState &= ~kPCIDeviceStatePaused; 284 } 285 ret = kIOReturnSuccess; 286 break; 287 288 case kConfigOpTestPause: 289 ret = kIOReturnSuccess; 290 break; 291 292 case kConfigOpScan: 293 if (kPCIDeviceStateScanned & entry->deviceState) 294 { 295 *((void **)arg) = NULL; 296 ret = kIOReturnSuccess; 297 return (ret); 298 break; 299 } 300 301 // always reset regs due to hotp interrupt clearing memory ranges 302 entry->rangeBaseChanges |= ((1 << kIOPCIRangeBridgeMemory) 303 | (1 << kIOPCIRangeBridgePFMemory)); 304 305 // fall thru 306 307 case kConfigOpRealloc: 308 309 DLOG("[ PCI configuration begin ]\n"); 310 fChangedServices = OSSet::withCapacity(8); 311 configure(0); 312 DLOG("[ PCI configuration end, bridges %d, devices %d, changed %d, waiting %d ]\n", 313 fBridgeCount, fDeviceCount, fChangedServices->getCount(), fWaitingPause); 314 315 if (arg) 316 { 317 *((void **)arg) = fChangedServices; 318 } 319 else 320 { 321 fChangedServices->release(); 322 } 323 fChangedServices = 0; 324 ret = kIOReturnSuccess; 325 return (ret); 326 break; 327 328 329 case kConfigOpEject: 330 entry->deviceState |= kPCIDeviceStateEjected; 331 ret = kIOReturnSuccess; 332 break; 333 334 case kConfigOpKill: 335 entry->deviceState |= kPCIDeviceStateToKill; 336 ret = kIOReturnSuccess; 337 break; 338 339 case kConfigOpTerminated: 340 DLOG("kConfigOpTerminated at "D()"\n", DEVICE_IDENT(entry)); 341 342// if (0x590111c1 != entry->vendorProduct) 343// if (!(kPCIDeviceStateEjected & entry->deviceState)) 344 { 345 bridgeRemoveChild(entry->parent, entry, 346 kIOPCIRangeAllBarsMask, kIOPCIRangeAllBarsMask, NULL); 347 } 348 ret = kIOReturnSuccess; 349 break; 350 351 case kConfigOpProtect: 352 entry->deviceState = (entry->deviceState & ~(kPCIDeviceStateConfigRProtect|kPCIDeviceStateConfigWProtect)) 353 | (*((uint32_t *) arg)); 354 DLOG("kConfigOpProtect at "D()" prot %x\n", 355 DEVICE_IDENT(entry), *((uint32_t *) arg)); 356 357 ret = kIOReturnSuccess; 358 break; 359 } 360 361 return (ret); 362} 363 364/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 365 366#if ACPI_SUPPORT 367void CLASS::removeFixedRanges(IORegistryEntry * root) 368{ 369 IORegistryIterator * iter; 370 IOService * service; 371 OSOrderedSet * all; 372 OSArray * array; 373 IOMemoryDescriptor * mem; 374 uint32_t idx, type; 375 IOPCIRange * range; 376 uint64_t start, size; 377 bool ok; 378 379 range = NULL; 380 iter = IORegistryIterator::iterateOver(root, gIOPCIACPIPlane, kIORegistryIterateRecursively); 381 if (iter) 382 { 383 all = iter->iterateAll(); 384 iter->release(); 385 if (all) 386 { 387 for ( ; (service = (IOService *) all->getFirstObject()); all->removeObject(service)) 388 { 389 array = service->getDeviceMemory(); 390 if (!array) 391 continue; 392 for (idx = 0; (mem = (IOMemoryDescriptor *) array->getObject(idx)); idx++) 393 { 394 type = mem->getTag(); 395 start = mem->getPhysicalSegment(0, NULL, kIOMemoryMapperNone); 396 size = mem->getLength(); 397 if (kIOACPIMemoryRange == type) 398 type = kIOPCIResourceTypeMemory; 399 else if (kIOACPIIORange == type) 400 { 401 if (start < 0x1000) 402 continue; 403 if ((start == 0xFFFF) && (size == 0x0001)) 404 continue; 405 type = kIOPCIResourceTypeIO; 406 } 407 else 408 continue; 409 if (!range) 410 range = IOPCIRangeAlloc(); 411 IOPCIRangeInit(range, type, start, size, 1); 412 ok = IOPCIRangeListAllocateSubRange(fRoot->ranges[BRN(type)], range); 413 DLOG("%s: %sfixed alloc type %d, 0x%llx len 0x%llx\n", 414 service->getName(), ok ? "" : "!", type, start, size); 415 if (ok) 416 range = NULL; 417 } 418 } 419 all->release(); 420 } 421 } 422 if (range) 423 IOPCIRangeFree(range); 424} 425#endif 426 427bool CLASS::createRoot(void) 428{ 429 IOPCIConfigEntry * root; 430 IOPCIRange * range; 431 uint64_t start, size; 432 uint32_t cpuPhysBits; 433 434 root = IONew(IOPCIConfigEntry, 1); 435 if (!root) return (false); 436 437 memset(root, 0, sizeof(*root)); 438 439 root->id = ++fNextID; 440 root->isHostBridge = true; 441 root->isBridge = true; 442 443 root->secBusNum = 0xff; 444 445#if defined(__i386__) || defined(__x86_64__) 446 cpuPhysBits = cpuid_info()->cpuid_address_bits_physical; 447 size = PFM64_SIZE; 448 if (cpuPhysBits > 44) cpuPhysBits = 44; 449 start = (1ULL << cpuPhysBits); 450// if (start > PFM64_MAX) start = PFM64_MAX; 451#if PLX8680 452 if (cpuPhysBits >= 36) size *= 16; // 32GB 453#endif 454 start -= size; 455 IOLog("pci (build %s %s), flags 0x%x, pfm64 (%d cpu) 0x%llx, 0x%llx\n", 456 __TIME__, __DATE__, gIOPCIFlags, cpuPhysBits, start, size); 457 kprintf("pci (build %s %s), flags 0x%x, pfm64 (%d cpu) 0x%llx, 0x%llx\n", 458 __TIME__, __DATE__, gIOPCIFlags, cpuPhysBits, start, size); 459 if (cpuPhysBits > 32) 460 { 461 range = IOPCIRangeAlloc(); 462 IOPCIRangeInitAlloc(range, kIOPCIResourceTypeMemory, start, size, 1); 463 root->ranges[kIOPCIRangeBridgeMemory] = range; 464 } 465 466#else /* defined(__i386__) || defined(__x86_64__) */ 467 468 IOLog ("pci (build %s %s), flags 0x%x\n", __TIME__, __DATE__, gIOPCIFlags); 469 kprintf("pci (build %s %s), flags 0x%x\n", __TIME__, __DATE__, gIOPCIFlags); 470 471#endif /* !defined(__i386__) || defined(__x86_64__) */ 472 473 root->deviceState |= kPCIDeviceStateScanned | kPCIDeviceStateConfigurationDone; 474 fRoot = root; 475 476 return (true); 477} 478 479IOReturn CLASS::addHostBridge(IOPCIBridge * hostBridge) 480{ 481 IOPCIConfigEntry * bridge; 482 IOPCIAddressSpace space; 483 IOPCIRange * range; 484 uint64_t start, size; 485 486 bridge = IONew(IOPCIConfigEntry, 1); 487 if (!bridge) return (kIOReturnNoMemory); 488 489 memset(bridge, 0, sizeof(*bridge)); 490 bridge->id = ++fNextID; 491 bridge->classCode = 0x060000; 492 bridge->headerType = kPCIHeaderType1; 493 bridge->secBusNum = hostBridge->firstBusNum(); 494 bridge->subBusNum = hostBridge->lastBusNum(); 495//#warning bus52 496// if (bridge->subBusNum > 250) bridge->subBusNum = 52; 497 bridge->space = hostBridge->getBridgeSpace(); 498 499 bridge->dtNub = hostBridge->getProvider(); 500 bridge->dtEntry = bridge->dtNub; 501#if ACPI_SUPPORT 502 bridge->acpiDevice = IOPCICopyACPIDevice(bridge->dtNub); 503#endif 504 bridge->isHostBridge = true; 505 bridge->isBridge = true; 506 bridge->supportsHotPlug = false; 507 508 if (OSDynamicCast(IOPCIDevice, bridge->dtNub)) panic("!host bridge"); 509 510 // fix - all config cycles use first host bridge 511 if (!fHostBridge) 512 { 513 fHostBridge = hostBridge; 514 space.bits = 0; 515 fRootVendorProduct = configRead32(space, kIOPCIConfigVendorID); 516#if defined(__i386__) || defined(__x86_64__) 517 if ( (0x27A08086 == fRootVendorProduct) 518 || (0x27AC8086 == fRootVendorProduct) 519 || (0x25C08086 == fRootVendorProduct) 520 || (CPUID_FEATURE_VMM & cpuid_features())) 521#endif 522 fFlags &= ~kIOPCIConfiguratorPFM64; 523 DLOG("root id 0x%x, flags 0x%x\n", fRootVendorProduct, (int) fFlags); 524 } 525 526 range = IOPCIRangeAlloc(); 527 start = bridge->secBusNum; 528 size = bridge->subBusNum - bridge->secBusNum + 1; 529 530 DLOG("host bridge acpi bus range 0x%llx len 0x%llx\n", start, size); 531 532 IOPCIRangeInitAlloc(range, kIOPCIResourceTypeBusNumber, start, size, kPCIBridgeBusNumberAlignment); 533 bridge->ranges[kIOPCIRangeBridgeBusNumber] = range; 534 535 DLOG("added(%s) host bridge resource %s 0x%llx len 0x%llx\n", 536 "ok", gPCIResourceTypeName[kIOPCIResourceTypeBusNumber], 537 range->start, range->size); 538 539 for (int type = 0; type < kIOPCIResourceTypeCount; type++) 540 { 541 IOPCIRange * thisRange; 542 for (thisRange = hostBridge->reserved->rangeLists[type]; 543 thisRange; 544 thisRange = thisRange->next) 545 { 546 bool ok; 547 start = thisRange->start; 548 size = thisRange->size; 549 DLOG("reported host bridge resource %s 0x%llx len 0x%llx\n", 550 gPCIResourceTypeName[type], 551 start, size); 552 ok = IOPCIRangeListAddRange(&fRoot->ranges[BRN(type)], 553 type, start, size); 554 DLOG("added(%s) host bridge resource %s 0x%llx len 0x%llx\n", 555 ok ? "ok" : "!", gPCIResourceTypeName[type], 556 start, size); 557 } 558 } 559 560#if ACPI_SUPPORT 561 if (bridge->acpiDevice) 562 removeFixedRanges(bridge->acpiDevice); 563#endif 564 565 bridge->deviceState |= kPCIDeviceStateConfigurationDone; 566 567 bridgeAddChild(fRoot, bridge); 568 569 configure(kIOPCIConfiguratorBoot); 570 571 return (kIOReturnSuccess); 572} 573 574void CLASS::free( void ) 575{ 576 super::free(); 577} 578 579//--------------------------------------------------------------------------- 580 581void CLASS::constructAddressingProperties(IOPCIConfigEntry * device, OSDictionary * propTable) 582{ 583 IOPCIRange * range; 584 IOPCIPhysicalAddress regData; 585 OSString * string; 586 OSData * prop; 587 OSData * regProp; 588 OSData * assignedProp; 589 OSData * rangeProp; 590 char tuple[64]; 591 size_t len; 592 593 len = snprintf(tuple, sizeof(tuple), "%u:%u:%u", PCI_ADDRESS_TUPLE(device)); 594 if (device->isBridge && (len < sizeof(tuple))) 595 { 596 snprintf(&tuple[len], sizeof(tuple) - len, "(%u:%u)", device->secBusNum, device->subBusNum); 597 } 598 string = OSString::withCString(tuple); 599 if (string) 600 { 601 propTable->setObject("pcidebug", string); 602 string->release(); 603 } 604 605 assignedProp = OSData::withCapacity(32); 606 regProp = OSData::withCapacity(32); 607 rangeProp = OSData::withCapacity(32); 608 if (!assignedProp || !regProp || !rangeProp) 609 return; 610 611 regData.physHi = device->space; 612 regData.physMid = 0; 613 regData.physLo = 0; 614 regData.lengthHi = 0; 615 regData.lengthLo = 0; 616 regProp->appendBytes(®Data, sizeof(regData)); 617 618 for (uint32_t i = 0; i < kIOPCIRangeCount; i++) 619 { 620 static const uint8_t barRegisters[kIOPCIRangeExpansionROM + 1] = { 621 kIOPCIConfigBaseAddress0, kIOPCIConfigBaseAddress1, kIOPCIConfigBaseAddress2, 622 kIOPCIConfigBaseAddress3, kIOPCIConfigBaseAddress4, kIOPCIConfigBaseAddress5, 623 kIOPCIConfigExpansionROMBase 624 }; 625 626 range = device->ranges[i]; 627 if (!range) 628 continue; 629 if (kIOPCIResourceTypeBusNumber == range->type) 630 continue; 631 632 regData.physHi = device->space; 633 switch (range->type) 634 { 635 case kIOPCIResourceTypeMemory: 636 regData.physHi.s.space = kIOPCI32BitMemorySpace; 637 break; 638 case kIOPCIResourceTypePrefetchMemory: 639 regData.physHi.s.space = kIOPCI32BitMemorySpace; 640 regData.physHi.s.prefetch = 1; 641 break; 642 643 case kIOPCIResourceTypeIO: 644 regData.physHi.s.space = kIOPCIIOSpace; 645 break; 646 } 647 648 regData.physMid = 0; 649 regData.physLo = 0; 650 regData.lengthHi = (range->size >> 32ULL); 651 regData.lengthLo = range->size; 652 if (i <= kIOPCIRangeExpansionROM) 653 { 654 regData.physHi.s.registerNum = barRegisters[i]; 655 if (range->start) 656 { 657 IOPCIPhysicalAddress assignedData; 658 assignedData = regData; 659 assignedData.physHi.s.reloc = 1; 660 assignedData.physMid = (range->start >> 32ULL); 661 assignedData.physLo = range->start; 662 assignedProp->appendBytes(&assignedData, sizeof(assignedData)); 663 } 664 // reg gets requested length 665 regData.lengthHi = (range->proposedSize >> 32ULL); 666 regData.lengthLo = range->proposedSize; 667 regProp->appendBytes(®Data, sizeof(regData)); 668 } 669 else 670 { 671 regData.physHi.s.reloc = 1; 672 regData.physMid = (range->start >> 32ULL); 673 regData.physLo = range->start; 674 regData.physHi.s.busNum = 0; 675 regData.physHi.s.deviceNum = 0; 676 regData.physHi.s.functionNum = 0; 677 regData.physHi.s.registerNum = 0; 678 rangeProp->appendBytes(®Data, sizeof(regData.physHi) + sizeof(regData.physMid) + sizeof(regData.physLo)); 679 rangeProp->appendBytes(®Data, sizeof(regData)); 680 } 681 } 682 propTable->setObject("reg", regProp); 683 regProp->release(); 684 if (assignedProp->getLength()) 685 propTable->setObject("assigned-addresses", assignedProp); 686 assignedProp->release(); 687 if (rangeProp->getLength()) 688 { 689 propTable->setObject("ranges", rangeProp); 690 691 regData.lengthLo = 3; 692 prop = OSData::withBytes(®Data.lengthLo, sizeof(regData.lengthLo)); 693 if (prop) 694 { 695 propTable->setObject("#address-cells", prop ); 696 prop->release(); 697 } 698 regData.lengthLo = 2; 699 prop = OSData::withBytes(®Data.lengthLo, sizeof(regData.lengthLo)); 700 if (prop) 701 { 702 propTable->setObject("#size-cells", prop ); 703 prop->release(); 704 } 705 } 706 rangeProp->release(); 707} 708 709OSDictionary * CLASS::constructProperties(IOPCIConfigEntry * device) 710{ 711 OSDictionary * propTable; 712 uint32_t value; 713 uint32_t vendor, product, classCode, revID; 714 uint32_t subVendor = 0, subProduct = 0; 715 OSData * prop; 716 const char * name; 717 const OSSymbol * nameProp; 718 char compatBuf[128]; 719 char * out; 720 721 struct IOPCIGenericNames 722 { 723 const char * name; 724 UInt32 mask; 725 UInt32 classCode; 726 }; 727 static const IOPCIGenericNames genericNames[] = { 728 { "display", 0xffffff, 0x000100 }, 729 { "scsi", 0xffff00, 0x010000 }, 730 { "ethernet", 0xffff00, 0x020000 }, 731 { "display", 0xff0000, 0x030000 }, 732 { "pci-bridge", 0xffff00, 0x060400 }, 733 { 0, 0, 0 } 734 }; 735 const IOPCIGenericNames * nextName; 736 737 propTable = OSDictionary::withCapacity( 8 ); 738 if (!propTable) 739 return (NULL); 740 741 constructAddressingProperties(device, propTable); 742 743 value = configRead32( device, kIOPCIConfigVendorID ); 744 vendor = value & 0xffff; 745 product = value >> 16; 746 747 prop = OSData::withBytes( &vendor, sizeof(vendor) ); 748 if (prop) 749 { 750 propTable->setObject("vendor-id", prop ); 751 prop->release(); 752 } 753 754 prop = OSData::withBytes( &product, sizeof(product) ); 755 if (prop) 756 { 757 propTable->setObject("device-id", prop ); 758 prop->release(); 759 } 760 761 value = configRead32( device, kIOPCIConfigRevisionID ); 762 revID = value & 0xff; 763 prop = OSData::withBytes( &revID, sizeof(revID) ); 764 if (prop) 765 { 766 propTable->setObject("revision-id", prop ); 767 prop->release(); 768 } 769 770 classCode = value >> 8; 771 prop = OSData::withBytes( &classCode, sizeof(classCode) ); 772 if (prop) 773 { 774 propTable->setObject("class-code", prop ); 775 prop->release(); 776 } 777 778 // make generic name 779 780 name = 0; 781 for (nextName = genericNames; 782 (0 == name) && nextName->name; 783 nextName++) 784 { 785 if ((classCode & nextName->mask) == nextName->classCode) 786 name = nextName->name; 787 } 788 789 // or name from IDs 790 791 value = configRead32( device, kIOPCIConfigSubSystemVendorID ); 792 if (value) 793 { 794 subVendor = value & 0xffff; 795 subProduct = value >> 16; 796 797 prop = OSData::withBytes( &subVendor, sizeof(subVendor) ); 798 if (prop) 799 { 800 propTable->setObject("subsystem-vendor-id", prop ); 801 prop->release(); 802 } 803 prop = OSData::withBytes( &subProduct, sizeof(subProduct) ); 804 if (prop) 805 { 806 propTable->setObject("subsystem-id", prop ); 807 prop->release(); 808 } 809 } 810 811 out = compatBuf; 812 if ((subVendor || subProduct) 813 && ((subVendor != vendor) || (subProduct != product))) 814 out += snprintf(out, sizeof("pcivvvv,pppp"), "pci%x,%x", subVendor, subProduct) + 1; 815 816 if (0 == name) 817 name = out; 818 819 out += snprintf(out, sizeof("pcivvvv,pppp"), "pci%x,%x", vendor, product) + 1; 820 out += snprintf(out, sizeof("pciclass,cccccc"), "pciclass,%06x", classCode) + 1; 821 822 if (device->dtEntry && ((nameProp = device->dtEntry->copyName()))) 823 { 824 out += strlcpy(out, nameProp->getCStringNoCopy(), 31) + 1; 825 nameProp->release(); 826 } 827 828 prop = OSData::withBytes( compatBuf, out - compatBuf ); 829 if (prop) 830 { 831 propTable->setObject("compatible", prop ); 832 prop->release(); 833 } 834 835 nameProp = OSSymbol::withCString( name ); 836 if (nameProp) 837 { 838 propTable->setObject( gIONameKey, (OSSymbol *) nameProp); 839 nameProp->release(); 840 } 841 842 prop = OSData::withBytes( name, strlen(name) + 1 ); 843 if (prop) 844 { 845 propTable->setObject("name", prop ); 846 prop->release(); 847 } 848 849 OSNumber * num; 850 if ((3 == (classCode >> 16)) 851 && (0x8086 == vendor) 852 && (!(kIOPCIConfiguratorIGIsMapped & fFlags)) 853 && (num = OSNumber::withNumber(kIOMemoryMapperNone, 32))) 854 { 855 propTable->setObject(kIOMemoryDescriptorOptionsKey, num); 856 num->release(); 857 } 858 859 if (kPCIHotPlugRoot == device->supportsHotPlug) 860 propTable->setObject(kIOPCIHotPlugKey, kOSBooleanTrue); 861 else if (kPCILinkChange == device->supportsHotPlug) 862 propTable->setObject(kIOPCILinkChangeKey, kOSBooleanTrue); 863 864 if (kPCIHotPlugTunnel == device->parent->supportsHotPlug) 865 propTable->setObject(kIOPCITunnelledKey, kOSBooleanTrue); 866 867 if (device->linkInterrupts) 868 propTable->setObject(kIOPCITunnelLinkChangeKey, kOSBooleanTrue); 869 870 if (device->linkInterrupts || (kPCIHotPlugRoot == device->supportsHotPlug)) 871 { 872 bool bootDefer = (kIOPCIConfiguratorBootDefer == (kIOPCIConfiguratorBootDefer & fFlags)); 873 if (bootDefer) 874 propTable->setObject(kIOPCITunnelBootDeferKey, kOSBooleanTrue); 875 else if (!(kPCIDeviceStateNoLink & device->deviceState)) 876 propTable->setObject(kIOPCIOnlineKey, kOSBooleanTrue); 877 } 878 879#if PLX8680 880 if (device->plxAperture 881 && (num = OSNumber::withNumber(device->plxAperture, 64))) 882 { 883 propTable->setObject("IODMAAddressAperture", num); 884 num->release(); 885 } 886#endif /* PLX8680 */ 887 888 return (propTable); 889} 890 891//--------------------------------------------------------------------------- 892 893#if ACPI_SUPPORT 894 895static IOACPIPlatformDevice * IOPCICopyACPIDevice( IORegistryEntry * device ) 896{ 897 IOACPIPlatformDevice * acpiDevice = 0; 898 OSString * acpiPath; 899 900 if (device) 901 { 902 acpiPath = (OSString *) device->copyProperty(kACPIDevicePathKey); 903 if (acpiPath && !OSDynamicCast(OSString, acpiPath)) 904 { 905 acpiPath->release(); 906 acpiPath = 0; 907 } 908 909 if (acpiPath) 910 { 911 IORegistryEntry * entry; 912 913 entry = IORegistryEntry::fromPath(acpiPath->getCStringNoCopy()); 914 acpiPath->release(); 915 916 if (entry && entry->metaCast("IOACPIPlatformDevice")) 917 acpiDevice = (IOACPIPlatformDevice *) entry; 918 else if (entry) 919 entry->release(); 920 } 921 } 922 923 return (acpiDevice); 924} 925 926#endif /* ACPI_SUPPORT */ 927 928//--------------------------------------------------------------------------- 929 930static UInt8 IOPCIIsHotplugPort(IORegistryEntry * bridgeDevice) 931{ 932 UInt8 type = kPCIStatic; 933 934#if ACPI_SUPPORT 935 936 IOACPIPlatformDevice * rp; 937 IOACPIPlatformDevice * child; 938 939 rp = IOPCICopyACPIDevice(bridgeDevice); 940 if (rp && gIOPCIACPIPlane) 941 { 942 child = (IOACPIPlatformDevice *) rp->getChildEntry(gIOPCIACPIPlane); 943 if (child) 944 { 945 IOReturn ret; 946 UInt32 result32 = 0; 947 OSObject * obj; 948 949 ret = child->evaluateInteger("_RMV", &result32); 950 if (kIOReturnSuccess == ret) 951 { 952 if (result32) 953 type = kPCIHotPlugRoot; 954 } 955 else if ((obj = child->copyProperty(kACPIDevicePropertiesKey))) 956 { 957 OSDictionary * dict; 958 if ((dict = OSDynamicCast(OSDictionary, obj)) 959 && dict->getObject(kACPIPCILinkChangeKey)) 960 type = kPCILinkChange; 961 } 962 } 963 } 964 if (rp) 965 rp->release(); 966 967#endif /* ACPI_SUPPORT */ 968 969 return (type); 970} 971 972//--------------------------------------------------------------------------- 973 974struct MatchDTEntryContext 975{ 976 CLASS * me; 977 IOPCIConfigEntry * bridge; 978}; 979 980void CLASS::matchDTEntry( IORegistryEntry * dtEntry, void * _context ) 981{ 982 MatchDTEntryContext * context = (MatchDTEntryContext *) _context; 983 IOPCIConfigEntry * bridge = context->bridge; 984 IOPCIConfigEntry * match = 0; 985 const OSSymbol * location; 986 987 assert(bridge); 988 assert(dtEntry); 989 990 if (dtEntry->inPlane(gIOServicePlane)) return; 991 992 location = dtEntry->copyLocation(); 993 if (!location) return; 994 995 uint32_t devfn = strtoul(location->getCStringNoCopy(), NULL, 16); 996 uint32_t deviceNum = ((devfn >> 16) & 0x1f); 997 uint32_t functionNum = (devfn & 0x7); 998 bool functionAll = ((devfn & 0xffff) == 0xffff); 999 1000 FOREACH_CHILD(bridge, child) 1001 { 1002 if (kPCIDeviceStateDead & child->deviceState) 1003 continue; 1004 if (child->space.s.deviceNum == deviceNum && 1005 (functionAll || (child->space.s.functionNum == functionNum))) 1006 { 1007 match = child; 1008 break; 1009 } 1010 } 1011 1012 if (dtEntry->inPlane(gIOServicePlane)) 1013 match = 0; 1014 1015 if (match) 1016 { 1017 if (!match->dtEntry) 1018 { 1019 match->dtEntry = dtEntry; 1020 DLOGC(context->me, "Found PCI device for DT entry [%s] "D()"\n", 1021 dtEntry->getName(), DEVICE_IDENT(match)); 1022 } 1023 } 1024 else 1025 { 1026 DLOGC(context->me, "NOT FOUND: PCI device for DT entry [%s] "D()"\n", 1027 dtEntry->getName(), 0, bridge->secBusNum, deviceNum, functionNum, 0, 0); 1028 } 1029 1030 if (location) 1031 location->release(); 1032} 1033 1034#if ACPI_SUPPORT 1035 1036void CLASS::matchACPIEntry( IORegistryEntry * dtEntry, void * _context ) 1037{ 1038 MatchDTEntryContext * context = (MatchDTEntryContext *) _context; 1039 IOPCIConfigEntry * bridge = context->bridge; 1040 IOPCIConfigEntry * match = 0; 1041 OSNumber * adr; 1042 1043 assert(bridge); 1044 assert(dtEntry); 1045 1046 adr = OSDynamicCast(OSNumber, dtEntry->getProperty("_ADR")); 1047 if (!adr) 1048 return; 1049 1050 uint32_t devfn = adr->unsigned32BitValue(); 1051 uint32_t deviceNum = ((devfn >> 16) & 0x1f); 1052 uint32_t functionNum = (devfn & 0x7); 1053 bool functionAll = ((devfn & 0xffff) == 0xffff); 1054 1055 FOREACH_CHILD( bridge, child ) 1056 { 1057 if (kPCIDeviceStateDead & child->deviceState) 1058 continue; 1059 if (child->space.s.deviceNum == deviceNum && 1060 (functionAll || (child->space.s.functionNum == functionNum))) 1061 { 1062 match = child; 1063 if (!functionAll) 1064 break; 1065 } 1066 } 1067 1068 if (match) 1069 { 1070 if (!match->acpiDevice) 1071 { 1072 match->acpiDevice = dtEntry; 1073 DLOGC(context->me, "Found PCI device for ACPI entry [%s] "D()"\n", 1074 dtEntry->getName(), DEVICE_IDENT(match)); 1075 } 1076 } 1077 else 1078 { 1079 DLOGC(context->me, "NOT FOUND: PCI device for ACPI entry [%s] "D()"\n", 1080 dtEntry->getName(), 0, bridge->secBusNum, deviceNum, functionNum, 0, 0); 1081 } 1082} 1083 1084#endif /* ACPI_SUPPORT */ 1085 1086//--------------------------------------------------------------------------- 1087 1088void CLASS::bridgeConnectDeviceTree(IOPCIConfigEntry * bridge) 1089{ 1090 IORegistryEntry * dtBridge = bridge->dtEntry; 1091 IOPCIConfigEntry * parent; 1092 OSObject * obj; 1093 MatchDTEntryContext context; 1094 IOPCIRange * childRange; 1095 bool oneChild; 1096 bool tbok = (0 == (kIOPCIConfiguratorNoTB & gIOPCIFlags)); 1097 1098 if ((kPCIHotPlugTunnel != bridge->supportsHotPlug) 1099 || (kPCIHotPlugTunnelRoot == bridge->parent->supportsHotPlug)) 1100 { 1101 context.me = this; 1102 context.bridge = bridge; 1103 if (dtBridge) 1104 { 1105 dtBridge->applyToChildren(&matchDTEntry, &context, gIODTPlane); 1106 } 1107#if ACPI_SUPPORT 1108 if (gIOPCIACPIPlane && bridge->acpiDevice) 1109 { 1110 bridge->acpiDevice->applyToChildren(&matchACPIEntry, &context, gIOPCIACPIPlane); 1111 } 1112#endif /* ACPI_SUPPORT */ 1113 } 1114 1115 oneChild = (bridge->child && !bridge->child->peer); 1116 1117 FOREACH_CHILD(bridge, child) 1118 { 1119 if (!child->isBridge) continue; 1120 if (kPCIDeviceStateTreeConnected & child->deviceState) continue; 1121// child->deviceState |= kPCIDeviceStateTreeConnected; 1122 do 1123 { 1124 if ((kPCIHotPlugTunnelRoot == bridge->supportsHotPlug) 1125 && (child == bridge->child)) 1126 { 1127 // assume the first DSB of the TB root is for NHI 1128 bridge->child->supportsHotPlug = kPCIStatic; 1129 bridge->child->linkInterrupts = false; 1130 DLOG("tunnel controller "D()"\n", DEVICE_IDENT(bridge->child)); 1131 continue; 1132 } 1133 1134 if (tbok && child->dtEntry) 1135 { 1136 if (child->dtEntry->getProperty(gIOPCIThunderboltKey)) 1137 { 1138 child->supportsHotPlug = kPCIHotPlugTunnelRoot; 1139 continue; 1140 } 1141 if ((obj = child->dtEntry->copyProperty(gIOPCIThunderboltKey, gIODTPlane, 1142 kIORegistryIterateRecursively))) 1143 { 1144 obj->release(); 1145 child->supportsHotPlug = kPCIHotPlugTunnelRootParent; 1146 continue; 1147 } 1148 } 1149 1150 if ((kPCIHotPlugTunnelRoot == bridge->supportsHotPlug) 1151 || (kPCIHotPlugTunnel == bridge->supportsHotPlug)) 1152 { 1153 child->supportsHotPlug = kPCIHotPlugTunnel; 1154 continue; 1155 } 1156 1157 if ((kPCIHotPlugRoot == bridge->supportsHotPlug) 1158 || (kPCIHotPlug == bridge->supportsHotPlug)) 1159 { 1160 child->supportsHotPlug = kPCIHotPlug; 1161 continue; 1162 } 1163 1164 if (child->headerType == kPCIHeaderType2) 1165 child->supportsHotPlug = kPCIHotPlugRoot; 1166 else if (child->dtEntry) 1167 { 1168 child->supportsHotPlug = IOPCIIsHotplugPort(child->dtEntry); 1169 } 1170 else 1171 child->supportsHotPlug = kPCIStatic; 1172 } 1173 while (false); 1174 } 1175 1176 bridge->countMaximize = 0; 1177 uint32_t flags = kIOPCIRangeFlagMaximizeRoot | kIOPCIRangeFlagNoCollapse; 1178 1179 FOREACH_CHILD(bridge, child) 1180 { 1181 if ((kPCIHotPlugTunnelRootParent == child->supportsHotPlug) 1182 || (kPCIHotPlugTunnelRoot == child->supportsHotPlug)) bridge->countMaximize++; 1183 } 1184 1185 for (parent = bridge; parent; parent = parent->parent) 1186 { 1187 if (parent->countMaximize > 1) 1188 { 1189 flags = kIOPCIRangeFlagMaximizeSize | kIOPCIRangeFlagNoCollapse; 1190 break; 1191 } 1192 } 1193 1194 FOREACH_CHILD(bridge, child) 1195 { 1196 if (!child->isBridge) continue; 1197 if (kPCIDeviceStateTreeConnected & child->deviceState) continue; 1198 child->deviceState |= kPCIDeviceStateTreeConnected; 1199 1200 DLOG("bridge "D()" supportsHotPlug %d, linkInterrupts %d\n", 1201 DEVICE_IDENT(child), 1202 child->supportsHotPlug, child->linkInterrupts); 1203 1204 for (int i = kIOPCIRangeBridgeMemory; i < kIOPCIRangeCount; i++) 1205 { 1206 childRange = child->ranges[i]; 1207 if (!childRange) 1208 continue; 1209 1210 if (kPCIHotPlugTunnelRootParent == child->supportsHotPlug) 1211 { 1212 childRange->flags |= flags; 1213 child->rangeSizeChanges |= (1 << BRN(childRange->type)); 1214 } 1215 else if (kPCIHotPlugTunnelRoot == child->supportsHotPlug) 1216 { 1217 childRange->flags |= flags; 1218 childRange->start = 0; 1219 child->rangeSizeChanges |= (1 << BRN(childRange->type)); 1220 } 1221 else if (child->linkInterrupts 1222 && (kPCIStatic != child->supportsHotPlug) 1223 && (!(kIOPCIConfiguratorNoSplay & fFlags))) 1224 { 1225 childRange->flags |= kIOPCIRangeFlagSplay; 1226 } 1227 } 1228 } 1229} 1230 1231//--------------------------------------------------------------------------- 1232 1233bool CLASS::bridgeConstructDeviceTree(void * unused, IOPCIConfigEntry * bridge) 1234{ 1235 IORegistryEntry * dtBridge = bridge->dtNub; 1236 uint32_t int32; 1237 bool ok = true; 1238 IOPCIDevice * nub; 1239 OSDictionary * initFrom; 1240 1241// DLOG("bridgeConstructDeviceTree(%p)\n", bridge); 1242 if (!dtBridge) return (ok); 1243 1244 int32 = 3; 1245 dtBridge->setProperty("#address-cells", &int32, sizeof(int32)); 1246 int32 = 2; 1247 dtBridge->setProperty("#size-cells", &int32, sizeof(int32)); 1248 1249 // Create missing device-tree entries for any child devices. 1250 1251 FOREACH_CHILD( bridge, child ) 1252 { 1253 IOPCIDevice * pciDevice; 1254 IORegistryEntry * copyReg; 1255 OSDictionary * propTable; 1256 OSObject * obj; 1257 const OSSymbol * sym; 1258 bool addProps; 1259 bool initDT; 1260 1261 if (kPCIDeviceStatePropertiesDone & child->deviceState) continue; 1262 child->deviceState |= kPCIDeviceStatePropertiesDone; 1263 1264 DLOG("bridgeConstructDeviceTree at "D()"\n", DEVICE_IDENT(child)); 1265 1266 propTable = constructProperties(child); 1267 if (!propTable) continue; 1268 1269#if ACPI_SUPPORT 1270 if (child->acpiDevice) 1271 { 1272 OSObject * obj; 1273 OSDictionary * mergeProps; 1274 obj = child->acpiDevice->copyProperty(kACPIDevicePropertiesKey); 1275 if (obj) 1276 { 1277 if ((mergeProps = OSDynamicCast(OSDictionary, obj))) 1278 propTable->merge(mergeProps); 1279 obj->release(); 1280 } 1281 } 1282#endif /* ACPI_SUPPORT */ 1283 1284 pciDevice = OSDynamicCast(IOPCIDevice, child->dtNub); 1285 addProps = true; 1286 if (!pciDevice) 1287 { 1288 nub = OSTypeAlloc(IOPCIDevice); 1289 if (!nub) continue; 1290 initFrom = 0; 1291 initDT = false; 1292 ok = false; 1293 if (child->dtEntry) 1294 { 1295#if ACPI_SUPPORT 1296 ok = nub->init(child->dtEntry, gIODTPlane); 1297 child->dtNub = child->dtEntry = 0; 1298 initDT = true; 1299#else /* !ACPI_SUPPORT */ 1300 initFrom = child->dtEntry->dictionaryWithProperties(); 1301#endif /* !ACPI_SUPPORT */ 1302 } 1303 if (!initDT) 1304 { 1305 if (!initFrom) 1306 { 1307 initFrom = propTable; 1308 initFrom->retain(); 1309 addProps = false; 1310 } 1311 ok = (nub->init(initFrom) && nub->attachToParent(dtBridge, gIODTPlane)); 1312 initFrom->release(); 1313 } 1314 nub->release(); 1315 if (!ok) continue; 1316 nub->reserved->configEntry = child; 1317 child->dtNub = nub; 1318#if ACPI_SUPPORT 1319 child->dtEntry = nub; 1320 copyReg = child->acpiDevice; 1321#else /* !ACPI_SUPPORT */ 1322 copyReg = child->dtEntry; 1323#endif /* !ACPI_SUPPORT */ 1324 1325 if (!initDT) 1326 { 1327 if (copyReg) 1328 { 1329 if ((sym = copyReg->copyName())) 1330 { 1331 nub->setName(sym); 1332 sym->release(); 1333 } 1334 } 1335 else if ((sym = OSDynamicCast(OSSymbol, propTable->getObject(gIONameKey)))) 1336 nub->setName(sym); 1337 } 1338 } 1339 1340 if (addProps) 1341 { 1342 // update existing device 1343 OSCollectionIterator * propIter = 1344 OSCollectionIterator::withCollection(propTable); 1345 if (propIter) 1346 { 1347 const OSSymbol * propKey; 1348 1349 child->dtNub->removeProperty("ranges"); 1350 child->dtNub->removeProperty("reg"); 1351 child->dtNub->removeProperty("assigned-addresses"); 1352 child->dtNub->removeProperty("pcidebug"); 1353 1354 while ((propKey = (const OSSymbol *)propIter->getNextObject())) 1355 { 1356 if (child->dtNub->getProperty(propKey)) continue; 1357 obj = propTable->getObject(propKey); 1358 child->dtNub->setProperty(propKey, obj); 1359 } 1360 propIter->release(); 1361 } 1362 } 1363 1364 if (pciDevice 1365 && (kPCIDeviceStatePaused & child->deviceState) 1366 && pciDevice->getProperty(kIOPCIResourcedKey)) 1367 { 1368 // relocate existing device 1369 DLOG("IOPCIDevice::relocate at "D()"\n", DEVICE_IDENT(child)); 1370 for (uint32_t idx = 0; idx < kIOPCIRangeCount; idx++) 1371 { 1372 IOPCIRange * range; 1373 range = child->ranges[idx]; 1374 if (!range) continue; 1375 if (range->size < range->proposedSize) 1376 { 1377 DLOG(" %s ", gPCIResourceTypeName[range->type]); 1378 DLOG_RANGE("short range", range); 1379 } 1380 } 1381 pciDevice->relocate(true); 1382 } 1383 propTable->release(); 1384 } 1385 dtBridge->setProperty(kIOPCIConfiguredKey, kOSBooleanTrue); 1386 1387 return (ok); 1388} 1389 1390//--------------------------------------------------------------------------- 1391 1392void CLASS::bridgeScanBus(IOPCIConfigEntry * bridge, uint8_t busNum, uint32_t resetMask) 1393{ 1394 IOPCIAddressSpace space; 1395 IOPCIConfigEntry * child; 1396 uint32_t noLink = 0; 1397 bool bootDefer = false; 1398 UInt8 scanDevice, scanFunction, lastFunction; 1399 uint32_t linkStatus; 1400 enum 1401 { 1402 kLinkCapDataLinkLayerActiveReportingCapable = (1 << 20), 1403 kLinkStatusDataLinkLayerLinkActive = (1 << 13) 1404 }; 1405 1406 space.bits = 0; 1407 space.s.busNum = busNum; 1408 1409 if (bridge->expressCapBlock) do 1410 { 1411 bootDefer = (bridge->linkInterrupts 1412 && (kIOPCIConfiguratorBootDefer == (kIOPCIConfiguratorBootDefer & fFlags))); 1413 if (bootDefer) 1414 break; 1415 1416 linkStatus = configRead16(bridge, bridge->expressCapBlock + 0x12); 1417 if ((kLinkCapDataLinkLayerActiveReportingCapable & bridge->linkCaps) 1418 && !(kLinkStatusDataLinkLayerLinkActive & linkStatus)) 1419 { 1420 noLink = kPCIDeviceStateNoLink; 1421 } 1422 1423 if ((kPCIDeviceStateNoLink & bridge->deviceState) != noLink) 1424 { 1425 bridge->deviceState &= ~kPCIDeviceStateNoLink; 1426 bridge->deviceState |= noLink; 1427 bridge->rangeBaseChanges |= ((1 << kIOPCIRangeBridgeMemory) 1428 | (1 << kIOPCIRangeBridgePFMemory)); 1429 } 1430 1431 DLOG("bridge "D()" %s%s linkStatus 0x%04x, linkCaps 0x%04x\n", 1432 DEVICE_IDENT(bridge), 1433 resetMask ? "reset " : "", 1434 noLink ? "nolink " : "", 1435 linkStatus, bridge->linkCaps); 1436 1437 if (noLink) 1438 { 1439 if (kPCIHotPlugTunnel <= bridge->supportsHotPlug) 1440 { 1441 configWrite32(bridge, kPCI2PCIMemoryRange, 0); 1442 configWrite32(bridge, kPCI2PCIPrefetchMemoryRange, 0); 1443 configWrite32(bridge, kPCI2PCIPrefetchUpperBase, 0); 1444 configWrite32(bridge, kPCI2PCIPrefetchUpperLimit, 0); 1445 } 1446 IOPCIConfigEntry * next; 1447 for (child = bridge->child; child; child = next) 1448 { 1449 next = child->peer; 1450 bridgeDeadChild(bridge, child); 1451 } 1452 } 1453 } 1454 while (false); 1455 1456 if (!bootDefer && !noLink) 1457 { 1458#if 0 1459 static const uint8_t deviceMap[32] = { 1460// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1461 0, 1, 3, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1462 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }; 1463#endif 1464 // Scan all PCI devices and functions on the secondary bus. 1465 for (scanDevice = 0; scanDevice <= 31; scanDevice++) 1466 { 1467 lastFunction = 0; 1468 for (scanFunction = 0; scanFunction <= lastFunction; scanFunction++) 1469 { 1470 space.s.deviceNum = scanDevice; // deviceMap[scanDevice]; 1471 space.s.functionNum = scanFunction; 1472 1473 bridgeProbeChild(bridge, space, resetMask); 1474 1475 // look in function 0 for multi function flag 1476 if (0 == scanFunction) 1477 { 1478 uint32_t flags = configRead32(space, kIOPCIConfigCacheLineSize); 1479 if ((flags != 0xFFFFFFFF) && (0x00800000 & flags)) 1480 { 1481 lastFunction = 7; 1482 } 1483 } 1484 } 1485 } 1486 } 1487} 1488 1489//--------------------------------------------------------------------------- 1490 1491void CLASS::markChanged(IOPCIConfigEntry * entry) 1492{ 1493 if (fChangedServices) 1494 { 1495 if (entry->dtNub && entry->dtNub->inPlane(gIOServicePlane)) 1496 fChangedServices->setObject(entry->dtNub); 1497 } 1498} 1499 1500//--------------------------------------------------------------------------- 1501 1502void CLASS::bridgeAddChild(IOPCIConfigEntry * bridge, IOPCIConfigEntry * child) 1503{ 1504 IOPCIConfigEntry ** prev = &bridge->child; 1505 IOPCIConfigEntry * next; 1506 1507 // tailq 1508 while ((next = *prev)) 1509 { 1510 prev = &next->peer; 1511 } 1512 *prev = child; 1513 child->parent = bridge; 1514 1515 if (child->isBridge) 1516 fBridgeCount++; 1517 else 1518 fDeviceCount++; 1519 1520 bridge->deviceState |= kPCIDeviceStateChildChanged | kPCIDeviceStateChildAdded; 1521} 1522 1523//--------------------------------------------------------------------------- 1524 1525bool CLASS::bridgeDeallocateChildRanges(IOPCIConfigEntry * bridge, IOPCIConfigEntry * dead, 1526 uint32_t deallocTypes, uint32_t freeTypes) 1527{ 1528 IOPCIRange * range; 1529 IOPCIRange * childRange; 1530 bool ok; 1531 bool dispose; 1532 bool didKeep = false; 1533 1534 for (int rangeIndex = 0; rangeIndex < kIOPCIRangeCount; rangeIndex++) 1535 { 1536 childRange = dead->ranges[rangeIndex]; 1537 if (!childRange) continue; 1538 if (!((1 << rangeIndex) & deallocTypes)) continue; 1539 1540 if ((kIOPCIRangeBridgeBusNumber == rangeIndex) && dead->busResv.nextSubRange) 1541 { 1542 ok = IOPCIRangeListDeallocateSubRange(childRange, &dead->busResv); 1543 if (!ok) panic("!IOPCIRangeListDeallocateSubRange busResv"); 1544 } 1545 1546 dispose = (0 != ((1 << rangeIndex) & freeTypes)); 1547 1548 if (childRange->nextSubRange) 1549 { 1550 IOPCIScalar size = childRange->size; 1551 IOPCIScalar start = childRange->start; 1552 1553 range = bridgeGetRange(bridge, childRange->type); 1554 if (!range) panic("!range"); 1555 ok = IOPCIRangeListDeallocateSubRange(range, childRange); 1556 if (!ok) panic("!IOPCIRangeListDeallocateSubRange"); 1557 if (rangeIndex <= kIOPCIRangeExpansionROM) 1558 { 1559 childRange->start = start; 1560 childRange->proposedSize = size; 1561 } 1562 else 1563 { 1564 childRange->proposedSize = 0; 1565 } 1566 bridge->haveAllocs |= (1 << childRange->type); 1567 dead->rangeBaseChanges |= (1 << rangeIndex); 1568 1569 didKeep |= !dispose; 1570 } 1571 if (dispose) 1572 { 1573 IOPCIRangeFree(childRange); 1574 dead->ranges[rangeIndex] = NULL; 1575 } 1576 } 1577 1578 return (didKeep); 1579} 1580 1581//--------------------------------------------------------------------------- 1582 1583void CLASS::bridgeRemoveChild(IOPCIConfigEntry * bridge, IOPCIConfigEntry * dead, 1584 uint32_t deallocTypes, uint32_t freeTypes, 1585 IOPCIConfigEntry ** childList) 1586{ 1587 IOPCIConfigEntry ** prev; 1588 IOPCIConfigEntry * child; 1589 IOPCIDevice * pciDevice; 1590 bool didKeep; 1591 1592 dead->deviceState |= kPCIDeviceStateDead; 1593 1594 while ((child = dead->child)) 1595 { 1596 bridgeRemoveChild(dead, child, deallocTypes, freeTypes, childList); 1597 } 1598 1599 DLOG("bridge "B()" removing child %p "D()"\n", 1600 BRIDGE_IDENT(bridge), dead, DEVICE_IDENT(dead)); 1601 1602 if (kPCIDeviceStateRequestPause & dead->deviceState) 1603 { 1604 dead->deviceState &= ~kPCIDeviceStateRequestPause; 1605 fWaitingPause--; 1606 } 1607 1608 prev = &bridge->child; 1609 while ((child = *prev)) 1610 { 1611 if (dead == child) 1612 { 1613 *prev = child->peer; 1614 break; 1615 } 1616 prev = &child->peer; 1617 } 1618 1619 if (!child) panic("bridgeRemoveChild"); 1620 1621 bridge->deviceState |= kPCIDeviceStateChildChanged; 1622 bridge->deviceState &= ~(kPCIDeviceStateTotalled | kPCIDeviceStateAllocated); 1623 1624 didKeep = bridgeDeallocateChildRanges(bridge, dead, deallocTypes, freeTypes); 1625 1626 if (childList && didKeep) 1627 { 1628 dead->parent = NULL; 1629 dead->peer = *childList; 1630 *childList = dead; 1631 } 1632 else 1633 { 1634 if ((pciDevice = OSDynamicCast(IOPCIDevice, dead->dtNub))) 1635 { 1636 pciDevice->reserved->configEntry = NULL; 1637 } 1638 if (dead->isBridge) 1639 fBridgeCount--; 1640 else 1641 fDeviceCount--; 1642 1643// memset(dead, 0xBB, sizeof(*dead)); 1644 IODelete(dead, IOPCIConfigEntry, 1); 1645 DLOG("deleted %p, bridges %d devices %d\n", dead, fBridgeCount, fDeviceCount); 1646 } 1647} 1648 1649//--------------------------------------------------------------------------- 1650 1651void CLASS::bridgeMoveChildren(IOPCIConfigEntry * to, IOPCIConfigEntry * list) 1652{ 1653 IOPCIConfigEntry * dead; 1654 IOPCIRange * range; 1655 IOPCIRange * childRange; 1656 bool ok; 1657 1658 while (list) 1659 { 1660 dead = list; 1661 list = list->peer; 1662 for (int rangeIndex = 0; rangeIndex <= kIOPCIRangeExpansionROM; rangeIndex++) 1663 { 1664 childRange = dead->ranges[rangeIndex]; 1665 if (!childRange) continue; 1666 if (!childRange->proposedSize) continue; 1667 if (!childRange->start) continue; 1668 1669 range = bridgeGetRange(to, childRange->type); 1670 if (!range) panic("!range"); 1671 1672 // reserve the alloc until terminate 1673 if (!dead->parent) 1674 { 1675 // head Q 1676 dead->parent = to; 1677 dead->peer = to->child; 1678 to->child = dead; 1679 DLOG("Reserves on ("D()") for ("D()"):\n", 1680 DEVICE_IDENT(to), DEVICE_IDENT(dead)); 1681 } 1682 DLOG(" %s: 0x%llx reserve 0x%llx, 0x%llx\n", 1683 gPCIResourceTypeName[childRange->type], 1684 childRange->start, childRange->proposedSize, childRange->totalSize); 1685 if (childRange->nextSubRange) panic("bridgeMoveChildren"); 1686// childRange->proposedSize = childRange->size; 1687 childRange->flags |= kIOPCIRangeFlagReserve; 1688 ok = IOPCIRangeListAllocateSubRange(range, childRange); 1689 if (!ok) panic("!IOPCIRangeListAllocateSubRange"); 1690 } 1691 } 1692} 1693 1694//--------------------------------------------------------------------------- 1695 1696void CLASS::bridgeDeadChild(IOPCIConfigEntry * bridge, IOPCIConfigEntry * dead) 1697{ 1698 IOPCIConfigEntry * pendingList = NULL; 1699 1700 if (kPCIDeviceStateDead & dead->deviceState) 1701 return; 1702 1703 DLOG("bridge %p dead child at "D()"\n", bridge, DEVICE_IDENT(dead)); 1704 markChanged(dead); 1705 bridgeRemoveChild(bridge, dead, 1706 kIOPCIRangeAllMask, kIOPCIRangeAllBridgeMask, &pendingList); 1707 if (pendingList) 1708 { 1709 bridgeMoveChildren(bridge, pendingList); 1710 } 1711} 1712 1713//--------------------------------------------------------------------------- 1714 1715void CLASS::bridgeProbeChild( IOPCIConfigEntry * bridge, IOPCIAddressSpace space, uint32_t resetMask ) 1716{ 1717 IOPCIConfigEntry * child = NULL; 1718 bool ok = true; 1719 uint32_t vendorProduct; 1720 1721 vendorProduct = configRead32(space, kIOPCIConfigVendorID); 1722 1723 if ((kPCIStatic != bridge->supportsHotPlug) 1724 && ((0 == (vendorProduct & 0xffff)) || (0xffff == (vendorProduct & 0xffff)))) 1725 { 1726 configWrite32(space, kIOPCIConfigVendorID, 0); 1727 vendorProduct = configRead32(space, kIOPCIConfigVendorID); 1728 } 1729 1730 for (child = bridge->child; child; child = child->peer) 1731 { 1732 if (kPCIDeviceStateDead & child->deviceState) 1733 continue; 1734 if (space.bits == child->space.bits) 1735 { 1736 DLOG("bridge %p scan existing child at "D()" state 0x%x\n", 1737 bridge, DEVICE_IDENT(child), child->deviceState); 1738 1739 // check bars? 1740 1741 if (!(kIOPCIConfiguratorNoTerminate & fFlags)) 1742 { 1743 if ((vendorProduct != child->vendorProduct) 1744 || (kPCIDeviceStateEjected & child->deviceState) 1745 || (kPCIDeviceStateToKill & child->deviceState)) 1746 { 1747 IOPCIConfigEntry * dead = child; 1748 if (!(kPCIDeviceStateEjected & child->deviceState)) 1749 { 1750 // create new if present 1751 child = NULL; 1752 } 1753 // may free child 1754 bridgeDeadChild(bridge, dead); 1755 } 1756 } 1757 break; 1758 } 1759 } 1760 1761 if (child) 1762 return; 1763 1764 uint32_t retries = 1; 1765 while ((0 == (vendorProduct & 0xffff)) || (0xffff == (vendorProduct & 0xffff))) 1766 { 1767 if (!--retries) 1768 return; 1769 vendorProduct = configRead32(space, kIOPCIConfigVendorID); 1770 } 1771 1772 child = IONew(IOPCIConfigEntry, 1); 1773 if (!child) return; 1774 1775 memset(child, 0, sizeof(*child)); 1776 child->id = ++fNextID; 1777 child->space = space; 1778 child->headerType = configRead8(child, kIOPCIConfigHeaderType) & 0x7f; 1779 child->classCode = configRead32(child, kIOPCIConfigRevisionID) >> 8; 1780 child->vendorProduct = vendorProduct; 1781 1782 DLOG("Probing type %u device class-code 0x%06x cmd 0x%04x at "D()" [state 0x%x]\n", 1783 child->headerType, child->classCode, configRead16(child, kIOPCIConfigCommand), 1784 DEVICE_IDENT(child), 1785 child->deviceState); 1786 1787 switch (child->headerType) 1788 { 1789 case kPCIHeaderType0: 1790 // skip devices aliased to host bridges 1791 if ((child->classCode & 0xFFFFFF) == 0x060000) 1792 break; 1793 1794 deviceProbeRanges(child, resetMask); 1795 break; 1796 1797 case kPCIHeaderType1: 1798 child->isBridge = true; 1799 bridgeProbeRanges(child, resetMask); 1800 break; 1801 1802 case kPCIHeaderType2: 1803 child->isBridge = true; 1804 cardbusProbeRanges(child, resetMask); 1805 break; 1806 1807 default: 1808 DLOG(" bad PCI header type 0x%x\n", child->headerType); 1809 ok = false; 1810 break; 1811 } 1812 1813 if (!ok) 1814 { 1815 IODelete(child, IOPCIConfigEntry, 1); 1816 return; 1817 } 1818 1819 if (findPCICapability(child, kIOPCIPCIExpressCapability, &child->expressCapBlock)) 1820 { 1821 if (child->isBridge) 1822 { 1823 enum 1824 { 1825 kLinkCapDataLinkLayerActiveReportingCapable = (1 << 20), 1826 kLinkStatusDataLinkLayerLinkActive = (1 << 13), 1827 kSlotCapHotplug = (1 << 6) 1828 }; 1829 uint32_t expressCaps, linkCaps, linkControl, slotCaps = kSlotCapHotplug; 1830 1831 expressCaps = configRead16(child, child->expressCapBlock + 0x02); 1832 linkCaps = configRead32(child, child->expressCapBlock + 0x0c); 1833 linkControl = configRead16(child, child->expressCapBlock + 0x10); 1834 if (0x100 & expressCaps) slotCaps = configRead32(child, child->expressCapBlock + 0x14); 1835 1836 if ((kPCIHotPlugTunnel <= bridge->supportsHotPlug) 1837 && (0x60 == (0xf0 & expressCaps))) // downstream port 1838 { 1839 if ((kLinkCapDataLinkLayerActiveReportingCapable & linkCaps) 1840 && (kSlotCapHotplug & slotCaps)) 1841 { 1842 child->linkInterrupts = true; 1843 } 1844 } 1845 1846 child->expressCaps = expressCaps; 1847 child->linkCaps = linkCaps; 1848 DLOG(" expressCaps 0x%x, linkControl 0x%x, linkCaps 0x%x, slotCaps 0x%x\n", 1849 child->expressCaps, linkControl, child->linkCaps, slotCaps); 1850 } 1851 child->expressDeviceCaps1 = configRead32(child, child->expressCapBlock + 0x04); 1852 child->expressMaxPayload = (child->expressDeviceCaps1 & 7); 1853 DLOG(" expressMaxPayload 0x%x\n", child->expressMaxPayload); 1854 } 1855 1856 bridgeAddChild(bridge, child); 1857 checkCacheLineSize(child); 1858} 1859 1860//--------------------------------------------------------------------------- 1861 1862uint32_t CLASS::findPCICapability(IOPCIConfigEntry * device, 1863 uint32_t capabilityID, uint32_t * found) 1864{ 1865 return(findPCICapability(device->space, capabilityID, found)); 1866} 1867 1868//--------------------------------------------------------------------------- 1869 1870uint32_t CLASS::findPCICapability(IOPCIAddressSpace space, 1871 uint32_t capabilityID, uint32_t * found) 1872{ 1873 uint32_t data; 1874 uint32_t offset, expressCap, firstOffset; 1875 1876 data = expressCap = firstOffset = 0; 1877 if (found) 1878 { 1879 firstOffset = *found; 1880 *found = 0; 1881 } 1882 1883 if (0 == ((kIOPCIStatusCapabilities << 16) 1884 & (configRead32(space, kIOPCIConfigCommand)))) 1885 return (0); 1886 1887 if (capabilityID >= 0x100) 1888 { 1889 if (!findPCICapability(space, kIOPCIPCIExpressCapability, &expressCap)) return (0); 1890 1891 capabilityID = -capabilityID; 1892 offset = 0x100; 1893 while (offset) 1894 { 1895 data = configRead32(space, offset); 1896 if ((offset > firstOffset) && (capabilityID == (data & 0xffff))) 1897 { 1898 if (found) 1899 *found = offset; 1900 break; 1901 } 1902 offset = (data >> 20) & 0xfff; 1903 if ((offset < 0x100) || (offset & 3)) 1904 offset = 0; 1905 } 1906 } 1907 else 1908 { 1909 offset = (0xff & configRead32(space, kIOPCIConfigCapabilitiesPtr)); 1910 if (offset & 3) 1911 offset = 0; 1912 while (offset) 1913 { 1914 data = configRead32(space, offset); 1915 if ((offset > firstOffset) && (capabilityID == (data & 0xff))) 1916 { 1917 if (found) 1918 *found = offset; 1919 break; 1920 } 1921 offset = (data >> 8) & 0xff; 1922 if (offset & 3) 1923 offset = 0; 1924 } 1925 } 1926 1927 return (offset ? data : 0); 1928} 1929 1930//--------------------------------------------------------------------------- 1931 1932struct BARProbeParam { 1933 CLASS * target; 1934 IOPCIConfigEntry * device; 1935 uint32_t lastBarNum; 1936 uint32_t resetMask; 1937}; 1938 1939void CLASS::safeProbeCallback( void * refcon ) 1940{ 1941 BARProbeParam * param = (BARProbeParam *) refcon; 1942 assert(param); 1943 1944 if (cpu_number() == 0) 1945 { 1946 param->target->probeBaseAddressRegister( 1947 param->device, param->lastBarNum, param->resetMask ); 1948 } 1949 if (cpu_number() == 99) 1950 { 1951 IOLog("safeProbeCallback() gcc workaround\n"); 1952 } 1953} 1954 1955void CLASS::safeProbeBaseAddressRegister(IOPCIConfigEntry * device, 1956 uint32_t lastBarNum, uint32_t resetMask) 1957{ 1958 uint32_t barNum; 1959 1960 for (barNum = 0; barNum <= lastBarNum; barNum++) 1961 { 1962 device->ranges[barNum] = IOPCIRangeAlloc(); 1963 IOPCIRangeInit(device->ranges[barNum], 0, 0, 0); 1964 } 1965 1966 { 1967#if NO_RENDEZVOUS_KERNEL 1968 boolean_t istate; 1969 istate = ml_set_interrupts_enabled(FALSE); 1970 probeBaseAddressRegister(device, lastBarNum, resetMask); 1971 ml_set_interrupts_enabled(istate); 1972#else 1973 BARProbeParam param; 1974 1975 param.target = this; 1976 param.device = device; 1977 param.lastBarNum = lastBarNum; 1978 param.resetMask = resetMask; 1979 1980 mp_rendezvous_no_intrs(&safeProbeCallback, ¶m); 1981#endif 1982 } 1983 1984#if PLX8680 1985 do 1986 { 1987 IOPCIRange * range; 1988 uint16_t command; 1989 volatile uint32_t * regs; 1990 uint32_t reg32, lut; 1991 IOPCIConfigEntry * parent; 1992 1993 if (0x868010b5 != device->vendorProduct) break; 1994 1995 command = configRead16(device, kIOPCIConfigCommand); 1996 configWrite16(device, kIOPCIConfigCommand, (command | kIOPCICommandMemorySpace | kIOPCICommandBusMaster)); 1997 1998 range = device->ranges[kIOPCIRangeBAR0]; 1999 if (!range) break; 2000 if (0x40000 != range->proposedSize) break; 2001 if (kIOPCIResourceTypeMemory != range->type) break; 2002 if (kPCIHeaderType1 != device->headerType) break; 2003 2004 parent = device; 2005 do { regs = parent->plx; } while (!regs && (parent = parent->parent)); 2006 if (regs) break; 2007 2008 IOMemoryDescriptor * 2009 md = IOMemoryDescriptor::withAddressRange(range->start, range->proposedSize, kIODirectionOutIn | kIOMemoryMapperNone, TASK_NULL); 2010 if (!md) break; 2011 IOMemoryMap * 2012 map = md->map(); 2013 if (!map) break; 2014 regs = (uint32_t *) map->getAddress(); 2015 2016 reg32 = regs[0]; 2017 IOLog("PLX regs 0x%x, 0x%x\n", (int) range->start, reg32); 2018 if (0x868010b5 != reg32) break; 2019 2020 reg32 = regs[(0x3e000 + 0xd4) / 4]; 2021 IOLog("PLX bar1 0x%x, 0x%x\n", (int) range->start, reg32); 2022 reg32 = regs[(0x3e000 + 0xd8) / 4]; 2023 IOLog("PLX bar1 0x%x, 0x%x\n", (int) range->start, reg32); 2024 2025 for (lut = 0; lut < 8; lut++) regs[((0x3e000 + 0xd94) / 4) + lut] = 0; 2026 2027 regs[(0x3e000 + 0xd4) / 4] = 0x0000000c; 2028 regs[(0x3e000 + 0xd8) / 4] = 0xfffffffc; 2029 2030 regs[(0x3e000 + 0xc3c) / 4] = 0x00000000; 2031 regs[(0x3e000 + 0xc40) / 4] = 0x00000000; 2032 2033 reg32 = regs[(0x3e000 + 0xd4) / 4]; 2034 IOLog("PLX bar1 0x%x, 0x%x\n", (int) range->start, reg32); 2035 reg32 = regs[(0x3e000 + 0xd8) / 4]; 2036 IOLog("PLX bar1 0x%x, 0x%x\n", (int) range->start, reg32); 2037 2038 for (barNum = 0; barNum <= lastBarNum; barNum++) 2039 { 2040 IOPCIRangeInit(device->ranges[barNum], 0, 0, 0); 2041 } 2042 2043 { 2044 BARProbeParam param; 2045 param.target = this; 2046 param.device = device; 2047 param.lastBarNum = lastBarNum; 2048 param.resetMask = resetMask; 2049 mp_rendezvous_no_intrs(&safeProbeCallback, ¶m); 2050 } 2051 2052 reg32 = regs[(0x3e000 + 0xd4) / 4]; 2053 IOLog("PLX bar1 0x%x, 0x%x\n", (int) range->start, reg32); 2054 reg32 = regs[(0x3e000 + 0xd8) / 4]; 2055 IOLog("PLX bar1 0x%x, 0x%x\n", (int) range->start, reg32); 2056 device->plx = regs; 2057 } 2058 while (false); 2059#endif /* PLX8680 */ 2060 2061 for (barNum = 0; barNum <= lastBarNum; barNum++) 2062 { 2063 if (!device->ranges[barNum]->proposedSize) 2064 { 2065 IOPCIRangeFree(device->ranges[barNum]); 2066 device->ranges[barNum] = NULL; 2067 } 2068 } 2069} 2070 2071//--------------------------------------------------------------------------- 2072 2073void CLASS::probeBaseAddressRegister(IOPCIConfigEntry * device, uint32_t lastBarNum, uint32_t resetMask) 2074{ 2075 IOPCIRange * range; 2076 uint32_t barNum, nextBarNum; 2077 uint32_t value; 2078 uint64_t value64, saved, upper, barMask; 2079 uint64_t start, size; 2080 uint32_t type; 2081 uint16_t command; 2082 uint8_t barOffset; 2083 bool clean64; 2084 2085 command = disableAccess(device, true); 2086 2087 if (kIOPCIRangeExpansionROM == lastBarNum) do 2088 { 2089 lastBarNum--; 2090 2091 barOffset = kIOPCIConfigExpansionROMBase; 2092 barMask = 0x7FF; 2093 2094 saved = configRead32(device, barOffset); 2095 configWrite32(device, barOffset, 0xFFFFFFFF & ~barMask); 2096 value = configRead32(device, barOffset); 2097 configWrite32(device, barOffset, saved); 2098 2099 // unimplemented BARs are hardwired to zero 2100 if (value == 0) continue; 2101 if (3 != (device->classCode >> 16)) continue; 2102 2103 range = device->ranges[kIOPCIRangeExpansionROM]; 2104 start = (resetMask & (1 << kIOPCIResourceTypeMemory)) ? 0 : (saved & ~barMask); 2105 value &= ~barMask; 2106 size = -value; 2107 IOPCIRangeInit(range, kIOPCIResourceTypeMemory, start, size, size); 2108 } 2109 while (false); 2110 2111 for (barNum = 0; barNum <= lastBarNum; barNum = nextBarNum) 2112 { 2113 barOffset = kIOPCIConfigBaseAddress0 + barNum * 4; 2114 nextBarNum = barNum + 1; 2115 value64 = (-1LL << 32); 2116 2117 saved = configRead32(device, barOffset); 2118 configWrite32(device, barOffset, 0xFFFFFFFF); 2119 value = configRead32(device, barOffset); 2120 configWrite32(device, barOffset, saved); 2121 2122 // unimplemented BARs are hardwired to zero 2123 if (value == 0) continue; 2124 2125 clean64 = false; 2126 if (value & 1) 2127 { 2128 barMask = 0x3; 2129 type = kIOPCIResourceTypeIO; 2130 2131 // If the upper 16 bits for I/O space 2132 // are all 0, then we should ignore them. 2133 if ((value & 0xFFFF0000) == 0) value |= 0xFFFF0000; 2134 } 2135 else 2136 { 2137 barMask = 0xf; 2138 if (value & 0x8) 2139 type = kIOPCIResourceTypePrefetchMemory; 2140 else 2141 type = kIOPCIResourceTypeMemory; 2142 2143 switch (value & 6) 2144 { 2145 case 2: /* below 1Mb */ 2146 case 0: /* 32-bit mem */ 2147 case 6: /* reserved */ 2148 type = kIOPCIResourceTypeMemory; 2149 break; 2150 2151 case 4: /* 64-bit mem */ 2152 clean64 = (kIOPCIResourceTypePrefetchMemory == type); 2153 if (clean64) 2154 { 2155 upper = configRead32(device, barOffset + 4); 2156 saved |= (upper << 32); 2157 configWrite32(device, barOffset + 4, 0xFFFFFFFF); 2158 value64 = configRead32(device, barOffset + 4); 2159 value64 <<= 32; 2160 configWrite32(device, barOffset + 4, upper); 2161 } 2162 nextBarNum = barNum + 2; 2163 break; 2164 } 2165 } 2166 2167 start = (resetMask & (1 << type)) ? 0 : (saved & ~barMask); 2168 value &= ~barMask; 2169 value64 |= value; 2170 size = -value64; 2171 2172 if (size > MAX_BAR_SIZE) 2173 { 2174 size &= 0xFFFFFFFF; 2175 clean64 = false; 2176 nextBarNum--; 2177 } 2178 if (start == value64) 2179 { 2180 DLOG(" [0x%x] can't probe\n", barOffset); 2181 continue; 2182 } 2183 2184 range = device->ranges[barNum]; 2185 IOPCIRangeInit(range, type, start, size, size); 2186 range->minAddress = minBARAddressDefault[type]; 2187 if (clean64 && (kIOPCIConfiguratorPFM64 & fFlags)) 2188 range->maxAddress = 0xFFFFFFFFFFFFFFFFULL; 2189#if 0 2190 if ((0x91821b4b == configRead32(device->space, kIOPCIConfigVendorID)) 2191 && (0x18 == barOffset)) 2192 { 2193 range->proposedSize = range->totalSize = 0x4000; 2194 } 2195#endif 2196 } 2197 2198 restoreAccess(device, command); 2199} 2200 2201//--------------------------------------------------------------------------- 2202 2203void CLASS::deviceProbeRanges( IOPCIConfigEntry * device, uint32_t resetMask ) 2204{ 2205 uint32_t idx; 2206 IOPCIRange * range; 2207 2208 // Probe BAR 0 through 5 and ROM 2209 safeProbeBaseAddressRegister(device, kIOPCIRangeExpansionROM, resetMask); 2210 2211 for (idx = kIOPCIRangeBAR0; idx <= kIOPCIRangeExpansionROM; idx++) 2212 { 2213 range = device->ranges[idx]; 2214 if (!range) 2215 continue; 2216 DLOG(" [0x%x %s] 0x%llx:0x%llx\n", 2217 (idx == kIOPCIRangeExpansionROM) ? 2218 kIOPCIConfigExpansionROMBase : idx * 4 + kIOPCIConfigBaseAddress0, 2219 gPCIResourceTypeName[range->type], range->start, range->proposedSize); 2220 } 2221} 2222 2223//--------------------------------------------------------------------------- 2224 2225void CLASS::bridgeProbeBusRange(IOPCIConfigEntry * bridge, uint32_t resetMask) 2226{ 2227 IOPCIRange * range; 2228 uint64_t start, size; 2229 2230 // Record the bridge secondary and subordinate bus numbers 2231 if (resetMask & (1 << kIOPCIResourceTypeBusNumber)) 2232 { 2233 bridge->secBusNum = 0; 2234 bridge->subBusNum = 0; 2235 } 2236 else 2237 { 2238 bridge->secBusNum = configRead8(bridge, kPCI2PCISecondaryBus); 2239 bridge->subBusNum = configRead8(bridge, kPCI2PCISubordinateBus); 2240 } 2241 2242 range = IOPCIRangeAlloc(); 2243 start = bridge->secBusNum; 2244 size = bridge->subBusNum - bridge->secBusNum + 1; 2245 IOPCIRangeInit(range, kIOPCIResourceTypeBusNumber, start, size, kPCIBridgeBusNumberAlignment); 2246 bridge->ranges[kIOPCIRangeBridgeBusNumber] = range; 2247} 2248 2249//--------------------------------------------------------------------------- 2250 2251void CLASS::bridgeProbeRanges( IOPCIConfigEntry * bridge, uint32_t resetMask ) 2252{ 2253 IOPCIRange * range; 2254 IOPCIScalar start, end, upper, size; 2255 2256 bridgeProbeBusRange(bridge, resetMask); 2257 2258 // Probe bridge BAR0 and BAR1 2259 safeProbeBaseAddressRegister(bridge, kIOPCIRangeBAR1, resetMask); 2260 2261#if 0 2262 // test bridge BARs 2263 if ((5 == bridge->space.s.busNum) && (0 == bridge->space.s.deviceNum) && (0 == bridge->space.s.functionNum)) 2264 { 2265 for (int barNum = 0; barNum <= kIOPCIRangeBAR1; barNum++) 2266 { 2267 bridge->ranges[barNum] = IOPCIRangeAlloc(); 2268 IOPCIRangeInit(bridge->ranges[barNum], kIOPCIResourceTypeMemory, 0, 0x40000, 0x40000); 2269 } 2270 } 2271#endif 2272 2273 DLOG_RANGE(" bridge BAR0", bridge->ranges[kIOPCIRangeBAR0]); 2274 DLOG_RANGE(" bridge BAR1", bridge->ranges[kIOPCIRangeBAR1]); 2275 2276 // Probe memory base and limit 2277 2278 end = configRead32(bridge, kPCI2PCIMemoryRange); 2279 2280 start = (end & 0xfff0) << 16; 2281 end |= 0x000fffff; 2282 if (start && (end > start)) 2283 size = end - start + 1; 2284 else 2285 size = start = 0; 2286 if (resetMask & (1 << kIOPCIResourceTypeMemory)) start = 0; 2287 2288 range = IOPCIRangeAlloc(); 2289 IOPCIRangeInit(range, kIOPCIResourceTypeMemory, start, size, 2290 kPCIBridgeMemoryAlignment); 2291 bridge->ranges[kIOPCIRangeBridgeMemory] = range; 2292 2293 // Probe prefetchable memory base and limit 2294 2295 end = configRead32(bridge, kPCI2PCIPrefetchMemoryRange); 2296 2297 if (true /* should check r/w */) 2298 { 2299 bridge->clean64 = (0x1 == (end & 0xf)); 2300 if (bridge->clean64) 2301 { 2302 upper = configRead32(bridge, kPCI2PCIPrefetchUpperBase); 2303 start |= (upper << 32); 2304 upper = configRead32(bridge, kPCI2PCIPrefetchUpperLimit); 2305 end |= (upper << 32); 2306 } 2307 2308 start = (end & 0xfff0) << 16; 2309 end |= 0x000fffff; 2310 if (start && (end > start)) 2311 size = end - start + 1; 2312 else 2313 size = start = 0; 2314 if (resetMask & (1 << kIOPCIResourceTypePrefetchMemory)) start = 0; 2315 2316 range = IOPCIRangeAlloc(); 2317 IOPCIRangeInit(range, kIOPCIResourceTypePrefetchMemory, start, size, 2318 kPCIBridgeMemoryAlignment); 2319 if (bridge->clean64 && (kIOPCIConfiguratorPFM64 & fFlags)) 2320 range->maxAddress = 0xFFFFFFFFFFFFFFFFULL; 2321 bridge->ranges[BRN(kIOPCIResourceTypePrefetchMemory)] = range; 2322 } 2323 2324 // Probe I/O base and limit 2325 2326 end = configRead32(bridge, kPCI2PCIIORange); 2327 2328 if ((end & (0x0e0e)) == 0) 2329 { 2330 // I/O Base and Limit register at dword 7 (0x1c). 2331 // If bridge does not implement an I/O address range, then both 2332 // the I/O Base and I/O Limit registers must be implemented as 2333 // read-only registers that return zero when read. The bottom 2334 // and the top of the I/O address range will always be aligned 2335 // to a 4KB boundary. 2336 // 2337 // I/O Limit | I/O Base 2338 // 7...4 3...0 | 7...4 3...0 2339 // ^ ^ ^ ^ 2340 // | | | | 2341 // | | | +- 0 for 16bit decode, 1 for 32-bit decode 2342 // | | | 2343 // | | +- Upper hex digit of 16-bit or 32-bit I/O range 2344 // | | start address. Read-only field. 2345 // | | 2346 // | +- 0 for 16bit decode, 1 for 32-bit decode 2347 // | 2348 // +- Upper hex digit of 16-bit or 32-bit I/O range end address. 2349 // Read-write field. 2350 2351 start = (end & 0xf0) << 8; 2352 end = (end & 0xffff) | 0xfff; 2353 2354 // Limit may be less than the base, when there are no I/O addresses 2355 // on the secondary side of the bridge. Or when BIOS has failed to 2356 // assign I/O resources to devices behind the bridge. 2357 2358 if (start && (end > start)) 2359 size = end - start + 1; 2360 else 2361 size = start = 0; 2362 if (resetMask & (1 << kIOPCIResourceTypeIO)) start = 0; 2363 2364 range = IOPCIRangeAlloc(); 2365 IOPCIRangeInit(range, kIOPCIResourceTypeIO, start, size, 2366 kPCIBridgeIOAlignment); 2367 bridge->ranges[kIOPCIRangeBridgeIO] = range; 2368 } 2369 2370 DLOG_RANGE(" BUS", bridge->ranges[kIOPCIRangeBridgeBusNumber]); 2371 DLOG_RANGE(" I/O", bridge->ranges[kIOPCIRangeBridgeIO]); 2372 DLOG_RANGE(" MEM", bridge->ranges[kIOPCIRangeBridgeMemory]); 2373 DLOG_RANGE(" PFM", bridge->ranges[kIOPCIRangeBridgePFMemory]); 2374} 2375 2376//--------------------------------------------------------------------------- 2377 2378void CLASS::cardbusProbeRanges(IOPCIConfigEntry * bridge, uint32_t resetMask) 2379{ 2380 IOPCIRange * range; 2381 2382 bridgeProbeBusRange(bridge, resetMask); 2383 2384 // Maximal bus range. 2385 2386 range = bridge->ranges[kIOPCIRangeBridgeBusNumber]; 2387 range->flags |= kIOPCIRangeFlagNoCollapse | kIOPCIRangeFlagPermanent; 2388 2389 // 4K register space 2390 2391 range = IOPCIRangeAlloc(); 2392 IOPCIRangeInit(range, kIOPCIResourceTypeMemory, 0, 4096, 4096); 2393 bridge->ranges[kIOPCIRangeBAR0] = range; 2394 2395 // Maximal memory and I/O range. 2396 2397 range = IOPCIRangeAlloc(); 2398 IOPCIRangeInit(range, kIOPCIResourceTypeIO, 0, kPCIBridgeIOAlignment, kPCIBridgeIOAlignment); 2399 range->flags = kIOPCIRangeFlagNoCollapse | kIOPCIRangeFlagPermanent; 2400 bridge->ranges[kIOPCIRangeBridgeIO] = range; 2401 2402 range = IOPCIRangeAlloc(); 2403 IOPCIRangeInit(range, kIOPCIResourceTypeMemory, 0, kPCIBridgeMemoryAlignment, kPCIBridgeMemoryAlignment); 2404 range->flags = kIOPCIRangeFlagNoCollapse | kIOPCIRangeFlagPermanent; 2405 bridge->ranges[kIOPCIRangeBridgeMemory] = range; 2406} 2407 2408 2409//--------------------------------------------------------------------------- 2410 2411int32_t CLASS::scanProc(void * ref, IOPCIConfigEntry * bridge) 2412{ 2413 int32_t ok = true; 2414 bool bootScan = (NULL != ref); 2415 bool haveBus; 2416 uint32_t resetMask; 2417 2418 if (kPCIDeviceStateDead & bridge->deviceState) return (ok); 2419 2420 if (!(kPCIDeviceStateScanned & bridge->deviceState)) 2421 { 2422 haveBus = ((bridge->secBusNum || bridge->isHostBridge) 2423 && ((bootScan && bridge->ranges[kIOPCIRangeBridgeBusNumber]->proposedSize) 2424 || ((!bootScan) && bridge->ranges[kIOPCIRangeBridgeBusNumber]->size))); 2425 if (haveBus) 2426 { 2427 DLOG("scan %s"B()"\n", bootScan ? "(boot) " : "", BRIDGE_IDENT(bridge)); 2428 resetMask = 0; 2429 if (kPCIStatic != bridge->supportsHotPlug) 2430 { 2431 resetMask = ((1 << kIOPCIResourceTypeMemory) 2432 | (1 << kIOPCIResourceTypePrefetchMemory) 2433 | (1 << kIOPCIResourceTypeIO)); 2434 if (!bootScan) resetMask |= (1 << kIOPCIResourceTypeBusNumber); 2435 } 2436 bridgeScanBus(bridge, bridge->secBusNum, resetMask); 2437 bridge->deviceState |= kPCIDeviceStateScanned; 2438 if (kPCIDeviceStateChildChanged & bridge->deviceState) 2439 { 2440 DLOG("bridge "B()" child change\n", BRIDGE_IDENT(bridge)); 2441#if 0 2442 IOPCIConfigEntry * parents; 2443 for (parents = bridge; 2444 parents = parents->parent; 2445 parents->deviceState &= ~(kPCIDeviceStateTotalled), true) {} 2446#elif 0 2447 bridge->parent->deviceState &= ~(kPCIDeviceStateTotalled | kPCIDeviceStateAllocated); 2448#endif 2449 bridge->deviceState &= ~(kPCIDeviceStateTotalled | kPCIDeviceStateAllocated 2450 | kPCIDeviceStateAllocatedBus); 2451 } 2452 } 2453 2454 // Associate bootrom devices. 2455 bridgeConnectDeviceTree(bridge); 2456 } 2457 if (!bootScan) 2458 { 2459 if (!(kPCIDeviceStateAllocatedBus & bridge->deviceState)) 2460 { 2461 FOREACH_CHILD(bridge, child) child->deviceState &= ~kPCIDeviceStateAllocatedBus; 2462 bridge->deviceState &= ~kPCIDeviceStateTotalled; 2463 ok = bridgeTotalResources(bridge, (1 << kIOPCIResourceTypeBusNumber)); 2464 if (ok) 2465 { 2466 ok = bridgeAllocateResources(bridge, (1 << kIOPCIResourceTypeBusNumber)); 2467 DLOG("bus alloc done (bridge "B()", state 0x%x, ok %d)\n", 2468 BRIDGE_IDENT(bridge), bridge->deviceState, ok); 2469 } 2470 if (ok > 0) bridge->deviceState |= kPCIDeviceStateAllocatedBus; 2471 else bridge->parent->deviceState &= ~kPCIDeviceStateAllocatedBus; 2472 } 2473 } 2474 return (ok); 2475} 2476 2477//--------------------------------------------------------------------------- 2478 2479int32_t CLASS::bootResetProc(void * ref, IOPCIConfigEntry * bridge) 2480{ 2481 bool ok = true; 2482 uint32_t reg32; 2483 2484 if ((kPCIStatic != bridge->supportsHotPlug) 2485 && bridge->ranges[kIOPCIRangeBridgeBusNumber] 2486 && !bridge->ranges[kIOPCIRangeBridgeBusNumber]->nextSubRange) 2487 { 2488 bridge->ranges[kIOPCIRangeBridgeBusNumber]->start = 0; 2489 bridge->ranges[kIOPCIRangeBridgeBusNumber]->size = 0; 2490 bridge->ranges[kIOPCIRangeBridgeBusNumber]->totalSize = 1; 2491 bridge->ranges[kIOPCIRangeBridgeBusNumber]->proposedSize = 1; 2492 if (kPCIHotPlugTunnelRootParent != bridge->supportsHotPlug) 2493 { 2494 DLOG("boot reset "B()"\n", BRIDGE_IDENT(bridge)); 2495 reg32 = configRead32(bridge, kPCI2PCIPrimaryBus); 2496 reg32 &= ~0x00ffffff; 2497 configWrite32(bridge, kPCI2PCIPrimaryBus, reg32); 2498 } 2499 } 2500 return (ok); 2501} 2502 2503//--------------------------------------------------------------------------- 2504 2505int32_t CLASS::totalProc(void * ref, IOPCIConfigEntry * bridge) 2506{ 2507 bool ok; 2508 2509 if (!(kPCIDeviceStateAllocatedBus & bridge->deviceState)) return (true); 2510 if (kPCIDeviceStateTotalled & bridge->deviceState) return (true); 2511 2512 ok = bridgeTotalResources(bridge, 2513 (1 << kIOPCIResourceTypeMemory) 2514 | (1 << kIOPCIResourceTypePrefetchMemory) 2515 | (1 << kIOPCIResourceTypeIO)); 2516 2517 if (!ok) bridge->parent->deviceState &= ~kPCIDeviceStateAllocated; 2518 bridge->deviceState |= kPCIDeviceStateTotalled; 2519 2520 return (true); 2521} 2522 2523//--------------------------------------------------------------------------- 2524 2525int32_t CLASS::allocateProc(void * ref, IOPCIConfigEntry * bridge) 2526{ 2527 int32_t ok = true; 2528 2529 if (!(kPCIDeviceStateAllocatedBus & bridge->deviceState)) return (ok); 2530 if (kPCIDeviceStateAllocated & bridge->deviceState) return (ok); 2531 2532 FOREACH_CHILD(bridge, child) child->deviceState &= ~kPCIDeviceStateAllocated; 2533 2534 ok = bridgeAllocateResources(bridge, 2535 (1 << kIOPCIResourceTypeMemory) 2536 | (1 << kIOPCIResourceTypePrefetchMemory) 2537 | (1 << kIOPCIResourceTypeIO)); 2538 DLOG("alloc done (bridge "B()", state 0x%x, ok %d)\n", 2539 BRIDGE_IDENT(bridge), bridge->deviceState, ok); 2540 2541 if (ok > 0) bridge->deviceState |= kPCIDeviceStateAllocated; 2542 else bridge->parent->deviceState &= ~kPCIDeviceStateAllocated; 2543 2544 return (ok); 2545} 2546 2547//--------------------------------------------------------------------------- 2548 2549void CLASS::doConfigure(uint32_t options) 2550{ 2551 bool bootConfig = (kIOPCIConfiguratorBoot & options); 2552 2553 fMaxPayload = 5; 2554 2555 if (bootConfig) iterate("boot reset", &CLASS::scanProc, &CLASS::bootResetProc, this); 2556 iterate("scan total", &CLASS::scanProc, &CLASS::totalProc, NULL); 2557 iterate("allocate", &CLASS::allocateProc, NULL, NULL); 2558 iterate("finalize", &CLASS::bridgeFinalizeConfigProc, NULL, NULL); 2559} 2560 2561//--------------------------------------------------------------------------- 2562 2563enum 2564{ 2565 kIteratorNew = 0, 2566 kIteratorCheck = 1, 2567 kIteratorDidCheck = 2, 2568 kIteratorDoneCheck = 3, 2569}; 2570 2571void CLASS::iterate(const char * what, IterateProc topProc, IterateProc bottomProc, void * ref) 2572{ 2573 IOPCIConfigEntry * device; 2574 IOPCIConfigEntry * parent; 2575 int32_t ok; 2576 uint32_t revisits; 2577 bool didCheck; 2578 2579 device = fRoot; 2580 device->iterator = kIteratorCheck; 2581 revisits = 0; 2582 2583 DLOG("iterate %s: start\n", what); 2584 do 2585 { 2586 parent = device->parent; 2587// DLOG("iterate(bridge "B()", state 0x%x, parent 0x%x)\n", BRIDGE_IDENT(device), device->iterator, parent ? parent->iterator : 0); 2588 ok = true; 2589 didCheck = false; 2590 2591 if (device->iterator == kIteratorCheck) 2592 { 2593 didCheck = true; 2594 if (topProc) 2595 { 2596 ok = (this->*topProc)(ref, device); 2597 } 2598 device->iterator = kIteratorDidCheck; 2599 } 2600 2601 if (!ok) 2602 { 2603 if (++revisits > (8 * fBridgeCount)) 2604 { 2605 DLOG("iterate %s: HUNG?\n", what); 2606 ok = -1; 2607 } 2608 } 2609 2610 if (ok < 0) break; 2611 2612 if (parent && !ok) 2613 { 2614 parent->iterator = kIteratorCheck; 2615 device = parent; 2616 } 2617 else 2618 { 2619 IOPCIConfigEntry * child; 2620 IOPCIConfigEntry * next = NULL; 2621 for (child = device->child; child; child = child->peer) 2622 { 2623 if (!child->isBridge) 2624 continue; 2625 if (didCheck) 2626 child->iterator = kIteratorCheck; 2627 if (!next && (child->iterator < kIteratorDidCheck)) 2628 next = child; 2629 } 2630 if (next) 2631 { 2632 device = next; 2633 } 2634 else 2635 { 2636 device->iterator = kIteratorDoneCheck; 2637 if (bottomProc) 2638 { 2639 (void) (this->*bottomProc)(ref, device); 2640 } 2641 device = parent; 2642 } 2643 } 2644 } 2645 while (device); 2646 DLOG("iterate %s: end(%d)\n", what, revisits); 2647} 2648 2649//--------------------------------------------------------------------------- 2650 2651void CLASS::configure(uint32_t options) 2652{ 2653 bool bootConfig = (kIOPCIConfiguratorBoot & options); 2654 2655 IOLog("[ PCI configuration begin ]\n"); 2656 2657 PE_Video consoleInfo; 2658 2659 fFlags |= options; 2660 2661#if defined(__i386__) || defined(__x86_64__) 2662 if (bootConfig) 2663 { 2664 if (!fPFMConsole) 2665 { 2666 IOService::getPlatform()->getConsoleInfo(&consoleInfo); 2667 fPFMConsole = consoleInfo.v_baseAddr; 2668#ifndef __LP64__ 2669 fPFMConsole |= (((uint64_t) consoleInfo.v_baseAddrHigh) << 32); 2670#endif 2671 DLOG("console %ld x %ld @ 0x%qx\n", 2672 consoleInfo.v_width, consoleInfo.v_height, fPFMConsole); 2673 } 2674 fConsoleRange = NULL; 2675 getPlatform()->setConsoleInfo(0, kPEDisableScreen); 2676 } 2677#endif 2678 2679 doConfigure(options); 2680 2681#if defined(__i386__) || defined(__x86_64__) 2682 if (bootConfig) 2683 { 2684 if (fConsoleRange) 2685 { 2686 if (fConsoleRange->start) 2687 fPFMConsole += fConsoleRange->start; 2688 else 2689 fPFMConsole = 0; 2690 } 2691 if (!fPFMConsole) 2692 { 2693 DLOG("!! lost console !!\n"); 2694 } 2695 else 2696 { 2697 if (fConsoleRange) 2698 { 2699 consoleInfo.v_baseAddr = (fPFMConsole | 1); 2700#ifdef __LP64__ 2701 DLOG("console setting @ %lx\n", 2702 consoleInfo.v_baseAddr); 2703#else 2704 consoleInfo.v_baseAddrHigh = (fPFMConsole >> 32); 2705 DLOG("console setting 0x%lx:%lx\n", 2706 consoleInfo.v_baseAddrHigh, consoleInfo.v_baseAddr); 2707#endif 2708 getPlatform()->setConsoleInfo(&consoleInfo, kPEBaseAddressChange); 2709 } 2710 getPlatform()->setConsoleInfo(NULL, kPEEnableScreen); 2711 if (fConsoleRange) 2712 IOLog("console relocated to 0x%llx\n", fPFMConsole); 2713 } 2714 } 2715#endif 2716 2717 fFlags &= ~options; 2718 2719 IOLog("[ PCI configuration end, bridges %d, devices %d ]\n", fBridgeCount, fDeviceCount); 2720} 2721 2722//--------------------------------------------------------------------------- 2723 2724IOPCIRange * CLASS::bridgeGetRange(IOPCIConfigEntry * bridge, uint32_t type) 2725{ 2726 IOPCIRange * range; 2727 2728 if (bridge->isHostBridge && (type != kIOPCIResourceTypeBusNumber)) 2729 { 2730 // use global host ranges 2731 bridge = fRoot; 2732 } 2733 switch (type) 2734 { 2735 case kIOPCIResourceTypePrefetchMemory: 2736 range = bridge->ranges[BRN(kIOPCIResourceTypePrefetchMemory)]; 2737 if (range) 2738 break; 2739 /* fall thru */ 2740 2741 case kIOPCIResourceTypeMemory: 2742 range = bridge->ranges[BRN(kIOPCIResourceTypeMemory)]; 2743 break; 2744 2745 case kIOPCIResourceTypeIO: 2746 case kIOPCIResourceTypeBusNumber: 2747 range = bridge->ranges[BRN(type)]; 2748 break; 2749 2750 default: 2751 range = NULL; 2752 break; 2753 } 2754 return (range); 2755} 2756 2757//--------------------------------------------------------------------------- 2758 2759void CLASS::logAllocatorRange(IOPCIConfigEntry * device, IOPCIRange * range, char c) 2760{ 2761 DLOG(" %s: 0x%llx:0x%llx,0x%llx-0x%llx,0x%llx:0x%llx (at "D()") %s%s%s%s%s%s%c", 2762 gPCIResourceTypeName[range->type], 2763 range->start, 2764 range->size, range->proposedSize, 2765 range->totalSize, range->extendSize, 2766 range->alignment, 2767 DEVICE_IDENT(device), 2768 (NULL != range->nextSubRange) ? "A" : "a", 2769 (kIOPCIRangeFlagRelocatable & range->flags) ? "R" : "r", 2770 (kIOPCIRangeFlagSplay & range->flags) ? "S" : "s", 2771 (kIOPCIRangeFlagMaximizeSize & range->flags) ? "M" : "m", 2772 (kIOPCIRangeFlagMaximizeRoot & range->flags) ? "B" : "b", 2773 (kIOPCIRangeFlagReserve & range->flags) ? "V" : "v", 2774 c); 2775} 2776 2777//--------------------------------------------------------------------------- 2778 2779bool CLASS::bridgeTotalResources(IOPCIConfigEntry * bridge, uint32_t typeMask) 2780{ 2781 IOPCIConfigEntry * child; 2782 IOPCIRange * range; 2783 IOPCIRange * childRange; 2784 uint32_t type; 2785 bool ok = true; 2786 2787 IOPCIScalar totalSize[kIOPCIResourceTypeCount]; 2788 IOPCIScalar maxAlignment[kIOPCIResourceTypeCount]; 2789 IOPCIScalar minAddress[kIOPCIResourceTypeCount]; 2790 IOPCIScalar maxAddress[kIOPCIResourceTypeCount]; 2791 IOPCIScalar countMaximize[kIOPCIResourceTypeCount]; 2792 2793 if (bridge == fRoot) return (ok); 2794 if (kPCIDeviceStateDead & bridge->deviceState) return (ok); 2795 2796 DLOG("bridgeTotalResources(bridge "B()", iter 0x%x, state 0x%x, type 0x%x)\n", 2797 BRIDGE_IDENT(bridge), bridge->iterator, bridge->deviceState, typeMask); 2798 2799 bzero(&totalSize[0], sizeof(totalSize)); 2800 if (bridge != fRoot) totalSize[kIOPCIResourceTypeBusNumber] = 1; 2801 2802 bcopy(&minBridgeAlignments[0], &maxAlignment[0], sizeof(maxAlignment)); 2803 2804 bzero(&minAddress[0], sizeof(minAddress)); 2805 bcopy(&maxBridgeAddressDefault[0], &maxAddress[0], sizeof(maxAddress)); 2806 if (bridge->clean64 && (kIOPCIConfiguratorPFM64 & fFlags)) 2807 maxAddress[kIOPCIResourceTypePrefetchMemory] = 0xFFFFFFFFFFFFFFFFULL; 2808 bzero(&countMaximize[0], sizeof(countMaximize)); 2809 2810 if ( ((1 << kIOPCIResourceTypeMemory) 2811 | (1 << kIOPCIResourceTypePrefetchMemory) 2812 | (1 << kIOPCIResourceTypeIO)) 2813 & typeMask) 2814 do 2815 { 2816 if (!bridge->child) break; 2817 for (child = bridge->child; child; child = child->peer) 2818 { 2819 if (!(kPCIDeviceStateDead & child->deviceState)) break; 2820 } 2821 if (child) break; 2822 // all children are dead, move reserved allocs to parent & free bridge ranges 2823 IOPCIConfigEntry * pendingList = NULL; 2824 IOPCIConfigEntry * next; 2825 for (child = bridge->child; child; child = next) 2826 { 2827 next = child->peer; 2828 bridgeRemoveChild(bridge, child, kIOPCIRangeAllBarsMask, 0, &pendingList); 2829 } 2830 bridgeDeallocateChildRanges(bridge->parent, bridge, 2831 kIOPCIRangeAllBridgeMask & ~(1 << kIOPCIRangeBridgeBusNumber), 0); 2832 if (!pendingList) panic("!pendingList"); 2833 bridgeMoveChildren(bridge->parent, pendingList); 2834 bridge->parent->deviceState &= ~(kPCIDeviceStateTotalled | kPCIDeviceStateAllocated); 2835 } 2836 while (false); 2837 2838 for (child = bridge->child; child; child = child->peer) 2839 { 2840 for (int i = 0; i < kIOPCIRangeCount; i++) 2841 { 2842 childRange = child->ranges[i]; 2843 if (!childRange) continue; 2844 if (!((1 << childRange->type) & typeMask)) continue; 2845 range = bridgeGetRange(bridge, childRange->type); 2846 if (!range) continue; 2847 type = range->type; 2848 if (kIOPCIRangeFlagMaximizeSize & childRange->flags) countMaximize[type]++; 2849 if (!(childRange->totalSize + childRange->extendSize)) continue; 2850 2851 logAllocatorRange(child, childRange, '\n'); 2852 2853 totalSize[type] += childRange->totalSize + childRange->extendSize; 2854 if (childRange->alignment > maxAlignment[type]) 2855 maxAlignment[type] = childRange->alignment; 2856 2857 if (childRange->minAddress < minAddress[type]) 2858 minAddress[type] = childRange->minAddress; 2859 if (childRange->maxAddress < maxAddress[type]) 2860 { 2861 DLOG(" %s: maxAddr change 0x%llx -> 0x%llx (at "D()")\n", 2862 gPCIResourceTypeName[type], 2863 maxAddress[type], childRange->maxAddress, DEVICE_IDENT(child)); 2864 maxAddress[type] = childRange->maxAddress; 2865 } 2866 2867 if (childRange->proposedSize 2868 && child->expressCapBlock 2869 && ((kIOPCIResourceTypeMemory == childRange->type) 2870 || (kIOPCIResourceTypePrefetchMemory == childRange->type))) 2871 { 2872 if (child->expressMaxPayload < fMaxPayload) 2873 { 2874 fMaxPayload = child->expressMaxPayload; 2875 } 2876 } 2877 } 2878 } 2879 2880 for (type = 0; type < kIOPCIResourceTypeCount; type++) 2881 { 2882 if (!((1 << type) & typeMask)) continue; 2883 if (bridge->isHostBridge) continue; 2884 range = bridgeGetRange(bridge, type); 2885 if (range) do 2886 { 2887 if (((kIOPCIRangeFlagMaximizeSize | kIOPCIRangeFlagMaximizeRoot) & range->flags) 2888 && !totalSize[type]) totalSize[type] = minBridgeAlignments[type]; 2889 totalSize[type] = IOPCIScalarAlign(totalSize[type], minBridgeAlignments[type]); 2890 2891 if (totalSize[type] != range->totalSize 2892 && !(kIOPCIRangeFlagPermanent & range->flags)) 2893 { 2894 DLOG(" %s: 0x%llx: size change 0x%llx -> 0x%llx\n", 2895 gPCIResourceTypeName[type], 2896 range->start, range->proposedSize, totalSize[type]); 2897 range->totalSize = totalSize[type]; 2898 if (kIOPCIRangeFlagMaximizeRoot & range->flags) {} 2899 else 2900 { 2901 bridge->rangeSizeChanges |= (1 << BRN(type)); 2902 bridge->rangeRequestChanges |= (1 << type); 2903 ok = false; 2904 } 2905 } 2906 if (!((kIOPCIRangeFlagMaximizeSize | kIOPCIRangeFlagMaximizeRoot) & range->flags)) 2907 { 2908 range->alignment = maxAlignment[type]; 2909 } 2910 range->minAddress = minAddress[type]; 2911 range->maxAddress = maxAddress[type]; 2912 2913 DLOG(" %s: total child reqs 0x%llx of 0x%llx maxalign 0x%llx\n", 2914 gPCIResourceTypeName[type], 2915 range->totalSize, range->size, range->alignment); 2916 } 2917 while (false); 2918 } 2919 2920 return (ok); 2921} 2922 2923bool CLASS::treeInState(IOPCIConfigEntry * entry, uint32_t state, uint32_t mask) 2924{ 2925 for (; entry; entry = entry->parent) 2926 { 2927 if (state == (mask & entry->deviceState)) break; 2928 } 2929 return (NULL != entry); 2930} 2931 2932static uint32_t IOPCIRangeStateOrder(IOPCIRange * range) 2933{ 2934 uint32_t order = 0; 2935 2936 // order 1st allocated, placed, nonresize or shrink, resize, maximise 2937 2938 if (range->nextSubRange) order |= (1 << 31); 2939 if (range->start) order |= (1 << 30); 2940 if (/*range->nextSubRange &&*/ (range->proposedSize <= range->size)) order |= (1 << 29); 2941 if (!((kIOPCIRangeFlagMaximizeRoot | kIOPCIRangeFlagMaximizeSize | kIOPCIRangeFlagSplay) 2942 & range->flags)) order |= (1 << 28); 2943 2944 return (order); 2945} 2946 2947bool IOPCIRangeAppendSubRange(IOPCIRange ** list, IOPCIRange * newRange) 2948{ 2949 IOPCIRange ** prev; 2950 IOPCIRange * range; 2951 uint32_t newOrder, oldOrder; 2952 2953 newOrder = IOPCIRangeStateOrder(newRange); 2954 prev = list; 2955 do 2956 { 2957 range = *prev; 2958 if (!range) break; 2959 oldOrder = IOPCIRangeStateOrder(range); 2960 if (newOrder > oldOrder) break; 2961 else if (newOrder < oldOrder) continue; 2962 if (newRange->alignment > range->alignment) break; 2963 else if (newRange->alignment < range->alignment) continue; 2964 if (newRange->proposedSize >= range->proposedSize) break; 2965 else if (newRange->proposedSize < range->proposedSize) continue; 2966 } 2967 while (prev = &range->nextToAllocate, true); 2968 2969 *prev = newRange; 2970 newRange->nextToAllocate = range; 2971 2972 return (true); 2973} 2974 2975int32_t CLASS::bridgeAllocateResources(IOPCIConfigEntry * bridge, uint32_t typeMask) 2976{ 2977 IOPCIRange * requests[kIOPCIResourceTypeCount]; 2978 IOPCIScalar shortage[kIOPCIResourceTypeCount]; 2979 IOPCIScalar shortageAlignments[kIOPCIResourceTypeCount]; 2980 IOPCIRange * range; 2981 IOPCIRange * childRange; 2982 IOPCIScalar shrink; 2983 uint32_t type; 2984 uint32_t haveAllocs = 0; 2985 uint32_t haveRelocs = 0; 2986 uint32_t doOptimize = 0; 2987 uint32_t failTypes = 0; 2988 int32_t result; 2989 bool expressCards = false; 2990 bool ok; 2991 bool canRelocate; 2992 2993 DLOG("bridgeAllocateResources(bridge "B()", state 0x%x, type 0x%x)\n", 2994 BRIDGE_IDENT(bridge), bridge->deviceState, typeMask); 2995 2996 if (bridge == fRoot) return (true); 2997 if (kPCIDeviceStateDead & bridge->deviceState) return (true); 2998 2999 if (treeInState(bridge, kPCIDeviceStateRequestPause, 3000 (kPCIDeviceStateRequestPause | kPCIDeviceStatePaused))) return (-1); 3001 3002 bzero(requests, sizeof(requests)); 3003 bzero(shortage, sizeof(shortage)); 3004 bzero(shortageAlignments, sizeof(shortageAlignments)); 3005 3006 haveAllocs = bridge->haveAllocs; 3007 bridge->haveAllocs = 0; 3008 3009 // determine kIOPCIRangeFlagRelocatable 3010 FOREACH_CHILD(bridge, child) 3011 { 3012 expressCards |= (kPCIHotPlugRoot == child->supportsHotPlug); 3013 if (kPCIStatic == child->supportsHotPlug) continue; 3014 for (int rangeIndex = 0; rangeIndex < kIOPCIRangeCount; rangeIndex++) 3015 { 3016 childRange = child->ranges[rangeIndex]; 3017 if (!childRange) continue; 3018 if (!((1 << childRange->type) & typeMask)) continue; 3019 3020 canRelocate = (kIOPCIConfiguratorBoot & fFlags); 3021 canRelocate |= (0 != (kPCIDeviceStatePaused & child->deviceState)); 3022 3023 if ((rangeIndex == kIOPCIRangeBridgeBusNumber) && !canRelocate) 3024 { 3025 // bridges with no i/o allocations are bus relocatable 3026 canRelocate |= 3027 ((!child->ranges[kIOPCIRangeBridgeMemory] 3028 || !child->ranges[kIOPCIRangeBridgeMemory]->nextSubRange) 3029 && (!child->ranges[kIOPCIRangeBridgePFMemory] 3030 || !child->ranges[kIOPCIRangeBridgePFMemory]->nextSubRange) 3031 && (!child->ranges[kIOPCIRangeBridgeIO] 3032 || !child->ranges[kIOPCIRangeBridgeIO]->nextSubRange)); 3033 } 3034 if (canRelocate) 3035 { 3036 childRange->flags |= kIOPCIRangeFlagRelocatable; 3037 } 3038 else 3039 { 3040 childRange->flags &= ~kIOPCIRangeFlagRelocatable; 3041 } 3042 } 3043 } 3044 3045 if (((1 << kIOPCIResourceTypeBusNumber) & typeMask) 3046 && (range = bridgeGetRange(bridge, kIOPCIResourceTypeBusNumber)) 3047 && !bridge->busResv.nextSubRange) 3048 { 3049 IOPCIRangeInit(&bridge->busResv, kIOPCIResourceTypeBusNumber, 3050 bridge->secBusNum, 1, kPCIBridgeBusNumberAlignment); 3051 ok = IOPCIRangeListAllocateSubRange(range, &bridge->busResv); 3052 DLOG(" BUS: reserved(%sok) 0x%llx\n", ok ? "" : "!", bridge->busResv.start); 3053 } 3054 3055 // Do any frees, look for relocs, look for new allocs 3056 3057 FOREACH_CHILD(bridge, child) 3058 { 3059 for (int rangeIndex = 0; rangeIndex < kIOPCIRangeCount; rangeIndex++) 3060 { 3061 childRange = child->ranges[rangeIndex]; 3062 if (!childRange) continue; 3063 if (!((1 << childRange->type) & typeMask)) continue; 3064 range = bridgeGetRange(bridge, childRange->type); 3065 if (!range) continue; 3066 3067 if (!childRange->nextSubRange 3068 && ((kIOPCIRangeFlagMaximizeRoot | kIOPCIRangeFlagMaximizeSize) & childRange->flags)) 3069 { 3070 // minSize 3071 childRange->size = minBridgeAlignments[childRange->type]; 3072 3073 // maxSize 3074 if (kIOPCIRangeFlagMaximizeRoot & childRange->flags) 3075 { 3076 if (bridge->isHostBridge && range && expressCards 3077 && (kIOPCIResourceTypeBusNumber == childRange->type)) 3078 { 3079 childRange->proposedSize = (range->size * 240) / 255; 3080 } 3081 else 3082 { 3083 childRange->proposedSize = -1ULL; 3084 } 3085 } 3086 else 3087 { 3088 childRange->proposedSize = childRange->totalSize + childRange->extendSize; 3089 } 3090 } 3091 else 3092 { 3093 // maxSize 3094 if (!childRange->nextSubRange 3095 || ((childRange->totalSize + childRange->extendSize) > childRange->size)) 3096 childRange->proposedSize = childRange->totalSize + childRange->extendSize; 3097 } 3098 // 3099 3100 logAllocatorRange(child, childRange, '\n'); 3101 3102 if (!fConsoleRange 3103 && fPFMConsole 3104 && (rangeIndex <= kIOPCIRangeBAR5) 3105 && (fPFMConsole >= childRange->start) 3106 && (fPFMConsole < (childRange->start + childRange->proposedSize))) 3107 { 3108 DLOG(" hit console\n"); 3109 fPFMConsole -= childRange->start; 3110 fConsoleRange = childRange; 3111 } 3112 3113 if (!range) continue; 3114 type = range->type; 3115 3116 if (bridge->isHostBridge 3117 && !childRange->nextSubRange 3118 && (kIOPCIResourceTypeMemory == type) 3119 && (childRange->maxAddress > 0xFFFFFFFFULL)) 3120 { 3121 childRange->minAddress = (1ULL << 32); 3122 childRange->start = 0; 3123 } 3124 3125 if (!childRange->proposedSize) 3126 { 3127 if (childRange->nextSubRange) 3128 { 3129 child->rangeBaseChanges |= (1 << rangeIndex); 3130 ok = IOPCIRangeListDeallocateSubRange(range, childRange); 3131 if (!ok) panic("IOPCIRangeListDeallocateSubRange"); 3132 haveAllocs |= (1 << type); 3133 } 3134 childRange->start = 0; 3135 childRange->end = 0; 3136 childRange->size = 0; 3137 continue; 3138 } 3139 if (kIOPCIRangeFlagRelocatable & childRange->flags) haveRelocs |= (1 << type); 3140 if (!childRange->nextSubRange) haveAllocs |= (1 << type); 3141 if (childRange->proposedSize != childRange->size) haveAllocs |= (1 << type); 3142 } 3143 } 3144 3145 // Free anything relocatable if new allocs needed 3146 3147 if (haveAllocs & haveRelocs) 3148 { 3149 FOREACH_CHILD(bridge, child) 3150 { 3151 for (int rangeIndex = 0; rangeIndex < kIOPCIRangeCount; rangeIndex++) 3152 { 3153 childRange = child->ranges[rangeIndex]; 3154 if (!childRange) continue; 3155 if (!((1 << childRange->type) & haveAllocs)) continue; 3156 if (!childRange->nextSubRange) continue; 3157 3158 range = bridgeGetRange(bridge, childRange->type); 3159 if (!range) continue; 3160 if (kIOPCIRangeFlagRelocatable & childRange->flags) 3161 { 3162 DLOG(" %s: free reloc 0x%llx:0x%llx (at "D()")\n", 3163 gPCIResourceTypeName[childRange->type], 3164 childRange->start, childRange->size, 3165 DEVICE_IDENT(child)); 3166 child->rangeBaseChanges |= (1 << rangeIndex); 3167 ok = IOPCIRangeListDeallocateSubRange(range, childRange); 3168 if (!ok) panic("IOPCIRangeListDeallocateSubRange"); 3169 childRange->start = 0; 3170 childRange->proposedSize = childRange->totalSize + childRange->extendSize; 3171 } 3172 } 3173 } 3174 } 3175 3176 // Apply configuration changes to all children. 3177 FOREACH_CHILD(bridge, child) 3178 { 3179 applyConfiguration(child, typeMask, false); 3180 } 3181 3182 // Find allocations to make 3183 3184 FOREACH_CHILD(bridge, child) 3185 { 3186 for (int rangeIndex = 0; rangeIndex < kIOPCIRangeCount; rangeIndex++) 3187 { 3188 childRange = child->ranges[rangeIndex]; 3189 if (!childRange) continue; 3190 if (!((1 << childRange->type) & typeMask)) continue; 3191 if (!childRange->proposedSize) continue; 3192 if (childRange->nextSubRange && (childRange->proposedSize == childRange->size)) continue; 3193 3194 range = bridgeGetRange(bridge, childRange->type); 3195 if (!range) continue; 3196 type = range->type; 3197 3198 child->rangeBaseChanges |= (1 << rangeIndex); 3199 childRange->device = child; 3200 IOPCIRangeAppendSubRange(&requests[type], childRange); 3201 3202 if ((kIOPCIRangeFlagSplay | kIOPCIRangeFlagMaximizeSize) 3203 & childRange->flags) 3204 { 3205 doOptimize |= (1 << type); 3206 if (!childRange->start) childRange->flags |= kIOPCIRangeFlagRelocatable; 3207 } 3208 } 3209 } 3210 3211 // Make allocations 3212 3213 for (type = 0; type < kIOPCIResourceTypeCount; type++) 3214 { 3215 if (!(haveAllocs & (1 << type))) continue; 3216 range = bridgeGetRange(bridge, type); 3217 if (!range) continue; 3218 while ((childRange = requests[type])) 3219 { 3220 requests[type] = childRange->nextToAllocate; 3221 childRange->nextToAllocate = NULL; 3222 3223 IOPCIScalar placed = childRange->start; 3224 ok = IOPCIRangeListAllocateSubRange(range, childRange); 3225 3226 logAllocatorRange(childRange->device, childRange, ' '); 3227 DLOG("%sok allocated%s\n", 3228 ok ? " " : "!", 3229 (ok && (childRange->size != childRange->proposedSize)) ? "(short)" : ""); 3230 3231 if (ok && (childRange->size == childRange->proposedSize)) continue; 3232 3233 canRelocate = (0 != (kIOPCIConfiguratorBoot & fFlags)); 3234 canRelocate |= (!childRange->nextSubRange); 3235 canRelocate |= (0 != (kIOPCIRangeFlagRelocatable & childRange->flags)); 3236 3237 if (canRelocate && placed) 3238 { 3239 if (childRange->nextSubRange) 3240 { 3241 DLOG(" %s: free 0x%llx:0x%llx\n", 3242 gPCIResourceTypeName[type], 3243 childRange->start, childRange->size); 3244 ok = IOPCIRangeListDeallocateSubRange(range, childRange); 3245 if (!ok) panic("IOPCIRangeListDeallocateSubRange"); 3246 } 3247 childRange->start = 0; 3248 IOPCIRangeAppendSubRange(&requests[type], childRange); 3249 } 3250 else 3251 { 3252 shortage[type] += childRange->proposedSize; 3253 if (childRange->nextSubRange) shortage[type] -= childRange->size; 3254 if (childRange->alignment > shortageAlignments[type]) 3255 shortageAlignments[type] = childRange->alignment; 3256 if (bridge->isHostBridge) 3257 { 3258 DLOG(" %s: new host req:\n", gPCIResourceTypeName[type]); 3259 IOPCIRangeDump(range); 3260 } 3261 } 3262 } 3263 3264 if (bridge->isHostBridge) continue; 3265 3266 if (shortage[type]) 3267 { 3268 IOPCIScalar newSize, extendAvail; 3269 extendAvail = IOPCIRangeListLastFree(range, shortageAlignments[type]); 3270 if (shortage[type] > extendAvail) 3271 { 3272 newSize = range->size + shortage[type] - extendAvail; 3273 if (newSize > (range->totalSize + range->extendSize)) 3274 { 3275 if (kIOPCIRangeFlagMaximizeRoot & range->flags) {} 3276 else 3277 { 3278 range->extendSize = IOPCIScalarAlign(newSize - range->totalSize, minBridgeAlignments[type]);; 3279 DLOG(" %s: shortage 0x%llx -> 0x%llx, 0x%llx\n", 3280 gPCIResourceTypeName[type], range->size, range->totalSize, range->extendSize); 3281 bridge->rangeSizeChanges |= (1 << BRN(type)); 3282 bridge->rangeRequestChanges |= (1 << type); 3283 } 3284 } 3285 } 3286 failTypes |= (1 << type); 3287 } 3288 else 3289 { 3290 if ((1 << type) & doOptimize) 3291 { 3292 DLOG(" %s: optimize\n", gPCIResourceTypeName[type]); 3293 IOPCIRangeListOptimize(range); 3294 } 3295 if (!(kIOPCIRangeFlagNoCollapse & range->flags)) 3296 { 3297 shrink = IOPCIRangeListCollapse(range, minBridgeAlignments[type]); 3298 if (shrink) 3299 { 3300 DLOG(" %s: shrunk 0x%llx:0x%llx-0x%llx, 0x%llx,0x%llx\n", 3301 gPCIResourceTypeName[type], range->start, 3302 range->size, range->proposedSize, 3303 range->totalSize, range->extendSize); 3304 bridge->rangeSizeChanges |= (1 << BRN(type)); 3305 bridge->rangeRequestChanges |= (1 << type); 3306 failTypes |= (1 << type); 3307 } 3308 } 3309 } 3310 } 3311 3312 result = (0 == failTypes); 3313 3314 if (failTypes && !(bridge->rangeRequestChanges & typeMask)) 3315 { 3316 result = true; 3317 FOREACH_CHILD(bridge, child) 3318 { 3319 if (!(kIOPCIConfiguratorUsePause & fFlags)) continue; 3320 // no pause for i/o 3321 if ((1 << kIOPCIResourceTypeIO) == failTypes) continue; 3322 if ((kPCIDeviceStateRequestPause | kPCIDeviceStatePaused) 3323 & child->deviceState) continue; 3324 if (child->supportsHotPlug < kPCIHotPlug) continue; 3325 if (!child->dtNub || !child->dtNub->inPlane(gIOServicePlane)) continue; 3326 if (treeInState(child, 3327 kPCIDeviceStatePaused, kPCIDeviceStatePaused)) continue; 3328 3329 DLOG("Request pause for "D()"\n", DEVICE_IDENT(child)); 3330 child->deviceState |= kPCIDeviceStateRequestPause; 3331 markChanged(child); 3332 fWaitingPause++; 3333 result = -1; 3334 } 3335 if (true == result) DLOG(" exhausted\n"); 3336 } 3337 3338 if (!result) 3339 { 3340 bridge->rangeRequestChanges &= ~typeMask; 3341 } 3342 3343 // Apply configuration changes to all children. 3344 FOREACH_CHILD(bridge, child) 3345 { 3346 applyConfiguration(child, typeMask, true); 3347 } 3348 3349 return (result); 3350} 3351 3352//--------------------------------------------------------------------------- 3353 3354uint16_t CLASS::disableAccess(IOPCIConfigEntry * device, bool disable) 3355{ 3356 uint16_t command; 3357 3358 command = configRead16(device, kIOPCIConfigCommand); 3359 if (disable) 3360 { 3361 configWrite16(device, kIOPCIConfigCommand, 3362 (command & ~(kIOPCICommandIOSpace | kIOPCICommandMemorySpace))); 3363 } 3364 return (command); 3365} 3366 3367void CLASS::restoreAccess( IOPCIConfigEntry * device, UInt16 command ) 3368{ 3369 configWrite16(device, kIOPCIConfigCommand, command); 3370} 3371 3372//--------------------------------------------------------------------------- 3373 3374void CLASS::applyConfiguration(IOPCIConfigEntry * device, uint32_t typeMask, bool dolog) 3375{ 3376 if ((!device->isHostBridge) && !(kPCIDeviceStateDead & device->deviceState)) 3377 { 3378 if (device->rangeBaseChanges || device->rangeSizeChanges) 3379 { 3380 switch (device->headerType) 3381 { 3382 case kPCIHeaderType0: 3383 deviceApplyConfiguration(device, typeMask, dolog); 3384 break; 3385 case kPCIHeaderType1: 3386 case kPCIHeaderType2: 3387 bridgeApplyConfiguration(device, typeMask, dolog); 3388 break; 3389 } 3390 device->deviceState &= ~kPCIDeviceStatePropertiesDone; 3391 } 3392 if (!(kPCIDeviceStatePropertiesDone & device->deviceState)) 3393 writeLatencyTimer(device); 3394 } 3395 3396 device->deviceState |= kPCIDeviceStateConfigurationDone; 3397} 3398 3399void CLASS::deviceApplyConfiguration(IOPCIConfigEntry * device, uint32_t typeMask, bool dolog) 3400{ 3401 IOPCIScalar start; 3402 IOPCIRange * range; 3403 uint16_t reg16; 3404 3405 DLOGI("Applying config (bm 0x%x, sm 0x%x) for device "D()"\n", 3406 device->rangeBaseChanges, device->rangeSizeChanges, 3407 DEVICE_IDENT(device)); 3408 3409 reg16 = disableAccess(device, true); 3410 3411 for (int rangeIndex = kIOPCIRangeBAR0; rangeIndex <= kIOPCIRangeExpansionROM; rangeIndex++) 3412 { 3413 uint32_t bar; 3414 bool change; 3415 range = device->ranges[rangeIndex]; 3416 if (!range) 3417 continue; 3418 if (!((1 << range->type) & typeMask)) 3419 continue; 3420 change = (0 != ((1 << rangeIndex) & device->rangeBaseChanges)); 3421 device->rangeBaseChanges &= ~(1 << rangeIndex); 3422 device->rangeSizeChanges &= ~(1 << rangeIndex); 3423 if (change) 3424 { 3425 start = range->start; 3426 if (!start) 3427 continue; 3428 if (rangeIndex <= kIOPCIRangeBAR5) 3429 bar = kIOPCIConfigBaseAddress0 + (rangeIndex * 4); 3430 else 3431 bar = kIOPCIConfigExpansionROMBase; 3432 configWrite32(device, bar, start); 3433 DLOGI(" [0x%x %s] 0x%llx, read 0x%x\n", 3434 bar, gPCIResourceTypeName[range->type], 3435 start & 0xFFFFFFFF, configRead32(device, bar)); 3436 if (kIOPCIConfigExpansionROMBase != bar) 3437 { 3438 start >>= 32; 3439 if (start) 3440 { 3441 rangeIndex++; 3442 bar += 4; 3443 configWrite32(device, bar, start); 3444 DLOGI(" [0x%x %s] 0x%llx, read 0x%x\n", 3445 bar, gPCIResourceTypeName[range->type], 3446 start, configRead32(device, bar)); 3447 } 3448 } 3449 } 3450 } 3451 3452// reg16 &= ~(kIOPCICommandIOSpace | kIOPCICommandMemorySpace | 3453// kIOPCICommandBusMaster | kIOPCICommandMemWrInvalidate); 3454 restoreAccess(device, reg16); 3455 3456 DLOGI(" Device Command = 0x%08x\n", (uint32_t) 3457 configRead32(device, kIOPCIConfigCommand)); 3458} 3459 3460void CLASS::bridgeApplyConfiguration(IOPCIConfigEntry * bridge, uint32_t typeMask, bool dolog) 3461{ 3462 IOPCIScalar start; 3463 IOPCIScalar end; 3464 IOPCIRange * range; 3465 uint16_t commandReg = 0; 3466 uint32_t baselim32; 3467 uint16_t baselim16; 3468 bool accessDisabled; 3469 3470 enum { 3471 kBridgeCommand = (kIOPCICommandIOSpace | kIOPCICommandMemorySpace | kIOPCICommandBusMaster) 3472 }; 3473 3474 do 3475 { 3476 accessDisabled = false; 3477 DLOGI("Applying config for bridge "B()" (disabled %d)\n", 3478 BRIDGE_IDENT(bridge), accessDisabled); 3479 3480 commandReg = disableAccess(bridge, accessDisabled); 3481 3482 // Program bridge BAR0 and BAR1 3483 3484 for (int rangeIndex = kIOPCIRangeBAR0; rangeIndex <= kIOPCIRangeBAR1; rangeIndex++) 3485 { 3486 int thisIndex = rangeIndex; 3487 range = bridge->ranges[rangeIndex]; 3488 if (!range) 3489 continue; 3490 if (!((1 << range->type) & typeMask)) 3491 continue; 3492 if ((1 << rangeIndex) & bridge->rangeBaseChanges) 3493 { 3494 uint32_t bar; 3495 start = range->start; 3496 bar = kIOPCIConfigBaseAddress0 + (rangeIndex * 4); 3497 configWrite32(bridge, bar, start); 3498 DLOGI(" [0x%x %s] 0x%llx, read 0x%x\n", 3499 bar, gPCIResourceTypeName[range->type], 3500 start & 0xFFFFFFFF, configRead32(bridge, bar)); 3501 start >>= 32; 3502 if (start) 3503 { 3504 rangeIndex++; 3505 bar += 4; 3506 configWrite32(bridge, bar, start); 3507 DLOGI(" [0x%x %s] 0x%llx, read 0x%x\n", 3508 bar, gPCIResourceTypeName[range->type], 3509 start, configRead32(bridge, bar)); 3510 } 3511 } 3512 bridge->rangeBaseChanges &= ~(1 << thisIndex); 3513 bridge->rangeSizeChanges &= ~(1 << thisIndex); 3514 } 3515 3516 if (((1 << kIOPCIResourceTypeBusNumber) & typeMask) 3517 && ((1 << kIOPCIRangeBridgeBusNumber) & (bridge->rangeBaseChanges | bridge->rangeSizeChanges))) 3518 { 3519 range = bridge->ranges[kIOPCIRangeBridgeBusNumber]; 3520 DLOGI_RANGE(" BUS", range); 3521 if (range->start && range->size) 3522 { 3523 bridge->secBusNum = range->start; 3524 bridge->subBusNum = range->start + range->size - 1; 3525 } 3526 else 3527 { 3528 bridge->secBusNum = bridge->subBusNum = 0; 3529 } 3530 3531 // Give children the correct bus 3532 3533 FOREACH_CHILD(bridge, child) 3534 { 3535 child->space.s.busNum = bridge->secBusNum; 3536 child->deviceState &= ~kPCIDeviceStatePropertiesDone; 3537 } 3538 3539 DLOGI(" OLD: prim/sec/sub = 0x%02x:0x%02x:0x%02x\n", 3540 configRead8(bridge, kPCI2PCIPrimaryBus), 3541 configRead8(bridge, kPCI2PCISecondaryBus), 3542 configRead8(bridge, kPCI2PCISubordinateBus)); 3543 3544 // Program bridge bus numbers 3545 3546 uint32_t reg32 = configRead32(bridge, kPCI2PCIPrimaryBus); 3547 reg32 &= ~0x00ffffff; 3548 reg32 |= bridge->space.s.busNum | (bridge->secBusNum << 8) | (bridge->subBusNum << 16); 3549 configWrite32(bridge, kPCI2PCIPrimaryBus, reg32); 3550 3551 DLOGI(" BUS: prim/sec/sub = 0x%02x:0x%02x:0x%02x\n", 3552 configRead8(bridge, kPCI2PCIPrimaryBus), 3553 configRead8(bridge, kPCI2PCISecondaryBus), 3554 configRead8(bridge, kPCI2PCISubordinateBus)); 3555 3556 bridge->rangeBaseChanges &= ~(1 << kIOPCIRangeBridgeBusNumber); 3557 bridge->rangeSizeChanges &= ~(1 << kIOPCIRangeBridgeBusNumber); 3558 } 3559 3560 // That's it for cardbus 3561 if (kPCIHeaderType2 == bridge->headerType) break; 3562 3563 if (((1 << kIOPCIResourceTypeIO) & typeMask) 3564 && ((1 << kIOPCIRangeBridgeIO) & (bridge->rangeBaseChanges | bridge->rangeSizeChanges))) 3565 { 3566 // Program I/O base and limit 3567 3568 DLOGI_RANGE(" I/O", bridge->ranges[kIOPCIRangeBridgeIO]); 3569 3570 baselim16 = 0x00f0; // closed range 3571 range = bridge->ranges[kIOPCIRangeBridgeIO]; 3572 if (range && range->size) 3573 { 3574 assert(range->start); 3575 assert((range->size & (4096-1)) == 0); 3576 assert((range->start & (4096-1)) == 0); 3577 assert((range->start & 0xffff0000) == 0); 3578 3579 start = range->start; 3580 end = start + range->size - 1; 3581 baselim16 = ((start >> 8) & 0xf0) | (end & 0xf000); 3582 } 3583 configWrite16(bridge, kPCI2PCIIORange, baselim16); 3584 configWrite32(bridge, kPCI2PCIUpperIORange, 0); 3585 3586 DLOGI(" I/O: base/limit = 0x%04x\n", 3587 configRead16(bridge, kPCI2PCIIORange)); 3588 3589 bridge->rangeBaseChanges &= ~(1 << kIOPCIRangeBridgeIO); 3590 bridge->rangeSizeChanges &= ~(1 << kIOPCIRangeBridgeIO); 3591 } 3592 3593 if (((1 << kIOPCIResourceTypeMemory) & typeMask) 3594 && ((1 << kIOPCIRangeBridgeMemory) & (bridge->rangeBaseChanges | bridge->rangeSizeChanges))) 3595 { 3596 // Program memory base and limit 3597 3598 DLOGI_RANGE(" MEM", bridge->ranges[kIOPCIRangeBridgeMemory]); 3599 3600 baselim32 = 0x0000FFF0; // closed range 3601 range = bridge->ranges[kIOPCIRangeBridgeMemory]; 3602 if (range && range->size && !(kPCIDeviceStateNoLink & bridge->deviceState)) 3603 { 3604 assert(range->start); 3605 assert((range->size & (0x100000-1)) == 0); 3606 assert((range->start & (0x100000-1)) == 0); 3607 3608 start = range->start; 3609 end = range->start + range->size - 1; 3610 baselim32 = ((start >> 16) & 0xFFF0) | (end & 0xFFF00000); 3611 } 3612 configWrite32(bridge, kPCI2PCIMemoryRange, baselim32); 3613 3614 DLOGI(" MEM: base/limit = 0x%08x\n", (uint32_t) 3615 configRead32(bridge, kPCI2PCIMemoryRange)); 3616 3617 bridge->rangeBaseChanges &= ~(1 << kIOPCIRangeBridgeMemory); 3618 bridge->rangeSizeChanges &= ~(1 << kIOPCIRangeBridgeMemory); 3619 } 3620 3621 if (((1 << kIOPCIResourceTypePrefetchMemory) & typeMask) 3622 && ((1 << kIOPCIRangeBridgePFMemory) & (bridge->rangeBaseChanges | bridge->rangeSizeChanges))) 3623 { 3624 // Program prefetchable memory base and limit 3625 3626 DLOGI_RANGE(" PFM", bridge->ranges[kIOPCIRangeBridgePFMemory]); 3627 3628 baselim32 = 0x0000FFF0; // closed range 3629 start = 0; 3630 end = 0; 3631 3632 if ((1 << kIOPCIRangeBridgePFMemory) & bridge->rangeBaseChanges) 3633 { 3634 configWrite32(bridge, kPCI2PCIPrefetchUpperBase, -1U); 3635 configWrite32(bridge, kPCI2PCIPrefetchUpperLimit, -1U); 3636 configWrite32(bridge, kPCI2PCIPrefetchMemoryRange, baselim32); 3637 } 3638 range = bridge->ranges[kIOPCIRangeBridgePFMemory]; 3639 if (range && range->size && !(kPCIDeviceStateNoLink & bridge->deviceState)) 3640 { 3641 assert(range->start); 3642 assert((range->size & (0x100000-1)) == 0); 3643 assert((range->start & (0x100000-1)) == 0); 3644 3645 start = range->start; 3646 end = range->start + range->size - 1; 3647 baselim32 = ((start >> 16) & 0xFFF0) | (end & 0xFFF00000); 3648 } 3649 configWrite32(bridge, kPCI2PCIPrefetchMemoryRange, baselim32); 3650 configWrite32(bridge, kPCI2PCIPrefetchUpperLimit, (end >> 32)); 3651 configWrite32(bridge, kPCI2PCIPrefetchUpperBase, (start >> 32)); 3652 3653 DLOGI(" PFM: base/limit = 0x%08x, 0x%08x, 0x%08x\n", 3654 (uint32_t)configRead32(bridge, kPCI2PCIPrefetchMemoryRange), 3655 (uint32_t)configRead32(bridge, kPCI2PCIPrefetchUpperBase), 3656 (uint32_t)configRead32(bridge, kPCI2PCIPrefetchUpperLimit)); 3657 3658 bridge->rangeBaseChanges &= ~(1 << kIOPCIRangeBridgePFMemory); 3659 bridge->rangeSizeChanges &= ~(1 << kIOPCIRangeBridgePFMemory); 3660 } 3661 } 3662 while (false); 3663 3664 // Set IOSE, memory enable, Bus Master transaction forwarding 3665 3666 DLOGI("Enabling bridge "B()"\n", BRIDGE_IDENT(bridge)); 3667 3668 if (kPCIHeaderType2 == bridge->headerType) 3669 { 3670 commandReg &= ~(kIOPCICommandIOSpace | kIOPCICommandMemorySpace | 3671 kIOPCICommandBusMaster | kIOPCICommandMemWrInvalidate); 3672 } 3673 else 3674 { 3675 uint16_t bridgeControl; 3676 3677 commandReg |= (kIOPCICommandIOSpace 3678 | kIOPCICommandMemorySpace 3679// | kIOPCICommandSERR 3680 | kIOPCICommandBusMaster); 3681 3682 // Turn off ISA bit. 3683 bridgeControl = configRead16(bridge, kPCI2PCIBridgeControl); 3684 if (bridgeControl & 0x0004) 3685 { 3686 bridgeControl &= ~0x0004; 3687 configWrite16(bridge, kPCI2PCIBridgeControl, bridgeControl); 3688 DLOGI(" Bridge Control = 0x%04x\n", 3689 configRead16(bridge, kPCI2PCIBridgeControl)); 3690 } 3691 } 3692 3693 restoreAccess(bridge, commandReg); 3694 3695 DLOGI(" Bridge Command = 0x%08x\n", 3696 configRead32(bridge, kIOPCIConfigCommand)); 3697} 3698 3699//--------------------------------------------------------------------------- 3700 3701#ifndef ExtractLSB 3702#define ExtractLSB(x) ((x) & (~((x) - 1))) 3703#endif 3704 3705void CLASS::checkCacheLineSize(IOPCIConfigEntry * device) 3706{ 3707 uint8_t cacheLineSize, cls, was; 3708 3709 if (device->isHostBridge) 3710 return; 3711 3712 if (kPCIStatic == device->parent->supportsHotPlug) 3713 return; 3714 3715 if ((kPCIHotPlugTunnelRoot == device->parent->supportsHotPlug) 3716 || (kPCIHotPlugTunnel == device->parent->supportsHotPlug)) 3717 cacheLineSize = 0x20; 3718 else 3719 cacheLineSize = 0x40; 3720 3721 cls = configRead8(device, kIOPCIConfigCacheLineSize); 3722 was = cls; 3723 3724 // config looks reasonable, keep original value 3725 if ((cls >= cacheLineSize) && ((cls % cacheLineSize) == 0)) 3726 return; 3727 3728 configWrite8(device, kIOPCIConfigCacheLineSize, cacheLineSize); 3729 cls = configRead8(device, kIOPCIConfigCacheLineSize); 3730 if (cls != cacheLineSize) 3731 { 3732 DLOG(" could not set CLS from %u to %u dwords\n", was, cls); 3733 configWrite8(device, kIOPCIConfigCacheLineSize, 0); 3734 } 3735 else 3736 { 3737 DLOG(" changed CLS from %u to %u dwords\n", was, cls); 3738 } 3739} 3740 3741//--------------------------------------------------------------------------- 3742 3743void CLASS::writeLatencyTimer(IOPCIConfigEntry * device) 3744{ 3745 const uint8_t defaultLT = 0x40; 3746 uint8_t was, now; 3747 3748 if (device == fRoot) 3749 return; 3750 3751 // Nothing fancy here, just set the latency timer to 64 PCI clocks. 3752 3753 was = configRead8(device, kIOPCIConfigLatencyTimer); 3754 configWrite8(device, kIOPCIConfigLatencyTimer, defaultLT); 3755 now = configRead8(device, kIOPCIConfigLatencyTimer); 3756 if (was != now) 3757 { 3758 DLOG(" changed LT %u->%u PCI clocks\n", was, now); 3759 } 3760 3761 // Bridges can act as an initiator on either side of the bridge, 3762 // and there is a separate register for the latency timer on the 3763 // secondary side. 3764 3765 if (device->isBridge) 3766 { 3767 was = configRead8(device, kPCI2PCISecondaryLT); 3768 configWrite8(device, kPCI2PCISecondaryLT, defaultLT); 3769 now = configRead8(device, kPCI2PCISecondaryLT); 3770 if (was != now) 3771 { 3772 DLOG(" changed SEC-LT %u->%u PCI clocks\n", was, now); 3773 } 3774 } 3775} 3776 3777//--------------------------------------------------------------------------- 3778 3779int32_t CLASS::bridgeFinalizeConfigProc(void * unused, IOPCIConfigEntry * bridge) 3780{ 3781 uint32_t deviceControl, newControl, maxReadReq; 3782 3783 if (!(kPCIDeviceStateAllocated & bridge->deviceState)) return (true); 3784 bridge->deviceState &= ~kPCIDeviceStateChildChanged; 3785 3786#if defined(__i386__) || defined(__x86_64__) 3787 if (bridge->supportsHotPlug >= kPCIHotPlug) 3788#endif 3789 { 3790 FOREACH_CHILD(bridge, child) 3791 { 3792 if (kPCIDeviceStateDead & child->deviceState) continue; 3793 if (kPCIDeviceStatePropertiesDone & child->deviceState) continue; 3794 if (!child->expressCapBlock) continue; 3795 deviceControl = configRead16(child, child->expressCapBlock + 0x08); 3796 newControl = deviceControl & ~((7 << 5) | (7 << 12)); 3797#if defined(__i386__) || defined(__x86_64__) 3798 maxReadReq = fMaxPayload; 3799#else 3800 maxReadReq = 0x05; // 4096 3801#endif 3802 newControl |= (fMaxPayload << 5) | (maxReadReq << 12); 3803 if (newControl != deviceControl) 3804 { 3805 configWrite16(child, child->expressCapBlock + 0x08, deviceControl); 3806 DLOG("payload set 0x%08x -> 0x%08x (at "D()"), fMaxPayload 0x%x\n", 3807 deviceControl, newControl, 3808 DEVICE_IDENT(child), fMaxPayload); 3809 } 3810 } 3811 } 3812 3813 if ((kPCIDeviceStateChildAdded & bridge->deviceState) && !fWaitingPause) 3814 { 3815 bridge->deviceState &= ~kPCIDeviceStateChildAdded; 3816 markChanged(bridge); 3817 } 3818 3819#if PLX8680 3820 do 3821 { 3822 volatile uint32_t * regs; 3823 uint32_t reg32, lut; 3824 IOPCIConfigEntry * parent; 3825 3826 parent = bridge; 3827 do { regs = parent->plx; } while (!regs && (parent = parent->parent)); 3828 if (!regs) break; 3829 3830 FOREACH_CHILD(bridge, child) 3831 { 3832 if (kPCIHeaderType0 != child->headerType) continue; 3833 if (0x868010b5 == child->vendorProduct) continue; 3834 3835 reg32 = (child->space.s.busNum << 8); 3836// reg32 |= (child->space.s.deviceNum << 3); 3837// reg32 |= (child->space.s.functionNum << 0); 3838 reg32 |= 0x80000000; 3839 3840 regs += ((0x3e000 + 0xd98) / 4); 3841 for (lut = 0; lut < 7; lut++) 3842 { 3843 if (reg32 == regs[lut]) break; 3844 if (0x80000000 & regs[lut]) continue; 3845 regs[lut] = reg32; 3846 DLOG("PLX LUT[0x%x] == 0x%x\n", ®s[lut], reg32); 3847 if (lut && parent->ranges[kIOPCIRangeBridgePFMemory]) 3848 { 3849 child->plxAperture = parent->ranges[kIOPCIRangeBridgePFMemory]->start; 3850 } 3851 break; 3852 } 3853 } 3854 } 3855 while (false); 3856#endif /* PLX8680 */ 3857 3858 return (bridgeConstructDeviceTree(unused, bridge)); 3859} 3860 3861/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 3862 * 3863 * Configuration Space Access 3864 * 3865 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3866 3867uint32_t CLASS::configRead32( IOPCIAddressSpace space, uint32_t offset ) 3868{ 3869 space.es.registerNumExtended = (offset >> 8); 3870 return (fHostBridge->configRead32(space, offset)); 3871} 3872 3873void CLASS::configWrite32( IOPCIAddressSpace space, uint32_t offset, uint32_t data ) 3874{ 3875 space.es.registerNumExtended = (offset >> 8); 3876 fHostBridge->configWrite32(space, offset, data); 3877} 3878 3879/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3880 3881bool CLASS::configAccess(IOPCIConfigEntry * device, bool write) 3882{ 3883 bool ok = 3884 (0 == ((write ? kPCIDeviceStateConfigWProtect : kPCIDeviceStateConfigRProtect) 3885 & device->deviceState)); 3886 if (!ok) 3887 { 3888 DLOG("config protect fail(1) for device "D()"\n", DEVICE_IDENT(device)); 3889 OSReportWithBacktrace("config protect fail(1) for device "D()"\n", 3890 DEVICE_IDENT(device)); 3891 } 3892 3893 return (ok); 3894} 3895 3896/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3897 3898enum 3899{ 3900 kConfigWrite = 0x00, 3901 kConfigRead = 0x01, 3902 kConfig32 = (sizeof(uint32_t) << 1), 3903 kConfig16 = (sizeof(uint16_t) << 1), 3904 kConfig8 = (sizeof(uint8_t) << 1), 3905}; 3906 3907void CLASS::configAccess(IOPCIConfigEntry * device, uint32_t access, uint32_t offset, void * data) 3908{ 3909 uint8_t * addr; 3910 3911 addr = device->configShadow + offset; 3912 if (kConfigRead & access) bcopy(addr, data, (access >> 1)); 3913 else bcopy(data, addr, (access >> 1)); 3914} 3915 3916/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3917 3918uint32_t CLASS::configRead32( IOPCIConfigEntry * device, uint32_t offset ) 3919{ 3920 if (device->configShadow) 3921 { 3922 uint32_t data; 3923 configAccess(device, kConfig32|kConfigRead, offset, &data); 3924 return (data); 3925 } 3926 3927 if (!configAccess(device, false)) return (0xFFFFFFFF); 3928 3929 IOPCIAddressSpace space = device->space; 3930 space.es.registerNumExtended = (offset >> 8); 3931 return (fHostBridge->configRead32(space, offset)); 3932} 3933 3934void CLASS::configWrite32( IOPCIConfigEntry * device, 3935 uint32_t offset, uint32_t data ) 3936{ 3937 if (device->configShadow) 3938 { 3939 configAccess(device, kConfig32|kConfigWrite, offset, &data); 3940 } 3941 3942 if (!configAccess(device, true)) return; 3943 3944 IOPCIAddressSpace space = device->space; 3945 space.es.registerNumExtended = (offset >> 8); 3946 fHostBridge->configWrite32(space, offset, data); 3947} 3948 3949uint16_t CLASS::configRead16( IOPCIConfigEntry * device, uint32_t offset ) 3950{ 3951 if (device->configShadow) 3952 { 3953 uint16_t data; 3954 configAccess(device, kConfig16|kConfigRead, offset, &data); 3955 return (data); 3956 } 3957 3958 if (!configAccess(device, false)) return (0xFFFF); 3959 3960 IOPCIAddressSpace space = device->space; 3961 space.es.registerNumExtended = (offset >> 8); 3962 return (fHostBridge->configRead16(space, offset)); 3963} 3964 3965void CLASS::configWrite16( IOPCIConfigEntry * device, 3966 uint32_t offset, uint16_t data ) 3967{ 3968 if (device->configShadow) 3969 { 3970 configAccess(device, kConfig16|kConfigWrite, offset, &data); 3971 } 3972 3973 if (!configAccess(device, true)) return; 3974 3975 IOPCIAddressSpace space = device->space; 3976 space.es.registerNumExtended = (offset >> 8); 3977 fHostBridge->configWrite16(space, offset, data); 3978} 3979 3980uint8_t CLASS::configRead8( IOPCIConfigEntry * device, uint32_t offset ) 3981{ 3982 if (device->configShadow) 3983 { 3984 uint8_t data; 3985 configAccess(device, kConfig8|kConfigRead, offset, &data); 3986 return (data); 3987 } 3988 3989 if (!configAccess(device, false)) return (0xFF); 3990 3991 IOPCIAddressSpace space = device->space; 3992 space.es.registerNumExtended = (offset >> 8); 3993 return (fHostBridge->configRead8(space, offset)); 3994} 3995 3996void CLASS::configWrite8( IOPCIConfigEntry * device, 3997 uint32_t offset, uint8_t data ) 3998{ 3999 if (device->configShadow) 4000 { 4001 configAccess(device, kConfig8|kConfigWrite, offset, &data); 4002 } 4003 4004 if (!configAccess(device, true)) return; 4005 4006 IOPCIAddressSpace space = device->space; 4007 space.es.registerNumExtended = (offset >> 8); 4008 fHostBridge->configWrite8(space, offset, data); 4009} 4010/* -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: t -*- */ 4011