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

📄 ep931xide.cpp

📁 EP931X系列的WinCE显卡驱动源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//**********************************************************************
//                                                                      
// Filename: EP931xide.cpp
//                                                                      
// Description: IDE driver for the internal EP931x port.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Use of this source code is subject to the terms of the Cirrus end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to 
// use this source code. For a copy of the EULA, please see the 
// EULA.RTF on your install media.
//
// Copyright(c) Cirrus Logic Corporation 2003, All Rights Reserved                       
//                                                                      
//**********************************************************************
#include "atamain.h"
#include <oalintr.h>
#include "ep931xide.h"
#include <hwdefs.h>
#include <dbgapi.h>

#define     DELAY_5NS                   __emit(0xe1a00000);

#define     DELAY_10NS                  __emit(0xe1a00000);     \
                                        __emit(0xe1a00000);     

#define     DELAY_50NS                  __emit(0xe1a00000);     \
                                        __emit(0xe1a00000);     \
                                        __emit(0xe1a00000);     \
                                        __emit(0xe1a00000);     \
                                        __emit(0xe1a00000);     \
                                        __emit(0xe1a00000);     \
                                        __emit(0xe1a00000);     \
                                        __emit(0xe1a00000);     \
                                        __emit(0xe1a00000);

#define     DELAY_100NS                 DELAY_50NS              \
                                        DELAY_50NS


//#define DATA_REGISTER         0x00
//#define ERRORREGISTER        0x01
//#define FEATURESREGISTER     0x01
//#define SECTORCOUNTREGISTER  0x02
//#define SECTORNUMBERREGISTER 0x03
//#define CYLINDERLOWREGISTER  0x04
//#define CYLINDERHIGHREGISTER 0x05
//#define DEVICEHEADREGISTER   0x06
//#define COMMANDREGISTER      0x07
//#define STATUSREGISTER       0x07
// ATA Control Registers

//#define DEVICECONTROLREGISTER   0x06
//#define ALTERNATESTATUSREGISTER 0x06

//****************************************************************************
// ATAReadRegister
//****************************************************************************
// 
// 
__inline ULONG ATAReadRegister(ULONG ulRegister)
{

    ULONG uiValue;
    register ULONG ulControl;
    

    //
    // Setup the control register for a read.
    //
    *IDE_CTRL = ulControl = IDE_CTRL_DIOR | IDE_CTRL_DIOW | ulRegister;

    //
    // See Section 10.2.2 of the ATA/ATAPI Specification Version 5 for Delay
    // Information.
    //
    // PIO Mode 0 - Delay for 70ns. 
    // PIO Mode 1 - Delay for 50ns. 
    // PIO Mode 2 - Delay for 30ns. 
    // PIO Mode 3 - Delay for 30ns. 
    // PIO Mode 4 - Delay for 25ns. 
    //
    // For a write to a APB register with HCLK at 100Mhz is 130ns.
    // No extra delay is needed.
    //
    *IDE_CTRL = ulControl &= ~IDE_CTRL_DIOR;

    //
    // See Section 10.2.2 of the ATA/ATAPI Specification Version 5 for Delay
    // Information.
    //
    // PIO Mode 0 - Delay for 290ns. 
    // PIO Mode 1 - Delay for 290s. 
    // PIO Mode 2 - Delay for 290s. 
    // PIO Mode 3 - Delay for 80ns. 
    // PIO Mode 4 - Delay for 70ns. 
    //
    // For a write to a APB register with HCLK at 100Mhz is 130ns.
    // No extra delay is needed.
    //

    *IDE_CTRL = ulControl |= IDE_CTRL_DIOR;

    uiValue = *IDE_DATAIN;

    if(ulRegister == CSDA_DATA_REG)
    {
        return(uiValue & 0xFFFF);
    }
    else
    {
        return(uiValue & 0xFF);
    }
}

