📄 atapishx.cpp
字号:
//
// Copyright(C) Renesas Technology Corp. 2005. All rights reserved.
//
// ATAPI(UDFS) driver for ITS-DS7
//
// FILE : atamain.cpp
// CREATED : 2005.02.10
// MODIFIED : 2005.04.14
// AUTHOR : Renesas Technology Corp.
// HARDWARE : RENESAS ITS-DS7
// HISTORY :
// 2005.02.10
// - Created release code.
// (based on PUBLIC ATAPI driver for WCE5.0)
// 2005.04.14
// - Modified adjustment of a timing.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft 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 LICENSE.RTF on your
// install media.
//
/*++
Module Name:
atapishx.cpp
Abstract:
Base ATA/ATAPI device abstraction.
Revision History:
--*/
#include <atapishx.h>
LONG CSHXDisk::m_lDeviceCount = 0;
static TCHAR *g_szSHXCDRomDisk = TEXT("CD-ROM");
static TCHAR *g_szSHXHardDisk = TEXT("Hard Disk");
// ----------------------------------------------------------------------------
// Function: CreateSHXHD
// Spawn function called by IDE/ATA controller enumerator
//
// Parameters:
// hDevKey -
// ----------------------------------------------------------------------------
EXTERN_C
CDisk *
CreateSHXHD(
HKEY hDevKey
)
{
return new CSHXDisk(hDevKey);
}
// ----------------------------------------------------------------------------
// Function: CSHXDisk
// Constructor
//
// Parameters:
// hKey -
// ----------------------------------------------------------------------------
CSHXDisk::CSHXDisk(
HKEY hKey
) : CDisk(hKey)
{
m_pPort = NULL;
InterlockedIncrement(&m_lDeviceCount);
DEBUGMSG(ZONE_INIT|ZONE_SHX, (_T(
"Atapi!CSHXDisk::CSHXDisk> device count(%d)\r\n"
), m_lDeviceCount));
}
// ----------------------------------------------------------------------------
// Function: ~CSHXDisk
// Destructor
//
// Parameters:
// None
// ----------------------------------------------------------------------------
CSHXDisk::~CSHXDisk(
)
{
FreeDMABuffers();
InterlockedDecrement(&m_lDeviceCount);
DEBUGMSG(ZONE_INIT|ZONE_SHX, (_T(
"Atapi!CSHXDisk::~CSHXDisk> device count(%d)\r\n"
), m_lDeviceCount));
}
// ----------------------------------------------------------------------------
// Function: FreeDMABuffers
// Deallocate DMA buffers
//
// Parameters:
// None
// ----------------------------------------------------------------------------
void
CSHXDisk::FreeDMABuffers(
)
{
}
// ----------------------------------------------------------------------------
// Function: CopyDiskInfoFromPort
// This function is not used
//
// Parameters:
// None
// ----------------------------------------------------------------------------
void
CSHXDisk::CopyDiskInfoFromPort(
)
{
ASSERT(m_pPort->m_dwRegBase != 0);
m_pATAReg = (PBYTE)m_pPort->m_dwRegBase;
m_pATARegAlt = (PBYTE)m_pPort->m_dwRegAlt;
m_pAtapiControl = (PBYTE)m_pPort->m_dwAtapiControl;
m_pAtapiBuffer = (PBYTE)m_pPort->m_dwAtapiBuffer;
}
// ----------------------------------------------------------------------------
// Function: WaitForInterrupt
// Wait for interrupt
//
// Parameters:
// dwTimeOut -
// ----------------------------------------------------------------------------
BOOL
CSHXDisk::WaitForInterrupt(
DWORD dwTimeOut
)
{
BYTE bStatus;
BOOL fRet = TRUE;
DWORD dwRet;
// wait for interrupt
dwRet = WaitForSingleObject(m_pPort->m_hIRQEvent, dwTimeOut);
if (dwRet == WAIT_TIMEOUT) {
fRet = FALSE;
}
else {
if (dwRet != WAIT_OBJECT_0) {
if (!WaitForDisc(WAIT_TYPE_DRQ, dwTimeOut, 10)) {
fRet = FALSE;
}
}
}
// read status; acknowledge interrupt
bStatus = GetBaseStatus();
if (bStatus & ATA_STATUS_ERROR) {
bStatus = GetError();
fRet = FALSE;
}
// signal interrupt done
InterruptDone(m_pPort->m_dwSysIntr);
return fRet;
}
// ----------------------------------------------------------------------------
// Function: EnableInterrupt
// Enable channel interrupt
//
// Parameters:
// None
// ----------------------------------------------------------------------------
void
CSHXDisk::EnableInterrupt(
)
{
GetBaseStatus(); // acknowledge interrupt, if pending
WRITE_REGISTER_ULONG(m_pAtapiControl + ATAPI_IRRN_OFFSET, 0x00000014); //iDEVINT,iERR
// signal interrupt done
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
CSHXDisk::ConfigureRegisterBlock(
DWORD dwStride
)
{
m_dwStride = dwStride;
m_dwDataDrvCtrlOffset = ATA_REG_DATA * dwStride;
m_dwFeatureErrorOffset = ATA_REG_FEATURE * dwStride;
m_dwSectCntReasonOffset = ATA_REG_SECT_CNT * dwStride;
m_dwSectNumOffset = ATA_REG_SECT_NUM * dwStride;
m_dwDrvHeadOffset = ATA_REG_DRV_HEAD * dwStride;
m_dwCommandStatusOffset = ATA_REG_COMMAND * dwStride;
m_dwByteCountLowOffset = ATA_REG_BYTECOUNTLOW * dwStride;
m_dwByteCountHighOffset = ATA_REG_BYTECOUNTHIGH * dwStride;
// ATA implementations don't assign I/O resources for the first four
// bytes, as they are unused
m_dwAltStatusOffset = 14 * dwStride;
m_dwAltDrvCtrl = 14 * dwStride;
}
// ----------------------------------------------------------------------------
// Function: Init
// Initialize channel
//
// Parameters:
// hActiveKey -
// ----------------------------------------------------------------------------
BOOL
CSHXDisk::Init(
HKEY hActiveKey
)
{
BOOL bRet = FALSE;
m_f16Bit = TRUE; // ExBus is 16-bit
// configure port
if (!ConfigPort()) {
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CSHXDisk::Init> Failed to configure port; device(%u)\r\n"
), m_dwDeviceId));
goto exit;
}
// assign the appropriate folder name
m_szDiskName = (IsCDRomDevice() ? g_szSHXCDRomDisk : g_szSHXHardDisk);
// finish intialization; i.e., initialize device
bRet = CDisk::Init(hActiveKey);
if (!bRet) {
goto exit;
}
exit:;
return bRet;
}
// ----------------------------------------------------------------------------
// Function: MainIoctl
// This is redundant
//
// Parameters:
// pIOReq -
// ----------------------------------------------------------------------------
DWORD
CSHXDisk::MainIoctl(
PIOREQ pIOReq
)
{
DEBUGMSG(ZONE_IOCTL, (_T(
"Atapi!CSHXDisk::MainIoctl> IOCTL(%d), device(%d) \r\n"
), pIOReq->dwCode, m_dwDeviceId));
return CDisk::MainIoctl(pIOReq);
}
// ----------------------------------------------------------------------------
// Function: ConfigPort
// Initialize IST/ISR
//
// Parameters:
// None
// ----------------------------------------------------------------------------
BOOL
CSHXDisk::ConfigPort(
)
{
m_pATAReg = (PBYTE)m_pPort->m_dwRegBase;
m_pATARegAlt = (PBYTE)m_pPort->m_dwRegAlt;
m_pAtapiControl = (PBYTE)m_pPort->m_dwAtapiControl;
m_pAtapiBuffer = (PBYTE)m_pPort->m_dwAtapiBuffer;
// this function is called for the master and slave on this channel; if
// this has already been called, then exit
if (m_pPort->m_hIRQEvent) {
m_dwDeviceFlags |= DFLAGS_DEVICE_INITIALIZED;
return TRUE;
}
WRITE_REGISTER_ULONG(m_pAtapiControl+ATAPI_CTL2_OFFSET, 0x00000003); //WORDSWAP,IFEN
// create interrupt event
if (NULL == (m_pPort->m_hIRQEvent = CreateEvent(NULL, FALSE, FALSE, NULL))) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!CSHXDisk::ConfigPort> Failed to create interrupt event for device(%d)\r\n"
), m_dwDeviceId));
return FALSE;
}
// associate interrupt event with IRQ
if (!InterruptInitialize(
m_pPort->m_dwSysIntr,
m_pPort->m_hIRQEvent,
NULL,
0)
) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!CSHXDisk::ConfigPort> Failed to initialize interrupt(SysIntr(%d)) for device(%d)\r\n"
), m_pPort->m_dwSysIntr, m_dwDeviceId));
return FALSE;
}
return TRUE;
}
// ----------------------------------------------------------------------------
// Function: SetupDMA
// Prepare DMA transfer
//
// Parameters:
// pSgBuf -
// dwSgCount -
// fRead -
// ----------------------------------------------------------------------------
#pragma optimize("", off)
BOOL
CSHXDisk::SetupDMA(
PSG_BUF pSgBuf,
DWORD dwSgCount,
BOOL fRead
)
{
DWORD dwActualBytes;
dwActualBytes = (pSgBuf->sb_len > ATAPI_BUFFER_SIZE) ? ATAPI_BUFFER_SIZE : pSgBuf->sb_len;
WRITE_REGISTER_ULONG(m_pAtapiControl+ATAPI_DMAS_OFFSET, ATAPI_BUFFER_BASE&0x07fffffc);
WRITE_REGISTER_ULONG(m_pAtapiControl+ATAPI_DMAC_OFFSET, dwActualBytes);
if ( !fRead ){
BYTE dmy;
LPBYTE pBuffer = (PBYTE)MapPtrToProcess((LPVOID)pSgBuf->sb_buf, GetCallerProcess());
memcpy(m_pAtapiBuffer, pBuffer, pSgBuf->sb_len);
dmy = *((PBYTE)m_pAtapiBuffer + pSgBuf->sb_len - 1); // Coherency measures
}
return TRUE;
}
#pragma optimize("", on)
// ----------------------------------------------------------------------------
// Function: BeginDMA
// Begin DMA transfer
//
// Parameters:
// fRead -
// ----------------------------------------------------------------------------
BOOL
CSHXDisk::BeginDMA(
BOOL fRead
)
{
if ( fRead ){
if ( m_dwDevice ){
if((m_bTransferMode & 0xF0) == 0x40){
WRITE_REGISTER_ULONG(m_pAtapiControl+ATAPI_CTRL_OFFSET, 0x00000035); // Slave,BUSSEL,UDMAEN,Read,START
}
else{
WRITE_REGISTER_ULONG(m_pAtapiControl+ATAPI_CTRL_OFFSET, 0x00000025); // Slave,BUSSEL,Read,START
}
}else{
if((m_bTransferMode & 0xF0) == 0x40){
WRITE_REGISTER_ULONG(m_pAtapiControl+ATAPI_CTRL_OFFSET, 0x00000075); // Master,BUSSEL,UDMAEN,Read,START
}
else{
WRITE_REGISTER_ULONG(m_pAtapiControl+ATAPI_CTRL_OFFSET, 0x00000065); // Master,BUSSEL,Read,START
}
}
}else{
if ( m_dwDevice ){
if((m_bTransferMode & 0xF0) == 0x40){
WRITE_REGISTER_ULONG(m_pAtapiControl+ATAPI_CTRL_OFFSET, 0x00000031); // Slave,BUSSEL,UDMAEN,Write,START
}
else{
WRITE_REGISTER_ULONG(m_pAtapiControl+ATAPI_CTRL_OFFSET, 0x00000021); // Slave,BUSSEL,Write,START
}
}else{
if((m_bTransferMode & 0xF0) == 0x40){
WRITE_REGISTER_ULONG(m_pAtapiControl+ATAPI_CTRL_OFFSET, 0x00000071); // Master,BUSSEL,UDMAEN,Write,START
}
else{
WRITE_REGISTER_ULONG(m_pAtapiControl+ATAPI_CTRL_OFFSET, 0x00000061); // Master,BUSSEL,Write,START
}
}
}
return TRUE;
}
// ----------------------------------------------------------------------------
// Function: EndDMA
// End DMA transfer
//
// Parameters:
// None
// ----------------------------------------------------------------------------
BOOL
CSHXDisk::EndDMA(
)
{
DWORD dwStatus = READ_REGISTER_ULONG(m_pAtapiControl+ATAPI_STAT_OFFSET);
if ( (dwStatus & 0x00000006) != 0x00000002 ){ //DMA Finish?
BOOL bCount = 0;
while (TRUE){
StallExecution(100);
bCount++;
dwStatus = READ_REGISTER_ULONG(m_pAtapiControl+ATAPI_STAT_OFFSET);
if ( (dwStatus & 0x00000006) != 0x00000002 ){
if ( bCount > 2000 ){
return FALSE;
}
}else{
break;
}
}
}
WRITE_REGISTER_ULONG(m_pAtapiControl+ATAPI_STAT_OFFSET, 0x00000000); // clear status
return TRUE;
}
// ----------------------------------------------------------------------------
// Function: AbortDMA
// Abort DMA transfer
//
// Parameters:
// None
// ----------------------------------------------------------------------------
BOOL
CSHXDisk::AbortDMA(
)
{
WRITE_REGISTER_ULONG(m_pAtapiControl+ATAPI_CTRL_OFFSET, 0x00000002); //stop DMA
WRITE_REGISTER_ULONG(m_pAtapiControl+ATAPI_STAT_OFFSET, 0x00000000); // clear status
return FALSE;
}
// ----------------------------------------------------------------------------
// Function: CompleteDMA
// Complete DMA transfer
//
// Parameters:
// pSgBuf -
// dwSgCount -
// fRead -
// ----------------------------------------------------------------------------
BOOL
CSHXDisk::CompleteDMA(
PSG_BUF pSgBuf,
DWORD dwSgCount,
BOOL fRead
)
{
DWORD dwOffset = 0;
DWORD dwBytesRead=0;
DWORD dwReadOffset=0;
DWORD dwRemain=0;
DWORD dwBufferOffset=0;
DWORD dwLen=0;
if ( fRead ){
for( DWORD dwSg=0; dwSg < dwSgCount; dwSg++ ){
LPBYTE pBuffer = (PBYTE)MapPtrToProcess((LPVOID)pSgBuf->sb_buf, GetCallerProcess());
memcpy(pBuffer, m_pAtapiBuffer+dwOffset, pSgBuf->sb_len);
dwOffset += pSgBuf->sb_len;
pSgBuf++;
}
}
return TRUE;
}
void CSHXDisk::SetDeviceTiming(DWORD dwDevice, BYTE dwPioMode, BYTE dwDmaMode, BYTE dwUdmaMode)
{
DWORD dwMask;
DWORD dwPioTiming = 0;
DWORD dwMDmaTiming = 0;
DWORD dwUDmaTiming = 0;
DWORD dwUDmaTimingValue[5] = {0x0191, 0x010e, 0x00cb, 0x00ab, 0x006b};
DWORD dwMDmaTimingValue[3] = {0x00000637, 0x00000209, 0x000001a8};
DWORD dwPioTimingValue[5] = {0x00003df0, 0x000028f6, 0x000022f4, 0x0000134c, 0x00000d44};
dwPioTiming = dwPioTimingValue[dwPioMode];
dwMDmaTiming = dwMDmaTimingValue[dwDmaMode];
dwUDmaTiming = dwUDmaTimingValue[dwUdmaMode];
if ( dwDevice ){
dwPioTiming <<= 16;
dwMDmaTiming <<= 16;
dwUDmaTiming <<= 16;
dwMask = 0x0000ffff;
}else{
dwMask = 0xffff0000;
}
WRITE_REGISTER_ULONG(m_pAtapiControl+ATAPI_PIOT_OFFSET,
(READ_REGISTER_ULONG(m_pAtapiControl+ATAPI_PIOT_OFFSET) & dwMask) | dwPioTiming);
WRITE_REGISTER_ULONG(m_pAtapiControl+ATAPI_MDMA_OFFSET,
(READ_REGISTER_ULONG(m_pAtapiControl+ATAPI_MDMA_OFFSET) & dwMask) | dwMDmaTiming);
WRITE_REGISTER_ULONG(m_pAtapiControl+ATAPI_UDMA_OFFSET,
(READ_REGISTER_ULONG(m_pAtapiControl+ATAPI_UDMA_OFFSET) & dwMask) | dwUDmaTiming);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -