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

📄 atamx27.cpp

📁 Microsoft WinCE 6.0 BSP FINAL release source code for use with the i.MX27ADS TO2 WCE600_FINAL_MX27_S
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//------------------------------------------------------------------------------
//
// Copyright (C) 2006, Freescale Semiconductor, Inc. All Rights Reserved.
// THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
// AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT 
//
//------------------------------------------------------------------------------
//
//  File:  atamx27.cpp
//
//  Base ATA MX27 device abstraction.
//
//------------------------------------------------------------------------------

#include <windows.h>
#include <devload.h>
#include <pm.h>
#include <nkintr.h>
#include <ceddk.h>
#include <diskio.h>
#include <atapi2.h>
#include "ataMX27.h"

//------------------------------------------------------------------------------
// Global Variables 
//------------------------------------------------------------------------------
LONG CMX27Disk::m_lDeviceCount = 0;

//------------------------------------------------------------------------------
// Extern Variables 
//------------------------------------------------------------------------------
// Result of PIO timing to send Timing register
extern int pio_timing_1[5];
extern int pio_timing_2[5];
extern int pio_timing_3[5];  
extern int pio_timing_4[5];  
extern int pio_timing_5[5];

// Result of Multword DMA timing to send Timing register
extern int mdma_timing_1[3];
extern int mdma_timing_2[3];
extern int mdma_timing_3[3];
extern int mdma_timing_4[3];

// Ultra DMA timing
extern int udma_timing_1[6];
extern int udma_timing_2[6];
extern int udma_timing_3[6];
extern int udma_timing_4[6];
extern int udma_timing_5[6];
extern int udma_timing_6[6];
extern int udma_timing_7[6];
extern int udma_timing_8[6];
extern int udma_timing_9[6];
extern int udma_timing_10[6];
extern int udma_timing_11[6];

//------------------------------------------------------------------------------
// Local Variables 
//------------------------------------------------------------------------------
static TCHAR *g_szATAHardDisk = TEXT("Hard Disk");

//------------------------------------------------------------------------------
// Local Functions
//------------------------------------------------------------------------------

//-----------------------------------------------------------------------------
//
//  Function:  AtaIntrServThread
//
//  This is the interrupt service thread for ATA interrupts.  
//
//  Parameters:
//      lpParam
//          [in] Thread data passed to the function using the 
//          lpParameter parameter of the CreateThread function.
//
//  Returns:
//      Returns thread exit code.
//
//-----------------------------------------------------------------------------

DWORD IntrServThread (LPVOID lpParam)
{
    DWORD rc = TRUE;
    CPort *pPort = (CPort *)lpParam;

    while(TRUE)
    {
        if(WaitForSingleObject(pPort->m_hIRQEvent, INFINITE) == WAIT_OBJECT_0)
        {
            // Signal the thread that called WaitForInterrupt to complete 
            // the interrupt servicing.
            SetEvent(pPort->m_hWaitEvent);
        }
        else 
        {
            // Abnormal signal
            rc = FALSE;
            break;
        }
    }

    return rc;
}

// ----------------------------------------------------------------------------
// Function: CreatePCIHD
//     Spawn function called by IDE/ATA controller enumerator
//
// Parameters:
//     hDevKey -
// ----------------------------------------------------------------------------

EXTERN_C
CDisk *
CreateMX27HD(
    HKEY hDevKey
    )
{
    return new CMX27Disk(hDevKey);
}

// ----------------------------------------------------------------------------
// Function: CMX27Disk
//     Constructor
//
// Parameters:
//     hKey -
// ----------------------------------------------------------------------------

CMX27Disk::CMX27Disk(
    HKEY hKey
    ) : CDisk(hKey)
{
    InterlockedIncrement(&m_lDeviceCount);

    g_pVAtaReg = NULL; 
    fDMAIntrEnable = FALSE;
     
    DEBUGMSG(ZONE_INIT|ZONE_MX27, (_T(
        "Ata!CMX27Disk::CMX27Disk> device count(%d)\r\n"
        ), m_lDeviceCount));
}

// ----------------------------------------------------------------------------
// Function: ~CMX27Disk
//     Destructor
//
// Parameters:
//     None
// ----------------------------------------------------------------------------

CMX27Disk::~CMX27Disk(
    )
{
    DeInitDMA(); 

    InterlockedDecrement(&m_lDeviceCount);

    DEBUGMSG(ZONE_INIT|ZONE_MX27, (_T(
        "Ata!CMX27Disk::~CMX27Disk> device count(%d)\r\n"
        ), m_lDeviceCount));
}

// ----------------------------------------------------------------------------
// Function: CopyDiskInfoFromPort
//     This function is not used
//
// Parameters:
//     None
// ----------------------------------------------------------------------------

