AppleEHCITestMode.cpp [plain text]
#include <IOKit/usb/IOUSBLog.h>
#include "AppleUSBEHCI.h"
enum
{
kEHCITestMode_Off = 0,
kEHCITestMode_J_State = 1,
kEHCITestMode_K_State = 2,
kEHCITestMode_SE0_NAK = 3,
kEHCITestMode_Packet = 4,
kEHCITestMode_ForceEnable = 5,
kEHCITestMode_Start = 10,
kEHCITestMode_End = 11
};
IOReturn
AppleUSBEHCI::EnterTestMode()
{
UInt32 usbcmd, usbsts;
UInt8 numPorts;
int i;
USBLog(1, "AppleUSBEHCI[%p]::EnterTestMode", this);
usbcmd = USBToHostLong(_pEHCIRegisters->USBCMD);
usbcmd &= ~kEHCICMDAsyncEnable;
usbcmd &= ~kEHCICMDPeriodicEnable;
_pEHCIRegisters->USBCMD = HostToUSBLong(usbcmd);
USBLog(1, "AppleUSBEHCI[%p]::EnterTestMode - async and periodic lists disabled", this);
GetNumberOfPorts(&numPorts);
USBLog(1, "AppleUSBEHCI[%p]::EnterTestMode - suspending %d ports", this, numPorts);
for (i=0; i < numPorts; i++)
{
UInt32 portStat;
portStat = USBToHostLong(_pEHCIRegisters->PortSC[i]);
if (portStat & kEHCIPortSC_Owner)
{
USBLog(1, "AppleUSBEHCI[%p]::EnterTestMode - port %d owned by OHCI", this, i);
}
else if (portStat & kEHCIPortSC_Enabled)
{
portStat |= kEHCIPortSC_Suspend;
_pEHCIRegisters->PortSC[i] = HostToUSBLong(portStat);
USBLog(1, "AppleUSBEHCI[%p]::EnterTestMode - port %d now suspended", this, i);
}
else
{
USBLog(1, "AppleUSBEHCI[%p]::EnterTestMode - port %d not enabled", this, i);
}
}
usbcmd &= ~kEHCICMDRunStop;
_pEHCIRegisters->USBCMD = HostToUSBLong(usbcmd);
_myBusState = kUSBBusStateReset;
USBLog(1, "AppleUSBEHCI[%p]::EnterTestMode - HC stop set, waiting for halted", this);
do
{
usbsts = USBToHostLong(_pEHCIRegisters->USBSTS);
} while (!(usbsts & kEHCIHCHaltedBit));
USBLog(1, "AppleUSBEHCI[%p]::EnterTestMode - HC halted - now in test mode", this);
_testModeEnabled = true;
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCI::PlacePortInMode(UInt32 port, UInt32 mode)
{
UInt32 portStat;
UInt8 numPorts;
USBLog(1, "AppleUSBEHCI[%p]::PlacePortinMode(port %d, mode %d)", this, (int)port, (int)mode);
if (!_testModeEnabled)
{
USBLog(1, "AppleUSBEHCI[%p]::PlacePortinMode - ERROR test mode not enabled", this);
return kIOReturnInternalError;
}
numPorts = USBToHostLong(_pEHCICapRegisters->HCSParams) & kEHCINumPortsMask;
if (port >= numPorts)
{
USBLog(1, "AppleUSBEHCI[%p]::PlacePortinMode - ERROR invalid port %d", this, (int)port);
return kIOReturnInternalError;
}
portStat = USBToHostLong(_pEHCIRegisters->PortSC[port]);
if (portStat & kEHCIPortSC_Owner)
{
USBLog(1, "AppleUSBEHCI[%p]::PlacePortinMode - ERROR port %d owned by OHCI", this, (int)port);
return kIOReturnInternalError;
}
USBLog(1, "AppleUSBEHCI[%p]::PlacePortinMode - old portStat = %x", this, (int)portStat);
portStat &= ~kEHCIPortSC_TestControl;
portStat |= (mode << kEHCIPortSC_TestControlPhase);
USBLog(1, "AppleUSBEHCI[%p]::PlacePortinMode - new portStat = %x", this, (int)portStat);
_pEHCIRegisters->PortSC[port] = HostToUSBLong(portStat);
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCI::LeaveTestMode()
{
UInt32 usbcmd, usbsts;
USBLog(1, "AppleUSBEHCI[%p]::LeaveTestMode", this);
usbcmd = USBToHostLong(_pEHCIRegisters->USBCMD);
usbsts = USBToHostLong(_pEHCIRegisters->USBSTS);
if (!(usbsts & kEHCIHCHaltedBit))
return kIOReturnInternalError;
usbcmd |= kEHCICMDHCReset;
_pEHCIRegisters->USBCMD = HostToUSBLong(usbcmd);
USBLog(1, "AppleUSBEHCI[%p]::LeaveTestMode - leaving with HC in reset", this);
_testModeEnabled = false;
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCI::UIMSetTestMode(UInt32 mode, UInt32 port)
{
IOReturn ret = kIOReturnInternalError;
USBLog(1, "AppleUSBEHCI[%p]::UIMSetTestMode(%d, %d)", this, (int)mode, (int)port);
switch (mode)
{
case kEHCITestMode_Off:
case kEHCITestMode_J_State:
case kEHCITestMode_K_State:
case kEHCITestMode_SE0_NAK:
case kEHCITestMode_Packet:
case kEHCITestMode_ForceEnable:
if (_testModeEnabled)
ret = PlacePortInMode(port, mode);
break;
case kEHCITestMode_Start:
ret = EnterTestMode();
break;
case kEHCITestMode_End:
ret = LeaveTestMode();
break;
}
return ret;
}