//-----------------------------------------------------------------------------
//
//  Function Name: ATAWriteCommandRegister
//
//  Function Description: Writes an 8-bit value to an ATA command register.
//
//-----------------------------------------------------------------------------
__inline void ATAWriteRegister(ULONG ulRegister, UINT uiData)
{
    register ULONG   ulControl;


    //
    // Setup the control register for a write.
    //
    *IDE_CTRL       = ulControl = IDE_CTRL_DIOR | IDE_CTRL_DIOW | ulRegister;
    *IDE_DATAOUT    = uiData;

    //
    // See Section 10.2.2 of the ATA/ATAPI Specification Version 5 for Delay
    // Information.
    //
    // PIO Mode 0 - Delay for 70ns. 
    // PIO Mode 1 - Delay for 50ns. 
    // PIO Mode 2 - Delay for 30ns. 
    // PIO Mode 3 - Delay for 30ns. 
    // PIO Mode 4 - Delay for 25ns. 
    //
    // For a write to a APB register with HCLK at 100Mhz is 130ns.
    // No extra delay is needed.
    //
    *IDE_CTRL = ulControl &= ~IDE_CTRL_DIOW;

    //
    // See Section 10.2.2 of the ATA/ATAPI Specification Version 5 for Delay
    // Information.
    //
    // PIO Mode 0 - Delay for 290ns. 
    // PIO Mode 1 - Delay for 290s. 
    // PIO Mode 2 - Delay for 290s. 
    // PIO Mode 3 - Delay for 80ns. 
    // PIO Mode 4 - Delay for 70ns. 
    //
    // For a write to a APB register with HCLK at 100Mhz is 130ns.
    // No extra delay is needed.
    //
    *IDE_CTRL = ulControl |= IDE_CTRL_DIOW;

    //
    // See Section 10.2.2 of the ATA/ATAPI Specification Version 5 for Delay
    // Information.  There are also delays from all the returns and
    // function calls so I am not putting the full delay in.
    //
    // PIO Mode 0 - N/A
    // PIO Mode 1 - N/A
    // PIO Mode 2 - N/A
    // PIO Mode 3 - Delay for 70ns. 
    // PIO Mode 4 - Delay for 25ns. 
    //
    // This 25ns easily gets eaten up by the function call return call and the few
    // necessary instructions in the functions were it is used.
    // DELAY_10NS
    // DELAY_10NS
    // DELAY_10NS
}



//****************************************************************************
// CEP931xPort::Init
//****************************************************************************
//
// Return TRUE  - Success
//        FALSE - Failure
//

BOOL CEP931xPort::Init()
{
    BOOL    bResult = TRUE;
    ULONG   ulShifted;
    
    //
    // Find out the shift factor for the page size.
    //
    m_ulPageShift = 0;
    ulShifted     = UserKInfo[KINX_PAGESIZE];  
    while(ulShifted != 1)
    {
        m_ulPageShift++;
        ulShifted= ulShifted>>1;
    }


    //
    // Create an event and a thread, and then associate them. 
    //
    m_hIdeIntEvent = CreateEvent( NULL, FALSE, FALSE, NULL);
    if(!m_hIdeIntEvent)
    {
        DEBUGMSG( ZONE_INIT, (TEXT("CEP931xDisk::Init Failed to Create Interrupt Event.\r\n")));
        bResult = FALSE;
    }

    //
    // Get the event handle, register the interrupt, and then
    // associate it with the event.
    //
    if(bResult)
    {
        bResult = InterruptInitialize(SYSINTR_IDE, m_hIdeIntEvent, NULL, 0) ;
        if(!bResult)
        {
            DEBUGMSG( ZONE_INIT, (TEXT("CEP931xDisk::Init Failed to InitializeInterrupt.\r\n")));
        }
    }

    //
    // Allocate a DMA buffer if the buffer is unaligned.  This is used if the 
    // buffer is unaligned.
    //
    if(bResult)
    {
        m_pucStaticBuffer = (PUCHAR) AllocPhysMem
        (
            MAX_DMA_SECT_PER_COMMAND * BYTES_PER_SECTOR,
            PAGE_READWRITE | PAGE_NOCACHE,
            0,
            0,
            &m_ulStaticPhysBuff
        );

        bResult = m_pucStaticBuffer ?TRUE:FALSE;
    }
    

    if(bResult)
    {
        //
        // Initialize the IDE interface to PIO mode 4.
        //
        *IDE_CFG    = IDE_CFG_IDEEN | IDE_CFG_PIOEN | IDE_CFG_PIO4 | (1 <<IDE_CFG_WST_SHIFT);

        *IDE_CTRL = IDE_CTRL_DIOR | IDE_CTRL_DIOW | CSDA_DATA_REG;


        //
        // Make sure that MDMA and UDMA are disabled.
        //
        *IDE_MDMAOP = 0;
        *IDE_UDMAOP = 0;    
    }
    

    return bResult;
}

