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

📄 ep931xide.cpp

📁 EP9315开发板的Wince6.0的BSP包文件
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//**********************************************************************
//                                                                      
// 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 2005, All Rights Reserved
//                                                                      
//**********************************************************************
#include "atamain.h"
#include <oalintr.h>
#include <CEDDK.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

//
// By expermentations it could be up to 10 Seconds between the time the
// dma completes before an interrupt is generated.
//
#define     UDMA_IDE_TIMEOUT            10000
#define     UDMA_DMA_TIMEOUT            50

//
// Include code to insure that IRQ/FIQ cannot interrupt PIO write
//
#define WLG_FIX_INTERRUPT_PIO_WRITE

//#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;
    // int ThreadPriority;
    
    //
    // 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 for the IDE interupt.
    //
    m_hIdeIntEvent = CreateEvent( NULL, FALSE, FALSE, NULL);
    if(!m_hIdeIntEvent)
    {
        DEBUGMSG( ZONE_INIT, (TEXT("CEP931xDisk::Init Failed to Create Interrupt Event for IDE.\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 for IDE.\r\n")));
        }
    }

    //
    // Create an event for the DMA interrupt. 
    //
    if(bResult)
    {
        m_hDmaIntEvent = CreateEvent( NULL, FALSE, FALSE, NULL);
        if(!m_hDmaIntEvent)
        {
            DEBUGMSG( ZONE_INIT, (TEXT("CEP931xDisk::Init Failed to Create Interrupt Event for DMA .\r\n")));
            bResult = FALSE;
        }
    }

    //
    // Create an DMA interrupt. 
    //
    if(bResult)
    {
        bResult = InterruptInitialize(SYSINTR_DMA_M2M0, m_hDmaIntEvent, NULL, 0) ;
        if(!bResult)
        {
            DEBUGMSG( ZONE_INIT, (TEXT("CEP931xDisk::Init Failed to InitializeInterrupt for DMA.\r\n")));
        }
    }

    //
    // Create an event to signal the IdeIst and the DmaIst to wait for there respective interrupts.
    // also used to clean up.
    //
    if(bResult)
    {
        m_hThreadWaitEvent = CreateEvent( NULL, TRUE, FALSE, NULL);
        if(!m_hThreadWaitEvent)
        {
            DEBUGMSG( ZONE_INIT, (TEXT("CEP931xDisk::Init Failed to Create Common Interrupt Event.\r\n")));
            bResult = FALSE;
        }
    }

    //
    // Create the DMA and IDE interrupt service threads.
    //
    if(bResult)
    {
        m_hDmaThread  = CreateThread
        (
            (LPSECURITY_ATTRIBUTES)NULL,
            0,
            (LPTHREAD_START_ROUTINE)CEP931xPort::DmaIst,
            (PVOID)this,
            0,
            NULL
        );
        if(!m_hDmaThread)
        {
            DEBUGMSG( ZONE_INIT, (TEXT("CEP931xDisk::Init Failed to Create Dma Thread.\r\n")));
            bResult = FALSE;
        }
    }


    if(bResult)
    {
        m_hIdeThread  = CreateThread
        (
            (LPSECURITY_ATTRIBUTES)NULL,
            0,
            (LPTHREAD_START_ROUTINE)CEP931xPort::IdeIst,
            (PVOID)this,
            0,
            NULL
        );
        if(!m_hIdeThread)
        {
            DEBUGMSG( ZONE_INIT, (TEXT("CEP931xDisk::Init Failed to Create Dma Thread.\r\n")));
            bResult = FALSE;
        }
    }

    if(bResult)
    {
        CeSetThreadPriority(m_hIdeThread, 50);
        CeSetThreadPriority(m_hDmaThread, 50);
    }


    //
    // Create two events for to signal WaitForDma.
    //
    if(bResult)
    {
        m_hIstEvent[DMA_EVENT] = CreateEvent( NULL, TRUE, FALSE, NULL);
        if(!m_hIstEvent[DMA_EVENT])
        {
            DEBUGMSG( ZONE_INIT, (TEXT("CEP931xDisk::Init Failed to Create Interrupt Event for DMA .\r\n")));
            bResult = FALSE;
        }
    }
    if(bResult)
    {
        m_hIstEvent[IDE_EVENT] = CreateEvent( NULL, TRUE, FALSE, NULL);
        if(!m_hIstEvent[IDE_EVENT])
        {
            DEBUGMSG( ZONE_INIT, (TEXT("CEP931xDisk::Init Failed to Create Interrupt Event for DMA .\r\n")));
            bResult = FALSE;
        }
    }


    //
    // Allocate a DMA buffer if the buffer is unaligned.  This is used if the 
    // buffer is unaligned. HalAllocateCommonBuffer
    //
    if(bResult)
    {
        m_pucStaticBuffer = (PUCHAR) AllocPhysMem
        (
            131072,                   
            PAGE_READWRITE | PAGE_NOCACHE,
            0,
            0,
            &m_ulStaticPhysBuff
        );
        bResult = m_pucStaticBuffer ? TRUE:FALSE;
    }
    

    if(bResult)
    {

        //
        // Make sure there are no glitches involving CS0 or CS1 and STOP/DIOWn
        // when switching modes:  deassert CS0 and CS1.
        //
        *IDE_CTRL |= IDE_CTRL_CS0 | IDE_CTRL_CS1;

        //
        // After returning from the dma state turn off the dma controller to reset
        // the pointers.
        //
        *IDE_CFG    = 0; 

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


    //
    // Free the memory in static DMA buffer.
    //    
    if(m_pucStaticBuffer)
    {
        FreePhysMem(m_pucStaticBuffer);
        m_pucStaticBuffer = 0;
    }

    //
    // Exit the DMA thread and clean up the thread event.
    //
    if(m_hDmaThread || m_hIdeThread)
    {
        m_bThreadExit = TRUE;
        SetEvent(m_hThreadWaitEvent);

        if(m_hDmaThread)
        {
            WaitForSingleObject(m_hDmaThread,1000);
            CloseHandle(m_hDmaThread);
            m_hDmaThread = 0;
        }

        if(m_hIdeThread)
        {
            WaitForSingleObject(m_hIdeThread, 1000);
            CloseHandle(m_hIdeThread);
            m_hIdeThread = 0;
        }

    }        

⌨️ 快捷键说明

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