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

📄 sc2440pdd.cpp

📁 S3C2440A的windows ce 5.0 bsp包
💻 CPP
📖 第 1 页 / 共 5 页
字号:

    FUNCTION_LEAVE_MSG();
} // DisableEndpointInterrupt

/*++

Routine Description:

Clear the interrupt status register index of an endpoint.

Arguments:

dwEndpoint - the target endpoint

Return Value:

None.

--*/
static
VOID
ClearEndpointInterrupt(
                       PCTRLR_PDD_CONTEXT pContext,
                       DWORD        dwEndpoint
                       )
{    
    SETFNAME();
    FUNCTION_ENTER_MSG();
    
    // Clear the Endpoint Interrupt
    BYTE bIntBit = EpToIrqStatBit(dwEndpoint);
    WriteReg(pContext, EP_INT_REG_OFFSET, bIntBit);

    FUNCTION_LEAVE_MSG();
} // _ClearInterrupt


// Reset an endpoint
static
VOID
ResetEndpoint(
              PCTRLR_PDD_CONTEXT pContext,
              EP_STATUS *peps
              )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    ValidateContext(pContext);
    PREFAST_DEBUGCHK(peps);

    // Since Reset can be called before/after an Endpoint has been configured,
    // it is best to clear all IN and OUT bits associated with endpoint. 
    DWORD dwEndpoint = peps->dwEndPointNumber;
    if(dwEndpoint == 0 ){
        // Clear all EP0 Status bits
        WriteIndexedReg(pContext, 0, IN_CSR1_REG_OFFSET,
            (SERVICED_OUT_PKY_RDY | SERVICED_SETUP_END));

    }
    else if(dwEndpoint < ENDPOINT_COUNT){

        // Clear the desired Endpoint - Clear both the In & Out Status bits
        BYTE bRegIn;
        BYTE bRegOut;
        if(peps->fInitialized){
            PREFAST_DEBUGCHK(peps->fInitialized); // Give prefast a clue.
            // First Read the CSR2 Reg bit so that it can be restored
            bRegIn = ReadIndexedReg(pContext, dwEndpoint, IN_CSR2_REG_OFFSET);
            bRegOut = ReadIndexedReg(pContext, dwEndpoint, OUT_CSR2_REG_OFFSET);
        }
        // Clear the in register - Must set the Mode_in to IN
        WriteIndexedReg(pContext, dwEndpoint, IN_CSR2_REG_OFFSET,(SET_MODE_IN | IN_DMA_INT_DISABLE));
        WriteIndexedReg(pContext, dwEndpoint, IN_CSR1_REG_OFFSET, ( IN_CLR_DATA_TOGGLE));

        // Clear the Out register  - Must set the Mode_in to OUT
        WriteIndexedReg(pContext, dwEndpoint, IN_CSR2_REG_OFFSET, (IN_DMA_INT_DISABLE)); // mode_in bit = OUT 
        WriteIndexedReg(pContext, dwEndpoint, OUT_CSR1_REG_OFFSET, (FLUSH_OUT_FIFO | OUT_CLR_DATA_TOGGLE));
        WriteIndexedReg(pContext, dwEndpoint,  OUT_CSR2_REG_OFFSET, OUT_DMA_INT_DISABLE);

        if(peps->fInitialized){
            // Set the Mode_In, ISO and other Modality type bits back to the way it was - this allows 
            // ResetEndpoint to be called without having to re-init the endpoint.
            WriteIndexedReg(pContext, dwEndpoint, IN_CSR2_REG_OFFSET, bRegIn);
            WriteIndexedReg(pContext, dwEndpoint, IN_CSR2_REG_OFFSET, bRegOut);
        }
    }
    else {
        DEBUGCHK(FALSE);
    }
    
    // Clear any outstanding Interrupts
    // Note that Endpoint 0 WILL NOT BE DISABLED
    DisableEndpointInterrupt(pContext, peps->dwEndPointNumber);

    FUNCTION_LEAVE_MSG();
}



// Reset the device and EP0.
static
VOID
ResetDevice(
            PCTRLR_PDD_CONTEXT pContext
            )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    DEBUGCHK(IS_VALID_SC2440_CONTEXT(pContext));

    // Disable Device  interrupts - write Zeros to Disable
    WriteReg(pContext, USB_INT_EN_REG_OFFSET, 0 );

    // Disable endpoint interrupts - write Zeros to Disable
    WriteReg(pContext, EP_INT_EN_REG_OFFSET, 0);

    // Clear any outstanding device & endpoint interrupts
    // USB Device Interrupt Status - Write a '1' to Clear 
    WriteReg(pContext, USB_INT_REG_OFFSET, 
        (USB_RESET_INTR | USB_RESUME_INTR | USB_SUSPEND_INTR));
    // End point Interrupt Status - Write a '1' to Clear
    WriteReg(pContext, EP_INT_REG_OFFSET, CLEAR_ALL_EP_INTRS);

    // Reset all endpoints
    for (DWORD dwEpIdx = 0; dwEpIdx < ENDPOINT_COUNT; ++dwEpIdx) {
        EP_STATUS *peps = GetEpStatus(pContext, dwEpIdx);
        ResetEndpoint(pContext, peps);
    }

    FUNCTION_LEAVE_MSG();
}


static
VOID
CompleteTransfer(
                 PCTRLR_PDD_CONTEXT pContext,
                 PEP_STATUS peps,
                 DWORD dwUsbError
                 )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    PSTransfer pTransfer = peps->pTransfer;
    peps->pTransfer = NULL;

    pTransfer->dwUsbError = dwUsbError;
    pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_TRANSFER_COMPLETE, 
        (DWORD) pTransfer);

    FUNCTION_LEAVE_MSG();
}


#ifdef DEBUG
static
VOID
ValidateTransferDirection(
                          PCTRLR_PDD_CONTEXT pContext,
                          PEP_STATUS peps,
                          PSTransfer pTransfer
                          )
{
    DEBUGCHK(pContext);
    PREFAST_DEBUGCHK(peps);
    PREFAST_DEBUGCHK(pTransfer);

    if (peps->dwEndPointNumber != 0) {
        DEBUGCHK(peps->dwDirectionAssigned == pTransfer->dwFlags);
    }
}
#else
#define ValidateTransferDirection(ptr1, ptr2, ptr3)
#endif


// Read data from an endpoint.
static
VOID
HandleRx(
         PCTRLR_PDD_CONTEXT       pContext,
         PEP_STATUS peps
         )
{
    DWORD dwBytesRead = 0;
    BOOL fCompleted = FALSE;
    DWORD dwStatus = ERROR_GEN_FAILURE;
    DWORD dwEndpoint = peps->dwEndPointNumber;

    SETFNAME();

    PSTransfer pTransfer = peps->pTransfer;

    pTransfer = peps->pTransfer;
    if (pTransfer) {
        FUNCTION_ENTER_MSG();

        DEBUGCHK(pTransfer->dwFlags == USB_OUT_TRANSFER);
        DEBUGCHK(pTransfer->dwUsbError == UFN_NOT_COMPLETE_ERROR);

        ValidateTransferDirection(pContext, peps, pTransfer);

        DEBUGCHK(peps->fInitialized);

        DWORD cbToRead = 0;
        volatile ULONG *pulFifoReg = _GetDataRegister(dwEndpoint);
        DEBUGCHK(pulFifoReg != NULL);

        DWORD dwCurrentPermissions = GetCurrentPermissions();
        SetProcPermissions(pTransfer->dwCallerPermissions);

        __try {
            PBYTE  pbBuffer =  (PBYTE)pTransfer->pvBuffer + pTransfer->cbTransferred;
            PUSB_DEVICE_REQUEST udr = (PUSB_DEVICE_REQUEST) pbBuffer;

            DWORD  cbBuffer = pTransfer->cbBuffer - pTransfer->cbTransferred;
            DWORD  cbRead =0;
            DWORD cbFifo = ReadIndexedReg(pContext, dwEndpoint, OUT_FIFO_CNT1_REG_OFFSET);

            // Read From  the FIFO
            dwBytesRead = 0;
            cbToRead = min(cbFifo, cbBuffer);
            for (dwBytesRead = 0; dwBytesRead < cbToRead ; dwBytesRead++) {
                pbBuffer [dwBytesRead] = (UCHAR) *pulFifoReg;
            }
            
            if(dwBytesRead < peps->dwPacketSizeAssigned) {
                // This is a short packet check to signal end of transfer
                fCompleted = TRUE;
                dwStatus = UFN_NO_ERROR;
            }

            cbRead = dwBytesRead;
            DEBUGCHK(cbRead <= pTransfer->cbBuffer - pTransfer->cbTransferred);
            pTransfer->cbTransferred += cbRead;

            if (pTransfer->cbTransferred == pTransfer->cbBuffer) {
                fCompleted = TRUE;
                dwStatus = UFN_NO_ERROR;
            }
            if (dwEndpoint != 0) {

                //Clear Receive Packet Complete - Allow next packet to come in.  
                BYTE bEpIrqStat = ReadIndexedReg(pContext, peps->dwEndPointNumber,OUT_CSR1_REG_OFFSET);
                if (bEpIrqStat & OUT_PACKET_READY) {
                    SetClearIndexedReg(pContext,dwEndpoint,OUT_CSR1_REG_OFFSET,
                        OUT_PACKET_READY, CLEAR);
                }
            }
        }
        __except(EXCEPTION_EXECUTE_HANDLER) {
            DEBUGMSG(ZONE_ERROR, (_T("%s Exception!\r\n"), pszFname));
            fCompleted = TRUE;
            dwStatus = UFN_CLIENT_BUFFER_ERROR;
        }

        SetProcPermissions(dwCurrentPermissions);
    }   
    else {
        goto EXIT;
    }
    
    DEBUGMSG(ZONE_RECEIVE, (_T("%s Rx Ep%x BufferSize=%u,Xfrd=%u \r\n"), 
        pszFname, dwEndpoint, pTransfer->cbBuffer, pTransfer->cbTransferred));

    if (fCompleted) {
        // Disable transfer interrupts until another transfer is issued.
        if (peps->dwEndPointNumber != 0) {
            ClearEndpointInterrupt(pContext, peps->dwEndPointNumber);
            DisableEndpointInterrupt(pContext, peps->dwEndPointNumber);
        }
        
        CompleteTransfer(pContext, peps, dwStatus);
        DEBUGMSG(ZONE_RECEIVE, (_T("%s RxDone Ep%x BufferSize=%u,Xfrd=%u \r\n"), 
            pszFname, dwEndpoint,pTransfer->cbBuffer, pTransfer->cbTransferred));
    }

EXIT:
    FUNCTION_LEAVE_MSG();
}


