📄 atamx27.cpp
字号:
//------------------------------------------------------------------------------
//
// 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 + -