IOPCIConfigurator.h [plain text]
#ifndef _IOPCICONFIGURATOR_H
#define _IOPCICONFIGURATOR_H
#if ACPI_SUPPORT
#define PLX8680 0
#endif
typedef uint64_t IOPCIScalar;
enum {
kIOPCIRangeFlagMaximizeSize = 0x00000001,
kIOPCIRangeFlagNoCollapse = 0x00000002,
kIOPCIRangeFlagSplay = 0x00000004,
kIOPCIRangeFlagRelocatable = 0x00000008,
kIOPCIRangeFlagForceReloc = 0x00000100,
kIOPCIRangeFlagRelocHalf = 0x00000200,
kIOPCIRangeFlagMaximizeFlags = kIOPCIRangeFlagMaximizeSize
| kIOPCIRangeFlagNoCollapse
};
struct IOPCIRange
{
IOPCIScalar start;
IOPCIScalar size;
IOPCIScalar proposedSize;
IOPCIScalar end;
IOPCIScalar zero;
IOPCIScalar alignment;
IOPCIScalar minAddress;
IOPCIScalar maxAddress;
uint8_t type;
uint8_t count;
uint8_t pri;
uint8_t resvB;
uint32_t flags;
struct IOPCIRange * next;
struct IOPCIRange * nextSubRange;
struct IOPCIRange * allocations;
};
IOPCIScalar IOPCIScalarAlign(IOPCIScalar num, IOPCIScalar alignment);
IOPCIScalar IOPCIScalarTrunc(IOPCIScalar num, IOPCIScalar alignment);
IOPCIRange * IOPCIRangeAlloc(void);
void IOPCIRangeFree(IOPCIRange * range);
void IOPCIRangeInit(IOPCIRange * range, uint32_t type,
IOPCIScalar start, IOPCIScalar size, IOPCIScalar alignment = 0);
void IOPCIRangeDump(IOPCIRange * head);
bool IOPCIRangeListAddRange(IOPCIRange ** rangeList,
uint32_t type,
IOPCIScalar start,
IOPCIScalar size,
IOPCIScalar alignment = 1);
bool IOPCIRangeDeallocateSubRange(IOPCIRange * headRange,
IOPCIRange * oldRange);
bool IOPCIRangeListAllocateSubRange(IOPCIRange * headRange,
IOPCIRange * newRange,
IOPCIScalar newStart = 0);
bool IOPCIRangeListDeallocateSubRange(IOPCIRange * headRange,
IOPCIRange * oldRange);
bool IOPCIRangeAppendSubRange(IOPCIRange ** headRange,
IOPCIRange * newRange );
IOPCIScalar IOPCIRangeListCollapse(IOPCIRange * headRange, IOPCIScalar alignment);
IOPCIScalar IOPCIRangeCollapse(IOPCIRange * headRange, IOPCIScalar alignment);
IOPCIScalar IOPCIRangeListLastFree(IOPCIRange * headRange, IOPCIScalar align);
IOPCIScalar IOPCIRangeLastFree(IOPCIRange * headRange, IOPCIScalar align);
#ifdef KERNEL
#include <IOKit/IOLib.h>
#include <IOKit/pci/IOPCIBridge.h>
#define kPCIBridgeIOAlignment (4096)
#define kPCIBridgeMemoryAlignment (1024*1024)
#define kPCIBridgeBusNumberAlignment (1)
#define FOREACH_CHILD(bridge, child) \
for(IOPCIConfigEntry * (child) = (bridge)->child; (child); (child) = (child)->peer)
enum {
kIOPCIConfiguratorIOLog = 0x00000001,
kIOPCIConfiguratorKPrintf = 0x00000002,
kIOPCIConfiguratorVTLog = 0x00000004,
kIOPCIConfiguratorCheckTunnel = 0x00000008,
kIOPCIConfiguratorNoTunnelDrv = 0x00000010,
kIOPCIConfiguratorNoTerminate = 0x00000020,
kIOPCIConfiguratorLogSaveRestore = 0x00000040,
kIOPCIConfiguratorDeferHotPlug = 0x00000080,
kIOPCIConfiguratorPanicOnFault = 0x00000100,
kIOPCIConfiguratorNoSplay = 0x00000200,
kIOPCIConfiguratorDeepIdle = 0x00000400,
kIOPCIConfiguratorNoTB = 0x00000800,
kIOPCIConfiguratorMSIEnable = 0x00001000,
kIOPCIConfiguratorPFM64 = 0x00002000,
kIOPCIConfiguratorBoot = 0x00004000,
kIOPCIConfiguratorIGIsMapped = 0x00008000,
kIOPCIConfiguratorReset = 0x00010000,
kIOPCIConfiguratorAllocate = 0x00020000,
kIOPCIConfiguratorUsePause = 0x00040000,
kIOPCIConfiguratorBootDefer = kIOPCIConfiguratorDeferHotPlug | kIOPCIConfiguratorBoot,
};
enum {
kIOPCIRangeBAR0 = 0,
kIOPCIRangeBAR1 = 1,
kIOPCIRangeBAR2 = 2,
kIOPCIRangeBAR3 = 3,
kIOPCIRangeBAR4 = 4,
kIOPCIRangeBAR5 = 5,
kIOPCIRangeExpansionROM = 6,
kIOPCIRangeBridgeMemory = 7,
kIOPCIRangeBridgePFMemory = 8,
kIOPCIRangeBridgeIO = 9,
kIOPCIRangeBridgeBusNumber = 10,
kIOPCIRangeCount,
kIOPCIRangeAllMask = (1 << kIOPCIRangeCount) - 1,
kIOPCIRangeAllBarsMask = (1 << (kIOPCIRangeExpansionROM + 1)) - 1,
kIOPCIRangeAllBridgeMask = (1 << kIOPCIRangeBridgeMemory)
| (1 << kIOPCIRangeBridgePFMemory)
| (1 << kIOPCIRangeBridgeIO)
| (1 << kIOPCIRangeBridgeBusNumber),
};
enum {
kPCIDeviceStatePropertiesDone = 0x00000002,
kPCIDeviceStateTreeConnected = 0x00000004,
kPCIDeviceStateConfigurationDone = 0x00000008,
kPCIDeviceStateScanned = 0x00000010,
kPCIDeviceStateAllocatedBus = 0x00000020,
kPCIDeviceStateAllocated = 0x00000040,
kPCIDeviceStateChildChanged = 0x00000080,
kPCIDeviceStateNoLink = 0x00000100,
kPCIDeviceStateConfigProtectShift = 15,
kPCIDeviceStateConfigRProtect = (VM_PROT_READ << kPCIDeviceStateConfigProtectShift),
kPCIDeviceStateConfigWProtect = (VM_PROT_WRITE << kPCIDeviceStateConfigProtectShift),
kPCIDeviceStateDead = 0x80000000,
kPCIDeviceStateEjected = 0x40000000,
kPCIDeviceStateToKill = 0x20000000,
kPCIDeviceStatePaused = 0x10000000,
kPCIDeviceStateRequestPause = 0x08000000,
kPCIDeviceStateSwizzled = 0x04000000,
};
enum {
kPCIHeaderType0 = 0,
kPCIHeaderType1 = 1,
kPCIHeaderType2 = 2
};
enum {
kPCIStatic = 0,
kPCILinkChange = 1,
kPCIHotPlug = 2,
kPCIHotPlugRoot = 3,
kPCIHotPlugTunnel = 4,
kPCIHotPlugTunnelRoot = 5,
kPCIHotPlugTunnelRootParent = 6,
};
enum {
kPCI2PCIPrimaryBus = 0x18,
kPCI2PCISecondaryBus = 0x19,
kPCI2PCISubordinateBus = 0x1a,
kPCI2PCISecondaryLT = 0x1b,
kPCI2PCIIORange = 0x1c,
kPCI2PCIMemoryRange = 0x20,
kPCI2PCIPrefetchMemoryRange = 0x24,
kPCI2PCIPrefetchUpperBase = 0x28,
kPCI2PCIPrefetchUpperLimit = 0x2c,
kPCI2PCIUpperIORange = 0x30,
kPCI2PCIBridgeControl = 0x3e
};
#define kPCIBridgeMaxCount 256
enum
{
kConfigOpAddHostBridge = 1,
kConfigOpScan,
kConfigOpRealloc,
kConfigOpGetState,
kConfigOpNeedsScan,
kConfigOpEject,
kConfigOpKill,
kConfigOpTerminated,
kConfigOpProtect,
kConfigOpPaused,
kConfigOpUnpaused,
kConfigOpTestPause,
};
struct IOPCIConfigEntry
{
IOPCIConfigEntry * parent;
IOPCIConfigEntry * child;
IOPCIConfigEntry * peer;
uint32_t classCode;
IOPCIAddressSpace space;
uint32_t vendorProduct;
uint32_t expressCapBlock;
uint32_t expressDeviceCaps1;
IOPCIRange * ranges[kIOPCIRangeCount];
IOPCIRange busResv;
uint32_t rangeBaseChanges;
uint32_t rangeSizeChanges;
uint32_t rangeRequestChanges;
uint32_t deviceState;
uint8_t iterator;
uint8_t headerType;
uint8_t isBridge;
uint8_t isHostBridge;
uint8_t supportsHotPlug;
uint8_t linkInterrupts;
uint8_t clean64;
uint8_t secBusNum; uint8_t subBusNum;
uint32_t linkCaps;
uint16_t expressCaps;
uint8_t expressMaxPayload;
uint8_t expressPayloadSetting;
IORegistryEntry * dtNub;
#if ACPI_SUPPORT
IORegistryEntry * acpiDevice;
#endif
#if PLX8680
volatile uint32_t * plx;
IOPCIScalar plxAperture;
#endif
};
class IOPCIConfigurator : public IOService
{
friend class IOPCIBridge;
OSDeclareDefaultStructors( IOPCIConfigurator );
IOWorkLoop * fWL;
IOOptionBits fFlags;
IOPCIBridge * fHostBridge;
IOPCIConfigEntry * fRoot;
uint32_t fRootVendorProduct;
uint8_t fMaxPayload;
IOPCIRange * fConsoleRange;
IOPCIScalar fPFMConsole;
OSSet * fChangedServices;
uint32_t fWaitingPause;
uint32_t fBridgeCount;
uint32_t fDeviceCount;
protected:
static void safeProbeCallback( void * refcon );
static void configProbeCallback( void * refcon );
static void matchDTEntry( IORegistryEntry * dtEntry, void * _context );
#if ACPI_SUPPORT
static void matchACPIEntry( IORegistryEntry * dtEntry, void * _context );
void removeFixedRanges(IORegistryEntry * root);
#endif
typedef int32_t (IOPCIConfigurator::*IterateProc)(void * ref, IOPCIConfigEntry * bridge);
void iterate(uint32_t options,
IterateProc topProc, IterateProc bottomProc,
void * ref = NULL);
int32_t scanProc(void * ref, IOPCIConfigEntry * bridge);
int32_t bootResetProc(void * ref, IOPCIConfigEntry * bridge);
int32_t totalProc(void * ref, IOPCIConfigEntry * bridge);
int32_t allocateProc(void * ref, IOPCIConfigEntry * bridge);
int32_t bridgeFinalizeConfigProc(void * unused, IOPCIConfigEntry * bridge);
void configure(uint32_t options);
void bridgeScanBus(IOPCIConfigEntry * bridge, uint8_t busNum, uint32_t resetMask);
IOPCIRange * bridgeGetRange(IOPCIConfigEntry * bridge, uint32_t type);
bool bridgeTotalResources(IOPCIConfigEntry * bridge, uint32_t typeMask);
int32_t bridgeAllocateResources( IOPCIConfigEntry * bridge, uint32_t typeMask );
bool bridgeDeallocateChildRanges(IOPCIConfigEntry * bridge, IOPCIConfigEntry * dead,
uint32_t deallocTypes, uint32_t freeTypes);
void doConfigure(uint32_t options);
void applyConfiguration(IOPCIConfigEntry * device, uint32_t typeMask);
void deviceApplyConfiguration(IOPCIConfigEntry * device, uint32_t typeMask);
void bridgeApplyConfiguration(IOPCIConfigEntry * bridge, uint32_t typeMask);
uint16_t disableAccess(IOPCIConfigEntry * device, bool disable);
void restoreAccess(IOPCIConfigEntry * device, UInt16 command);
void bridgeAddChild(IOPCIConfigEntry * bridge, IOPCIConfigEntry * child);
void bridgeRemoveChild(IOPCIConfigEntry * bridge, IOPCIConfigEntry * dead,
uint32_t deallocTypes, uint32_t freeTypes,
IOPCIConfigEntry ** childList);
void bridgeMoveChildren(IOPCIConfigEntry * to, IOPCIConfigEntry * list);
void bridgeDeadChild(IOPCIConfigEntry * bridge, IOPCIConfigEntry * dead);
void bridgeProbeChild(IOPCIConfigEntry * bridge, IOPCIAddressSpace space, uint32_t resetMask);
void probeBaseAddressRegister(IOPCIConfigEntry * device, uint32_t lastBarNum, uint32_t resetMask);
void safeProbeBaseAddressRegister(IOPCIConfigEntry * device, uint32_t lastBarNum, uint32_t resetMask);
void deviceProbeRanges(IOPCIConfigEntry * device, uint32_t resetMask);
void bridgeProbeRanges(IOPCIConfigEntry * bridge, uint32_t resetMask);
void cardbusProbeRanges(IOPCIConfigEntry * bridge, uint32_t resetMask);
void bridgeProbeBusRange(IOPCIConfigEntry * bridge, uint32_t resetMask);
uint32_t findPCICapability(IOPCIConfigEntry * device,
uint32_t capabilityID, uint32_t * found);
void checkCacheLineSize(IOPCIConfigEntry * device);
void writeLatencyTimer(IOPCIConfigEntry * device);
void markChanged(IOPCIConfigEntry * entry);
void bridgeConnectDeviceTree(IOPCIConfigEntry * bridge);
bool bridgeConstructDeviceTree(void * unused, IOPCIConfigEntry * bridge);
OSDictionary * constructProperties(IOPCIConfigEntry * device);
void constructAddressingProperties(IOPCIConfigEntry * device, OSDictionary * propTable);
bool createRoot(void);
IOReturn addHostBridge(IOPCIBridge * hostBridge);
bool configAccess(IOPCIConfigEntry * device, bool write);
uint32_t configRead32( IOPCIAddressSpace space, uint32_t offset);
void configWrite32(IOPCIAddressSpace space, uint32_t offset, uint32_t data);
uint32_t findPCICapability(IOPCIAddressSpace space,
uint32_t capabilityID, uint32_t * found);
uint32_t configRead32( IOPCIConfigEntry * device, uint32_t offset);
uint16_t configRead16( IOPCIConfigEntry * device, uint32_t offset);
uint8_t configRead8( IOPCIConfigEntry * device, uint32_t offset);
void configWrite32(IOPCIConfigEntry * device, uint32_t offset, uint32_t data);
void configWrite16(IOPCIConfigEntry * device, uint32_t offset, uint16_t data);
void configWrite8( IOPCIConfigEntry * device, uint32_t offset, uint8_t data);
public:
bool init(IOWorkLoop * wl, uint32_t flags);
virtual IOWorkLoop * getWorkLoop() const;
virtual void free(void);
IOReturn configOp(IOService * device, uintptr_t op, void * result);
};
#endif
#endif