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

📄 trans.cpp

📁 Microsoft WinCE 6.0 BSP FINAL release source code for use with the i.MX27ADS TO2 WCE600_FINAL_MX27_S
💻 CPP
📖 第 1 页 / 共 4 页
字号:
}

//***********************************************************************************************
CSITransfer::~CSITransfer()
//
// Purpose: De-constructor for CSITransfer (Class for Full/Low Speed isochronous transfer)
//
// Parameters: 
//
// Returns: Nothing
//
// Notes: 
//**************************************************************************************************
{
    ASSERT(m_dwSchedTDIndex==m_dwNumOfTD);
    ASSERT(m_dwDequeuedTDIndex ==  m_dwNumOfTD);
    if (m_pCSITDList && m_dwNumOfTD) {
        AbortTransfer();
        for (DWORD dwIndex=0;dwIndex<m_dwNumOfTD;dwIndex++)
            if (*(m_pCSITDList + dwIndex)) {
                ASSERT((*(m_pCSITDList + dwIndex) )->GetLinkValid() != TRUE); // Invalid Next Link
                GetPipe()->FreeCSITD(*(m_pCSITDList + dwIndex));
                *(m_pCSITDList + dwIndex) = NULL;
            }
        delete m_pCSITDList;
    }
}

//****************************************************************************************
BOOL CSITransfer::ArmTD()
//
// Purpose: Arm/schedule the transfer descriptor - this is to setup the transfer descriptor
//          and perform the IssueTransfer on the iTD to do the actual transfer. Called by
//          AddTransfer()
//
// Parameters: 
//
// Returns: TRUE - something has to be scheduled/armed
//          FALSE - nothing
//
// Notes:
// ******************************************************************
{
    BOOL bAnyArmed = FALSE;
    if (m_pCSITDList && m_dwArmedTDIndex<m_dwNumOfTD ) { // Something TD wait for Arm.
        DWORD dwCurDataPhysAddr =   m_sTransfer.paBuffer + m_dwArmedBufferIndex ;
        CSITD * pPrevCSITD= (m_dwArmedTDIndex==0?NULL:*(m_pCSITDList + m_dwArmedTDIndex-1));
        while( m_dwArmedTDIndex < m_dwNumOfTD) {
            DWORD dwLength=  *(m_sTransfer.aLengths + m_dwArmedTDIndex);
            *(m_pCSITDList + m_dwArmedTDIndex) = GetPipe()->AllocateCSITD( this,pPrevCSITD);
            if (*(m_pCSITDList + m_dwArmedTDIndex) == NULL) {
                break;
            }
            else {
                pPrevCSITD = *(m_pCSITDList + m_dwArmedTDIndex);
                BOOL bReturn=(*(m_pCSITDList + m_dwArmedTDIndex))->IssueTransfer(dwCurDataPhysAddr,dwCurDataPhysAddr+ dwLength -1, dwLength,
                    TRUE,// Interrupt On Completion
                    (m_sTransfer.dwFlags & USB_IN_TRANSFER)!=0);
                ASSERT(bReturn == TRUE);
                // Interrupt on any CITD completion
                (*(m_pCSITDList+ m_dwArmedTDIndex))->SetIOC(TRUE);
                dwCurDataPhysAddr += dwLength;
                m_dwArmedBufferIndex +=dwLength;
                m_dwArmedTDIndex ++ ;
                bAnyArmed = TRUE;
            }
        }
        
    }
    return bAnyArmed;
}

//****************************************************************************************
BOOL CSITransfer::AddTransfer() 
//
// Purpose: Setup all the queue transfer descriptor list and called up ArmTD to do the transfer
//
// Parameters: None
//
// Returns: TRUE - success, FALSE - failure
//
// Notes:
// ******************************************************************
{
    DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("CSITransfer::AddTransfer (this=0x%x,id=0x%xm_dwFrameIndexStart=%x)\r\n"),this,m_dwTransferID,m_dwFrameIndexStart));
    if (m_dwNumOfTD!=0 || m_pCSITDList != NULL) {
        ASSERT(FALSE);
        return FALSE;
    }
    m_dwNumOfTD = m_sTransfer.dwFrames ;
    m_dwSchedTDIndex=0;
    m_dwArmedTDIndex =0;
    m_dwArmedBufferIndex=0;
    m_dwFirstError =  USB_NO_ERROR;
    if (m_sTransfer.lpvBuffer &&  m_sTransfer.paBuffer && m_sTransfer.dwBufferSize) {
        // Allocate space for CITD List
        m_pCSITDList = (CSITD **)new PVOID[m_dwNumOfTD];
        if (m_pCSITDList!=NULL) {
            memset(m_pCSITDList,0,sizeof(CSITD *)*m_dwNumOfTD);
            ArmTD();
            return TRUE;
        }
    }
    ASSERT(FALSE);
    return FALSE;
}

