AppleUSBOHCI_RootHub.cpp [plain text]
extern "C" {
#include <kern/clock.h>
}
#include <libkern/OSByteOrder.h>
#include <IOKit/usb/USB.h>
#include <IOKit/usb/IOUSBLog.h>
#include <IOKit/usb/IOUSBRootHubDevice.h>
#include "AppleUSBOHCI.h"
#define super IOUSBControllerV3
#define _rootHubTransactionWasAborted _v3ExpansionData->_rootHubTransactionWasAborted
#ifndef APPLEOHCIROOTHUB_USE_KPRINTF
#define APPLEOHCIROOTHUB_USE_KPRINTF 0
#endif
#if APPLEOHCIROOTHUB_USE_KPRINTF
#undef USBLog
#undef USBError
void kprintf(const char *format, ...)
__attribute__((format(printf, 1, 2)));
#define USBLog( LEVEL, FORMAT, ARGS... ) if ((LEVEL) <= APPLEOHCIROOTHUB_USE_KPRINTF) { kprintf( FORMAT "\n", ## ARGS ) ; }
#define USBError( LEVEL, FORMAT, ARGS... ) { kprintf( FORMAT "\n", ## ARGS ) ; }
#endif
#pragma mark Public root hub methods
IOReturn AppleUSBOHCI::GetRootHubDeviceDescriptor(IOUSBDeviceDescriptor *desc)
{
IOUSBDeviceDescriptor newDesc =
{
sizeof(IOUSBDeviceDescriptor), kUSBDeviceDesc, HostToUSBWord(kUSBRel20), kUSBHubClass, kUSBHubSubClass, 0, 8, HostToUSBWord(kAppleVendorID), HostToUSBWord(kPrdRootHubApple), HostToUSBWord(0x0200), 2, 1, 0, 1 };
if (!desc)
return(kIOReturnNoMemory);
bcopy(&newDesc, desc, newDesc.bLength);
return(kIOReturnSuccess);
}
IOReturn AppleUSBOHCI::GetRootHubDescriptor(IOUSBHubDescriptor *desc)
{
IOUSBHubDescriptor hubDesc;
UInt8 pps, nps, cd, ppoc, noc;
UInt32 descriptorA, descriptorB, data;
UInt8 * dstP;
unsigned int i, numBytes;
UInt32 appleCaptive = 0;
OSNumber * appleCaptiveProperty = NULL;
descriptorA = USBToHostLong(_pOHCIRegisters->hcRhDescriptorA);
if (descriptorA == kOHCIInvalidRegisterValue)
{
USBLog(2, "AppleUSBOHCI[%p]::GetRootHubDescriptor - invalid register (A). We must be disconnected", this);
_controllerAvailable = false;
return kIOReturnNotResponding;
}
descriptorB = USBToHostLong(_pOHCIRegisters->hcRhDescriptorB);
if (descriptorB == kOHCIInvalidRegisterValue)
{
USBLog(2, "AppleUSBOHCI[%p]::GetRootHubDescriptor - invalid register (B). We must be disconnected", this);
_controllerAvailable = false;
return kIOReturnNotResponding;
}
hubDesc.length = sizeof(IOUSBHubDescriptor);
hubDesc.hubType = kUSBHubDescriptorType;
hubDesc.numPorts = ((descriptorA & kOHCIHcRhDescriptorA_NDP) >> kOHCIHcRhDescriptorA_NDPPhase);
_rootHubNumPorts = hubDesc.numPorts;
pps = (descriptorA & kOHCIHcRhDescriptorA_PSM) ? 1 : 0;
nps = (descriptorA & kOHCIHcRhDescriptorA_NPS) ? 1 : 0;
cd = (descriptorA & kOHCIHcRhDescriptorA_DT) ? 1 : 0;
ppoc = (descriptorA & kOHCIHcRhDescriptorA_OCPM) ? 1 : 0;
noc = (descriptorA & kOHCIHcRhDescriptorA_NOCP) ? 1 : 0;
hubDesc.characteristics = 0;
hubDesc.characteristics |= (pps ? kPerPortSwitchingBit : 0);
hubDesc.characteristics |= (nps ? kNoPowerSwitchingBit : 0);
hubDesc.characteristics |= (cd ? kCompoundDeviceBit : 0);
hubDesc.characteristics |= (ppoc ? kPerPortOverCurrentBit : 0);
hubDesc.characteristics |= (noc ? kNoOverCurrentBit : 0);
hubDesc.characteristics = HostToUSBWord(hubDesc.characteristics);
hubDesc.powerOnToGood = ((descriptorA & kOHCIHcRhDescriptorA_POTPGT)
>> kOHCIHcRhDescriptorA_POTPGTPhase);
hubDesc.hubCurrent = 0;
numBytes = (hubDesc.numPorts + 1) / 8 + 1;
dstP = (UInt8 *)&hubDesc.removablePortFlags[0];
appleCaptiveProperty = OSDynamicCast(OSNumber, _device->getProperty(kAppleInternalUSBDevice));
if (appleCaptiveProperty)
appleCaptive = appleCaptiveProperty->unsigned32BitValue();
else
appleCaptive = (UInt32) (descriptorB & kOHCIHcRhDescriptorB_DR) >> kOHCIHcRhDescriptorB_DRPhase;
for (i = 0; i < numBytes; i++)
{
*dstP++ = (UInt8) (appleCaptive & 0xFF);
appleCaptive >>= 8;
}
data = (descriptorB & kOHCIHcRhDescriptorB_PPCM) >> kOHCIHcRhDescriptorB_PPCMPhase;
for (i=0; i<numBytes; i++)
{
*dstP++ = (UInt8)data;
data >>= 8;
}
hubDesc.length -= ((sizeof(hubDesc.removablePortFlags) - numBytes) +
(sizeof(hubDesc.pwrCtlPortFlags) - numBytes));
if (!desc)
return kIOReturnNoMemory;
bcopy(&hubDesc, desc, hubDesc.length);
return kIOReturnSuccess;
}
IOReturn AppleUSBOHCI::GetRootHubConfDescriptor(OSData *desc)
{
IOUSBConfigurationDescriptor confDesc =
{
sizeof(IOUSBConfigurationDescriptor), kUSBConfDesc, HostToUSBWord(sizeof(IOUSBConfigurationDescriptor) +
sizeof(IOUSBInterfaceDescriptor) +
sizeof(IOUSBEndpointDescriptor)), 1, 1, 0, 0x60, 0, };
IOUSBInterfaceDescriptor intfDesc =
{
sizeof(IOUSBInterfaceDescriptor), kUSBInterfaceDesc, 0, 0, 1, kUSBHubClass, kUSBHubSubClass, 0, 0 };
IOUSBEndpointDescriptor endptDesc =
{
sizeof(IOUSBEndpointDescriptor), kUSBEndpointDesc, 0x81, kUSBInterrupt, HostToUSBWord(8), kUSBRootHubPollingRate, };
if (!desc)
return(kIOReturnNoMemory);
if (!desc->appendBytes(&confDesc, confDesc.bLength))
return(kIOReturnNoMemory);
if (!desc->appendBytes(&intfDesc, intfDesc.bLength))
return(kIOReturnNoMemory);
if (!desc->appendBytes(&endptDesc, endptDesc.bLength))
return(kIOReturnNoMemory);
return(kIOReturnSuccess);
}
IOReturn AppleUSBOHCI::SetRootHubDescriptor(OSData * buffer)
{
#pragma unused (buffer)
return(kIOReturnSuccess);
}
IOReturn AppleUSBOHCI::GetRootHubStatus(IOUSBHubStatus *status)
{
UInt32 rhStatus = 0;
IOReturn ret = kIOReturnSuccess;
if ( _controllerAvailable )
{
rhStatus = _pOHCIRegisters->hcRhStatus;
if (rhStatus == kOHCIInvalidRegisterValue)
{
USBLog(2, "AppleUSBOHCI[%p]::GetRootHubStatus - it appears that we no longer have real access to our registers", this);
rhStatus = 0;
_controllerAvailable = false;
ret = kIOReturnNotResponding;
}
}
else
{
rhStatus = 0; ret = kIOReturnNotResponding;
}
*(UInt32*)status = rhStatus;
return ret;
}
IOReturn
AppleUSBOHCI::SetRootHubFeature(UInt16 wValue)
{
switch(wValue)
{
case kUSBHubLocalPowerChangeFeature :
USBLog(3,"AppleUSBOHCI[%p]::SetRootHubFeature - unimplemented Set Power Change Feature", this);
break;
case kUSBHubOverCurrentChangeFeature :
USBLog(3,"AppleUSBOHCI[%p]::SetRootHubFeature - unimplemented Set Overcurrent Change Feature", this);
break;
default:
USBLog(3,"AppleUSBOHCI[%p]::SetRootHubFeature - Unknown feature (%d)", this, wValue);
break;
}
return(kIOReturnSuccess);
}
IOReturn
AppleUSBOHCI::ClearRootHubFeature(UInt16 wValue)
{
switch(wValue)
{
case kUSBHubLocalPowerChangeFeature :
USBLog(3, "AppleUSBOHCI[%p]::ClearRootHubFeature - unimplemented Clear Power Change Feature", this);
break;
case kUSBHubOverCurrentChangeFeature :
USBLog(3, "AppleUSBOHCI[%p]::ClearRootHubFeature - writing to clear the OCIC bit", this);
_pOHCIRegisters->hcRhStatus = HostToUSBLong(kOHCIHcRhStatus_OCIC); IOSync();
break;
default:
USBLog(3, "AppleUSBOHCI[%p]::ClearRootHubFeature - Unknown feature (%d)", this, wValue);
break;
}
return(kIOReturnSuccess);
}
IOReturn
AppleUSBOHCI::GetRootHubPortStatus(IOUSBHubPortStatus *status, UInt16 port)
{
if ( _myBusState == kUSBBusStateSuspended )
return kIOReturnNotResponding;
if (port < 1 || port > 15)
return(kIOReturnBadArgument);
*(UInt32*)status = _pOHCIRegisters->hcRhPortStatus[port-1];
return kIOReturnSuccess;
}
IOReturn
AppleUSBOHCI::SetRootHubPortFeature(UInt16 wValue, UInt16 wIndex)
{
UInt16 port = wIndex-1;
IOReturn err = kIOReturnSuccess;
switch(wValue)
{
case kUSBHubPortSuspendFeature :
if ( (_errataBits & kErrataLucentSuspendResume) && ((_disablePortsBitmap & (1 << wIndex)) != 0))
{
USBLog(3,"AppleUSBOHCI[%p]::SetRootHubPortFeature - Ignoring suspend feature", this);
err = kIOUSBPipeStalled;
}
else
OHCIRootHubPortSuspend(port, true);
break;
case kUSBHubPortResetFeature :
OHCIRootHubResetPort(port);
break;
case kUSBHubPortEnableFeature :
OHCIRootHubPortEnable(port, true);
break;
case kUSBHubPortPowerFeature :
OHCIRootHubPortPower(port, true);
OHCIRootHubPower(true);
showRegisters(7, "SetRootHubPortFeature");
break;
default:
USBLog(3,"AppleUSBOHCI[%p]::SetRootHubPortFeature - Unknown feature (%d)", this, wValue);
break;
}
return err;
}
IOReturn
AppleUSBOHCI::ClearRootHubPortFeature(UInt16 wValue, UInt16 wIndex)
{
UInt16 port = wIndex-1;
bool renableRHSCInterrupt = false;
IOReturn err = kIOReturnSuccess;
switch(wValue)
{
case kUSBHubPortEnableFeature :
OHCIRootHubPortEnable(port, false);
break;
case kUSBHubPortSuspendFeature :
OHCIRootHubPortSuspend(port, false);
break;
case kUSBHubPortPowerFeature :
if (_errataBits & kErrataIgnoreRootHubPowerClearFeature)
{
USBLog(5,"AppleUSBOHCI[%p]::ClearRootHubPortFeature (kUSBHubPortPowerFeature) port %d, ignoring per errata bit", this, port+1);
err = kIOReturnUnsupported;
}
else
{
OHCIRootHubPortPower(port, false);
}
break;
case kUSBHubPortConnectionChangeFeature :
OHCIRootHubResetChangeConnection(port);
renableRHSCInterrupt = true;
break;
case kUSBHubPortEnableChangeFeature :
OHCIRootHubResetEnableChange(port);
renableRHSCInterrupt = true;
break;
case kUSBHubPortSuspendChangeFeature :
OHCIRootHubResetSuspendChange(port);
renableRHSCInterrupt = true;
break;
case kUSBHubPortOverCurrentChangeFeature :
OHCIRootHubResetOverCurrentChange(port);
renableRHSCInterrupt = true;
break;
case kUSBHubPortResetChangeFeature :
OHCIRootHubResetResetChange(port);
renableRHSCInterrupt = true;
break;
default:
USBLog(3,"AppleUSBOHCI[%p]::ClearRootHubPortFeature - Unknown feature (%d)", this, wValue);
break;
}
if ( renableRHSCInterrupt && _needToReEnableRHSCInterrupt)
{
UInt32 interrupts;
USBLog(3,"AppleUSBOHCI[%p]::ClearRootHubPortFeature - renabling RHSC interrupt due to clear feature %d", this, wValue);
_needToReEnableRHSCInterrupt = false;
_pOHCIRegisters->hcInterruptEnable = HostToUSBLong (kOHCIHcInterrupt_MIE | kOHCIHcInterrupt_RHSC);
IOSync();
}
return err;
}
IOReturn
AppleUSBOHCI::GetRootHubPortState(UInt8 *state, UInt16 port)
{
#pragma unused(state, port)
USBLog(3,"AppleUSBOHCI[%p]::GetRootHubPortState - UNIMPLEMENTED", this);
return(kIOReturnSuccess);
}
IOReturn
AppleUSBOHCI::SetHubAddress(UInt16 wValue)
{
USBLog(3,"AppleUSBOHCI[%p]::SetHubAddress - Setting RootHub Address to %d", this, wValue);
_rootHubFuncAddress = wValue;
return (kIOReturnSuccess);
}
IOReturn
AppleUSBOHCI::GetRootHubStringDescriptor(UInt8 index, OSData *desc)
{
UInt8 productName[] = {
0, kUSBStringDesc, 0x4F, 0x00, 0x48, 0x00, 0x43, 0x00, 0x49, 0x00, 0x20, 0x00, 0x52, 0x00, 0x6F, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x20, 0x00, 0x48, 0x00, 0x75, 0x00, 0x62, 0x00, 0x20, 0x00, 0x53, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, };
UInt8 vendorName[] = {
0, kUSBStringDesc, 0x41, 0x00, 0x70, 0x00, 0x70, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00 };
if ( index > 2 )
return kIOReturnBadArgument;
vendorName[0] = sizeof(vendorName);
productName[0] = sizeof(productName);
if ( index == 1 )
{
if (!desc)
return kIOReturnNoMemory;
if (!desc->appendBytes(&productName, productName[0]))
return kIOReturnNoMemory;
}
if ( index == 2 )
{
if (!desc)
return kIOReturnNoMemory;
if (!desc->appendBytes(&vendorName, vendorName[0]))
return kIOReturnNoMemory;
}
return kIOReturnSuccess;
}
void
AppleUSBOHCI::UIMRootHubStatusChange( bool abort )
{
USBLog(1, "AppleUSBOHCI[%p]::UIMRootHubStatusChange - calling obsolete method UIMRootHubStatusChange(bool)", this);
}
void
AppleUSBOHCI::UIMRootHubStatusChange(void)
{
UInt32 tempStatus = 0xFFFF, hubStatus, portStatus, statusBit;
UInt16 statusChangedBitmap; unsigned int index, port, move;
UInt32 descriptorA;
statusChangedBitmap = 0;
statusBit = 1;
if ( _controllerAvailable && !_wakingFromHibernation && (GetRootHubStatus((IOUSBHubStatus *)&tempStatus) == kIOReturnSuccess) )
{
hubStatus = USBToHostLong( tempStatus );
if ((hubStatus & kOHCIHcRhStatus_Change ) != 0)
{
statusChangedBitmap |= statusBit;
}
for (port = 1; port <= _rootHubNumPorts; port++)
{
statusBit <<= 1;
GetRootHubPortStatus((IOUSBHubPortStatus *)&tempStatus, port);
portStatus = USBToHostLong( tempStatus);
if ((portStatus & kOHCIHcRhPortStatus_Change) != 0)
{
statusChangedBitmap |= statusBit;
}
}
}
else
{
USBLog(6, "AppleUSBOHCI[%p]::UIMRootHubStatusChange - didn't go into checking for bits", this);
}
if (statusChangedBitmap)
{
USBLog(5, "AppleUSBOHCI[%p]::UIMRootHubStatusChange - reporting status of %p", this, (void*)statusChangedBitmap);
}
_rootHubStatusChangedBitmap = statusChangedBitmap;
}
#pragma mark Internal root hub methods
void
AppleUSBOHCI::OHCIRootHubPower(bool on)
{
USBLog(2,"AppleUSBOHCI[%p]::OHCIRootHubPower (%s)", this, on ? "true" : "false");
if (on)
{
_pOHCIRegisters->hcRhStatus = HostToUSBLong(kOHCIHcRhStatus_LPSC); }
else
{
_pOHCIRegisters->hcRhStatus = HostToUSBLong(kOHCIHcRhStatus_LPS); }
IOSync();
return;
}
void
AppleUSBOHCI::OHCIRootHubResetChangeConnection(UInt16 port)
{
UInt32 value = 0;
value |= kOHCIHcRhPortStatus_CSC;
_pOHCIRegisters->hcRhPortStatus[port] = HostToUSBLong(value);
IOSync();
if (_errataBits & kErrataNECIncompleteWrite)
{
UInt32 newValue = 0, count = 0;
newValue = USBToHostLong(_pOHCIRegisters->hcRhPortStatus[port]); while ((count++ < 10) && (newValue & kOHCIHcRhPortStatus_CSC))
{
USBError(1, "OHCI driver: OHCIRootHubResetChangeConnection bit not sticking. Retrying.");
_pOHCIRegisters->hcRhPortStatus[port] = HostToUSBLong(value);
IOSync();
newValue = USBToHostLong(_pOHCIRegisters->hcRhPortStatus[port]);
}
}
return;
}
void
AppleUSBOHCI::OHCIRootHubResetResetChange(UInt16 port)
{
UInt32 value = 0;
value |= kOHCIHcRhPortStatus_PRSC;
_pOHCIRegisters->hcRhPortStatus[port] = HostToUSBLong(value);
IOSync();
if (_errataBits & kErrataNECIncompleteWrite)
{
UInt32 newValue = 0, count = 0;
newValue = USBToHostLong(_pOHCIRegisters->hcRhPortStatus[port]); while ((count++ < 10) && (newValue & kOHCIHcRhPortStatus_PRSC))
{
USBError(1, "OHCI driver: OHCIRootHubResetResetChange bit not sticking. Retrying.");
_pOHCIRegisters->hcRhPortStatus[port] = HostToUSBLong(value);
IOSync();
newValue = USBToHostLong(_pOHCIRegisters->hcRhPortStatus[port]);
}
}
return;
}
void
AppleUSBOHCI::OHCIRootHubResetSuspendChange(UInt16 port)
{
UInt32 value = 0;
value |= kOHCIHcRhPortStatus_PSSC;
_pOHCIRegisters->hcRhPortStatus[port] = HostToUSBLong(value);
IOSync();
if (_errataBits & kErrataNECIncompleteWrite)
{
UInt32 newValue = 0, count = 0;
newValue = USBToHostLong(_pOHCIRegisters->hcRhPortStatus[port]); while ((count++ < 10) && (newValue & kOHCIHcRhPortStatus_PSSC))
{
USBError(1, "OHCI driver: OHCIRootHubResetSuspendChange bit not sticking. Retrying.");
_pOHCIRegisters->hcRhPortStatus[port] = HostToUSBLong(value);
IOSync();
newValue = USBToHostLong(_pOHCIRegisters->hcRhPortStatus[port]);
}
}
return;
}
void
AppleUSBOHCI::OHCIRootHubResetEnableChange(UInt16 port)
{
UInt32 value = 0;
value |= kOHCIHcRhPortStatus_PESC;
_pOHCIRegisters->hcRhPortStatus[port] = HostToUSBLong(value);
IOSync();
if (_errataBits & kErrataNECIncompleteWrite)
{
UInt32 newValue = 0, count = 0;
newValue = USBToHostLong(_pOHCIRegisters->hcRhPortStatus[port]); while ((count++ < 10) && (newValue & kOHCIHcRhPortStatus_PESC))
{
USBError(1, "OHCI driver: OHCIRootHubResetEnableChange bit not sticking. Retrying.");
_pOHCIRegisters->hcRhPortStatus[port] = HostToUSBLong(value);
IOSync();
newValue = USBToHostLong(_pOHCIRegisters->hcRhPortStatus[port]);
}
}
return;
}
void
AppleUSBOHCI::OHCIRootHubResetOverCurrentChange(UInt16 port)
{
UInt32 value = 0;
value |= kOHCIHcRhPortStatus_OCIC;
_pOHCIRegisters->hcRhPortStatus[port] = HostToUSBLong(value);
IOSync();
if (_errataBits & kErrataNECIncompleteWrite)
{
UInt32 newValue = 0, count = 0;
newValue = USBToHostLong(_pOHCIRegisters->hcRhPortStatus[port]); while ((count++ < 10) && (newValue & kOHCIHcRhPortStatus_OCIC))
{
USBError(1, "OHCI driver: OHCIRootHubResetOverCurrentChange bit not sticking. Retrying.");
_pOHCIRegisters->hcRhPortStatus[port] = HostToUSBLong(value);
IOSync();
newValue = USBToHostLong(_pOHCIRegisters->hcRhPortStatus[port]);
}
}
return;
}
void
AppleUSBOHCI::OHCIRootHubResetPort (UInt16 port)
{
UInt32 value = 0;
value = kOHCIHcRhPortStatus_PRS; _pOHCIRegisters->hcRhPortStatus[port] = HostToUSBLong(kOHCIHcRhPortStatus_PRS);
IOSync();
if (_errataBits & kErrataNECIncompleteWrite)
{
UInt32 count = 0;
value = USBToHostLong(_pOHCIRegisters->hcRhPortStatus[port]);
while ((count++ < 10) && !(value & kOHCIHcRhPortStatus_PRS))
{
USBError(1, "OHCI driver: SetPortReset bit not sticking. Retrying.");
value = kOHCIHcRhPortStatus_PRS;
_pOHCIRegisters->hcRhPortStatus[port] = HostToUSBLong(value);
IOSync();
value = USBToHostLong(_pOHCIRegisters->hcRhPortStatus[port]);
}
}
return;
}
void
AppleUSBOHCI::OHCIRootHubPortEnable(UInt16 port, bool on)
{
UInt32 value = 0;
if (on)
value |= kOHCIHcRhPortStatus_PES; else
value |= kOHCIHcRhPortStatus_CCS;
_pOHCIRegisters->hcRhPortStatus[port] = HostToUSBLong(value);
IOSync();
if (_errataBits & kErrataNECIncompleteWrite)
{
UInt32 newValue = 0, count = 0;
newValue = USBToHostLong(_pOHCIRegisters->hcRhPortStatus[port]);
while ((count++ < 10) && (on ? !(newValue & kOHCIHcRhPortStatus_PES) : (newValue & kOHCIHcRhPortStatus_PES)))
{
USBError(1, "OHCI driver: OHCIRootHubPortEnable bit not sticking (%d). Retrying.", on);
_pOHCIRegisters->hcRhPortStatus[port] = HostToUSBLong(value);
IOSync();
newValue = USBToHostLong(_pOHCIRegisters->hcRhPortStatus[port]);
}
}
return;
}
void
AppleUSBOHCI::OHCIRootHubPortSuspend(UInt16 port, bool on)
{
UInt32 value = 0;
if (on)
value |= kOHCIHcRhPortStatus_PSS; else
value |= kOHCIHcRhPortStatus_POCI;
_pOHCIRegisters->hcRhPortStatus[port] = HostToUSBLong(value);
IOSync();
if ((_errataBits & kErrataNECIncompleteWrite) && on)
{
UInt32 newValue = 0, count = 0;
IOSleep(1); newValue = USBToHostLong(_pOHCIRegisters->hcRhPortStatus[port]);
while ((count++ < 10) && !(newValue & kOHCIHcRhPortStatus_PSS))
{
USBError(1, "OHCI driver: OHCIRootHubPortSuspend bit not sticking (on). Retrying.");
_pOHCIRegisters->hcRhPortStatus[port] = HostToUSBLong(value);
IOSync();
IOSleep(count);
newValue = USBToHostLong(_pOHCIRegisters->hcRhPortStatus[port]);
}
}
return;
}
void
AppleUSBOHCI::OHCIRootHubPortPower(UInt16 port, bool on)
{
UInt32 value = 0;
USBLog(5,"AppleUSBOHCI[%p]::OHCIRootHubPortPower(%s) for port %d", this, on ? "on" : "off", port);
if (on)
value |= kOHCIHcRhPortStatus_PPS; else
value |= kOHCIHcRhPortStatus_LSDA;
_pOHCIRegisters->hcRhPortStatus[port] = HostToUSBLong(value);
IOSync();
if (_errataBits & kErrataNECIncompleteWrite)
{
UInt32 newValue = 0, count = 0;
newValue = USBToHostLong(_pOHCIRegisters->hcRhPortStatus[port]);
while ((count++ < 10) && (on ? !(newValue & kOHCIHcRhPortStatus_PPS) : (newValue & kOHCIHcRhPortStatus_PPS)))
{
USBError(1, "OHCI driver: OHCIRootHubPortPower bit not sticking (%d). Retrying.", on);
_pOHCIRegisters->hcRhPortStatus[port] = HostToUSBLong(value);
IOSync();
newValue = USBToHostLong(_pOHCIRegisters->hcRhPortStatus[port]);
}
}
return;
}
IOReturn
AppleUSBOHCI::SimulateControlEDCreate (UInt16 maxPacketSize)
{
return kIOReturnSuccess;
}
IOReturn
AppleUSBOHCI::SimulateEDDelete (short endpointNumber, short direction)
{
return SimulateEDAbort(endpointNumber, direction);
}
IOReturn
AppleUSBOHCI::SimulateEDAbort (short endpointNumber, short direction)
{
int i;
if (endpointNumber == 1)
{
if (direction != kUSBIn)
{
USBLog(3, "AppleUSBOHCI[%p]::SimulateEDAbort - Root hub wrong direction Int pipe %d", this, direction);
return kIOReturnInternalError;
}
USBLog(5, "AppleUSBOHCI[%p]::SimulateEDAbort Root hub aborting int transactions", this);
RootHubAbortInterruptRead();
}
else
{
USBLog(5, "AppleUSBOHCI[%p]::SimulateEDAbort Root hub aborting control pipe (NOP)", this);
}
return kIOReturnSuccess;
}
IOReturn
AppleUSBOHCI::SimulateEDClearStall (short endpointNumber, short direction)
{
return kIOReturnSuccess;
}
AbsoluteTime
AppleUSBOHCI::LastRootHubPortStatusChanged( bool resetTime )
{
uint64_t currentTime;
if ( resetTime )
{
currentTime = mach_absolute_time();
_lastRootHubStatusChanged = *(AbsoluteTime*) ¤tTime;
}
return _lastRootHubStatusChanged;
}
#pragma mark Used binary compatibilty slots
OSMetaClassDefineReservedUsed(IOUSBController, 14);