📄 pdd.c
字号:
{
CheckEndpoint(pPdd, i );
}
}
} while (INREG32(&pUSBDRegs->OTG.ENDPTSETUPSTAT) ||INREG32(&pUSBDRegs->OTG.ENDPTCOMPLETE));
}
}
while (!pPdd->exitIntrThread)
{
DWORD dwErr = 0;
if (pPdd->IsOTGSupport)
timeout = INFINITE;
// Wait for interrupt from USB controller
dwErr = WaitForSingleObject(pPdd->hIntrEvent, timeout);
if (dwErr == WAIT_TIMEOUT)
{
// Now I am ready to put the transceiver into suspend mode.
// But be aware there is a device attach when boot up
USB_CTRL_T ctrl;
DWORD *temp3;
USB_PORTSC_T portsc;
DWORD *temp = (DWORD *)&portsc;
*temp = INREG32(&(pUSBDRegs)->OTG.PORTSC);
if ((portsc.SUSP == 0) && (pPdd->devState == 1))
{
// there is a device attached, don't do anything
timeout = INFINITE;
continue;
}
// If there is a device attached at this time
// Handling of device attach
// Even though it is pure client, still, we have no other way to isolate the
// host from the device, we need to use ID pin to detect.
if (portsc.SUSP == 0)
{
USB_OTGSC_T otgsc;
DWORD *temp4 = (DWORD *)&otgsc;
*temp4 = INREG32(&(pUSBDRegs)->OTG.OTGSC);
timeout = IDLE_TIMEOUT;
if (otgsc.ID != 0)
{
DEBUGMSG(1, (TEXT("Port is not suspend and no A-device is detected\r\n")));
LOCK();
USBControllerRun(pUSBDRegs, FALSE);
HardwareInitialize(pUSBDRegs);
UfnPdd_Start(pPdd);
USBControllerRun(pUSBDRegs, TRUE);
UNLOCK();
goto PROCESS_INTERRUPT;
}
}
// Now the device is not attached
// Check and make sure all wakeup interrupt are enabled
temp3 = (DWORD *)&ctrl;
*temp3 = INREG32(&pUSBDRegs->USB_CTRL);
ctrl.OWIE = 1;
ctrl.OUIE = 1;
OUTREG32(&pUSBDRegs->USB_CTRL, *temp3);
// stop the controller before accessing the ULPI
LOCK();
USBControllerRun(pUSBDRegs, FALSE);
// May need to set ULPI here
// It is not waking up now ...must be something wrong
*temp = INREG32(&(pUSBDRegs)->OTG.PORTSC);
if (portsc.PHCD == 0)
SetULPIToClientMode(pUSBDRegs);
portsc.PHCD = 1;
OUTREG32(&(pUSBDRegs)->OTG.PORTSC, *temp);
//DEBUGMSG(1, (TEXT("Lower core voltage now with portsc(0x%x) usbctrl(0x%x)\r\n"), INREG32(&(pUSBDRegs)->OTG.PORTSC), INREG32(&pUSBDRegs->USB_CTRL)));
{
BOOL bTemp;
if (pPdd->bUSBPanicMode == TRUE)
{
bTemp = DDKClockDisablePanicMode();
//RETAILMSG(1, (TEXT("DDKClockDisablePanicMode = 0x%x\r\n"), bTemp));
pPdd->bUSBPanicMode = FALSE;
}
}
if (pPdd->bUSBCoreClk == TRUE)
{
pPdd->bUSBCoreClk = FALSE;
USBClockDisable(TRUE);
}
UNLOCK();
// Now we can stop the USB clock
DEBUGMSG(1, (TEXT("PDD - SUSPEND\r\n")));
timeout = INFINITE;
continue;
}
PROCESS_INTERRUPT:
LOCK();
if (pPdd->bUSBCoreClk == FALSE)
{
USBClockDisable(FALSE);
pPdd->bUSBCoreClk = TRUE;
}
if (pPdd->bUSBPanicMode == FALSE)
{
DDKClockEnablePanicMode();
pPdd->bUSBPanicMode = TRUE;
DEBUGMSG(1, (TEXT("DDKClockEnablePanicMode\r\n")));
DEBUGMSG(1, (TEXT("WakeUp - PORTSC: 0x%x\r\n"), INREG32(&pUSBDRegs->OTG.PORTSC[0])));
}
if (INREG32(&pUSBDRegs->OTG.PORTSC[0]) & 0x800000)
{
// Clear the PHCD
CLRREG32(&pUSBDRegs->OTG.PORTSC[0], INREG32(&pUSBDRegs->OTG.PORTSC[0]) & 0x800000);
// Force Resume bit
OUTREG32(&pUSBDRegs->OTG.PORTSC[0], INREG32(&pUSBDRegs->OTG.PORTSC[0])|0x40);
DEBUGMSG(1, (TEXT("Force resume\r\n")));
}
UNLOCK();
InterruptDone(pPdd->sysIntr);
CeLogMsg(_T("Intr:Signalled"));
{
USB_CTRL_T ctrl;
temp = (DWORD *)&ctrl;
*temp = INREG32(&pUSBDRegs->USB_CTRL);
if (ctrl.OWIR == 1)
{
*temp = 0;
ctrl.OWIE = 1;
CLRREG32(&pUSBDRegs->USB_CTRL, *temp);
// We move to here since only when we have wakeup should we
// set the Run bit of USB Controller again.
USBControllerRun(pUSBDRegs, TRUE);
}
}
// Exit thread when we are asked so...
if (pPdd->exitIntrThread)
{
break;
}
if ( pPdd->bEnterTestMode )
{
LOCK();
SetDeviceTestMode( pPdd, pPdd->iTestMode );
/* clear whatever interrupt there was */
temp=(DWORD *)&source;
*temp = INREG32(&pUSBDRegs->OTG.USBSTS);
// Clear source bits
OUTREG32(&pUSBDRegs->OTG.USBSTS, *temp);
/*
* when device is in test mode, there is no longer any more normal operation and
* we could just busy-stall here, since exit from the mode is via power-off.
*/
pPdd->exitIntrThread = TRUE;
UNLOCK();
break;
}
if (pPdd->m_CurSelfPowerState == D3 || pPdd->m_CurSelfPowerState == D4)
{
pPdd->m_CurSelfPowerState = D2;
UpdateDevicePower(pPdd);
}
temp=(DWORD *)&source;
// Get interrupt source
*temp = INREG32(&pUSBDRegs->OTG.USBSTS);
do
{
// Clear the reg
OUTREG32(&pUSBDRegs->OTG.USBSTS, *temp);
if (source.URI)
{
HandleUSBReset(pPdd);
}
if (source.SLI)
{
CeLogMsg(_T("Intr:SLI"));
LOCK();
DevStatEvent(pPdd); // Handle device state change
if ((pPdd->devState == 0) && (pPdd->IsOTGSupport == 0))
timeout = IDLE_TIMEOUT;
UNLOCK();
}
// USB Interrupt
if (source.UI)
{
CeLogMsg(_T("Intr:UI SETUPSTAT %x ENDPTCOMP %x"),
INREG32(&pUSBDRegs->OTG.ENDPTSETUPSTAT),
INREG32(&pUSBDRegs->OTG.ENDPTCOMPLETE) );
while (INREG32(&pUSBDRegs->OTG.ENDPTSETUPSTAT) || INREG32(&pUSBDRegs->OTG.ENDPTCOMPLETE))
{
if (INREG32(&pUSBDRegs->OTG.ENDPTSETUPSTAT))
SetupEvent(pPdd); // locks internally, and checks setupstat internally
if (INREG32(&pUSBDRegs->OTG.ENDPTCOMPLETE))
{
for (i=0;i<USBD_EP_COUNT;i++)
{
// check endpoint sees if endptcomplete bit is set for individual endpoint i
CheckEndpoint(pPdd, i ); // locks internally, and checks regs internally
// and clears the endptcomplete bit for that endpoint
}
}
}
}
*temp = INREG32(&pUSBDRegs->OTG.USBSTS);
if ((*temp & 0xffffff6f)==0)
{
CeLogMsg(_T("Intr:Done"));
//CheckForEventLost(pPdd,k);
break;
}
} while (1);
if (pPdd->bResume)
{
CeLogMsg(_T("Resume"));
//RETAILMSG(1, (TEXT("+UFN_DETACH called\r\n")));
pPdd->pfnNotify(pPdd->pMddContext, UFN_MSG_BUS_EVENTS, UFN_DETACH);
//RETAILMSG(1, (TEXT("-UFN_DETACH called\r\n")));
LOCK();
// Don't process other changes (we are disconnected)
pPdd->devState=0;
pPdd->bResume = FALSE;
// SetSelfPowerState to D4
pPdd->m_CurSelfPowerState = D4; // Do we need set to D3 as wake up source?
UpdateDevicePower(pPdd);
OUTREG32(&pPdd->pUSBDRegs->OTG.T_154H.USBADR, 0);
UNLOCK();
if (pPdd->IsOTGSupport)
{
InterruptDisable(pPdd->sysIntr);
// wait for client function class and make sure everything is disconnected
// this is not a very good design but since we need to make sure we can get proper
// disconnect before we switch back to XVR, we have to do that especially on Active Sync.
//RETAILMSG(1, (TEXT("Leave Client back to XVR mode\r\n")));
Sleep(500);
SetEvent(hXcvr);
goto XCVR_SIG;
}
}
// Handle detach condition for OTG
LOCK();
if (pPdd->IsOTGSupport && pPdd->devState == 0)
{
USB_PORTSC_T state;
USB_OTGSC_T otgsc;
DWORD *temp2;
DWORD *temp3;
temp2 = (DWORD *)&state;
*temp2 = INREG32(&pUSBDRegs->OTG.PORTSC[0]);
temp3 = (DWORD *)&otgsc;
*temp3 = INREG32(&pUSBDRegs->OTG.OTGSC);
CeLogMsg(_T("Detach: PORTSC 0x%x"), *temp2);
if ((state.SUSP == 1) || (otgsc.ID == 0))
{
DEBUGMSG(1, (TEXT("Device Detach, with susp(%d), id(%d)\r\n"), state.SUSP, otgsc.ID));
if (otgsc.IDIS)
{
// clear the register. since other is not used, we can simply
// use the SETREG32 instead of OUTREG32
*temp3 = 0;
otgsc.IDIS = 1;
SETREG32(&pUSBDRegs->OTG.OTGSC, *temp3);
}
UNLOCK();
InterruptDisable(pPdd->sysIntr);
SetEvent(hXcvr);
goto XCVR_SIG;
}
}
if ((pPdd->IsOTGSupport == 0) && (pPdd->devState == 0))
timeout = IDLE_TIMEOUT;
UNLOCK();
}
if (pPdd->bEnterTestMode)
{
RETAILMSG(1, (TEXT("USBOTG Client Test Mode set and loop forever\r\n")));
pPdd->bEnterTestMode = FALSE;
while(1);
}
return ERROR_SUCCESS;
}
//-----------------------------------------------------------------
//
// Function: BuildTdBufferList
//
// Given a mapped endpoint and a TransferDescriptor and a length of data to put into it,
// build the list of buffer pointers from previously locked page data (including current page).
// ep is current endpoint, pTd points to the TD being built in uncached mem
//
// Parameter:
//
// [IN] ep - endpoint to be processed
// [IN] pTd - pointer to transfer descriptor
// [IN] len - transfer length
//
// Return:
//
// NULL
//
//-------------------------------------------------------------------
static void BuildTdBufferList( USBFN_EP *ep, PUSBD_dTD_R_T pTd, DWORD len )
{
DWORD dwOffset;
DWORD dwPageIdx;
if ( len > 0 )
{
dwPageIdx = ep->dwNextPageIdx;
DEBUGCHK( dwPageIdx < ep->dwNumPages );
pTd->bp0 = (ep->pdwPageList[dwPageIdx++] << UserKInfo[KINX_PFN_SHIFT]) >> 12;
// get current buffer pointer's offset into first page
pTd->curr_off = dwOffset = ((DWORD)ep->pMappedBufPtr) & (UserKInfo[KINX_PAGESIZE] - 1);
/* the first buffer page will contain either one MAX_SIZE_PER_BP or less (if there was an offset) */
if ( len > (MAX_SIZE_PER_BP - dwOffset) )
len -= (MAX_SIZE_PER_BP - dwOffset);
else
len = 0; // first bp contains all the data
// continue to buffer page 1
if ( len > 0 )
{
DEBUGCHK( dwPageIdx < ep->dwNumPages );
pTd->bp1 = (ep->pdwPageList[dwPageIdx++] << UserKInfo[KINX_PFN_SHIFT])>>12;
// each of the following pages will start at offset 0
if ( len > MAX_SIZE_PER_BP )
len -= MAX_SIZE_PER_BP;
else
len = 0;
// continue to buffer page 2
if ( len > 0 )
{
DEBUGCHK( dwPage
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -