📄 pxa25xpdd.cpp
字号:
while (bContinue) {
if (pContext->fExitIST || pContext->fRestartIST) {
break;
}
// GetEndpoint Interrupt Flag.
ULONG ulUdccr = g_pUDCBase->udccr ;
ULONG ulIsr0 = g_pUDCBase->uisr0 ;
ULONG ulIsr1 = g_pUDCBase->uisr1 ;
bContinue = ((ulUdccr & (USB_UDCCR_RSTIR | USB_UDCCR_SUSIR | USB_UDCCR_RESIR))!=0 || ulIsr0!=0 || ulIsr1!=0) ;
if (!bContinue)
break;
DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Interrupt Event ulUdccr=0x%x, ulIsr=0x%x, ulIsr1=0x%x, uicr0=0x%x, uicr1=0x%x \r\n"),
pszFname,ulUdccr,ulIsr0,ulIsr1,g_pUDCBase->uicr0,g_pUDCBase->uicr1));
// Ack bit first.
g_pUDCBase->udccr = ulUdccr ;
g_pUDCBase->uisr0 = ulIsr0 ;
g_pUDCBase->uisr1 = ulIsr1 ;
// Take the valid bit.
ulUdccr &= (USB_UDCCR_RSTIR | USB_UDCCR_SUSIR | USB_UDCCR_RESIR);
ulIsr0 &= (~g_pUDCBase->uicr0);
ulIsr1 &= (~g_pUDCBase->uicr1);
if ((ulUdccr & USB_UDCCR_RSTIR)==0 ) { // Work around Multiple Reset Problem.
pContext->fIgnoreReset = FALSE;
}
// Device Event
if (ulUdccr) {
if ( (ulUdccr & ( USB_UDCCR_SUSIR | USB_UDCCR_RESIR))!= NULL) { // Suspend Resume.
// Check for Attach/Detach
ATTACH_DETACH_INTERRUPT adi =
Pxa25xLibCheckAttachDetach(pContext->pvLibContext);
DEBUGCHK(IS_VALID_ATTACH_DETACH_INTERRUPT(adi));
if(adi != ADI_NONE){
Pxa25xLibClearAttachDetach(pContext->pvLibContext, adi);
if (adi == ADI_ATTACH) {
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_ATTACH);
pContext->attachedState = UFN_ATTACH;
}
else {
DEBUGCHK(adi == ADI_DETACH);
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_DETACH);
pContext->attachedState = UFN_DETACH;
}
SetRequestInfo(&pContext->ep0Request, EP0Setup);
}
}
if ((ulUdccr & USB_UDCCR_RSTIR)!=0 && !pContext->fIgnoreReset) {
DEBUGCHK(pContext->fRunning);
// Disable Double Buffering on Endpoints 1 and 2
g_pUDCBase->rsvd0[0] &= ~(0x06);
// Reset Has been report multiple time . Ignore following one.
pContext->fIgnoreReset = TRUE;
DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Reset\r\n"), pszFname));
// If the cable was connected to a host at boot, the attach interrupt
// will be missed. Generate it here.
if ((pContext->attachedState != UFN_ATTACH)){
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_ATTACH);
pContext->attachedState = UFN_ATTACH;
}
pContext->fSpeedReported = FALSE;
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_RESET);
SetRequestInfo(&pContext->ep0Request, EP0Setup);
}
}
if(ulIsr0 & USB_UISR0_IR0) {
ServiceEP0(pContext);
}
// inspect each interrupt/status register for a pending interrupt
if (ulIsr0) {
for (ulI = 1; ulI < 8; ulI += 1) {
if (ulIsr0 & (1 << ulI)){
// an interrupt is pending, notify the function driver
HandleEndpointEvent(pContext, ulI);
}
}
}
if (ulIsr1) {
for (ulI = 0; ulI < 8; ulI += 1) {
// an interrupt is pending, notify the function driver
if (ulIsr1 & (1 << ulI)) {
HandleEndpointEvent(pContext, (8 + ulI) );
}
}
}
}
FUNCTION_LEAVE_MSG();
}
// interrupt service routine.
static
DWORD
WINAPI
ISTMain(
LPVOID lpParameter
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
PCTRLR_PDD_CONTEXT pContext = (PCTRLR_PDD_CONTEXT) lpParameter;
ValidateContext(pContext);
CeSetThreadPriority(pContext->hIST, pContext->dwISTPriority);
// Enable Acking
// Calling InitClock() once before calling StartClock() or StopClock().
InitClock();
while (!pContext->fExitIST) {
pContext->fRestartIST = FALSE;
pContext->fEndpoint0AckNeeded = FALSE;
if (!(StartClock(CLK_USB, FALSE))) {
DEBUGMSG(ZONE_ERROR, (_T("%s Unable to start USB clock!\r\n"), pszFname));
}
// Disable USB interface
UDCCR_UDE_DISABLE(g_pUDCBase->udccr);//g_pUDCBase->udccr &= ~USB_UDCCR_UDE
// We are currently disconnected. Make sure that we have been
// disconnected long enough for the host to notice.
Sleep(1); // USB spec 7.1.7 says disconnect requires >= 2.5 us
// Disable All endpoint Interrupt.
g_pUDCBase->uicr0 = DISABLE_INTRS_0TO7; // Endpoints 0-7
g_pUDCBase->uicr1 = DISABLE_INTRS_0TO7; // Endpoints 8-15
// Clear any outstanding endpoint interrupts
g_pUDCBase->uisr0 = CLEAR_INTRS_0TO7; // Clear Enpoint Interrupts 0-7
g_pUDCBase->uisr1 = CLEAR_INTRS_8TO15; // Clear Enpoint Interrupts 8-15
// Enable USB interface , Enable Reset Interrupt, Enable Suspen/Resume Interrup
// Clear any outstanding device interrupts
g_pUDCBase->udccr = USB_UDCCR_UDE |USB_UDCCR_RSM| (USB_UDCCR_RSTIR | USB_UDCCR_SUSIR | USB_UDCCR_RESIR);
// Enable (UnMask) Endpoint 0 interrupts
EnableEndpointInterrupt( pContext, 0 );
SetRequestInfo(&pContext->ep0Request, EP0Setup);
//g_pUDCBase->rsvd0[1] |= 0x04;
//g_pUDCBase->rsvd0[1] &= ~0x80;
pContext->fIgnoreReset = FALSE;
while (TRUE) {
DWORD dwWait = WaitForSingleObject(pContext->hevInterrupt, INFINITE);
if (pContext->fExitIST || pContext->fRestartIST) {
break;
}
if (dwWait == WAIT_OBJECT_0) {
HandleUSBEvent(pContext);
InterruptDone(pContext->dwSysIntr);
}
else {
DEBUGMSG(ZONE_ERROR, (_T("%s WaitForMultipleObjects failed. Exiting IST.\r\n"),
pszFname));
pContext->fExitIST = TRUE;
break;
}
}
// Disable USB interface
UDCCR_UDE_DISABLE(g_pUDCBase->udccr);//g_pUDCBase->udccr &= ~USB_UDCCR_UDE
// Disable Bus Reset interrupts
UDCCR_REM_DISABLE(g_pUDCBase->udccr);//g_pUDCBase->udccr &= ~USB_UDCCR_REM
// Disable (Mask) Endpoint 0 interrupts
g_pUDCBase->uicr0 |= USB_UICR0_IM0;
if (!StopClock(CLK_USB, FALSE)) {
DEBUGMSG(ZONE_ERROR, (_T("%s Unable to stop USB clock!\r\n"), pszFname));
}
// Send detach
pContext->pfnNotify(pContext->pvMddContext,
UFN_MSG_BUS_EVENTS, UFN_DETACH);
pContext->attachedState = UFN_DETACH;
pContext->fSpeedReported = FALSE;
}
FUNCTION_LEAVE_MSG();
return 0;
}
/*++
Routine Description:
Map the base I/O address of the XScale UDC to virtual memory.
Arguments:
None.
Return Value:
Success.
--*/
static
DWORD MapRegisterSet(PCTRLR_PDD_CONTEXT pContext)
{
SETFNAME();
FUNCTION_ENTER_MSG();
PREFAST_DEBUGCHK(pContext);
DEBUGCHK(g_pUDCBase == NULL);
PBYTE pVMem;
DWORD dwRet = ERROR_SUCCESS;
// Map CSR registers.
pVMem = (PBYTE)VirtualAlloc(0, PAGE_SIZE, MEM_RESERVE, PAGE_NOACCESS);
if (pVMem) {
BOOL fSuccess = VirtualCopy( pVMem, (LPVOID)pContext->dwIOBase,
PAGE_SIZE, PAGE_READWRITE | PAGE_NOCACHE);
if (!fSuccess) {
VirtualFree(pVMem, 0, MEM_RELEASE);
dwRet = GetLastError();
DEBUGMSG(ZONE_ERROR, (_T("%s Virtual Copy: FAILED\r\n"), pszFname));
}
else {
g_pUDCBase = (volatile UDC_REGS *)pVMem;
DEBUGMSG(ZONE_INIT, (_T("%s VirtualCopy Succeeded, pVMem:%x\r\n"),
pszFname, pVMem));
}
}
else {
dwRet = GetLastError();
DEBUGMSG(ZONE_ERROR, (_T("%s Virtual Alloc: FAILED\r\n"), pszFname));
}
FUNCTION_LEAVE_MSG();
return dwRet;
}
/*++
Routine Description:
Deallocate register space.
Arguments:
None.
Return Value:
None.
--*/
static
VOID
UnmapRegisterSet(
)
{
if (g_pUDCBase) {
VirtualFree((PVOID) g_pUDCBase, 0, MEM_RELEASE);
g_pUDCBase = NULL;
}
}
static
VOID
StartTransfer(
PCTRLR_PDD_CONTEXT pContext,
PEP_STATUS peps,
PSTransfer pTransfer
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
PREFAST_DEBUGCHK(pContext);
PREFAST_DEBUGCHK(peps);
DEBUGCHK(!peps->pTransfer);
ValidateTransferDirection(pContext, peps, pTransfer);
DEBUGMSG(ZONE_TRANSFER, (_T("%s Xfer ep %u for %u bytes\r\n"),
pszFname, peps->dwEndPointNumber, pTransfer->cbBuffer));
// Enable transfer interrupts.
peps->pTransfer = pTransfer;
// Enable transfer interrupts.
if (peps->dwEndPointNumber == 0) {
peps->fZeroPacketNeeded = TRUE;
if ((pTransfer->dwFlags & USB_IN_TRANSFER) != 0) {
DEBUGCHK(pContext->ep0Request.eDir == EP0In);
}
else {
DEBUGCHK(pContext->ep0Request.eDir == EP0Out);
}
if (!peps->fInIST) {
ServiceSetup(pContext,peps);
}
}
else {
EnableEndpointInterrupt(pContext,peps->dwEndPointNumber);
peps->fZeroPacketNeeded = ((pTransfer->cbBuffer== 0 || pTransfer->pvBuffer== 0) && (pTransfer->dwFlags & USB_IN_TRANSFER) != 0) ;
// Note For the Xscale the HW NAKs IN requests and DOES NOT let SW
// know that the Host is trying to send a request. SO... Start the Transfer
// In Now!
// Start the Transfer
if(!peps->fInIST) {
if ((pTransfer->dwFlags & USB_IN_TRANSFER) != 0) {
pContext->numInPacketsSent = 0;
HandleTx(pContext,peps);
}
else{
HandleRx(pContext,peps);
}
}
}
FUNCTION_LEAVE_MSG();
}
DWORD
WINAPI
UfnPdd_IssueTransfer(
PVOID pvPddContext,
DWORD dwEndpoint,
PSTransfer pTransfer
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DEBUGCHK(EP_VALID(dwEndpoint));
PCTRLR_PDD_CONTEXT pContext = (PCTRLR_PDD_CONTEXT) pvPddContext;
ValidateContext(pContext);
PEP_STATUS peps = GetEpStatus(pContext, dwEndpoint);
LOCK_ENDPOINT(peps);
DEBUGCHK(peps->fInitialized);
DEBUGCHK(pTransfer->dwUsbError == UFN_NOT_COMPLETE_ERROR);
DEBUGCHK(pTransfer->cbTransferred == 0);
DWORD dwRet = ERROR_SUCCESS;
// Note For the HW NAKs IN requests and DOES NOT let SW
// know that the Host is trying to send a request. SO... Start the Transfer
// In Now!
// Start the Transfer
DEBUGCHK(peps->pTransfer == NULL);
if (peps->dwEndPointNumber == 0) {
if ((pTransfer->dwFlags & USB_IN_TRANSFER)!= 0 ) {
if (pContext->ep0Request.eDir != EP0In) {
DEBUGMSG(ZONE_WARNING, (_T("%s EP0 is not in IN state. State = %u\r\n"),
pszFname, pContext->ep0Request.eDir));
dwRet = ERROR_NOT_READY;
goto EXIT;
}
}
else {
if (pContext->ep0Request.eDir != EP0Out) {
DEBUGMSG(ZONE_WARNING, (_T("%s EP0 is not in OUT state. State = %u\r\n"),
pszFname, pContext->ep0Request.eDir));
dwRet = ERROR_NOT_READY;
goto EXIT;
}
}
}
StartTransfer(pContext, peps, pTransfer);
EXIT:
UNLOCK_ENDPOINT(peps);
FUNCTION_LEAVE_MSG();
return dwRet;
}
DWORD
WINAPI
UfnPdd_AbortTransfer(
PVOID pvPddContext,
DWORD dwEndpoint,
PSTransfer pTransfer
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
PREFAST_DEBUGCHK(pTransfer);
DEBUGCHK(EP_VALID(dwEndpoint));
PCTRLR_PDD_CONTEXT pContext = (PCTRLR_PDD_CONTEXT) pvPddContext;
ValidateContext(pContext);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -