AppleUSBOHCI_Interrupts.cpp [plain text]
#include "AppleUSBOHCI.h"
#include <libkern/OSByteOrder.h>
#include <IOKit/usb/IOUSBLog.h>
#define nil (0)
#define DEBUGGING_LEVEL 0 // 1 = low; 2 = high; 3 = extreme
#define super IOUSBController
#define self this
void AppleUSBOHCI::PollInterrupts(IOUSBCompletionAction safeAction)
{
register UInt32 activeInterrupts;
register UInt32 interruptEnable;
interruptEnable = USBToHostLong(_pOHCIRegisters->hcInterruptEnable);
activeInterrupts = interruptEnable & USBToHostLong(_pOHCIRegisters->hcInterruptStatus);
if ((interruptEnable & kOHCIHcInterrupt_MIE) && (activeInterrupts != 0))
{
if (activeInterrupts & kOHCIHcInterrupt_SO)
{
_errors.scheduleOverrun++;
_pOHCIRegisters->hcInterruptStatus = USBToHostLong(kOHCIHcInterrupt_SO);
IOSync();
USBLog(3,"%s[%p] SchedulingOverrun Interrupt on bus %d", getName(), this, _busNumber );
}
if (activeInterrupts & kOHCIHcInterrupt_WDH)
{
UIMProcessDoneQueue(safeAction);
#if (DEBUGGING_LEVEL > 0)
IOLog("<WritebackDoneHead Interrupt>\n");
#endif
}
if (activeInterrupts & kOHCIHcInterrupt_SF)
{
_pOHCIRegisters->hcInterruptStatus = USBToHostLong(kOHCIHcInterrupt_SF);
_pOHCIRegisters->hcInterruptDisable = USBToHostLong(kOHCIHcInterrupt_SF);
#if (DEBUGGING_LEVEL > 0)
IOLog("<Frame Interrupt>\n");
#endif
}
if (activeInterrupts & kOHCIHcInterrupt_RD)
{
_remote_wakeup_occurred = true; _pOHCIRegisters->hcInterruptStatus = USBToHostLong(kOHCIHcInterrupt_RD);
USBLog(1,"%s[%p] ResumeDetected Interrupt on bus %d", getName(), this, _busNumber );
if ( _idleSuspend )
setPowerState(kOHCISetPowerLevelRunning,self);
}
if (activeInterrupts & kOHCIHcInterrupt_UE)
{
_errors.unrecoverableError++;
_pOHCIRegisters->hcCommandStatus = USBToHostLong(kOHCIHcCommandStatus_HCR);
delay(10 * MICROSECOND);
_pOHCIRegisters->hcInterruptStatus = USBToHostLong(kOHCIHcInterrupt_UE);
_pOHCIRegisters->hcControl = USBToHostLong((kOHCIFunctionalState_Operational << kOHCIHcControl_HCFSPhase) | kOHCIHcControl_PLE);
#if (DEBUGGING_LEVEL > 0)
IOLog("<Unrecoverable Error Interrupt>\n");
#endif
}
if (activeInterrupts & kOHCIHcInterrupt_FNO)
{
_errors.frameNumberOverflow++;
if ((USBToHostWord(*(UInt16*)(_pHCCA + 0x80)) & kOHCIFmNumberMask) < kOHCIBit15)
_frameNumber += kOHCIFrameOverflowBit;
_pOHCIRegisters->hcInterruptStatus = USBToHostLong(kOHCIHcInterrupt_FNO);
#if (DEBUGGING_LEVEL > 0)
IOLog("<FrameNumberOverflow Interrupt>\n");
#endif
}
if (activeInterrupts & kOHCIHcInterrupt_RHSC)
{
_pOHCIRegisters->hcInterruptStatus = USBToHostLong(kOHCIHcInterrupt_RHSC);
_remote_wakeup_occurred = true;
#if (DEBUGGING_LEVEL > 0)
IOLog("<RHSC Interrupt>\n");
#endif
UIMRootHubStatusChange( false );
LastRootHubPortStatusChanged ( true );
}
if (activeInterrupts & kOHCIHcInterrupt_OC)
{
_errors.ownershipChange++;
_pOHCIRegisters->hcInterruptStatus = USBToHostLong(kOHCIHcInterrupt_OC);
#if (DEBUGGING_LEVEL > 0)
IOLog("<OwnershipChange Interrupt>\n");
#endif
}
}
}
void AppleUSBOHCI::InterruptHandler(OSObject *owner,
IOInterruptEventSource * ,
int )
{
register AppleUSBOHCI *controller = (AppleUSBOHCI *) owner;
if (!controller || controller->isInactive() || (controller->_onCardBus && controller->_pcCardEjected) )
return;
controller->finishPending();
controller->PollInterrupts();
}