//****************************************************************************
// CEP931xPort::~CEP931xPort
//****************************************************************************
// Destructor
// 
//
CEP931xPort::~CEP931xPort()
{
    BOOL    bResult = TRUE;

    if(m_hIdeIntEvent)
    {
        CloseHandle(m_hIdeIntEvent);
    }

    DeleteCriticalSection( &m_CriticalSection);
}

//****************************************************************************
// CEP931xPort::SetupDMA
//****************************************************************************
// Sets up the dma controller and prepares the DMA buffers.
// 
//
BOOL CEP931xPort::SetupDMA
( 
    PSG_BUF pSgBuf, 
    DWORD   dwSgCount, 
    BOOL    fRead,
    ULONG   ulCurrentMode
) 
{
    BOOL    fLockRet;
    ULONG   ulDmaCount;
    ULONG   ulIDESource, ulIDEDest;
    ULONG   ulBuffer;
    LPBYTE  pBuffer;
    BOOL    fPagesLocked;
    DWORD   PFNs[16];
    ULONG   ulPage, ulNumPages;
    ULONG   ulPageSize = UserKInfo[KINX_PAGESIZE];  

    

    DEBUGMSG
    ( 
        ZONE_DMA, 
        (
            TEXT("ATAPI:SetupDMA Request = %s SgCount=%ld\r\n"), 
            fRead ? TEXT("Read") : TEXT("Write"), 
            dwSgCount
        )
    );

    //
    // Stop any DMA that is occuring.
    //
    m_pulDmaBase[M2M_CTRL>>2] &= ~M2M_CTRL_START;

    //
    // Lets save off the DMA information.
    //
    m_pDMASgBuf         = pSgBuf;
    m_dwDMASgCount      = dwSgCount;
    m_fDMARead          = fRead;
    m_fAligned          = TRUE; 
    m_ulCurrentMode     = ulCurrentMode;

    ulDmaCount        = 0;

    //
    // Check if either the buffer or the buffer length is unaligned.  If the buffers are not 
    //
    if(dwSgCount ==1 && !((ULONG)pSgBuf[0].sb_buf & 0x3) && !(pSgBuf[0].sb_len & 0x3))
    {
        //
        // Map the pointer to the process so that we have a valid pointer in our process.
        //
        m_pucDmaBuffer = (LPBYTE)MapPtrToProcess(pSgBuf[0].sb_buf, GetCallerProcess());

        //
        // Lock the pages for reading or writing.
        //
        fPagesLocked = LockPages
        ( 
            m_pucDmaBuffer, 
            pSgBuf[0].sb_len, 
            PFNs, 
            fRead ? LOCKFLAG_WRITE : LOCKFLAG_READ
        );
            

        //
        // If the function succeds, Check to make sure that the pages are physically contiguous.
        // If they are not then do the unaligned buffer case.
        //
        if(fPagesLocked)
        {
            ulNumPages = 1 + ( (ULONG(m_pucDmaBuffer) + pSgBuf[0].sb_len) >> m_ulPageShift) - 
                             ( ULONG(m_pucDmaBuffer) >> m_ulPageShift);

            for(ulPage = 0; ulPage< (ulNumPages - 1); ulPage++)
            {
                if(PFNs[ulPage] !=PFNs[ulPage + 1])
                {
                    m_fAligned = FALSE;    
                    break;
                }
            }

            //
            // If it is aligned then calculate the current physical address.
            //
            if(m_fAligned )
            {
                m_ulDmaPhysBuff = PFNs[0] + ((ULONG)m_pucDmaBuffer & (ulPageSize -1));
                m_ulDmaCount    = pSgBuf[0].sb_len;

⌨️ 快捷键说明

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