void
CMX27Disk::CopyDiskInfoFromPort(
    )
{
    ASSERT(m_pPort->m_dwRegBase != 0);
    m_pATAReg = (PBYTE)m_pPort->m_dwRegBase;
    m_pATARegAlt = (PBYTE)m_pPort->m_dwRegAlt;

    ASSERT(m_pPort->m_dwBMR != 0);
}

// ----------------------------------------------------------------------------
// Function: WaitForInterrupt
//     Wait for interrupt
//
// Parameters:
//     dwTimeOut -
// ----------------------------------------------------------------------------

BOOL
CMX27Disk::WaitForInterrupt(
    DWORD dwTimeOut
    )
{
    BYTE bStatus;
    BOOL fRet = TRUE;
    DWORD dwRet;

    DEBUGMSG(ZONE_FUNC, (TEXT("CMX27Disk: WaitForInterrupt+\r\n")));
    
    bIntrPending = 0;
next_wait:    
    // wait for interrupt
    dwRet = WaitForSingleObject(m_pPort->m_hWaitEvent, dwTimeOut);
    if (dwRet == WAIT_TIMEOUT) {
        fRet = FALSE;
    }
    else {
        if (dwRet != WAIT_OBJECT_0) {
            if (!WaitForDisc(WAIT_TYPE_DRQ, dwTimeOut, 10)) {
                fRet = FALSE;
            }
        }
    }

    bIntrPending = ((INREG32(&g_pVAtaReg->InterruptPending))&(INREG32(&g_pVAtaReg->InterruptEnable)));
    if(bIntrPending & 0x08)
    {
        // read status; acknowledge interrupt
        bStatus = GetBaseStatus();
        if (bStatus & ATA_STATUS_ERROR) {
            bStatus = GetError();
            fRet = FALSE;
            DEBUGMSG(ZONE_FUNC, (TEXT("CMX27Disk: WaitForInterrupt(Error: %x)\r\n"), bStatus));
        }
    } else
    if(bIntrPending & 0x20)
    {
        OUTREG32(&g_pVAtaReg->InterruptClear, 0x20);
        while(INREG32(&g_pVAtaReg->FIFO_FILL) >= 2)
        {
           *((PDWORD)(m_rgbDoubleBuffer+dwDoubleBufferPos)) = INREG32(&g_pVAtaReg->FIFO_DATA_32[0]) ;
            dwDoubleBufferPos += 4;
        }
    }

    // signal interrupt done
    InterruptDone(m_pPort->m_dwSysIntrRX);
    InterruptDone(m_pPort->m_dwSysIntrTX);
    InterruptDone(m_pPort->m_dwSysIntr);
    
    if(fRet && dwTimeOut && fDMAIntrEnable && !(bIntrPending & 0x80)) 
    {
        //fRet = FALSE;
        goto next_wait;
    }

    DEBUGMSG(ZONE_FUNC, (TEXT("CMX27Disk: WaitForInterrupt-:%d,%x\r\n"), fRet, bIntrPending));
    return fRet;
}

// ----------------------------------------------------------------------------
// Function: EnableInterrupt
//     Enable channel interrupt
//
// Parameters:
//     None
// ----------------------------------------------------------------------------

void
CMX27Disk::EnableInterrupt(
    )
{
    GetBaseStatus(); // acknowledge interrupt, if pending

    OUTREG32(&g_pVAtaReg->InterruptClear, 0xff);
    OUTREG32(&g_pVAtaReg->InterruptEnable, 0x68); //0x08);
    // signal interrupt done
    InterruptDone(m_pPort->m_dwSysIntr);
    InterruptDone(m_pPort->m_dwSysIntrRX);
    InterruptDone(m_pPort->m_dwSysIntrTX);
}

// ----------------------------------------------------------------------------
// Function: ConfigureRegisterBlock
//     This function is called by DSK_Init before any other CDisk function to
//     set up the register block.
//
// Parameters:
//     dwStride -
// ----------------------------------------------------------------------------

