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

📄 sc2440pdd.cpp

📁 基于WinCE5.0平台的三星S3C2440的BSP包更新.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
                       )
{    
    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_PKT_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, OUT_CSR2_REG_OFFSET, bRegOut);
        }

        // Clear and disable interrupt
        WriteReg(pContext, EP_INT_REG_OFFSET, EpToIrqStatBit(peps->dwEndpointNumber));
        DisableEndpointInterrupt(pContext, peps->dwEndpointNumber);
    }
    else {
        DEBUGCHK(FALSE);
    }

    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
BYTE
HandleRx(
         PCTRLR_PDD_CONTEXT       pContext,
         PEP_STATUS peps,
         PBOOL pfCompleted,
         PDWORD pdwStatus
         )
{
    BOOL fCompleted = FALSE;
    DWORD dwStatus = ERROR_GEN_FAILURE;
    DWORD dwEndpoint = peps->dwEndpointNumber;
    BYTE bRet = 0;

    SETFNAME();
    FUNCTION_ENTER_MSG();

    PSTransfer pTransfer = peps->pTransfer;

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

        ValidateTransferDirection(pContext, peps, pTransfer);

        DEBUGCHK(peps->fInitialized);

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

        __try {
            volatile ULONG *pulFifoReg = _GetDataRegister(dwEndpoint);
            DEBUGCHK(pulFifoReg != NULL);
            
            PBYTE  pbBuffer =  (PBYTE)pTransfer->pvBuffer + pTransfer->cbTransferred;

            DWORD cbBuffer = pTransfer->cbBuffer - pTransfer->cbTransferred;
            DWORD cbFifo = ReadIndexedReg(pContext, dwEndpoint, OUT_FIFO_CNT1_REG_OFFSET);
            DEBUGCHK(cbFifo <= peps->dwPacketSizeAssigned);

            // Read from the FIFO
            const DWORD cbRead = min(cbFifo, cbBuffer);
            DWORD cbToRead = cbRead;
            while (cbToRead--) {
                *pbBuffer++ = (BYTE) *pulFifoReg;
            }

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

            if ( (cbRead < peps->dwPacketSizeAssigned) ||
                 (pTransfer->cbTransferred == pTransfer->cbBuffer) ) {
                // Short packet or filled buffer. Complete transfer.
                fCompleted = TRUE;
                dwStatus = UFN_NO_ERROR;
            }

            if (dwEndpoint == 0) {
                bRet |= SERVICED_OUT_PKT_RDY;

                if (fCompleted) {
                    bRet |= DATA_END;
                    pContext->Ep0State = EP0_STATE_IDLE;
                }
            }
            else {
                // Clear Out Packet Ready - Allow next packet to come in.
                DEBUGCHK( (bRet & OUT_PACKET_READY) == 0);
            }
        }
        __except(EXCEPTION_EXECUTE_HANDLER) {
            DEBUGMSG(ZONE_ERROR, (_T("%s Exception!\r\n"), pszFname));
            fCompleted = TRUE;
            dwStatus = UFN_CLIENT_BUFFER_ERROR;
        }

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

        if (fCompleted) {
            DEBUGMSG(ZONE_RECEIVE, (_T("%s RxDone Ep%x BufferSize=%u, Xfrd=%u\r\n"), 
                pszFname, dwEndpoint,pTransfer->cbBuffer, pTransfer->cbTransferred));
        }
    }

    *pfCompleted = fCompleted;
    *pdwStatus = dwStatus;
    FUNCTION_LEAVE_MSG();

    return bRet;
}


// Write data to an endpoint.
static 
BYTE
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();

    BYTE bRet = 0;

    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);

            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);

            DEBUGMSG(ZONE_SEND, (_T("%s Tx on EP %u, Bytes = %u\r\n"), 
                pszFname, dwEndpoint, cbToWrite));

            if (dwEndpoint == 0) {
                for (cbWritten = 0; cbWritten < cbToWrite; cbWritten++) {
                    *pulFifoReg = *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 && pTransfer->pvPddData == 0) {
                    dwStatus = UFN_NO_ERROR;
                    fCompleted = TRUE;
                    pContext->Ep0State = EP0_STATE_IDLE;
                    bRet |= DATA_END;
                }
                
                /* Update the register - Set the IPR bit
                and possibly data end*/
                if( (cbWritten > 0) || (pTransfer->cbBuffer == 0) ) {
                    bRet |= EP0_IN_PACKET_RDY;
                }
                // Also set IPR if a 0 byte packet needs to go out.
                else if(pTransfer->pvPddData) {
                    bRet |= EP0_IN_PACKET_RDY;
                    pTransfer->pvPddData = 0;
                }
            }
            else {
                // Enable Interrupts before writing to the FIFO. This insures
                // That any interrupts generated because of the write will be
                // "latched"
                if (fEnableInterrupts) {
                    DEBUGCHK(dwEndpoint != 0);
                    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
                    */
                    bRet |= IN_PACKET_READY;
                }
                
                // 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
        // so... just ignore it.
        goto EXIT;
    }

    if (fCompleted) {
        // Disable transfer interrupts until another transfer is issued.
        if (peps->dwEndpointNumber != 0) {
            DisableEndpointInterrupt(pContext, peps->dwEndpointNumber);
        }

        DEBUGMSG(ZONE_SEND, (_T("%s Tx Done  Ep%x  Status %u\r\n"), pszFname, 
            dwEndpoint, dwStatus));
        CompleteTransfer(pContext, peps, dwStatus);
    }
    else {
        DEBUGMSG(ZONE_SEND, (_T("%s Tx EP%x BufferSize=%u, Xfrd=%u\r\n"), 
            pszFname, dwEndpoint, pTransfer->cbBuffer, pTransfer->cbTransferred));
    }

EXIT:
    FUNCTION_LEAVE_MSG();

    return bRet;
}


static
VOID
HandleEndpoint0Event(
                    PCTRLR_PDD_CONTEXT  pContext
                    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    ValidateContext(pContext);
    DEBUGCHK(pContext->fRunning);

    PEP_STATUS peps = GetEpStatus(pContext, 0);
    LOCK_ENDPOINT(peps);

    ClearEndpointInterrupt(pContext, 0);
    BYTE bEP0IrqStatus = ReadIndexedReg(pContext, 0, EP0_CSR_REG_OFFSET);

    DEBUGMSG(ZONE_USB_EVENTS, (_T("%s EP0_CSR_REG = 0x%02x. Data phase = %u\r\n"), 
        pszFname, bEP0IrqStatus, pContext->Ep0State));

⌨️ 快捷键说明

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