AppleEHCITestMode.cpp [plain text]
#include <IOKit/usb/IOUSBLog.h>
#include "AppleUSBEHCI.h"
#include "USBEHCI.h"
#ifdef SUPPORTS_SS_USB
void
AppleUSBEHCI::SwitchMuxes(UInt8 numPorts, UInt32 type)
{
int i;
if( _xhciController )
{
USBLog(1, "AppleUSBEHCI[%p]::SwitchMuxes found AppleUSBXHCI %p sending %p numPorts %d", this, _xhciController, (void*)type, numPorts);
for (i=0; i < numPorts; i++)
{
_xhciController->message(type, _device, (void*)i);
}
}
else
{
USBLog(1, "AppleUSBEHCI[%p]::SwitchMuxes could not discover AppleUSBXHCI dropping %p message", this, (void*)type);
}
}
#endif
IOReturn
AppleUSBEHCI::EnterTestMode()
{
UInt32 usbcmd, usbsts;
UInt8 numPorts;
int i;
USBLog(1, "AppleUSBEHCI[%p]::EnterTestMode", this);
GetNumberOfPorts(&numPorts);
#ifdef SUPPORTS_SS_USB
if ( _xhciController )
{
SwitchMuxes(numPorts, kIOUSBMessageMuxFromXHCIToEHCI);
}
#endif
usbcmd = USBToHostLong(_pEHCIRegisters->USBCMD);
usbcmd &= ~kEHCICMDAsyncEnable;
usbcmd &= ~kEHCICMDPeriodicEnable;
_pEHCIRegisters->USBCMD = HostToUSBLong(usbcmd);
USBLog(1, "AppleUSBEHCI[%p]::EnterTestMode - async and periodic lists disabled", this);
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()
{
int i;
UInt32 usbcmd, usbsts;
USBLog(1, "AppleUSBEHCI[%p]::LeaveTestMode", this);
usbcmd = USBToHostLong(_pEHCIRegisters->USBCMD);
usbsts = USBToHostLong(_pEHCIRegisters->USBSTS);
if (!(usbsts & kEHCIHCHaltedBit))
return kIOReturnInternalError;
#ifdef SUPPORTS_SS_USB
if ( _xhciController )
{
SwitchMuxes(_rootHubNumPorts, kIOUSBMessageMuxFromEHCIToXHCI);
}
#endif
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;
}