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

📄 ep931xide.cpp

📁 CIRRUS 公司EP93XX系列CPU的WINCE下的BSP
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    BOOL    fRet = TRUE;
    DWORD   dwRet;

    // 
    // Wait for the IDE interrupt.  If it doesn't occur, timeout.
    //
    dwRet = WaitForSingleObject( m_pPort->m_hIdeIntEvent, dwTimeOut);


    //
    // If we are currently using DMA, switch to PIO mode to read the
    // registers.
    //
    m_pPort->PIOMode();

    if (dwRet == WAIT_TIMEOUT ) 
    {
        fRet = FALSE;
    } 
    else if (dwRet != WAIT_OBJECT_0 && dwTimeOut >0) 
    {
        //
        // This case is for if we don't use the interrupt. 
        // Not applicable for us.
        //
        if (!WaitForDisc( WAIT_TYPE_DRQ,  dwTimeOut, 10)) 
        {
            fRet = FALSE;
        }   
    }

    //
    // Ack interrupt!!!!!
    //
    bStatus = GetBaseStatus();
    
    if (bStatus & ATA_STATUS_ERROR  ) 
    {
        DEBUGMSG( ZONE_WARNING, (TEXT("CEP931xDisk::WaitforInterrupt bStatus = 0x%02x\n"), (ULONG) bStatus));
        bStatus = GetError();
        fRet = FALSE;
    }    

    //
    // Clear the IDE interrupt.
    //
    InterruptDone(SYSINTR_IDE);        

    return fRet;
} 


//****************************************************************************
// WaitForDMARQCleared
//****************************************************************************
// Wait for DMARQ to be cleared.
// 
//
BOOL WaitForDMARQCleared(ULONG ulTime)
{
    BOOL            bRet = TRUE;
    LARGE_INTEGER   liStart, liCurrent;
    ULONG           ulIdeCtrl;

    QueryPerformanceCounter(&liStart);
    for(;;)
    {
        QueryPerformanceCounter(&liCurrent);
        ulIdeCtrl = *IDE_CTRL;
        if(!(ulIdeCtrl & IDE_CTRL_DMARQ))
        {
            break;
        }
        if(ULONG(liCurrent.QuadPart - liStart.QuadPart) > ulTime)
        {
            bRet = FALSE;
        }
    }
    return bRet;   
}

