1/* 2 * Copyright (c) 1998-2008 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * Copyright (c) 1998-2003 Apple Computer, Inc. All rights reserved. 30 * 31 * DRI: Josh de Cesare 32 * 33 */ 34 35#include <IOKit/IOTypes.h> 36#include <IOKit/IOLib.h> 37#include <IOKit/pwr_mgt/RootDomain.h> 38 39#include <IOKit/platform/AppleNMI.h> 40 41extern "C" { 42#include <pexpert/pexpert.h> 43} 44 45bool RootRegistered( OSObject * us, void *, IOService * yourDevice, __unused IONotifier * yourNotifier ); 46 47/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 48 49#define super IOService 50 51OSDefineMetaClassAndStructors(AppleNMI, IOService); 52OSMetaClassDefineReservedUnused(AppleNMI, 0); 53OSMetaClassDefineReservedUnused(AppleNMI, 1); 54OSMetaClassDefineReservedUnused(AppleNMI, 2); 55OSMetaClassDefineReservedUnused(AppleNMI, 3); 56 57/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 58 59bool AppleNMI::start(IOService *provider) 60{ 61 if (!super::start(provider)) return false; 62 63 enable_debugger = FALSE; 64 mask_NMI = FALSE; 65 66 if (provider->getProperty("enable_debugger")) 67 enable_debugger = TRUE; // Flag to automatically jump to debugger at NMI press 68 69 if (provider->getProperty("mask_NMI")) 70 mask_NMI = TRUE; // Flag to mask/unmask NMI @ sleep/wake 71 72 // Get notified when Root Domain registers 73 addMatchingNotification( gIOPublishNotification, serviceMatching("IOPMrootDomain"), (IOServiceMatchingNotificationHandler) RootRegistered, this, 0 ); 74 75 // Register the interrupt. 76 IOInterruptAction handler = OSMemberFunctionCast(IOInterruptAction, 77 this, &AppleNMI::handleInterrupt); 78 provider->registerInterrupt(0, this, handler, 0); 79 provider->enableInterrupt(0); 80 81 return true; 82} 83 84// ********************************************************************************** 85// The Root Power Domain has registered, so now we register as an interested driver 86// so we know when the system is going to sleep or wake 87// ********************************************************************************** 88bool RootRegistered( OSObject * us, void *, IOService * yourDevice, __unused IONotifier * yourNotifier) 89{ 90 if ( yourDevice != NULL ) { 91 ((AppleNMI *)us)->rootDomain = yourDevice; 92 ((IOPMrootDomain *)yourDevice)->registerInterestedDriver((IOService *) us); 93 } 94 95 return true; 96} 97 98IOReturn AppleNMI::initNMI(IOInterruptController *parentController, OSData *parentSource) 99{ 100 return kIOReturnSuccess; 101} 102 103IOReturn AppleNMI::handleInterrupt(void * /*refCon*/, IOService * /*nub*/, int /*source*/) 104{ 105 if(enable_debugger == TRUE) 106 Debugger("NMI"); // This is a direct call to the Debugger 107 else 108 PE_enter_debugger("NMI"); // This is a indirect call the Debugger that is dependent on the debug flag 109 110 return kIOReturnSuccess; 111} 112 113//********************************************************************************* 114// powerStateWillChangeTo 115// 116// We are notified here of power changes in the root domain. The root domain 117// cannot actually turn itself on and off, but it notifies us anyway. 118//********************************************************************************* 119IOReturn AppleNMI::powerStateWillChangeTo ( IOPMPowerFlags theFlags, unsigned long, IOService*) 120{ 121 volatile unsigned long *nmiIntSourceAddr; 122 unsigned long nmiIntSource; 123 124 if (mask_NMI == TRUE) 125 { 126 if ( ! (theFlags & IOPMPowerOn) ) 127 { 128 // Mask NMI and change from edge to level whilst sleeping (copied directly from OS9 code) 129 nmiIntSourceAddr = (volatile unsigned long *)kExtInt9_NMIIntSource; 130 nmiIntSource = ml_phys_read((vm_address_t)nmiIntSourceAddr); 131 nmiIntSource |= kNMIIntLevelMask; 132 ml_phys_write((vm_address_t)nmiIntSourceAddr, nmiIntSource); 133 eieio(); 134 nmiIntSource |= kNMIIntMask; 135 ml_phys_write((vm_address_t)nmiIntSourceAddr, nmiIntSource); 136 eieio(); 137 } 138 else 139 { 140 // Unmask NMI and change back to edge (copied directly from OS9 code) 141 nmiIntSourceAddr = (volatile unsigned long *)kExtInt9_NMIIntSource; 142 nmiIntSource = ml_phys_read((vm_address_t)nmiIntSourceAddr); 143 nmiIntSource &= ~kNMIIntLevelMask; 144 ml_phys_write((vm_address_t)nmiIntSourceAddr, nmiIntSource); 145 eieio(); 146 nmiIntSource &= ~kNMIIntMask; 147 ml_phys_write((vm_address_t)nmiIntSourceAddr, nmiIntSource); 148 eieio(); 149 } 150 } 151 152 return IOPMAckImplied; 153} 154