#include <ppc/proc_reg.h>
#include <IOKit/IOLib.h>
#include <IOKit/IOService.h>
#include <IOKit/IODeviceTreeSupport.h>
#include <IOKit/IODeviceMemory.h>
#include <IOKit/IOPlatformExpert.h>
#include <sys/kdebug.h>
#include "AppleMPIC.h"
#ifdef DLOG
#undef DLOG
#endif
#ifdef APPLEMPIC_DEBUG
#define DLOG(fmt, args...) kprintf(fmt, ## args)
#else
#define DLOG(fmt, args...)
#endif
#undef super
#define super IOInterruptController
OSDefineMetaClassAndStructors(AppleMPICInterruptController, IOInterruptController);
bool AppleMPICInterruptController::start(IOService *provider)
{
long cnt, regTemp;
OSObject *tmpObject;
IOInterruptAction handler;
mpic_getProvider = OSSymbol::withCString("mpic_getProvider");
mpic_getIPIVector= OSSymbol::withCString("mpic_getIPIVector");
mpic_setCurrentTaskPriority = OSSymbol::withCString("mpic_setCurrentTaskPriority");
mpic_setUpForSleep = OSSymbol::withCString("mpic_setUpForSleep");
mpic_dispatchIPI = OSSymbol::withCString("mpic_dispatchIPI");
if (!super::start(provider))
return false;
tmpObject = provider->getProperty("InterruptControllerName");
interruptControllerName = OSDynamicCast(OSSymbol, tmpObject);
if (interruptControllerName == 0) return false;
setProperty("InterruptControllerName", interruptControllerName);
isHostMPIC = (provider->getProperty("interrupts") == NULL);
accessBigEndian = (provider->getProperty("big-endian") != NULL);
resetOnWake = (provider->getProperty("reset-on-wake") != NULL);
htIntLock = IOLockAlloc();
if (htIntLock == NULL)
{
IOLog("AppleMPIC returning false with no htIntLock\n");
return false;
}
mpicMemoryMap = provider->mapDeviceMemoryWithIndex(0);
if (mpicMemoryMap == 0) return false;
mpicBaseAddress = mpicMemoryMap->getVirtualAddress();
regTemp = LWBRX(mpicBaseAddress + kFeatureOffset);
numCPUs = ((regTemp & kFRRNumCPUMask) >> kFRRNumCPUShift) + 1;
numVectors = ((regTemp & kFRRNumIRQsMask) >> kFRRNumIRQsShift) + 1;
senses = (UInt32 *)IOMalloc ((numVectors + numCPUs) * sizeof (long));
if (senses == NULL) return false;
for (cnt = 0; cnt < (numVectors + numCPUs); cnt++)
senses[cnt] = 0;
vectors = (IOInterruptVector *)IOMalloc((numVectors + numCPUs) *
sizeof(IOInterruptVector));
if (vectors == NULL) return false;
bzero(vectors, (numVectors + numCPUs) * sizeof(IOInterruptVector));
for (cnt = 0; cnt < (numVectors + numCPUs) ; cnt++)
{
vectors[cnt].interruptLock = IOLockAlloc();
if (vectors[cnt].interruptLock == NULL)
{
for (cnt = 0; cnt < (numVectors + numCPUs); cnt++)
{
if (vectors[cnt].interruptLock != NULL)
IOLockFree(vectors[cnt].interruptLock);
}
return false;
}
}
STWBRX(kGCR0Reset, mpicBaseAddress + kGlobal0Offset);
EIEIO();
do
{
regTemp = LWBRX(mpicBaseAddress + kGlobal0Offset);
EIEIO();
} while (regTemp & kGCR0Reset);
for (cnt = 0; cnt < (numVectors + numCPUs); cnt++)
{
STWBRX(kIntnVPRMask, mpicBaseAddress+kIntnVecPriOffset+kIntnStride*cnt);
}
EIEIO();
STWBRX(kSpuriousVectorNumber, mpicBaseAddress + kSpurVectOffset);
STWBRX(kGCR0Cascade, mpicBaseAddress + kGlobal0Offset);
for(cnt = 0; cnt < numCPUs; cnt++)
{
STWBRX(0, mpicBaseAddress + kPnCurrTskPriOffset + (kPnStride * cnt));
EIEIO();
}
originalIpivecPriOffsets = (UInt32*)IOMalloc(sizeof(UInt32) * numCPUs);
if (originalIpivecPriOffsets == NULL)
{
return false;
}
originalCurrentTaskPris = (UInt32*)IOMalloc(sizeof(UInt32) * numCPUs);
if (originalCurrentTaskPris == NULL)
{
return false;
}
if (resetOnWake)
{
mpicSavedStatePtr = (MPICStatePtr)IOMalloc (sizeof (MPICState));
if (mpicSavedStatePtr)
{
mpicSavedStatePtr->mpicInterruptSourceVectorPriority = (UInt32 *)IOMalloc (sizeof(UInt32) * numVectors);
mpicSavedStatePtr->mpicInterruptSourceDestination = (UInt32 *)IOMalloc (sizeof(UInt32) * numVectors);
}
}
registerService();
handler = getInterruptHandlerAddress();
if (isHostMPIC)
{
getPlatform()->setCPUInterruptProperties(provider);
for (cnt = 0; cnt < numCPUs; cnt++)
{
provider->registerInterrupt(cnt, this, handler, 0);
provider->enableInterrupt(cnt);
}
}
else
{
provider->registerInterrupt(0, this, handler, 0);
provider->enableInterrupt(0);
}
getPlatform()->registerInterruptController(interruptControllerName, this);
return true;
}
IOReturn AppleMPICInterruptController::callPlatformFunction(const OSSymbol *functionName,
bool waitForFunction,
void *param1, void *param2,
void *param3, void *param4)
{
if (functionName == mpic_getProvider)
{
IORegistryEntry **tmpIORegistryEntry = (IORegistryEntry**)param1;
*tmpIORegistryEntry = getProvider();
return kIOReturnSuccess;
}
if (functionName == mpic_getIPIVector)
{
OSData **tmpOSData = (OSData**)param2;
*tmpOSData = getIPIVector(*(long *)param1);
return kIOReturnSuccess;
}
if (functionName == mpic_setCurrentTaskPriority)
{
setCurrentTaskPriority(*(long *)param1);
return kIOReturnSuccess;
}
if (functionName == mpic_setUpForSleep)
{
setUpForSleep((bool)param1, (int)param2);
return kIOReturnSuccess;
}
if (functionName == mpic_dispatchIPI)
{
dispatchIPI(*(long *)param1, (long)param2);
return kIOReturnSuccess;
}
return super::callPlatformFunction(functionName, waitForFunction, param1, param2, param3, param4);
}
IOReturn AppleMPICInterruptController::getInterruptType(IOService *nub,
int source,
int *interruptType)
{
IOInterruptSource *interruptSources;
OSData *vectorData;
long vectorNumber;
if (interruptType == 0)
return kIOReturnBadArgument;
interruptSources = nub->_interruptSources;
vectorData = interruptSources[source].vectorData;
vectorNumber = *(long *)vectorData->getBytesNoCopy();
*interruptType = (((long *)vectorData->getBytesNoCopy())[1]) & kIntrTypeMask;
return kIOReturnSuccess;
}
IOInterruptAction AppleMPICInterruptController::getInterruptHandlerAddress(void)
{
#ifdef OSMemberFunctionCast
return OSMemberFunctionCast(IOInterruptAction, this, &AppleMPICInterruptController::handleInterrupt);
#else
return (IOInterruptAction)&AppleMPICInterruptController::handleInterrupt;
#endif
}
IOReturn AppleMPICInterruptController::handleInterrupt( void * ,
IOService * ,
int source)
{
long vectorNumber, level, sense;
IOInterruptVector *vector;
do
{
vectorNumber = LWBRX(mpicBaseAddress + source*kPnStride + kPnIntAckOffset);
EIEIO();
if (vectorNumber == kSpuriousVectorNumber)
break;
sense = senses[vectorNumber];
level = sense & kIntrTypeMask;
if ( ! level )
{
STWBRX(0, mpicBaseAddress + source * kPnStride + kPnEOIOffset);
EIEIO();
}
vector = &vectors[vectorNumber];
vector->interruptActive = 1;
sync();
isync();
if ( ! vector->interruptDisabledSoft )
{
isync();
KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_IHDLR, 0), vectorNumber, (unsigned int)vector->handler, (unsigned int)vector->target, 0, 0);
if (vector->interruptRegistered)
{
vector->handler(vector->target, vector->refCon, vector->nub, vector->source);
if (level && vector->interruptDisabledSoft)
{
vector->interruptDisabledHard = 1;
disableVectorHard(vectorNumber, vector);
}
else if ((sense & (kIntrHTMask | kIOInterruptTypeLevel)) == (kIntrHTMask | kIOInterruptTypeLevel))
{
htWaitEOI( sense >> 16 );
}
}
}
else
{
vector->interruptDisabledHard = 1;
disableVectorHard(vectorNumber, vector);
}
if ( level )
{
STWBRX(0, mpicBaseAddress + source * kPnStride + kPnEOIOffset);
EIEIO();
}
vector->interruptActive = 0;
} while (1);
return kIOReturnSuccess;
}
bool AppleMPICInterruptController::vectorCanBeShared(long , IOInterruptVector *)
{
return true;
}
void AppleMPICInterruptController::initVector(long vectorNumber, IOInterruptVector *vector)
{
IOInterruptSource *interruptSources;
long vectorType;
OSData *vectorData;
long regTemp, vectorBase;
interruptSources = vector->nub->_interruptSources;
vectorData = interruptSources[vector->source].vectorData;
vectorType = ((long *)vectorData->getBytesNoCopy())[1];
senses[vectorNumber] = vectorType;
if (vectorType & kIntrHTMask)
{
if ( ! fHTInterruptProvider )
fHTInterruptProvider = configureHTInterruptProvider (&fHTIntCapabilities, &fHTIntDataPort);
}
if (vectorNumber < numVectors)
{
vectorBase = mpicBaseAddress + kIntnStride * vectorNumber;
regTemp = 0x1; STWBRX(regTemp, vectorBase + kIntnDestOffset);
EIEIO();
regTemp = kIntnVPRMask | (8 << kIntnVPRPriorityShift);
if (vectorType & kIntrHTMask)
initHTVector (vectorType, false); else
regTemp |= ((vectorType & kIntrTypeMask) == kIOInterruptTypeLevel) ? kIntnVPRSense : 0;
regTemp |= vectorNumber << kIntnVPRVectorShift;
STWBRX(regTemp, vectorBase + kIntnVecPriOffset);
EIEIO();
}
else
{
vectorBase = mpicBaseAddress + kIPInVecPriStride*(vectorNumber-numVectors);
regTemp = kIntnVPRMask | (14 << kIntnVPRPriorityShift);
regTemp |= vectorNumber << kIntnVPRVectorShift;
STWBRX(regTemp, vectorBase + kIPInVecPriOffset);
EIEIO();
}
return;
}
void AppleMPICInterruptController::disableVectorHard(long vectorNumber, IOInterruptVector *)
{
long regTemp, vectorBase;
if (vectorNumber < numVectors)
{
vectorBase = mpicBaseAddress + kIntnVecPriOffset + kIntnStride * vectorNumber;
}
else
{
vectorBase = mpicBaseAddress + kIPInVecPriOffset + kIPInVecPriStride * (vectorNumber - numVectors);
}
regTemp = LWBRX(vectorBase);
if ( ! (regTemp & kIntnVPRMask) )
{
regTemp |= kIntnVPRMask;
STWBRX(regTemp, vectorBase);
}
return;
}
void AppleMPICInterruptController::enableVector(long vectorNumber, IOInterruptVector *)
{
long regTemp, vectorBase, sense;
sense = senses[vectorNumber];
if (vectorNumber < numVectors)
{
vectorBase = mpicBaseAddress + kIntnVecPriOffset + kIntnStride * vectorNumber;
}
else
{
vectorBase = mpicBaseAddress + kIPInVecPriOffset + kIPInVecPriStride * (vectorNumber - numVectors);
}
regTemp = LWBRX(vectorBase);
if (regTemp & kIntnVPRMask)
{
regTemp &= ~kIntnVPRMask;
STWBRX(regTemp, vectorBase);
}
if ((sense & (kIntrHTMask | kIOInterruptTypeLevel)) == (kIntrHTMask | kIOInterruptTypeLevel))
{
htWaitEOI(sense >> 16);
}
return;
}
OSData *AppleMPICInterruptController::getIPIVector(long physCPU)
{
long tmpLongs[2];
OSData *tmpData;
if ((physCPU < 0) && (physCPU >= numCPUs))
return 0;
tmpLongs[0] = numVectors + physCPU;
tmpLongs[1] = kIOInterruptTypeEdge;
tmpData = OSData::withBytes(tmpLongs, 2 * sizeof(long));
return tmpData;
}
void AppleMPICInterruptController::dispatchIPI(long source, long targetMask)
{
long ipiBase, cnt;
ipiBase = mpicBaseAddress + kPnIPImDispOffset + kPnStride * source;
for (cnt = 0; cnt < numCPUs; cnt++)
{
if (targetMask & (1 << cnt))
{
STWBRX((1 << cnt), ipiBase + kPnIPImDispStride * cnt);
EIEIO();
}
}
return;
}
void AppleMPICInterruptController::setCurrentTaskPriority(long priority)
{
long cnt;
for(cnt = 0; cnt < numCPUs; cnt++)
{
STWBRX(priority, mpicBaseAddress + kPnCurrTskPriOffset + (kPnStride*cnt));
EIEIO();
}
return;
}
void AppleMPICInterruptController::setUpForSleep(bool goingToSleep, int cpu)
{
int i;
volatile UInt32 *ipivecPriOffset = (UInt32*)(mpicBaseAddress + kIPInVecPriOffset + (cpu << 4));
volatile UInt32 *currentTaskPri = (UInt32*)(mpicBaseAddress + kPnCurrTskPriOffset + (kPnStride * cpu));
DLOG("\nAppleMPICInterruptController::setUpForSleep(%s, %d)\n",(goingToSleep ? "true" : "false"), cpu);
if ( goingToSleep )
{
DLOG("AppleMPICInterruptController::setUpForSleep ipivecPriOffset(0x%08lx) = 0x%08lx\n",(UInt32)ipivecPriOffset, 0x00000080);
DLOG("AppleMPICInterruptController::setUpForSleep currentTaskPri(0x%08lx) = 0x%08lx\n",(UInt32)currentTaskPri, (0x0000000F << 24));
if ( resetOnWake && (cpu == 0) )
{
mpicSavedStatePtr->mpicGlobal0 = *(UInt32 *)(mpicBaseAddress + kGlobal0Offset);
DLOG( "MPIC: saved(0x%08x): 0x%08x\n", kGlobal0Offset, mpicSavedStatePtr->mpicGlobal0 );
for (i = 0; i < kMPICIPICount; i++)
{
mpicSavedStatePtr->mpicIPI[i] = *(UInt32 *)(mpicBaseAddress + kIPInVecPriOffset + (i * kIPInVecPriStride));
DLOG( "MPIC: saved(0x%08x): 0x%08x\n", kIPInVecPriOffset + (i * kIPInVecPriStride), mpicSavedStatePtr->mpicIPI[i] );
}
mpicSavedStatePtr->mpicSpuriousVector = *(UInt32 *)(mpicBaseAddress + kSpurVectOffset);
DLOG( "MPIC: saved(0x%08x): 0x%08x\n", kSpurVectOffset, mpicSavedStatePtr->mpicSpuriousVector);
mpicSavedStatePtr->mpicTimerFrequencyReporting = *(UInt32 *)(mpicBaseAddress + kTmrFreqOffset);
DLOG( "MPIC: saved(0x%08x): 0x%08x\n", kTmrFreqOffset, mpicSavedStatePtr->mpicTimerFrequencyReporting );
for (i = 0; i < kMPICTimerCount; i++)
{
mpicSavedStatePtr->mpicTimers[i].currentCountRegister = *(UInt32 *)(mpicBaseAddress + kTnBaseCntOffset + (i * kTnStride));
DLOG( "MPIC: saved(0x%08x): 0x%08x\n", kTnBaseCntOffset + (i * kTnStride), mpicSavedStatePtr->mpicTimers[i].currentCountRegister );
mpicSavedStatePtr->mpicTimers[i].baseCountRegister = *(UInt32 *)(mpicBaseAddress + kTnBaseCntOffset + (i * kTnStride) + 0x10);
DLOG( "MPIC: saved(0x%08x): 0x%08x\n", kTnBaseCntOffset + (i * kTnStride + 0x10), mpicSavedStatePtr->mpicTimers[i].baseCountRegister );
mpicSavedStatePtr->mpicTimers[i].vectorPriorityRegister = *(UInt32 *)(mpicBaseAddress + kTnBaseCntOffset + (i * kTnStride) + 0x20);
DLOG( "MPIC: saved(0x%08x): 0x%08x\n", kTnBaseCntOffset + (i * kTnStride + 0x20), mpicSavedStatePtr->mpicTimers[i].vectorPriorityRegister );
mpicSavedStatePtr->mpicTimers[i].destinationRegister = *(UInt32 *)(mpicBaseAddress + kTnBaseCntOffset + (i * kTnStride) + 0x30);
DLOG( "MPIC: saved(0x%08x): 0x%08x\n", kTnBaseCntOffset + (i * kTnStride + 0x30), mpicSavedStatePtr->mpicTimers[i].destinationRegister );
}
for (i = 0; i < numVectors; i++)
{
mpicSavedStatePtr->mpicInterruptSourceVectorPriority[i] = *(UInt32 *)(mpicBaseAddress + kIntnVecPriOffset + (i * kIntnStride)) &
(accessBigEndian ? (~0x40000000) : (~0x00000040));
DLOG( "MPIC: saved(0x%08x): 0x%08x\n", kIntnVecPriOffset + (i * kIntnStride), mpicSavedStatePtr->mpicInterruptSourceVectorPriority[i] );
mpicSavedStatePtr->mpicInterruptSourceDestination[i] = *(UInt32 *)(mpicBaseAddress + kIntnDestOffset + (i * kIntnStride));
DLOG( "MPIC: saved(0x%08x): 0x%08x\n", kIntnDestOffset + (i * kIntnStride), mpicSavedStatePtr->mpicInterruptSourceDestination[i] );
}
for (i = 0; i < kMPICTaskPriorityCount; i++)
{
mpicSavedStatePtr->mpicCurrentTaskPriorities[i] = *(UInt32 *)(mpicBaseAddress + kPnCurrTskPriOffset + (kPnStride * cpu));
DLOG( "MPIC: saved(0x%08x): 0x%08x\n", kPnCurrTskPriOffset + (kPnStride * cpu), mpicSavedStatePtr->mpicCurrentTaskPriorities[i] );
}
}
originalIpivecPriOffsets[cpu] = *ipivecPriOffset;
EIEIO();
originalCurrentTaskPris[cpu] = *currentTaskPri;
EIEIO();
if (numCPUs > 1)
{
*ipivecPriOffset = 0x00000080;
EIEIO();
}
*currentTaskPri = (0x0000000F << 24);
EIEIO();
}
else
{
DLOG( "AppleMPICInterruptController::setUpForSleep ipivecPriOffset(0x%08lx) = 0x%08lx\n",(UInt32)ipivecPriOffset, originalIpivecPriOffsets[cpu] );
DLOG( "AppleMPICInterruptController::setUpForSleep currentTaskPri(0x%08lx) = 0x%08lx\n",(UInt32)currentTaskPri, originalCurrentTaskPris[cpu] );
if (resetOnWake && (cpu == 0))
{
*(UInt32 *)(mpicBaseAddress + kGlobal0Offset) = mpicSavedStatePtr->mpicGlobal0;
DLOG( "MPIC: restored(0x%08x): 0x%08x\n", kGlobal0Offset, mpicSavedStatePtr->mpicGlobal0);
for (i = 0; i < kMPICIPICount; i++)
{
*(UInt32 *)(mpicBaseAddress + kIPInVecPriOffset + (i * kIPInVecPriStride)) = mpicSavedStatePtr->mpicIPI[i];
DLOG( "MPIC: restored(0x%08x): 0x%08x\n", kIPInVecPriOffset + (i * kIPInVecPriStride), mpicSavedStatePtr->mpicIPI[i] );
}
*(UInt32 *)(mpicBaseAddress + kSpurVectOffset) = mpicSavedStatePtr->mpicSpuriousVector;
DLOG( "MPIC: restored(0x%08x): 0x%08x\n", kSpurVectOffset, mpicSavedStatePtr->mpicSpuriousVector );
*(UInt32 *)(mpicBaseAddress + kTmrFreqOffset) = mpicSavedStatePtr->mpicTimerFrequencyReporting;
DLOG( "MPIC: restored(0x%08x): 0x%08x\n", kTmrFreqOffset, mpicSavedStatePtr->mpicTimerFrequencyReporting );
for (i = 0; i < kMPICTimerCount; i++)
{
*(UInt32 *)(mpicBaseAddress + kTnBaseCntOffset + (i * kTnStride)) = mpicSavedStatePtr->mpicTimers[i].currentCountRegister;
DLOG( "MPIC: restored(0x%08x): 0x%08x\n", kTnBaseCntOffset + (i * kTnStride), mpicSavedStatePtr->mpicTimers[i].currentCountRegister );
*(UInt32 *)(mpicBaseAddress + kTnBaseCntOffset + (i * kTnStride) + 0x10) = mpicSavedStatePtr->mpicTimers[i].baseCountRegister;
DLOG( "MPIC: restored(0x%08x): 0x%08x\n", kTnBaseCntOffset + (i * kTnStride + 0x10), mpicSavedStatePtr->mpicTimers[i].baseCountRegister );
*(UInt32 *)(mpicBaseAddress + kTnBaseCntOffset + (i * kTnStride) + 0x20) = mpicSavedStatePtr->mpicTimers[i].vectorPriorityRegister;
DLOG( "MPIC: restored(0x%08x): 0x%08x\n", kTnBaseCntOffset + (i * kTnStride + 0x20), mpicSavedStatePtr->mpicTimers[i].vectorPriorityRegister );
*(UInt32 *)(mpicBaseAddress + kTnBaseCntOffset + (i * kTnStride) + 0x30) = mpicSavedStatePtr->mpicTimers[i].destinationRegister;
DLOG( "MPIC: restored(0x%08x): 0x%08x\n", kTnBaseCntOffset + (i * kTnStride + 0x30), mpicSavedStatePtr->mpicTimers[i].destinationRegister );
}
for (i = 0; i < numVectors; i++)
{
*(UInt32 *)(mpicBaseAddress + kIntnVecPriOffset + (i * kIntnStride)) = mpicSavedStatePtr->mpicInterruptSourceVectorPriority[i];
DLOG( "MPIC: restored(0x%08x): 0x%08x\n", kIntnVecPriOffset + (i * kIntnStride), mpicSavedStatePtr->mpicInterruptSourceVectorPriority[i] );
*(UInt32 *)(mpicBaseAddress + kIntnDestOffset + i * kIntnStride) = mpicSavedStatePtr->mpicInterruptSourceDestination[i];
DLOG( "MPIC: restored(0x%08x): 0x%08x\n", kIntnDestOffset + (i * kIntnStride), mpicSavedStatePtr->mpicInterruptSourceDestination[i] );
}
for (i = 0; i < kMPICTaskPriorityCount; i++)
{
*(UInt32 *)(mpicBaseAddress + kPnCurrTskPriOffset + (kPnStride * i)) = mpicSavedStatePtr->mpicCurrentTaskPriorities[i];
DLOG( "MPIC: restored(0x%08x): 0x%08x\n", kPnCurrTskPriOffset + (kPnStride * i), mpicSavedStatePtr->mpicCurrentTaskPriorities[i] );
}
for (i = 0; i < (numVectors + numCPUs); i++)
{
if (senses[i] & kIntrHTMask)
initHTVector (senses[i], true); }
}
if (numCPUs > 1)
{
*ipivecPriOffset = originalIpivecPriOffsets[cpu];
EIEIO();
}
*currentTaskPri = (0x00000000 << 24); EIEIO();
STWBRX(kGCR0Cascade, mpicBaseAddress + kGlobal0Offset);
EIEIO();
}
return;
}
bool AppleMPICInterruptController::matchPropertyTable(OSDictionary * table)
{
return compareProperty(table, "InterruptControllerName");
}
IOPCIDevice *AppleMPICInterruptController::configureHTInterruptProvider ( UInt32 *htIntCapOffset, UInt32 *htIntDataPort )
{
IOByteCount offset;
UInt32 configData;
IOService *service;
IOPCIDevice *ht;
ht = NULL;
service = waitForService( resourceMatching("ht-interrupt-sequencer") );
if (service)
if (ht = OSDynamicCast (IOPCIDevice, service->getProperty("ht-interrupt-sequencer")))
{
offset = 0;
do
{
configData = ht->extendedFindPCICapability (kHTIntCapID, &offset);
if (configData && offset)
{
if (((configData >> 24) & 0xFF) == kHTIntCapType)
{
*htIntCapOffset = offset;
*htIntDataPort = offset + sizeof (UInt32);
break;
}
}
else
break; } while (1);
}
return ht;
}
IOReturn AppleMPICInterruptController::initHTVector (UInt32 vectorType, bool waking)
{
UInt32 index, intDefLow;
IOReturn status;
if ( ! fHTInterruptProvider )
{
DLOG( "AppleMPIC::initHTVector - no HyperTransport interrupt provider\n" );
return kIOReturnError;
}
index = vectorType >> 16;
if (index <= kHTMaxInterrupt)
{
index = (index << 1) + kHTIntIndexBase;
if ( ! waking )
IOLockLock (htIntLock);
fHTInterruptProvider->configWrite32 (fHTIntCapabilities, index << 16);
intDefLow = fHTInterruptProvider->configRead32 (fHTIntDataPort) & ~kHTIntDefRegMask;
intDefLow |= (vectorType & kIOInterruptTypeLevel) ? (kHTIntRequestEOI | kHTIntPolarity) : 0;
DLOG( "AppleMPIC::initHTVector - source 0x%x, index 0x%x, writing 0x%x\n", vectorType >> 16, index, intDefLow );
fHTInterruptProvider->configWrite32 (fHTIntDataPort, intDefLow);
if ( ! waking )
IOLockUnlock (htIntLock);
status = kIOReturnSuccess;
}
else
{
DLOG( "AppleMPIC::initHTVector - illegal interrupt source 0x%x\n", index );
status = kIOReturnBadArgument;
}
return status;
}
void AppleMPICInterruptController::htWaitEOI(UInt32 source)
{
UInt32 offset;
offset = ((source >> 3) & ~3) + kHTWaitEOIBase; fHTInterruptProvider->configWrite32 (offset, 1 << (source & 0x1F));
return;
}