AppleUSBEHCI_Interrupts.cpp [plain text]
#include "AppleUSBEHCI.h"
#include <libkern/OSByteOrder.h>
#include <IOKit/usb/IOUSBLog.h>
#define nil (0)
#define super IOUSBControllerV2
#define self this
void
AppleUSBEHCI::PollInterrupts(IOUSBCompletionAction safeAction)
{
if (_hostErrorInterrupt & kEHCIHostErrorIntBit)
{
_hostErrorInterrupt = 0;
_errors.hostSystemError++;
USBError(1, "%s[%p]::PollInterrupts - Host System Error Occurred - not restarted", getName(), this);
}
if (_errorInterrupt & kEHCIErrorIntBit)
{
_errorInterrupt = 0;
USBLog(7, "%s[%p]::PollInterrupts - completion (_errorInterrupt) interrupt", getName(), this);
scavengeCompletedTransactions(safeAction);
}
if (_completeInterrupt & kEHCICompleteIntBit)
{
_completeInterrupt = 0;
USBLog(7, "%s[%p]::PollInterrupts - completion (_completeInterrupt) interrupt", getName(), this);
scavengeCompletedTransactions(safeAction);
}
if (_portChangeInterrupt & kEHCIPortChangeIntBit)
{
_portChangeInterrupt = 0;
_remote_wakeup_occurred = true;
USBLog(3, "%s[%p]::PollInterrupts - port change detect interrupt", getName(), this);
if ( _idleSuspend )
{
USBLog(1, "%s[%p]::PollInterrupts - port change detect interrupt while in idlesuspend - restarting bus", getName(), this);
setPowerState(kEHCISetPowerLevelRunning, self);
}
UIMRootHubStatusChange();
}
if (_asyncAdvanceInterrupt & kEHCIAAEIntBit)
{
_asyncAdvanceInterrupt = 0;
_errors.ownershipChange++;
_pEHCIRegisters->USBSTS = USBToHostLong(kEHCIAAEIntBit);
USBLog(3, "%s[%p]::PollInterrupts - async advance interrupt", getName(), this);
}
}
void
AppleUSBEHCI::InterruptHandler(OSObject *owner, IOInterruptEventSource * , int )
{
register AppleUSBEHCI *controller = (AppleUSBEHCI *) owner;
static Boolean emitted;
if (!controller || controller->isInactive() || (controller->_onCardBus && controller->_pcCardEjected) || !controller->_ehciAvailable)
return;
if(!emitted)
{
emitted = true;
}
controller->PollInterrupts();
}
bool
AppleUSBEHCI::PrimaryInterruptFilter(OSObject *owner, IOFilterInterruptEventSource *source)
{
register AppleUSBEHCI *controller = (AppleUSBEHCI *)owner;
bool result = true;
if (!controller || controller->isInactive() || (controller->_onCardBus && controller->_pcCardEjected) || !controller->_ehciAvailable)
return false;
if (controller->_ehciBusState == kEHCIBusStateSuspended)
{
return true;
}
controller->_filterInterruptActive = true;
result = controller->FilterInterrupt(0);
controller->_filterInterruptActive = false;
return result;
}
bool
AppleUSBEHCI::FilterInterrupt(int index)
{
register UInt32 activeInterrupts;
register UInt32 enabledInterrupts;
Boolean needSignal = false;
enabledInterrupts = USBToHostLong(_pEHCIRegisters->USBIntr);
activeInterrupts = enabledInterrupts & USBToHostLong(_pEHCIRegisters->USBSTS);
if (activeInterrupts != 0)
{
if (activeInterrupts & kEHCIFrListRolloverIntBit)
{
UInt32 frindex;
frindex = USBToHostLong(_pEHCIRegisters->FRIndex);
if (frindex < kEHCIFRIndexRolloverBit)
_frameNumber += kEHCIFrameNumberIncrement;
_pEHCIRegisters->USBSTS = HostToUSBLong(kEHCIFrListRolloverIntBit); IOSync();
}
if (activeInterrupts & kEHCIAAEIntBit)
{
_asyncAdvanceInterrupt = kEHCIAAEIntBit;
_pEHCIRegisters->USBSTS = HostToUSBLong(kEHCIAAEIntBit); needSignal = true;
}
if (activeInterrupts & kEHCIHostErrorIntBit)
{
_hostErrorInterrupt = kEHCIHostErrorIntBit;
_pEHCIRegisters->USBSTS = HostToUSBLong(kEHCIHostErrorIntBit); needSignal = true;
}
if (activeInterrupts & kEHCIPortChangeIntBit)
{
_portChangeInterrupt = kEHCIPortChangeIntBit;
_pEHCIRegisters->USBSTS = HostToUSBLong(kEHCIPortChangeIntBit); needSignal = true;
}
if (activeInterrupts & kEHCIErrorIntBit)
{
_errorInterrupt = kEHCIErrorIntBit;
_pEHCIRegisters->USBSTS = HostToUSBLong(kEHCIErrorIntBit); needSignal = true;
}
if (activeInterrupts & kEHCICompleteIntBit)
{
_completeInterrupt = kEHCICompleteIntBit;
_pEHCIRegisters->USBSTS = HostToUSBLong(kEHCICompleteIntBit); IOSync();
needSignal = true;
if ((_pEHCIRegisters->USBCMD & HostToUSBLong(kEHCICMDPeriodicEnable)) && (_outSlot < kEHCIPeriodicListEntries))
{
AppleEHCIIsochListElement * cachedHead;
UInt32 cachedProducer;
UInt32 frIndex;
UInt16 curSlot;
frIndex = USBToHostLong(_pEHCIRegisters->FRIndex);
curSlot = (frIndex >> 3) & (kEHCIPeriodicListEntries-1);
cachedHead = (AppleEHCIIsochListElement*)_savedDoneQueueHead;
cachedProducer = _producerCount;
while (_outSlot != curSlot)
{
AppleEHCIListElement *thing;
AppleEHCIListElement *nextThing;
AppleEHCIIsochListElement *isochEl;
thing = _logicalPeriodicList[_outSlot];
while(thing != NULL)
{
nextThing = thing->_logicalNext;
isochEl = OSDynamicCast(AppleEHCIIsochListElement, thing);
if(isochEl)
{
_logicalPeriodicList[_outSlot] = nextThing;
_periodicList[_outSlot] = thing->GetPhysicalLink();
if (isochEl->lowLatency)
isochEl->UpdateFrameList();
isochEl->doneQueueLink = cachedHead;
cachedHead = isochEl;
cachedProducer++;
}
else
{
break;
}
thing = nextThing;
}
_outSlot = (_outSlot+1) & (kEHCIPeriodicListEntries-1);
}
IOSimpleLockLock( _wdhLock );
_savedDoneQueueHead = cachedHead; _producerCount = cachedProducer;
IOSimpleLockUnlock( _wdhLock );
}
}
}
if (needSignal)
_filterInterruptSource->signalInterrupt();
return false;
}