⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pxa25xpdd.cpp

📁 pxa25x library for windows ce
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    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 + -