?? phcd.cpp
字號:
ulValue |= gcHcCommandStatusHCRmask;
/********************Add by Zou Ying for ISP1161*/
m_HcBulkCurrentED = 0;
m_HcControlCurrentED = 0;
m_HcBulkHeadED = 0;
m_HcBulkCurrentED = 0;
m_HcControlHeadED = 0;
m_HcControlCurrentED = 0;
m_HcHCCA = 0;
m_HcPeriodCurrentED = 0;
m_HcDoneHead = 0;
m_HcPeriodicStart = 0;
m_HcControlCBSR = 0;
m_HcControlPLE = 0;
m_HcControlIE = 0;
m_HcControlCLE = 0;
m_HcControlBLE = 0;
m_HcCommandCLF = 0;
m_HcCommandBLF = 0;
/**************************************************/
WRITE_REGISTER_ULONG(HcCommandStatus(regBase), ulValue);
// Wait for HC to complete reset (max 10us)
while (READ_REGISTER_ULONG(HcCommandStatus(regBase)) & gcHcCommandStatusHCRmask)
;
// Put the HC into the USB_RESET state (must do this within 1ms of the above)
ulValue = READ_REGISTER_ULONG(HcControl(regBase));
ulValue &= ~gcHcControlHCFSmask;
ulValue |= gcHcControlFSReset;
WRITE_REGISTER_ULONG(HcControl(regBase), ulValue);
// Restore the registers we just saved.
// They will be restored by PowerManagementCallback if this is a warm boot.
if (!m_bPoweredUpAfterPowerDown)
{
WRITE_REGISTER_ULONG(HcBulkHeadEd(regBase), m_paHcBulkHeadEdSave);
WRITE_REGISTER_ULONG(HcControlHeadEd(regBase), m_paHcControlHeadEdSave);
}
// Tell the PHCI chip where the Host Controller Communications Area is.
physAddr = m_pobMem->VaToPa(m_pHcca);
WRITE_REGISTER_ULONG(HcHCCA(regBase), physAddr);
DEBUGMSG(ZONE_INIT && !m_bPoweredUpAfterPowerDown,
(TEXT("Wrote HCCA phys addr = 0x%08X, virt addr 0x%08X\r\n"),
physAddr, m_pHcca));
//Enable ISP 1161 interrupts
/**************************************************/
//Interrupt enalbe, enable the SOF, ATLInt, and OPR_Reg
WRITE_REGISTER_USHORT(HcWRInterruptEnable(m_regBase), 0x13);
//ITL BufferLen
WRITE_REGISTER_USHORT(HcWRITLBufferLength(m_regBase), 1024);
//ATL BufferLen
WRITE_REGISTER_USHORT(HcWRATLBufferLength(m_regBase), 2048);
/**************************************************/
// Enable interrupts
ulValue = READ_REGISTER_ULONG(HcInterruptEnable(regBase));
ulValue |=
gcHcInterruptStatusSOmask | // Scheduling Overrun
gcHcInterruptStatusWDHmask | // WritebackDoneHead
gcHcInterruptStatusUEmask | // UnrecoverableError
gcHcInterruptStatusRHSCmask | // Root Hub Status Change
gcHcInterruptStatusFNOmask | // frame number overflow
gcHcInterruptStatusMIEmask; // Master Enable
WRITE_REGISTER_ULONG(HcInterruptEnable(regBase), ulValue);
// Enable processing of the different lists
EnableAllLists(regBase);
// We need to set the FullSpeedMaxPacketSize value.
ulValue = READ_REGISTER_ULONG(HcFmInterval(regBase)) & gcHcFmIntervalFImask;
// This algorithm is straight out of section 5.4 of the OHCI spec
ulValue |= (((ulValue - gcHcFmIntervalMaxOverhead) * 6) / 7) << 16;
// ulValue |= (((ulValue - gcHcFmIntervalMaxOverhead) * 1) / 7) << 16;
WRITE_REGISTER_ULONG(HcFmInterval(regBase), ulValue);
// We need to put 90% of the FmInterval into the Periodic Start Reg.
// This means roughly ten percent of the frame time is devoted to
// control and bulk.
ulValue = 9 * (READ_REGISTER_ULONG(HcFmInterval(regBase)) &
gcHcFmIntervalFImask) / 10;
WRITE_REGISTER_ULONG(HcPeriodicStart(regBase), ulValue);
// let's reset the frame number so that it doesn't overflow after 50 days
// of suspend
m_dwFrameNumber = 0;
DEBUGMSG(1 && !m_bPoweredUpAfterPowerDown,
(TEXT("-PHCD::InitializeHardware\r\n")));
return(successful);
}
// Put HC in OPERATIONAL state. In this state, the HC may process lists and
// will generate SOFs.
VOID CPhcd::EnterOperationalState()
{
REGISTER regBase = m_regBase;
ULONG ulValue;
// InitializeHardware left the HC in the USB_RESET state
// but we don't know how long ago that was. He can't sleep
// because he might've been called from the power mgmt callback
// so we'll wait the full 10 msec right here.
Sleep(10);
DEBUGMSG(ZONE_INIT, (TEXT("PHCD:EnterOperationalState - leaving stabilization mode\n")));
m_fStabilizing = FALSE;
// Set the functional state to USBOPERATIONAL - this will cause
// SOF generation to begin in 1ms. Set the Control Bulk Service
// ratio at the same time.
ulValue = READ_REGISTER_ULONG(HcControl(regBase)) &
~(gcHcControlCBSRmask | gcHcControlHCFSmask);
// ulValue |= gcHcControlCBSR4to1 | gcHcControlFSOperational;
//ISP 1161, put this value to 1:1
ulValue |= gcHcControlCBSR1to1 | gcHcControlFSOperational;
//ISP 1161 According to W.J. Add 0x600 to it.
ulValue |= 0x600;
WRITE_REGISTER_ULONG(HcControl(regBase), ulValue);
// The system should now be running. Enable power to the root hub ports.
ulValue = READ_REGISTER_ULONG(HcRhDescriptorA(regBase));
if ((ulValue & gcRhDescriptorANPSmask) == 0)
{
ulValue |= gcRhDescriptorANPSmask; // No power switching
WRITE_REGISTER_ULONG(HcRhDescriptorA(regBase), ulValue);
}
ulValue = READ_REGISTER_ULONG(HcRhStatus(regBase));
ulValue |= gcRhStatusLPSCmask;
WRITE_REGISTER_ULONG(HcRhStatus(regBase), ulValue);
// We must wait until power is OK before accessing any ports on the root hub
Sleep(m_PowerOnToPowerGoodTime);
}
static inline BOOL IsHub (SDevice *pDev)
{
return pDev->pHubPorts != NULL;
}
// Function to check whether a particular device (or hub) is drawing power from
// the bus. This is static - it is based on the configuration that was selected
// when the device was set up.
static BOOL
IsStaticSelfPowered(SDevice *pDev)
{
if (pDev->ohciDevice.lpActiveConfig)
return !!(pDev->ohciDevice.lpActiveConfig->Descriptor.bmAttributes & SELF_POWERED);
else
// No config selected yet, assume bus power
return FALSE;
}
//REVIEW aLenthgs must be a valid array of Lengths!
BOOL CPhcd::IssueTransfer(UINT iDevice, UINT iEndpointIndex,
LPTRANSFER_NOTIFY_ROUTINE lpStartAddress, LPVOID lpvNotifyParameter,
DWORD dwFlags, LPCVOID lpvControlHeader, DWORD dwStartingFrame,
DWORD dwFrames, LPCDWORD aLengths, DWORD dwBufferSize, LPVOID lpvBuffer,
ULONG paBuffer, LPCVOID lpvCancelId, LPDWORD adwIsochErrors,
LPDWORD adwIsochLengths, LPBOOL lpfComplete,
LPDWORD lpdwBytesTransfered, LPDWORD lpdwError)
{
SDevice * pDev;
SEndpoint * pEndpt;
SPhysAddr * pPhysAddrHead = NULL;
SPhysAddr * pCur;
SPhysAddr * * ppCur;
EError errorCode = successful;
ULONG paSetupBuf;
STransfer * pTransfer;
BOOL fToDevice = !(dwFlags & USB_IN_TRANSFER);
BOOL fShortTransferOk = !!(dwFlags & USB_SHORT_TRANSFER_OK);
BOOL fUseStartingFrame = !(dwFlags & USB_START_ISOCH_ASAP);
INT cPhysAddr = 0;
DWORD dwMemAllocFlags;
EnterCriticalSection(&m_csDeviceListLock);
pDev = m_ppDevices[iDevice];
LeaveCriticalSection(&m_csDeviceListLock);
DEBUGMSG(ISPDBG,(TEXT("+PHCD::IssueTransfer, iDev:%u, iEp:%u, Fl:0x%X, StartFrame:%u, Frames:%u, BufSiz:%u\r\n"),
iDevice, iEndpointIndex, dwFlags,dwStartingFrame,dwFrames,dwBufferSize));
if (pDev == NULL)
{
DEBUGMSG(ZONE_ERROR,
(TEXT("!PHCD: Error transfer sent to non-existant device, pDev:0x%X\r\n"),pDev));
return FALSE;
}
if (pDev->fDetached == TRUE)
{
DEBUGMSG(ZONE_WARNING,(TEXT("PHCD::IssueTransfer, pDev:0x%X has been detached\r\n"),pDev));
return FALSE;
}
EnterCriticalSection(&pDev->csAccessingEndpointArray);
pEndpt = pDev->ppEndpts[iEndpointIndex];
LeaveCriticalSection(&pDev->csAccessingEndpointArray);
if (pEndpt == NULL)
{
DEBUGMSG(ZONE_ERROR,
(TEXT("!PHCD: Error transfer sent to closed endpt\r\n")));
return FALSE;
}
BOOL fIsIsoch = (pEndpt->endptType == gcEndptTypeIsochronous);
// Set up our flags for memory allocations - isoch buffers come from a special high
// priority pool, and don't block. Other transfer types default to blocking to wait
// for memory unless the DONT_BLOCK flag is set by the client.
if (fIsIsoch)
dwMemAllocFlags = USBALLOCF_HIGHPRIORITY;
else if (dwFlags & USB_DONT_BLOCK_FOR_MEM)
dwMemAllocFlags = USBALLOCF_NOBLOCK;
else
dwMemAllocFlags = 0; // Default, block until memory available (or pipe closed)
//either we have a list of offsets with the # of offsets in the array
//or we have a non isoch transfer
ASSERT((adwIsochErrors && adwIsochLengths && aLengths && dwFrames) || !fIsIsoch);
ASSERT(lpfComplete && lpdwBytesTransfered && lpdwError && lpvCancelId);
ASSERT(iDevice);
*lpfComplete = FALSE;
*lpdwBytesTransfered = 0;
*lpdwError = USB_NO_ERROR;
EnterCriticalSection(&m_csOtherListsLock);
if (m_pFreeTransferHead != NULL)
{
pTransfer = m_pFreeTransferHead;
m_pFreeTransferHead = pTransfer->pNext;
}
else
{
pTransfer = new STransfer;
}
LeaveCriticalSection(&m_csOtherListsLock);
if (pTransfer == NULL)
{
DEBUGMSG(ZONE_ERROR,(TEXT("!PHCD: Error allocating transfer struct\r\n")));
return FALSE;
}
pTransfer->lpbClientBuffer = (PBYTE)lpvBuffer;
// Store the current process permissions, so the IST can access the
// client buffer directly.
pTransfer->dwClientBufferPerms = GetCurrentPermissions();
pTransfer->lpCompletionParameter = lpvNotifyParameter;
pTransfer->lpCompletionStartAddress = lpStartAddress;
pTransfer->lpCancelParameter = NULL;
pTransfer->lpCancelStartAddress = NULL;
pTransfer->lpvCancelId = lpvCancelId;
pTransfer->pfComplete = lpfComplete;
pTransfer->pdwBytesTransfered = lpdwBytesTransfered;
pTransfer->pdwError = lpdwError;
pTransfer->adwIsochErrors = adwIsochErrors;
pTransfer->adwIsochLengths = adwIsochLengths;
pTransfer->pSetupBuffer = NULL;
pTransfer->cbBuffer1 = 0;
pTransfer->pDataBuffer1 = NULL;
pTransfer->paDataBuffer1 = 0;
pTransfer->cbBuffer2 = 0;
pTransfer->pDataBuffer2 = NULL;
pTransfer->paDataBuffer2 = 0;
pTransfer->aCopyLengths = NULL;
pTransfer->pCopyLength = NULL;
#ifdef USE_CRITICAL_THREAD
pTransfer->cCriticalTds = 0;
#endif
pTransfer->cNormalTds = 0;
pTransfer->fCanceled = FALSE;
pTransfer->fActiveCanceled = FALSE;
pTransfer->fIn = !!(dwFlags & USB_IN_TRANSFER);
pTransfer->fCompress = !!(dwFlags & USB_COMPRESS_ISOCH);
pTransfer->bufType = gcBufTypeAlt;
pTransfer->paLastTD = 0;
pTransfer->pNext = NULL;
// Create a chain of SPhysAddr structures that describe the client buffer
if(!(dwBufferSize == 0 && pEndpt->endptType == gcEndptTypeControl))
{
UINT cbBuffer1Bytes = 0;
UINT cbBuffer2Bytes = 0;
UINT cbTransfer;
BOOL fFirstBuffer = TRUE;
ppCur = &pPhysAddrHead;
if (fIsIsoch)
{
UINT cOffsets;
UINT iCurrentOffset = 0;
UINT cbSegment;
// This code does not consider zero byte isoch transfers
// we need to test how PHCI works before implementing this - it is not
// clear how to set up the TDs.
while(iCurrentOffset < dwFrames)
{
cbTransfer = 0;
cOffsets = 0;
while((cOffsets < gcMaxOffsetsPerTd) && (iCurrentOffset < dwFrames))
{
cbSegment = aLengths[iCurrentOffset];
ASSERT(cbSegment <= pEndpt->maxPacket);
if(cbTransfer + cbSegment > gcMaxTransferSize)
break;
*adwIsochErrors++ = USB_NO_ERROR;
*adwIsochLengths++ = cbSegment;
++cOffsets;
cbTransfer += cbSegment;
++iCurrentOffset;
}
EnterCriticalSection(&m_csOtherListsLock);
if (m_pFreePhysAddrHead != NULL)
{
*ppCur = m_pFreePhysAddrHead;
m_pFreePhysAddrHead = (*ppCur)->pNext;
}
else
{
*ppCur = new SPhysAddr;
}
LeaveCriticalSection(&m_csOtherListsLock);
++cPhysAddr;
pCur = *ppCur;
pCur->pNext = NULL;
ppCur = &pCur->pNext;
pCur->cIsochOffsets = cOffsets;
pCur->length = cbTransfer;
// We use two physical buffers to copy to/from the client buffer.
// Here, determine size needed for each of these buffers.
if(fFirstBuffer)
{
if(cbTransfer > cbBuffer1Bytes)
cbBuffer1Bytes = cbTransfer;
fFirstBuffer = FALSE;
}
else
{
if(cbTransfer > cbBuffer2Bytes)
cbBuffer2Bytes = cbTransfer;
fFirstBuffer = TRUE;
}
}
ASSERT(iCurrentOffset == dwFrames);
}
else
{
//all packets must be maxPacket divisible except the last (USB spec)
UINT cbMaxTransferSize =
(gcMaxTransferSize / pEndpt->maxPacket) * pEndpt->maxPacket;
UINT cbRemaining = dwBufferSize;
if(dwBufferSize > cbMaxTransferSi
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -