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

📄 atamx31.cpp

📁 Freescale ARM11系列CPU MX31的WINCE 5.0下的BSP
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//------------------------------------------------------------------------------
//
//  Copyright (C) 2004-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
//
//------------------------------------------------------------------------------

/*++

Module Name:
    atamx31.cpp

Abstract:
    Base ATA MX31 device abstraction.

Revision History:

--*/

#include <bsp.h>
#include "atamx31.h"

//------------------------------------------------------------------------------
// Local Constants

// MX31 device registry value definitions
#define REG_VAL_MX31_IORDYENABLE	 (_T("IORDYEnable"))      // 0 to disable Host IORDY 


//------------------------------------------------------------------------------
// Global Variables 

HANDLE g_hWaitEvent = NULL;

LONG CMX31Disk::m_lDeviceCount = 0;

//------------------------------------------------------------------------------
// Local Variables 

// PIO spec
int t0_spec[5]   = {600, 383, 240, 180, 120} ;
int t1_spec[5]   = {70, 50, 30, 30, 25} ;
int t2_8spec[5]  = {290, 290, 290, 80, 70} ;
int t2_16spec[5] = {165, 125, 100, 80, 70} ;
int t2i_spec[5]  = {0,0,0,0,0} ;
int t4_spec[5]   = {30, 20, 15, 10, 10} ;
int t9_spec[5]   = {20, 15, 10, 10, 10} ;
int tA_spec[5]   = {50,50,50,50,50} ;

// MDMA spec
int t0M_spec[3]  = {480, 150, 120} ;
int tD_spec[3]   = {215, 80, 70} ;
int tH_spec[3]   = {20, 15, 10} ;
int tJ_spec[3]   = {20, 5, 5} ;
int tKW_spec[3]  = {215, 50, 25} ;
int tM_spec[3]   = {50, 30, 25} ;
int tN_spec[3]   = {15, 10, 10} ;
int tJNH_spec[3] = {20, 15, 10} ;

// UDMA spec
int t2CYC_spec[6]   = {235, 156, 117, 86, 57, 38} ;
int tCYC_spec[6]    = {114, 75, 55, 39, 25, 17} ;
int tDS_spec[6]     = {15,10,7, 7, 5, 4} ;
int tDH_spec[6]     = {5,5,5,5,5,5} ;
int tDVS_spec[6]    = {70, 48, 34, 20, 7, 5} ;
int tDVH_spec[6]    = {6,6,6,6,6,6} ;
int tCVS_spec[6]    = {70,48,34,20,7,10} ;
int tCVH_spec[6]    = {6,6,6,6,6,10} ;
int tFS_minspec[6]  = {0,0,0,0,0,0} ;
int tLI_maxspec[6]  = {100,100,100,100,100,75} ;
int tMLI_spec[6]    = {20,20,20,20,20,20} ;
int tAZ_spec[6]     = {10,10,10,10,10,10} ;
int tZAH_spec[6]    = {20,20,20,20,20,20} ;
int tENV_minspec[6] = {20,20,20,20,20,20} ;
int tSR_spec[6]     = {50,30,20,20,20,20} ;
int tRFS_spec[6]    = {75, 70, 60, 60, 60, 50} ;
int tRP_spec[6]     = {160,125,100,100,100,85} ;
int tACK_spec[6]    = {20,20,20,20,20,20} ;
int tSS_spec[6]     = {50,50,50,50,50,50} ;
int tDZFS_spec[6]   = {80,63,47,35,25,40} ;

static TCHAR *g_szATAHardDisk = TEXT("Hard Disk");

//#undef DEBUGMSG
//#define DEBUGMSG(a,b) RETAILMSG(1,b)
void DumpBuffer(PBYTE pInBuf, USHORT uBufSize);
void DumpFIFO(PBYTE g_pATA_BASE);

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


// Populate MX31_ registry value set from registry
BOOL
GetMX31RegistryValueSet(
    HKEY hInstanceKey,
    PMX31REG pMx31Reg
    )
{
    BOOL fRet;

    // fetch IORDY Enable
    fRet = AtaGetRegistryValue(hInstanceKey, REG_VAL_MX31_IORDYENABLE, &pMx31Reg->dwIORDYEnable);
    if (!fRet) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Ata!GetMX31RegistryValueSet> Failed to read %s from MX31 instance key\r\n"
            ), REG_VAL_MX31_IORDYENABLE));
        return FALSE;
    }

	return TRUE;
    }


//-----------------------------------------------------------------------------
//
//  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;
    
    // Bump up priority to prevent starvation
    CeSetThreadPriority(GetCurrentThread(), 97);
    
    while(TRUE)
    {
        if(WaitForSingleObject(pPort->m_hIRQEvent, INFINITE) == WAIT_OBJECT_0)
        {
            // Signal the thread that called WaitForInterrupt to complete 
            // the interrupt servicing.
            SetEvent(g_hWaitEvent);
        }
        else 
        {
            // Abnormal signal
            rc = FALSE;
            break;
        }
    }

    return rc;
}


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

EXTERN_C
CDisk *
CreateMX31(
    HKEY hDevKey
    )
{
	return new CMX31Disk(hDevKey);
}

// ----------------------------------------------------------------------------
// Function: CMX31Disk
//     Constructor
//
// Parameters:
//     hKey -
// ----------------------------------------------------------------------------

CMX31Disk::CMX31Disk(
    HKEY hKey
    ) : CDisk(hKey)
{
	
	m_lDeviceCount = 0;

    InterlockedIncrement(&m_lDeviceCount);

	  g_pVAtaReg = NULL; 
	  fSDMAIntrEnable = FALSE;
	 
    if (!GetMX31RegistryValueSet(hKey, &m_Mx31Reg)) {
            DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
                "Ata!CMX31Disk> Failed to read MX31_ registry value set from registry\r\n")));
    }

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

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

CMX31Disk::~CMX31Disk(
    )
{
    DeInitDMA(); 

    InterlockedDecrement(&m_lDeviceCount);

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

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

void
CMX31Disk::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
CMX31Disk::WaitForInterrupt(
    DWORD dwTimeOut
    )
{
    BYTE bStatus;
    BOOL fRet = TRUE;
    DWORD dwRet;

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

    bIntrPending = INREG8(&g_pVAtaReg->InterruptPending);
	if(bIntrPending & 0x08)
	{
		// read status; acknowledge interrupt
		bStatus = GetBaseStatus();
		if (bStatus & ATA_STATUS_ERROR) {
			bStatus = GetError();
			fRet = FALSE;
      DEBUGMSG(ZONE_FUNC, (TEXT("CMX31Disk: WaitForInterrupt(Error: %x)\r\n"), bStatus));
		}
    } else
	if(bIntrPending & 0x20)
	{
        DEBUGCHK(0);
		OUTREG8(&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_dwSysIntr);
    
	  if(fRet && dwTimeOut && fSDMAIntrEnable && !(bIntrPending & 0x80)) 
	  {
	  	//fRet = FALSE;
	  	goto next_wait;
	  }

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

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

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

    OUTREG8(&g_pVAtaReg->InterruptClear, 0xff);
    OUTREG8(&g_pVAtaReg->InterruptEnable, 0x08);
    // signal interrupt done
    WaitForSingleObject(g_hWaitEvent,0);
    InterruptDone(m_pPort->m_dwSysIntr);
}


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

VOID
CMX31Disk::ConfigureRegisterBlock(
    DWORD dwStride
    )
{
    DEBUGMSG(ZONE_FUNC, (TEXT("CMX31Disk: 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("CMX31Disk: ConfigureRegisterBlock-\r\n")));
}

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

⌨️ 快捷键说明

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