//******************************************************************************************************
BOOL CSITransfer::ScheduleTD(DWORD dwCurFrameIndex,DWORD /*dwCurMicroFrameIndex*/)
//
// Purpose: Schedule a USB Transfer on this pipe, this is used by AbortTransfer only.
//
// Parameters: dwCurrFrameIndex - current frame index
//
// Returns: requestOK if transfer issued ok, else requestFailed
//
// Notes: 
//******************************************************************************************************
{
    DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("CSITransfer::ScheduleTD (this=0x%x,id=0x%x,curFrameIndex=0x%x,m_dwFrameIndexStart=0x%x)\r\n"),this,m_dwTransferID, dwCurFrameIndex,m_dwFrameIndexStart));
    BOOL bReturn = FALSE;
    ArmTD();
    if (m_dwSchedTDIndex < m_dwNumOfTD && m_pCSITDList !=0 && m_pCEhcd) {
        if ((long)(dwCurFrameIndex - m_dwFrameIndexStart) > (long)m_dwSchedTDIndex) {
            m_dwSchedTDIndex = dwCurFrameIndex - m_dwFrameIndexStart;
        }
        m_dwSchedTDIndex = min( m_dwSchedTDIndex , m_dwNumOfTD);
        
        DWORD EndShedTDIndex = dwCurFrameIndex +  (m_pCEhcd->GetPeriodicMgr()).GetFrameSize()-1;
        DWORD dwNumTDCanSched;
        if ( (long)(EndShedTDIndex - m_dwFrameIndexStart ) >= 0)
            dwNumTDCanSched =EndShedTDIndex - m_dwFrameIndexStart ;
        else  // Too Early.
            dwNumTDCanSched = 0;
        dwNumTDCanSched= min(m_dwNumOfTD ,dwNumTDCanSched);        
        dwNumTDCanSched= min(m_dwArmedTDIndex ,dwNumTDCanSched);
        
        if (m_dwSchedTDIndex < dwNumTDCanSched) { // Do scudule those index.
            for (DWORD dwIndex = m_dwSchedTDIndex ; dwIndex<dwNumTDCanSched; dwIndex++) {
                m_pCEhcd->PeriodQueueSITD(*(m_pCSITDList+dwIndex),m_dwFrameIndexStart + dwIndex );
                (*(m_pCSITDList+dwIndex))->CheckStructure ();
                ASSERT((*(m_pCSITDList+dwIndex))->m_pTrans == this);
            }
            m_dwSchedTDIndex = dwNumTDCanSched;
            bReturn = TRUE;
        }
    }
    DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("CITransfer::ScheduleTD (this=0x%x) return %d\r\n"),this,bReturn));
    return bReturn;
}
//***************************************************************************************
BOOL CSITransfer::IsTransferDone(DWORD dwCurFrameIndex,DWORD /*dwCurMicroFrameIndex*/)
//
// Purpose: This is to check if the transfer has been completed for Isochronous High Speed Transfer
//
// Parameters: dwCurFrameIndex - minimal frame index to which the transfer to check against if completed.
//
// Returns: TRUE - successfully tranferred, FALSE - failure
//
// Notes: 
//****************************************************************************************