VOID
CMX27Disk::ConfigureRegisterBlock(
    DWORD dwStride
    )
{
    DEBUGMSG(ZONE_FUNC, (TEXT("CMX27Disk: ConfigureRegisterBlock+\r\n")));
    m_dwStride = dwStride;
    m_dwDataDrvCtrlOffset = ATA_REG_DATA * dwStride+ATA_DRIVE_REG_OFFSET;
    m_dwFeatureErrorOffset = ATA_REG_FEATURE * dwStride+ATA_DRIVE_REG_OFFSET;
    m_dwSectCntReasonOffset = ATA_REG_SECT_CNT * dwStride+ATA_DRIVE_REG_OFFSET;
    m_dwSectNumOffset = ATA_REG_SECT_NUM * dwStride+ATA_DRIVE_REG_OFFSET;
    m_dwDrvHeadOffset = ATA_REG_DRV_HEAD * dwStride+ATA_DRIVE_REG_OFFSET;
    m_dwCommandStatusOffset = ATA_REG_COMMAND * dwStride+ATA_DRIVE_REG_OFFSET;
    m_dwByteCountLowOffset = ATA_REG_BYTECOUNTLOW * dwStride+ATA_DRIVE_REG_OFFSET;
    m_dwByteCountHighOffset = ATA_REG_BYTECOUNTHIGH * dwStride+ATA_DRIVE_REG_OFFSET;
    m_dwAltStatusOffset = ATA_DRIVE_ALT_OFFSET; //ATA_REG_ALT_STATUS_CS1 * dwStride+atabase;
    m_dwAltDrvCtrl = ATA_DRIVE_ALT_OFFSET; //ATA_REG_DRV_CTRL_CS1 * dwStride+atabase;
    DEBUGMSG(ZONE_FUNC, (TEXT("CMX27Disk: ConfigureRegisterBlock-\r\n")));
}

// ----------------------------------------------------------------------------
// Function: Init
//     Initialize channel
//
// Parameters:
//     hActiveKey -
// ----------------------------------------------------------------------------

BOOL
CMX27Disk::Init(
    HKEY hActiveKey
    )
{
    BOOL bRet = FALSE;

    DEBUGMSG(ZONE_FUNC, (_T("CMX27Disk: Init+")));
    m_f16Bit = TRUE; // ATA is 16-bit

    // configure port
    if (!ConfigPort()) {
        DEBUGMSG(ZONE_INIT, (_T(
            "Ata!CMX27Disk::Init> Failed to configure port; device(%u)\r\n"
            ), m_dwDeviceId));
        goto exit;
    }

    // assign the appropriate folder name
    m_szDiskName = g_szATAHardDisk;

    if(!InitDMA())
    {
        DEBUGMSG(ZONE_ERROR, (TEXT("MMCSD_DMAInit: cannot init DMA!\r\n")));
        goto exit;
    }

    // finish intialization; i.e., initialize device
    bRet = CDisk::Init(hActiveKey);
    if (!bRet) {
        goto exit;
    }

    BYTE bPIOMode = 0; // default PIO mode
    BYTE bDMAMode = 0;
    BYTE bTransferMode = (BYTE)m_pPort->m_pDskReg[m_dwDeviceId]->dwTransferMode;
    BYTE bIORDYEnable = (BYTE)m_pPort->m_pDskReg[m_dwDeviceId]->dwIORDYEnable;
    switch(bTransferMode)
    {
        case  0x08:
        case  0x09:
        case  0x0a:
        case  0x0b:
        case  0x0c:
            bPIOMode = bTransferMode - 0x08;
            if(bIORDYEnable && bPIOMode >= 3)
            {
                Sleep(10);
                OUTREG32(&g_pVAtaReg->ATAControl, 0x41);
                Sleep(10);
            }
            break;
        case 0x40:
        case 0x41:
        case 0x42:
        case 0x43:
        case 0x44:
        case 0x45:
            bDMAMode = (BYTE)(bTransferMode - 0x40);
            SetTimingRegisters(bDMAMode, UDMA_MODE, CLOCK_PERIOD);
            break;
        case 0x20:
        case 0x21:
        case 0x22:
            bDMAMode = (BYTE)(bTransferMode - 0x20);
            SetTimingRegisters(bDMAMode, MDMA_MODE, CLOCK_PERIOD);
            break;
        default:
//            bPIOMode = 0;
            break;
    }
    SetTimingRegisters(bPIOMode, PIO_MODE, CLOCK_PERIOD);
//    ShowRegisters(0x01);

    DEBUGMSG(ZONE_FUNC, (_T("CMX27Disk: Init-")));

exit:;
    return bRet;
}

// ----------------------------------------------------------------------------
// Function: MainIoctl
//     This is redundant
//
// Parameters:
//     pIOReq -
// ----------------------------------------------------------------------------

DWORD
CMX27Disk::MainIoctl(
    PIOREQ pIOReq
    )
{
    DEBUGMSG(ZONE_FUNC, (_T(
        "Ata!CMX27Disk::MainIoctl> IOCTL(%d), device(%d) \r\n"
        ), pIOReq->dwCode, m_dwDeviceId));

    return CDisk::MainIoctl(pIOReq);
}

// ----------------------------------------------------------------------------
// Function: ConfigPort
//     Initialize IST/ISR
//
// Parameters:
//     None
// ----------------------------------------------------------------------------

⌨️ 快捷键说明

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