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#ifndef _IOPCICONFIGURATOR_H 24#define _IOPCICONFIGURATOR_H 25 26#if ACPI_SUPPORT 27#define PLX8680 0 28#endif 29 30/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 31 32typedef uint64_t IOPCIScalar; 33 34enum { 35 kIOPCIRangeFlagMaximizeSize = 0x00000001, 36 kIOPCIRangeFlagNoCollapse = 0x00000002, 37 kIOPCIRangeFlagMaximizeRoot = 0x00000004, 38 kIOPCIRangeFlagSplay = 0x00000008, 39 kIOPCIRangeFlagRelocatable = 0x00000010, 40 kIOPCIRangeFlagReserve = 0x00000020, 41 kIOPCIRangeFlagPermanent = 0x00000040, 42}; 43 44struct IOPCIRange 45{ 46 IOPCIScalar start; 47 IOPCIScalar size; 48 IOPCIScalar totalSize; 49 IOPCIScalar extendSize; 50 IOPCIScalar proposedSize; 51 52 // end marker 53 IOPCIScalar end; 54 IOPCIScalar zero; 55 56 IOPCIScalar alignment; 57 IOPCIScalar minAddress; 58 IOPCIScalar maxAddress; 59 60 uint8_t type; 61 uint8_t resvB[3]; 62 uint32_t flags; 63 struct IOPCIRange * next; 64 struct IOPCIRange * nextSubRange; 65 struct IOPCIRange * allocations; 66 67 struct IOPCIRange * nextToAllocate; 68 struct IOPCIConfigEntry * device; // debug 69}; 70 71IOPCIScalar IOPCIScalarAlign(IOPCIScalar num, IOPCIScalar alignment); 72IOPCIScalar IOPCIScalarTrunc(IOPCIScalar num, IOPCIScalar alignment); 73 74IOPCIRange * IOPCIRangeAlloc(void); 75 76void IOPCIRangeFree(IOPCIRange * range); 77 78void IOPCIRangeInit(IOPCIRange * range, uint32_t type, 79 IOPCIScalar start, IOPCIScalar size, IOPCIScalar alignment = 0); 80void IOPCIRangeInitAlloc(IOPCIRange * range, uint32_t type, 81 IOPCIScalar start, IOPCIScalar size, IOPCIScalar alignment = 0); 82 83void IOPCIRangeDump(IOPCIRange * head); 84 85bool IOPCIRangeListAddRange(IOPCIRange ** rangeList, 86 uint32_t type, 87 IOPCIScalar start, 88 IOPCIScalar size, 89 IOPCIScalar alignment = 1); 90 91bool IOPCIRangeDeallocateSubRange(IOPCIRange * headRange, 92 IOPCIRange * oldRange); 93 94bool IOPCIRangeListAllocateSubRange(IOPCIRange * headRange, 95 IOPCIRange * newRange, 96 IOPCIScalar newStart = 0); 97 98bool IOPCIRangeListDeallocateSubRange(IOPCIRange * headRange, 99 IOPCIRange * oldRange); 100 101bool IOPCIRangeAppendSubRange(IOPCIRange ** headRange, 102 IOPCIRange * newRange ); 103 104IOPCIScalar IOPCIRangeListCollapse(IOPCIRange * headRange, IOPCIScalar alignment); 105 106IOPCIScalar IOPCIRangeCollapse(IOPCIRange * headRange, IOPCIScalar alignment); 107 108IOPCIScalar IOPCIRangeListLastFree(IOPCIRange * headRange, IOPCIScalar align); 109IOPCIScalar IOPCIRangeLastFree(IOPCIRange * headRange, IOPCIScalar align); 110void IOPCIRangeListOptimize(IOPCIRange * headRange); 111 112/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 113 114#ifdef KERNEL 115 116#include <IOKit/IOLib.h> 117#include <IOKit/pci/IOPCIBridge.h> 118 119 120#define kPCIBridgeIOAlignment (4096) 121#define kPCIBridgeMemoryAlignment (1024*1024) 122#define kPCIBridgeBusNumberAlignment (1) 123 124 125#define FOREACH_CHILD(bridge, child) \ 126 for(IOPCIConfigEntry * (child) = (bridge)->child; (child); (child) = (child)->peer) 127 128enum { 129 kIOPCIConfiguratorIOLog = 0x00000001, 130 kIOPCIConfiguratorKPrintf = 0x00000002, 131 kIOPCIConfiguratorVTLog = 0x00000004, 132 133 kIOPCIConfiguratorAER = 0x00000008, 134 // = 0x00000010, 135 // = 0x00000020, 136 137 kIOPCIConfiguratorLogSaveRestore = 0x00000040, 138 kIOPCIConfiguratorDeferHotPlug = 0x00000080, 139 kIOPCIConfiguratorPanicOnFault = 0x00000100, 140 kIOPCIConfiguratorNoSplay = 0x00000200, 141 142 kIOPCIConfiguratorDeepIdle = 0x00000400, 143 kIOPCIConfiguratorNoTB = 0x00000800, 144 kIOPCIConfiguratorTBMSIEnable = 0x00001000, 145 146 kIOPCIConfiguratorPFM64 = 0x00002000, 147 kIOPCIConfiguratorBoot = 0x00004000, 148 kIOPCIConfiguratorIGIsMapped = 0x00008000, 149 kIOPCIConfiguratorReset = 0x00010000, 150 kIOPCIConfiguratorAllocate = 0x00020000, 151 kIOPCIConfiguratorUsePause = 0x00040000, 152 153 kIOPCIConfiguratorCheckTunnel = 0x00080000, 154 kIOPCIConfiguratorNoTunnelDrv = 0x00100000, 155 kIOPCIConfiguratorNoTerminate = 0x00200000, 156 157 kIOPCIConfiguratorBootDefer = kIOPCIConfiguratorDeferHotPlug | kIOPCIConfiguratorBoot, 158}; 159 160enum { 161 kIOPCIRangeBAR0 = 0, 162 kIOPCIRangeBAR1 = 1, 163 kIOPCIRangeBAR2 = 2, 164 kIOPCIRangeBAR3 = 3, 165 kIOPCIRangeBAR4 = 4, 166 kIOPCIRangeBAR5 = 5, 167 kIOPCIRangeExpansionROM = 6, 168 169 // order matches kIOPCIResourceType* 170 kIOPCIRangeBridgeMemory = 7, 171 kIOPCIRangeBridgePFMemory = 8, 172 kIOPCIRangeBridgeIO = 9, 173 kIOPCIRangeBridgeBusNumber = 10, 174 175 kIOPCIRangeCount, 176 177 kIOPCIRangeAllMask = (1 << kIOPCIRangeCount) - 1, 178 kIOPCIRangeAllBarsMask = (1 << (kIOPCIRangeExpansionROM + 1)) - 1, 179 kIOPCIRangeAllBridgeMask = (1 << kIOPCIRangeBridgeMemory) 180 | (1 << kIOPCIRangeBridgePFMemory) 181 | (1 << kIOPCIRangeBridgeIO) 182 | (1 << kIOPCIRangeBridgeBusNumber), 183 184 185}; 186 187enum { 188// kPCIDeviceStateResourceAssigned = 0x00000001, 189 kPCIDeviceStatePropertiesDone = 0x00000002, 190 kPCIDeviceStateTreeConnected = 0x00000004, 191 kPCIDeviceStateConfigurationDone = 0x00000008, 192 193 kPCIDeviceStateScanned = 0x00000010, 194 kPCIDeviceStateAllocatedBus = 0x00000020, 195 kPCIDeviceStateTotalled = 0x00000040, 196 kPCIDeviceStateAllocated = 0x00000080, 197 kPCIDeviceStateChildChanged = 0x00000100, 198 kPCIDeviceStateChildAdded = 0x00000200, 199 kPCIDeviceStateNoLink = 0x00000400, 200 201 kPCIDeviceStateConfigProtectShift = 15, 202 kPCIDeviceStateConfigRProtect = (VM_PROT_READ << kPCIDeviceStateConfigProtectShift), 203 kPCIDeviceStateConfigWProtect = (VM_PROT_WRITE << kPCIDeviceStateConfigProtectShift), 204 205 kPCIDeviceStateDead = 0x80000000, 206 kPCIDeviceStateEjected = 0x40000000, 207 kPCIDeviceStateToKill = 0x20000000, 208 kPCIDeviceStatePaused = 0x10000000, 209 kPCIDeviceStateRequestPause = 0x08000000 210}; 211 212enum { 213 kPCIHeaderType0 = 0, 214 kPCIHeaderType1 = 1, 215 kPCIHeaderType2 = 2 216}; 217 218// value of supportsHotPlug 219enum { 220 kPCIStatic = 0, 221 kPCILinkChange = 1, 222 kPCIHotPlug = 2, 223 kPCIHotPlugRoot = 3, 224 kPCIHotPlugTunnel = 4, 225 kPCIHotPlugTunnelRoot = 5, 226 kPCIHotPlugTunnelRootParent = 6, 227}; 228 229#define kPCIBridgeMaxCount 256 230 231enum 232{ 233 kConfigOpAddHostBridge = 1, 234 kConfigOpScan, 235 kConfigOpRealloc, 236 kConfigOpGetState, 237 kConfigOpNeedsScan, 238 kConfigOpEject, 239 kConfigOpKill, 240 kConfigOpTerminated, 241 kConfigOpProtect, 242 kConfigOpShadowed, 243 kConfigOpPaused, 244 kConfigOpUnpaused, 245 kConfigOpTestPause, 246 kConfigOpFindEntry, 247}; 248 249/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 250 251struct IOPCIConfigEntry 252{ 253 IOPCIConfigEntry * parent; 254 IOPCIConfigEntry * child; 255 IOPCIConfigEntry * peer; 256 uint32_t id; 257 uint32_t classCode; 258 IOPCIAddressSpace space; 259 uint32_t vendorProduct; 260 261 uint32_t expressCapBlock; 262 uint32_t expressDeviceCaps1; 263 264 IOPCIRange * ranges[kIOPCIRangeCount]; 265 IOPCIRange busResv; 266 uint32_t rangeBaseChanges; 267 uint32_t rangeSizeChanges; 268 uint32_t rangeRequestChanges; 269 uint32_t haveAllocs; 270 271 uint32_t deviceState; 272 uint8_t iterator; 273 274 uint8_t headerType; 275 uint8_t isBridge; 276 uint8_t countMaximize; 277 uint8_t isHostBridge; 278 uint8_t supportsHotPlug; 279 uint8_t linkInterrupts; 280 uint8_t clean64; 281 uint8_t secBusNum; // bridge only 282 uint8_t subBusNum; // bridge only 283 284 uint32_t linkCaps; 285 uint16_t expressCaps; 286 uint8_t expressMaxPayload; 287 uint8_t expressPayloadSetting; 288// uint16_t pausedCommand; 289 290 IORegistryEntry * dtEntry; 291#if ACPI_SUPPORT 292 IORegistryEntry * acpiDevice; 293#endif 294 IORegistryEntry * dtNub; 295 296 297 uint8_t * configShadow; 298 299#if PLX8680 300 volatile uint32_t * plx; 301 IOPCIScalar plxAperture; 302#endif 303}; 304 305/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 306 307class IOPCIConfigurator : public IOService 308{ 309 friend class IOPCIBridge; 310 OSDeclareDefaultStructors( IOPCIConfigurator ); 311 312 IOWorkLoop * fWL; 313 IOOptionBits fFlags; 314 IOPCIBridge * fHostBridge; 315 IOPCIConfigEntry * fRoot; 316 uint32_t fRootVendorProduct; 317 318 uint8_t fMaxPayload; 319 320 IOPCIRange * fConsoleRange; 321 IOPCIScalar fPFMConsole; 322 323 OSSet * fChangedServices; 324 uint32_t fWaitingPause; 325 326 uint32_t fBridgeCount; 327 uint32_t fDeviceCount; 328 uint32_t fNextID; 329 330protected: 331 332 static void safeProbeCallback( void * refcon ); 333 static void configProbeCallback( void * refcon ); 334 335 static void matchDTEntry( IORegistryEntry * dtEntry, void * _context ); 336#if ACPI_SUPPORT 337 static void matchACPIEntry( IORegistryEntry * dtEntry, void * _context ); 338 void removeFixedRanges(IORegistryEntry * root); 339#endif 340 341 typedef int32_t (IOPCIConfigurator::*IterateProc)(void * ref, IOPCIConfigEntry * bridge); 342 void iterate(const char * what, 343 IterateProc topProc, IterateProc bottomProc, 344 void * ref = NULL); 345 346 int32_t scanProc(void * ref, IOPCIConfigEntry * bridge); 347 int32_t bootResetProc(void * ref, IOPCIConfigEntry * bridge); 348 int32_t totalProc(void * ref, IOPCIConfigEntry * bridge); 349 int32_t allocateProc(void * ref, IOPCIConfigEntry * bridge); 350 int32_t bridgeFinalizeConfigProc(void * unused, IOPCIConfigEntry * bridge); 351 352 void configure(uint32_t options); 353 void bridgeScanBus(IOPCIConfigEntry * bridge, uint8_t busNum, uint32_t resetMask); 354 355 void logAllocatorRange(IOPCIConfigEntry * device, IOPCIRange * range, char c); 356 IOPCIRange * bridgeGetRange(IOPCIConfigEntry * bridge, uint32_t type); 357 bool bridgeTotalResources(IOPCIConfigEntry * bridge, uint32_t typeMask); 358 int32_t bridgeAllocateResources( IOPCIConfigEntry * bridge, uint32_t typeMask ); 359 360 bool bridgeDeallocateChildRanges(IOPCIConfigEntry * bridge, IOPCIConfigEntry * dead, 361 uint32_t deallocTypes, uint32_t freeTypes); 362 363 void doConfigure(uint32_t options); 364 365 void applyConfiguration(IOPCIConfigEntry * device, uint32_t typeMask, bool dolog); 366 void deviceApplyConfiguration(IOPCIConfigEntry * device, uint32_t typeMask, bool dolog); 367 void bridgeApplyConfiguration(IOPCIConfigEntry * bridge, uint32_t typeMask, bool dolog); 368 uint16_t disableAccess(IOPCIConfigEntry * device, bool disable); 369 void restoreAccess(IOPCIConfigEntry * device, UInt16 command); 370 void bridgeAddChild(IOPCIConfigEntry * bridge, IOPCIConfigEntry * child); 371 void bridgeRemoveChild(IOPCIConfigEntry * bridge, IOPCIConfigEntry * dead, 372 uint32_t deallocTypes, uint32_t freeTypes, 373 IOPCIConfigEntry ** childList); 374 void bridgeMoveChildren(IOPCIConfigEntry * to, IOPCIConfigEntry * list); 375 void bridgeDeadChild(IOPCIConfigEntry * bridge, IOPCIConfigEntry * dead); 376 void bridgeProbeChild(IOPCIConfigEntry * bridge, IOPCIAddressSpace space, uint32_t resetMask); 377 void probeBaseAddressRegister(IOPCIConfigEntry * device, uint32_t lastBarNum, uint32_t resetMask); 378 void safeProbeBaseAddressRegister(IOPCIConfigEntry * device, uint32_t lastBarNum, uint32_t resetMask); 379 void deviceProbeRanges(IOPCIConfigEntry * device, uint32_t resetMask); 380 void bridgeProbeRanges(IOPCIConfigEntry * bridge, uint32_t resetMask); 381 void cardbusProbeRanges(IOPCIConfigEntry * bridge, uint32_t resetMask); 382 void bridgeProbeBusRange(IOPCIConfigEntry * bridge, uint32_t resetMask); 383 uint32_t findPCICapability(IOPCIConfigEntry * device, 384 uint32_t capabilityID, uint32_t * found); 385 void checkCacheLineSize(IOPCIConfigEntry * device); 386 void writeLatencyTimer(IOPCIConfigEntry * device); 387 388 bool treeInState(IOPCIConfigEntry * entry, uint32_t state, uint32_t mask); 389 void markChanged(IOPCIConfigEntry * entry); 390 void bridgeConnectDeviceTree(IOPCIConfigEntry * bridge); 391 bool bridgeConstructDeviceTree(void * unused, IOPCIConfigEntry * bridge); 392 OSDictionary * constructProperties(IOPCIConfigEntry * device); 393 void constructAddressingProperties(IOPCIConfigEntry * device, OSDictionary * propTable); 394 395 bool createRoot(void); 396 IOReturn addHostBridge(IOPCIBridge * hostBridge); 397 IOPCIConfigEntry * findEntry(IOPCIAddressSpace space); 398 399 bool configAccess(IOPCIConfigEntry * device, bool write); 400 void configAccess(IOPCIConfigEntry * device, uint32_t access, uint32_t offset, void * data); 401 402 uint32_t configRead32( IOPCIAddressSpace space, uint32_t offset); 403 void configWrite32(IOPCIAddressSpace space, uint32_t offset, uint32_t data); 404 uint32_t findPCICapability(IOPCIAddressSpace space, 405 uint32_t capabilityID, uint32_t * found); 406 407 uint32_t configRead32( IOPCIConfigEntry * device, uint32_t offset); 408 uint16_t configRead16( IOPCIConfigEntry * device, uint32_t offset); 409 uint8_t configRead8( IOPCIConfigEntry * device, uint32_t offset); 410 void configWrite32(IOPCIConfigEntry * device, uint32_t offset, uint32_t data); 411 void configWrite16(IOPCIConfigEntry * device, uint32_t offset, uint16_t data); 412 void configWrite8( IOPCIConfigEntry * device, uint32_t offset, uint8_t data); 413 414public: 415 bool init(IOWorkLoop * wl, uint32_t flags); 416 virtual IOWorkLoop * getWorkLoop() const; 417 virtual void free(void); 418 419 IOReturn configOp(IOService * device, uintptr_t op, void * result, void * arg2 = NULL); 420}; 421 422#endif /* KERNEL */ 423 424#endif /* !_IOPCICONFIGURATOR_H */ 425