[plain text]
#include <IOKit/IOLib.h>
#include <IOKit/IOPlatformExpert.h>
#include "Apple8259PIC.h"
#include "PICShared.h"
#define super IOInterruptController
OSDefineMetaClassAndStructors( Apple8259PICInterruptController,
IOInterruptController )
bool Apple8259PIC::start( IOService * provider )
{
IOInterruptAction handler;
const OSSymbol * name;
if ( super::start(provider) == false ) return false;
_handleSleepWakeFunction = OSSymbol::withCString(
kHandleSleepWakeFunction );
if (!_handleSleepWakeFunction) return false;
_interruptLock = IOSimpleLockAlloc();
if (!_interruptLock) return false;
vectors = IONew( IOInterruptVector, kNumVectors );
if ( 0 == vectors ) return false;
bzero( vectors, sizeof(IOInterruptVector) * kNumVectors );
for ( int cnt = 0; cnt < kNumVectors; cnt++ )
{
vectors[cnt].interruptLock = IOLockAlloc();
if ( 0 == vectors[cnt].interruptLock )
return false;
}
_interruptMasks = 0xffff & ~(1 << kPICSlaveID);
initializePIC( kPIC1BasePort,
kPIC_ICW1_IC4,
kBaseIOInterruptVectors,
(1 << kPICSlaveID),
kPIC_ICW4_uPM );
outb( kPIC_OCW1(kPIC1BasePort), _interruptMasks & 0xff );
outb( kPIC_OCW3(kPIC1BasePort), kPIC_OCW3_MBO | kPIC_OCW3_RR );
outb( kPIC_OCW2(kPIC1BasePort), kPIC_OCW2_R |
kPIC_OCW2_SL |
kPIC_OCW2_LEVEL(2) );
initializePIC( kPIC2BasePort,
kPIC_ICW1_IC4,
kBaseIOInterruptVectors + 8,
kPICSlaveID,
kPIC_ICW4_uPM );
outb( kPIC_OCW1(kPIC2BasePort), _interruptMasks >> 8 );
outb( kPIC_OCW3(kPIC2BasePort), kPIC_OCW3_MBO | kPIC_OCW3_RR );
_interruptTriggerTypes = inb( kPIC1TriggerTypePort ) |
( inb( kPIC2TriggerTypePort ) << 8 );
registerService();
getPlatform()->setCPUInterruptProperties( provider );
handler = getInterruptHandlerAddress();
if ( provider->registerInterrupt(0, this, handler, 0) != kIOReturnSuccess )
IOPanic("8259-PIC: registerInterrupt failed");
provider->enableInterrupt(0);
name = OSSymbol::withString( (OSString *)
provider->getProperty(kInterruptControllerNameKey) );
if ( 0 == name )
{
IOLog("8259-PIC: no interrupt controller name\n");
return false;
}
getPlatform()->registerInterruptController( (OSSymbol *) name, this );
name->release();
return true;
}
void Apple8259PIC::free( void )
{
if ( vectors )
{
for ( int cnt = 0; cnt < kNumVectors; cnt++ )
{
if (vectors[cnt].interruptLock)
IOLockFree(vectors[cnt].interruptLock);
}
IODelete( vectors, IOInterruptVector, kNumVectors );
vectors = 0;
}
if ( _handleSleepWakeFunction )
{
_handleSleepWakeFunction->release();
_handleSleepWakeFunction = 0;
}
if ( _interruptLock )
{
IOSimpleLockFree( _interruptLock );
_interruptLock = 0;
}
super::free();
}
void Apple8259PIC::initializePIC( UInt16 port,
UInt8 icw1, UInt8 icw2,
UInt8 icw3, UInt8 icw4 )
{
outb( kPIC_ICW1(port), kPIC_ICW1_MBO | icw1 );
outb( kPIC_ICW2(port), icw2 );
outb( kPIC_ICW3(port), icw3 );
outb( kPIC_ICW4(port), icw4 );
}
int Apple8259PIC::getVectorType( long vectorNumber,
IOInterruptVector * vector )
{
if (_interruptTriggerTypes & (1 << vectorNumber))
return kIOInterruptTypeLevel;
else
return kIOInterruptTypeEdge;
}
IOReturn Apple8259PIC::getInterruptType( IOService * nub,
int source,
int * interruptType )
{
IOInterruptSource * interruptSources;
OSData * vectorData;
if (!nub || !interruptType)
{
return kIOReturnBadArgument;
}
interruptSources = nub->_interruptSources;
vectorData = interruptSources[source].vectorData;
if (vectorData->getLength() < sizeof(UInt64))
{
UInt32 vectorNumber = DATA_TO_VECTOR(vectorData);
*interruptType = getVectorType(vectorNumber, 0);
}
else
{
UInt32 vectorFlags = DATA_TO_FLAGS(vectorData);
*interruptType = ((vectorFlags & kInterruptTriggerModeMask) ==
kInterruptTriggerModeEdge) ?
kIOInterruptTypeEdge : kIOInterruptTypeLevel;
}
APIC_LOG("PIC: %s( %s, %d ) = %s (vector %ld)\n",
__FUNCTION__,
nub->getName(), source,
*interruptType == kIOInterruptTypeLevel ? "level" : "edge",
DATA_TO_VECTOR(vectorData));
return kIOReturnSuccess;
}
IOReturn Apple8259PIC::setVectorType( long vectorNumber, long vectorType )
{
IOInterruptState state;
if ( vectorNumber >= kNumVectors || vectorNumber == kPICSlaveID ||
( vectorType != kIOInterruptTypeLevel &&
vectorType != kIOInterruptTypeEdge ) )
{
return kIOReturnBadArgument;
}
state = IOSimpleLockLockDisableInterrupt( _interruptLock );
if ( vectorType == kIOInterruptTypeLevel )
_interruptTriggerTypes |= ( 1 << vectorNumber );
else
_interruptTriggerTypes &= ~( 1 << vectorNumber );
outb( kPIC1TriggerTypePort, (UInt8) _interruptTriggerTypes );
outb( kPIC2TriggerTypePort, (UInt8)(_interruptTriggerTypes >> 8));
IOSimpleLockUnlockEnableInterrupt( _interruptLock, state );
return kIOReturnSuccess;
}
IOInterruptAction Apple8259PIC::getInterruptHandlerAddress( void )
{
return (IOInterruptAction) &Apple8259PIC::handleInterrupt;
}
IOReturn Apple8259PIC::handleInterrupt( void * savedState,
IOService * nub,
int source )
{
IOInterruptVector * vector;
long vectorNumber;
long level;
void * refCon;
vectorNumber = source - kBaseIOInterruptVectors;
if (vectorNumber < 0 || vectorNumber >= kNumVectors)
return kIOReturnSuccess;
level = (_interruptTriggerTypes & (1 << vectorNumber));
if (0 == level) ackInterrupt( vectorNumber );
vector = &vectors[ vectorNumber ];
refCon = ((vectorNumber == 0) ? savedState : vector->refCon);
vector->interruptActive = 1;
if ( !vector->interruptDisabledSoft && vector->interruptRegistered )
{
vector->handler( vector->target, refCon,
vector->nub, vector->source );
if ( vector->interruptDisabledSoft )
{
vector->interruptDisabledHard = 1;
disableVectorHard( vectorNumber, vector );
}
}
else
{
vector->interruptDisabledHard = 1;
disableVectorHard( vectorNumber, vector );
}
if (level) ackInterrupt( vectorNumber );
vector->interruptActive = 0;
return kIOReturnSuccess;
}
bool Apple8259PIC::vectorCanBeShared( long vectorNumber,
IOInterruptVector * vector )
{
if (getVectorType(vectorNumber, vector) == kIOInterruptTypeLevel)
return true; else
return false; }
void Apple8259PIC::initVector( long vectorNumber,
IOInterruptVector * vector )
{
IOInterruptSource * interruptSources;
UInt32 vectorFlags;
OSData * vectorData;
interruptSources = vector->nub->_interruptSources;
vectorData = interruptSources[vector->source].vectorData;
if (vectorData->getLength() >= sizeof(UInt64))
{
vectorFlags = DATA_TO_FLAGS( vectorData );
if ((vectorFlags & kInterruptTriggerModeMask) ==
kInterruptTriggerModeEdge)
setVectorType(vectorNumber, kIOInterruptTypeEdge);
else
setVectorType(vectorNumber, kIOInterruptTypeLevel);
}
}
void Apple8259PIC::disableVectorHard( long vectorNumber,
IOInterruptVector * vector )
{
IOInterruptState state;
if ( vectorNumber == kPICSlaveID ) return;
state = IOSimpleLockLockDisableInterrupt( _interruptLock );
disableInterrupt( vectorNumber );
IOSimpleLockUnlockEnableInterrupt( _interruptLock, state );
}
void Apple8259PIC::enableVector( long vectorNumber,
IOInterruptVector * vector )
{
IOInterruptState state;
state = IOSimpleLockLockDisableInterrupt( _interruptLock );
enableInterrupt( vectorNumber );
IOSimpleLockUnlockEnableInterrupt( _interruptLock, state );
}
void Apple8259PIC::prepareForSleep( void )
{
outb( kPIC_OCW1(kPIC2BasePort), 0xff );
outb( kPIC_OCW1(kPIC1BasePort), 0xff );
}
void Apple8259PIC::resumeFromSleep( void )
{
outb( kPIC_OCW1(kPIC2BasePort), 0xff );
outb( kPIC_OCW1(kPIC1BasePort), 0xff );
outb( kPIC1TriggerTypePort, (UInt8) _interruptTriggerTypes );
outb( kPIC2TriggerTypePort, (UInt8)(_interruptTriggerTypes >> 8));
initializePIC( kPIC1BasePort,
kPIC_ICW1_IC4,
kBaseIOInterruptVectors,
(1 << kPICSlaveID),
kPIC_ICW4_uPM );
outb( kPIC_OCW1(kPIC1BasePort), _interruptMasks & 0xff );
outb( kPIC_OCW3(kPIC1BasePort), kPIC_OCW3_MBO | kPIC_OCW3_RR );
outb( kPIC_OCW2(kPIC1BasePort), kPIC_OCW2_R |
kPIC_OCW2_SL |
kPIC_OCW2_LEVEL(2) );
initializePIC( kPIC2BasePort,
kPIC_ICW1_IC4,
kBaseIOInterruptVectors + 8,
kPICSlaveID,
kPIC_ICW4_uPM );
outb( kPIC_OCW1(kPIC2BasePort), _interruptMasks >> 8 );
outb( kPIC_OCW3(kPIC2BasePort), kPIC_OCW3_MBO | kPIC_OCW3_RR );
}
IOReturn Apple8259PIC::callPlatformFunction( const OSSymbol * function,
bool waitForFunction,
void * param1, void * param2,
void * param3, void * param4 )
{
if ( function == _handleSleepWakeFunction )
{
if ( param1 )
prepareForSleep();
else
resumeFromSleep();
return kIOReturnSuccess;
}
return super::callPlatformFunction( function, waitForFunction,
param1, param2, param3, param4 );
}
Generated by GNU enscript 1.6.4.