#include <IOKit/IOTypes.h>
#include <IOKit/IOLib.h>
#include <IOKit/pwr_mgt/RootDomain.h>
#include <IOKit/platform/AppleNMI.h>
extern "C" {
#include <pexpert/pexpert.h>
}
bool RootRegistered( OSObject * us, void *, IOService * yourDevice );
#define super IOService
OSDefineMetaClassAndStructors(AppleNMI, IOService);
OSMetaClassDefineReservedUnused(AppleNMI, 0);
OSMetaClassDefineReservedUnused(AppleNMI, 1);
OSMetaClassDefineReservedUnused(AppleNMI, 2);
OSMetaClassDefineReservedUnused(AppleNMI, 3);
bool AppleNMI::start(IOService *provider)
{
if (!super::init()) return false;
enable_debugger = FALSE;
mask_NMI = FALSE;
if (provider->getProperty("enable_debugger"))
enable_debugger = TRUE;
if (provider->getProperty("mask_NMI"))
mask_NMI = TRUE;
addNotification( gIOPublishNotification, serviceMatching("IOPMrootDomain"), (IOServiceNotificationHandler)RootRegistered, this, 0 );
provider->registerInterrupt(0, this, (IOInterruptAction) &AppleNMI::handleInterrupt, 0);
provider->enableInterrupt(0);
return true;
}
bool RootRegistered( OSObject * us, void *, IOService * yourDevice )
{
if ( yourDevice != NULL ) {
((AppleNMI *)us)->rootDomain = yourDevice;
((IOPMrootDomain *)yourDevice)->registerInterestedDriver((IOService *) us);
}
return true;
}
IOReturn AppleNMI::initNMI(IOInterruptController *parentController, OSData *parentSource)
{
_interruptSources = (IOInterruptSource *)IOMalloc(sizeof(IOInterruptSource));
if (_interruptSources == 0) return kIOReturnNoMemory;
_numInterruptSources = 1;
_interruptSources[0].interruptController = parentController;
_interruptSources[0].vectorData = parentSource;
if (!start(this)) return kIOReturnError;
return kIOReturnSuccess;
}
IOReturn AppleNMI::handleInterrupt(void * , IOService * , int )
{
if(enable_debugger == TRUE)
Debugger("NMI"); else
PE_enter_debugger("NMI");
return kIOReturnSuccess;
}
IOReturn AppleNMI::powerStateWillChangeTo ( IOPMPowerFlags theFlags, unsigned long, IOService*)
{
volatile unsigned long *nmiIntSourceAddr;
unsigned long nmiIntSource;
if (mask_NMI == TRUE)
{
if ( ! (theFlags & IOPMPowerOn) )
{
IOLog("AppleNMI mask NMI\n");
nmiIntSourceAddr = (volatile unsigned long *)kExtInt9_NMIIntSource;
nmiIntSource = *nmiIntSourceAddr;
nmiIntSource |= kNMIIntLevelMask;
*nmiIntSourceAddr = nmiIntSource;
eieio();
nmiIntSource |= kNMIIntMask;
*nmiIntSourceAddr = nmiIntSource;
eieio();
}
else
{
IOLog("AppleNMI unmask NMI\n");
nmiIntSourceAddr = (volatile unsigned long *)kExtInt9_NMIIntSource;
nmiIntSource = *nmiIntSourceAddr;
nmiIntSource &= ~kNMIIntLevelMask;
*nmiIntSourceAddr = nmiIntSource;
eieio();
nmiIntSource &= ~kNMIIntMask;
*nmiIntSourceAddr = nmiIntSource;
eieio();
}
}
return IOPMAckImplied;
}