// Write data to an endpoint.
static VOID
HandleTx(
         PCTRLR_PDD_CONTEXT       pContext,
         PEP_STATUS peps,
         BOOL fEnableInterrupts
         )
{
    SETFNAME();
    DEBUGCHK(pContext);
    PREFAST_DEBUGCHK(peps);

    // This routine can be entered from both ISTMain and MDD/Client threads so
    // need critical section.

    FUNCTION_ENTER_MSG();

    BOOL fCompleted = FALSE;
    PSTransfer pTransfer = peps->pTransfer;
    DWORD dwStatus = ERROR_GEN_FAILURE;
    DEBUGCHK(peps->fInitialized);
    DWORD dwEndpoint = peps->dwEndPointNumber;

    pTransfer = peps->pTransfer;
    if (pTransfer) {
        ValidateTransferDirection(pContext, peps, pTransfer);

        DEBUGCHK(pTransfer->dwFlags == USB_IN_TRANSFER);
        DEBUGCHK(pTransfer->dwUsbError == UFN_NOT_COMPLETE_ERROR);

        DWORD dwCurrentPermissions = GetCurrentPermissions();
        SetProcPermissions(pTransfer->dwCallerPermissions);

        // Transfer is ready
        __try {
            PBYTE pbBuffer = (PBYTE) pTransfer->pvBuffer + pTransfer->cbTransferred;
            DWORD cbBuffer = pTransfer->cbBuffer - pTransfer->cbTransferred;

            volatile ULONG *pulFifoReg = _GetDataRegister(dwEndpoint);
            BYTE bValToWrite = 0;

            DWORD cbWritten = 0;

            // Min of input byte count and supported size
            DWORD cbToWrite = min(cbBuffer, peps->dwPacketSizeAssigned);
            BYTE bRegStatus = ReadIndexedReg(pContext, dwEndpoint, 
                IN_CSR1_REG_OFFSET);

            if (dwEndpoint == 0) {
                for (cbWritten = 0; cbWritten < cbToWrite; cbWritten++) {
                    *pulFifoReg = (ULONG)*pbBuffer++;
                }

                /* We can complete on a packet which is full. We need to wait till
                * next time and generate a zero length packet, so only complete
                * if we're at the end and it is not the max packet size.
                */
                pTransfer->cbTransferred += cbWritten;
                if (pTransfer->cbTransferred == pTransfer->cbBuffer) {
                    dwStatus = UFN_NO_ERROR;

                    if(cbWritten != peps->dwPacketSizeAssigned){
                        fCompleted = TRUE;
                        peps->dwEpState = EP_STATE_IDLE;
                        bValToWrite |= DATA_END;
                    }

                }
                /* Update the register - Set the IPR bit
                and possibly data end*/
                if( (cbWritten >0) || (pTransfer->cbBuffer == 0) ) {
                    bValToWrite |= EP0_IN_PACKET_RDY;
                }
                // Also set IPR if a 0 byte packet needs to go out.
                else if( (pTransfer->cbTransferred == pTransfer->cbBuffer) &&
                         (pTransfer->cbBuffer % peps->dwPacketSizeAssigned == 0) ) {
                    bValToWrite |= EP0_IN_PACKET_RDY;
                }
                
                SetClearIndexedReg(pContext, dwEndpoint,
                    IN_CSR1_REG_OFFSET, bValToWrite, SET);
            }
            else if (dwEndpoint < ENDPOINT_COUNT) {
                DEBUGMSG(ZONE_SEND, (_T("%s Tx on EP %u , Bytes = %u\r\n"), 
                    pszFname, dwEndpoint,cbToWrite));

                // Enable Interrupts before writing to the FIFO. This insures
                // That any interrupts generated because of the write will be
                // "latched"
                if (fEnableInterrupts) 
                    EnableEndpointInterrupt(pContext,dwEndpoint);

                // Write to the FIFO directly to send the bytes.
                for (cbWritten = 0; cbWritten < cbToWrite; cbWritten++) {
                    *pulFifoReg = (ULONG) *pbBuffer++;
                }

                // By Placing the check for packet complete here, before
                // cbTransferred is updated, there is a 1 interrupt cycle delay
                // That is complete is not declared until the data has actually
                // been ACKd (TPC set) by the host
                if ( (pTransfer->cbTransferred == pTransfer->cbBuffer) || 
                     (cbWritten == 0) ){
                    fCompleted = TRUE;
                    dwStatus = UFN_NO_ERROR;
                }
                else {
                    /* Set In Packet Ready , this will Tells the HW the FIFO is 
                    ready to be transitted to be sent
                    */
                    SetClearIndexedReg(pContext, dwEndpoint,
                        IN_CSR1_REG_OFFSET, IN_PACKET_READY, SET);
                }
                
                // Update the Transfered Count
                pTransfer->cbTransferred += cbWritten;
            }
        }
        __except(EXCEPTION_EXECUTE_HANDLER) {
            DEBUGMSG(ZONE_ERROR, (_T("%s Exception!\r\n"), pszFname));
            fCompleted = TRUE;
            dwStatus = UFN_CLIENT_BUFFER_ERROR;
        }

        SetProcPermissions(dwCurrentPermissions);
    }   
    else {
        // It is possible for an interrupt to come in while still in this 
        // function for first pass of transfer. If this happens it is possible
        // to complete the transfer and have that interrupt be unnecessary

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -