#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::start(provider)) 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)
{
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) )
{
nmiIntSourceAddr = (volatile unsigned long *)kExtInt9_NMIIntSource;
nmiIntSource = ml_phys_read(nmiIntSourceAddr);
nmiIntSource |= kNMIIntLevelMask;
ml_phys_write(nmiIntSourceAddr, nmiIntSource);
eieio();
nmiIntSource |= kNMIIntMask;
ml_phys_write(nmiIntSourceAddr, nmiIntSource);
eieio();
}
else
{
nmiIntSourceAddr = (volatile unsigned long *)kExtInt9_NMIIntSource;
nmiIntSource = ml_phys_read(nmiIntSourceAddr);
nmiIntSource &= ~kNMIIntLevelMask;
ml_phys_write(nmiIntSourceAddr, nmiIntSource);
eieio();
nmiIntSource &= ~kNMIIntMask;
ml_phys_write(nmiIntSourceAddr, nmiIntSource);
eieio();
}
}
return IOPMAckImplied;
}