{
    DWORD dwCount = 0;
    // Dequeue those TD has Transfered.
    m_dwLastFrameIndex = dwCurFrameIndex - m_dwFrameIndexStart;
    if ((long)(dwCurFrameIndex - m_dwFrameIndexStart)>= 1 ) {
        DWORD dwTransfered = min(dwCurFrameIndex - m_dwFrameIndexStart , m_dwSchedTDIndex);
        ASSERT(m_dwSchedTDIndex<=m_dwArmedTDIndex);
        for (DWORD dwIndex=m_dwDequeuedTDIndex;dwIndex<dwTransfered && dwIndex < m_dwNumOfTD ; dwIndex++) {
            dwCount = 0;
DO_RECHECK:
            if ( *(m_pCSITDList+dwIndex) != NULL && (*(m_pCSITDList + dwIndex) )->GetLinkValid()) {
                (*(m_pCSITDList+dwIndex))->CheckStructure ();
                ASSERT((*(m_pCSITDList+dwIndex))->m_pTrans == this);
                m_pCEhcd->PeriodDeQueueTD((*(m_pCSITDList+dwIndex))->GetPhysAddr(),dwIndex + m_dwFrameIndexStart);
                (*(m_pCSITDList + dwIndex) )->SetLinkValid(FALSE);
                
            }
            if (*(m_pCSITDList + dwIndex)!=NULL) {
                DWORD dwTDError = USB_NO_ERROR;
                (*(m_pCSITDList+dwIndex))->CheckStructure ();
                if ((*(m_pCSITDList +dwIndex))->sITD_TransferState.sITD_TSContext.Active!=0) 
                {
                    dwTDError = USB_NOT_COMPLETE_ERROR;
                    // Do a 50 msec check
                    if (dwCount++ < 25)
                    {
                        Sleep(2);
                        goto DO_RECHECK;                    
                    }
                }
                else
                if ((*(m_pCSITDList + dwIndex))->sITD_TransferState.sITD_TSContext.XactErr!=0) 
                    dwTDError = USB_ISOCH_ERROR;
                else
                if ((*(m_pCSITDList + dwIndex))->sITD_TransferState.sITD_TSContext.BabbleDetected!=0) 
                    dwTDError = USB_STALL_ERROR;
                else
                if ((*(m_pCSITDList + dwIndex))->sITD_TransferState.sITD_TSContext.DataBufferError!=0) 
                    dwTDError = ((m_sTransfer.dwFlags & USB_IN_TRANSFER)!=0?USB_DATA_OVERRUN_ERROR:USB_DATA_UNDERRUN_ERROR);
                else 
                if (((*(m_pCSITDList + dwIndex))->sITD_TransferState.dwSITD_TransferState & 0xff)!=0 )
                    dwTDError = USB_BIT_STUFFING_ERROR;
                
                if (m_dwFirstError == USB_NO_ERROR   ) { // only update first time
                    m_dwFirstError = dwTDError;
                }
                if (dwTDError!= USB_NO_ERROR) {
                    DEBUGMSG( ZONE_TRANSFER , (TEXT("CITransfer::DoneTransfer (this=0x%x, dwFrameIndex=%d) Error(%d) \r\n"),
                        this,dwIndex, dwTDError));
                }
                if (dwIndex< m_sTransfer.dwFrames) {
#pragma prefast(disable: 322, "Recover gracefully from hardware failure")
                    __try { // setting isoch OUT status parameters
                        m_sTransfer.adwIsochErrors[ dwIndex] = dwTDError;
                        m_sTransfer.adwIsochLengths[ dwIndex ] = *(m_sTransfer.aLengths + dwIndex) - (*(m_pCSITDList + dwIndex))->sITD_TransferState.sITD_TSContext.BytesToTransfer;
                        m_DataTransferred += m_sTransfer.adwIsochLengths[ dwIndex ];
                    } __except( EXCEPTION_EXECUTE_HANDLER ) {
                    }
#pragma prefast(pop)
                }

                GetPipe()->FreeCSITD(*(m_pCSITDList + dwIndex));
                *(m_pCSITDList + dwIndex) = NULL;
            }
        }
        m_dwDequeuedTDIndex = dwIndex;
    }
    BOOL bReturn= ((long)(dwCurFrameIndex-m_dwFrameIndexStart)>=(long)m_dwNumOfTD);
    DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("CITransfer:::IsTransferDone (this=0x%x,curFrameIndex=0x%x) return %d \r\n"),this, dwCurFrameIndex,bReturn));
    return bReturn;
}

//*******************************************************************
BOOL CSITransfer::AbortTransfer()
//
// Purpose: Abort the current transfer
//
// Parameters: None
//
// Returns: TRUE - success, FALSE - failure
//
// Notes:
// ******************************************************************
{
    for (DWORD dwIndex=m_dwDequeuedTDIndex;dwIndex < m_dwNumOfTD && dwIndex<m_dwSchedTDIndex ; dwIndex++) {
        if ( *(m_pCSITDList+dwIndex) != NULL ) {
            BOOL bResult =m_pCEhcd->PeriodDeQueueTD((*(m_pCSITDList+dwIndex))->GetPhysAddr(),dwIndex + m_dwFrameIndexStart);
            ASSERT(bResult == TRUE);
            (*(m_pCSITDList + dwIndex) )->SetLinkValid(FALSE);
            
            if (dwIndex< m_sTransfer.dwFrames) {
#pragma prefast(disable: 322, "Recover gracefully from hardware failure")
                __try { // setting isoch OUT status parameters
                    m_sTransfer.adwIsochErrors[ dwIndex] = USB_NOT_COMPLETE_ERROR;
                    m_sTransfer.adwIsochLengths[ dwIndex ] = 0;
                } __except( EXCEPTION_EXECUTE_HANDLER ) {
                }
#pragma prefast(pop)
            }
            if (m_dwFirstError == USB_NO_ERROR   ) { // only update first time
                m_dwFirstError = USB_NOT_COMPLETE_ERROR;
            }
            GetPipe()->FreeCSITD(*(m_pCSITDList + dwIndex));
            *(m_pCSITDList + dwIndex) = NULL;
        }
    }
    m_dwArmedTDIndex = m_dwDequeuedTDIndex = m_dwSchedTDIndex = m_dwNumOfTD;
    Sleep(2); // Make Sure EHCI nolong reference to those TD;
    return DoneTransfer(m_dwFrameIndexStart+m_dwNumOfTD, 0);
};

//******************************************************************************
BOOL CSITransfer::DoneTransfer(DWORD dwCurFrameIndex,DWORD dwCurMicroFrameIndex)
//
// Purpose: Check if transfer is done and success, acknowledge back into MDD
//
// Parameters: 
//
// Returns: TRUE - success, FALSE - failure
//
// Notes:
// ******************************************************************
{
    BOOL bIsTransDone = IsTransferDone(dwCurFrameIndex, dwCurMicroFrameIndex);
    DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, 
            (TEXT("CITransfer::DoneTransfer (this=0x%x,id=0x%x,curFrameIndex=0x%x, bIsTransDone=%d \r\n")
        ,this,m_dwTransferID, dwCurFrameIndex,bIsTransDone));
    ASSERT(bIsTransDone == TRUE);
    if (bIsTransDone && !m_fDoneTransferCalled) {
        m_fDoneTransferCalled = TRUE;
        // We have to update the buffer when this is IN Transfer.
        if ((m_sTransfer.dwFlags & USB_IN_TRANSFER)!=NULL && m_pAllocatedForClient!=NULL) {
            __try { // copying client buffer for OUT transfer
                memcpy( m_sTransfer.lpvBuffer, m_pAllocatedForClient, m_sTransfer.dwBufferSize );
            } __except( EXCEPTION_EXECUTE_HANDLER ) {
                  // bad lpvBuffer.
                if (m_dwFirstError == USB_NO_ERROR)
                    m_dwFirstError = USB_CLIENT_BUFFER_ERROR;
            }
        }
#pragma prefast(disable: 322, "Recover gracefully from hardware failure")
        __try { // setting transfer status and executing callback function
            if (m_sTransfer.lpfComplete !=NULL)
                *m_sTransfer.lpfComplete = TRUE;
            if (m_sTransfer.lpdwError!=NULL)
                *m_sTransfer.lpdwError = m_dwFirstError;
            if (m_sTransfer.lpdwBytesTransferred)
                *m_sTransfer.lpdwBytesTransferred =  m_DataTransferred;            
            if ( m_sTransfer.lpStartAddress ) {
                ( *m_sTransfer.lpStartAddress )(m_sTransfer.lpvNotifyParameter );
                m_sTransfer.lpStartAddress = NULL ; // Make sure only do once.
            }
        } __except( EXCEPTION_EXECUTE_HANDLER ) {
        }
#pragma prefast(pop)
        return (m_dwFirstError==USB_NO_ERROR);
    }
    else
        return TRUE;

}



⌨️ 快捷键说明

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