//****************************************************************************
// CEP931xPort::WaitForDmaInterrupt
//****************************************************************************
// Waits for the IDE interrupt.  This is used for waiting in PIO mode.
//
// dwTimeOut - Time out in mS
// 
// Return      TRUE  - Success
//             FALSE - Failure
//          
ULONG CEP931xPort::WaitForDmaInterrupt(DWORD dwTimeOut)
{
    BYTE    bStatus;
    BOOL    fRet = TRUE;
    DWORD   dwWaitRet;
    ULONG   ulRet = DMAWAIT_NOERROR;
    // LARGE_INTEGER   liStart, liCurrent;
    // volatile register ULONG           ulIdeCtrl;
    // volatile register ULONG           ulDmaM2MInt;
    BOOL    b;


    b = QueryPerformanceCounter(&m_liTotalStart);

    // 
    // Wait for the IDE interrupt.  If it doesn't occur, timeout.
    //
    dwWaitRet = WaitForMultipleObjects( 2, m_hIstEvent, FALSE, dwTimeOut);
    b = QueryPerformanceCounter(&m_liTotalEnd);

    //
    // Both IDE and DMA interrupts never occured, report an error.
    //
    if (dwWaitRet == (WAIT_OBJECT_0 + DMA_EVENT))
    {
        #if 0
        if(m_bWaitForDMARQCleared)
        {
            dwWaitRet = WaitForDMARQCleared(10000)?WAIT_OBJECT_0:WAIT_TIMEOUT;
        }
        else
        {
            dwWaitRet = WaitForSingleObject(m_hIstEvent[IDE_EVENT], 10);

            //
            // If DMARQ is cleared the transfer occured successfully but
            // the interrupt never asserted.  Use DMARQ from now on.
            //
            ulIdeCtrl = *IDE_CTRL;
            if(!(ulIdeCtrl & IDE_CTRL_DMARQ))
            {
                m_bWaitForDMARQCleared = 1;
                dwWaitRet = WAIT_OBJECT_0;
            }

        }
        #endif // 0

        dwWaitRet = WaitForSingleObject(m_hIstEvent[IDE_EVENT], 10);
        
        if(dwWaitRet == WAIT_TIMEOUT)
        {
            //
            // The IDE interface is asking for more data.
            //
            DEBUGMSG
            ( 
                ZONE_DMA, 
                (TEXT("CEP931xPort::WaitForDmaInterrupt DMA transfer completed but IDE interface is requesting to recieve more data.\r\n"))
            );

            if(!m_fDMARead)
            {

                //
                // DMA Hardware Write bug #1
                //
                CleanUpDmaUDMAWrite();
                ulRet = DMAWAIT_ERROR_WRITE_1;
                DEBUGMSG
                ( 
                    ZONE_DMA, 
                    (TEXT("CEP931xPort::WaitForDmaInterrupt Hit DMA Write Bug #1.\r\n"))
                );
            }
            else
            {
                ulRet = DMAWAIT_ERROR;
            }
        }

    }
    else if (dwWaitRet == (WAIT_OBJECT_0 + IDE_EVENT))
    {
        dwWaitRet = WaitForSingleObject(m_hIstEvent[DMA_EVENT], 10);
        if(dwWaitRet == WAIT_TIMEOUT)
        {
            //
            // The DMA interface is asking for more data.
            //
            DEBUGMSG
            ( 
                ZONE_DMA, 
                (TEXT("CEP931xPort::WaitForDmaInterrupt IDE transfer completed but DMA is requesting to send more data.\r\n"))
            );

            if(!m_fDMARead)
            {
                DEBUGMSG
                ( 
                    ZONE_DMA, 
                    (TEXT("CEP931xPort::WaitForDmaInterrupt Hit DMA Write Bug #2.\r\n"))
                );

                //
                // If we ever hit write bug #2 use pio mode since we cannot detect
                // write bug #2 all of the time.
                //
                // m_bForcePIO = TRUE;
                ulRet = DMAWAIT_ERROR_WRITE_2;

                // DumpDmaState();
                // DumpIDEState();
            }
            else
            {
                DEBUGMSG
                ( 
                    ZONE_DMA, 
                    (TEXT("CEP931xPort::WaitForDmaInterrupt Hit DMA Read Bug #1.\r\n"))
                );
                ulRet = DMAWAIT_ERROR_READ_1;
            }
        }
    }
    else

    {
        DEBUGMSG
        ( 
            ZONE_DMA, 
            (TEXT("CEP931xPort::WaitForDmaInterrupt Both IDE and DMA interrupts did not occur.\r\n"))
        );
        ulRet = DMAWAIT_ERROR;
    }
  

    //
    // Switch to PIO mode.
    // 
    PIOMode();

    DEBUGMSG
    ( 
        ZONE_DMA, 
        (
            TEXT("CEP931xPort::WaitForDmaInterrupt  Event = %d, IDE= %d DMA = %d.\r\n"),
            ULONG(m_liTotalEnd.QuadPart - m_liTotalStart.QuadPart),
            ULONG(m_liIdeEnd.QuadPart   - m_liIdeStart.QuadPart),
            ULONG(m_liDmaEnd.QuadPart   - m_liDmaStart.QuadPart)
        )            
    );    

    

    //
    // Ack interrupt!!!!!
    //
    // bStatus = GetBaseStatus();
    bStatus = (BYTE) ATAReadRegister(CSDA_STAT_REG) & 0xFF;
    

    //*************************************************************************
    // Seagate St340014A has DRQ asserted after the transfer has been completed
    // also DMARQ goes high after this read?
    //*************************************************************************
    if ((bStatus & ATA_STATUS_ERROR) /* || (bStatus & ATA_STATUS_DATA_REQ ) */ ) 
    {
        DEBUGMSG
        ( 
            ZONE_WARNING, 
            (
                TEXT("CEP931xPort::WaitForDmaInterrupt bStatus = 0x%04x\n"), 
                (ULONG) bStatus
            )
        );
        // bStatus = GetError();
        bStatus = (BYTE)ATAReadRegister(CSDA_ERROR_REG);
        if(ulRet == DMAWAIT_NOERROR)
        {
            ulRet = DMAWAIT_ERROR;
        }
    }    

    return ulRet;
}
//****************************************************************************
// CEP931xDisk::WaitForDmaInterrupt
//****************************************************************************
// Waits for the IDE interrupt.  This is used for waiting in PIO mode.
//
// dwTimeOut - Time out in mS
// 
// Return      TRUE  - Success
//             FALSE - Failure
//          
ULONG CEP931xDisk::WaitForDmaInterrupt(DWORD dwTimeOut)
{
    ULONG   ulRet;
    ulRet = m_pPort->WaitForDmaInterrupt(dwTimeOut);


    if(m_pPort->m_fDMARead)
    {
        m_DmaStatistics.ulDmaTotalRead++;
    }
    else
    {
        m_DmaStatistics.ulDmaTotalWrite++;
    }


    switch(ulRet)
    {
        case DMAWAIT_NOERROR:
            m_DmaStatistics.ulDmaNoError++;
            break;
        case DMAWAIT_ERROR:
            m_DmaStatistics.ulDmaOtherError++;
            break;
        case DMAWAIT_ERROR_WRITE_1:
            m_DmaStatistics.ulDmaWriteBug1++;
            break;
        case DMAWAIT_ERROR_WRITE_2:
            m_DmaStatistics.ulDmaWriteBug2++;
            break;
        case DMAWAIT_ERROR_READ_1:
            m_DmaStatistics.ulDmaReadBug1++;
            break;
        default:
            break;
    }
    return ulRet;

}

//****************************************************************************
// CEP931xDisk::EnableInterrupt
//****************************************************************************
// 
// 
//
void CEP931xDisk::EnableInterrupt()
{
    GetBaseStatus();// Ack interrupt!!!!!
    InterruptDone(SYSINTR_IDE);        
}

#define ATA_DMA_ULTRA_MODE      0x40
//****************************************************************************
// CEP931xDisk::SetBestTransferMode
//****************************************************************************
// Sets the Best Transfer mode based on the registry and the device 
// specifcations.
//
// m_dwBestUDmaMode Comes from the drive.
// m_ulBestUDmaModeReg Comes frm the registry.
// 
//
void CEP931xDisk::SetBestTransferMode()
{
    ULONG   ulMwDmaMode, ulUDmaMode;

    if ((m_dwBestPioMode != -1) && (m_dwBestPioMode >= 2)) 
    {
        SetTransferMode( (BYTE)m_dwBestPioMode | ATA_PIO_FCT_MODE);
    }    

    ulMwDmaMode = (int)m_ulBestMwDmaModeReg>(int) m_dwBestMwDmaMode? 
                                        m_dwBestMwDmaMode: 
                                        m_ulBestMwDmaModeReg;

    ulUDmaMode = (int)m_ulBestUDmaModeReg > (int)m_dwBestUDmaMode? 
                                        m_dwBestUDmaMode: 
                                        m_ulBestUDmaModeReg;


    if(m_fUDMAActive && ulUDmaMode != -1)
    {
        m_dwTransferModeCurrent = (UDMA_MODE0 << ulUDmaMode);
        SetTransferMode( (BYTE)ulUDmaMode | ATA_DMA_ULTRA_MODE);
        DEBUGMSG
        (
             ZONE_INIT, 
            (
                (L"ATAPI:SetBestTransferMode Current mode is UDMA mode = %1x\r\n"),
                ulUDmaMode
            )
        );
        m_fForcePIO          = FALSE;        
    }
    //
    // If the Drive supports UDMA but it is not enabled, set the mode to
    // mode 0 so that the other drive works.
    //
    // You can't mix UDMA on one drive and MDMA on the other.
    //
    else if(m_dwBestUDmaMode != -1)
    {
        SetTransferMode( (BYTE) (UDMA_MODE0 | ATA_DMA_ULTRA_MODE));
        m_fForcePIO          = TRUE;
    }
    else
    {
        m_pPort->m_fForcePIO = TRUE;
        m_fForcePIO          = TRUE;
    }
    // else if (ulMwDmaMode != -1 ) 
    // {
    //     m_dwTransferModeCurrent = (MWDMA_MODE0 << ulMwDmaMode);
    //     SetTransferMode( (BYTE)ulMwDmaMode | ATA_DMA_MULTI_WORD_MODE);
    //     //* * * CAMSDB - Added this for setting the mode in CPort class. (START)
    //     m_pPort->m_ulCurrentMode = m_dwTransferModeCurrent;
    //     //* * * CAMSDB - Added this for setting the mode in CPort class. (END)
    // 
    //     DEBUGMSG
    //     (
    //          ZONE_INIT, 
    //         (
    //             (L"ATAPI:SetBestTransferMode Current mode is MDMA mode = %1x\r\n"),
    //             ulMwDmaMode
    //         )
    //     );
    // }
}

//****************************************************************************
// CEP931xDisk::ForceTransferMode
//****************************************************************************
// fUDMAActive - Acts exactly like UDMAActive Registry setting.
// UDmaMode    - Acts exactly like UDMAMode Registry setting.
//
DWORD CEP931xDisk::ForceTransferMode(BOOL fUDMAActive, ULONG ulUDmaMode)
{

    m_fUDMAActive           = fUDMAActive;
    m_ulBestUDmaModeReg     = ulUDmaMode;

    //
    // Reset the read and write failure bugs for testing.
    //
    m_fReadBug1Failure      = FALSE;
    m_fWriteBug1Failure     = FALSE;
    m_fWriteBug2Failure     = FALSE;

    SetBestTransferMode();

    return ERROR_SUCCESS;
}



//****************************************************************************
// CEP931xDisk::IsDMASupported
//****************************************************************************
// For DMA to be supported the following:
//     1.  Both Drives must support UDMA.   
//     2.

⌨️ 快捷键说明

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