📄 diskmain.cpp
字号:
//**********************************************************************
//
// Filename: diskmain.cpp
//
// Description:
//
// 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
//
//**********************************************************************
//
// 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.
//
//**********************************************************************
#include <atamain.h>
#define MIN(a,b) (a)<(b)? (a):(b);
static HANDLE g_hTestUnitReadyThread = NULL;
/*------------------------------------------------------------------------------------------*/
BOOL CDisk::Init(HKEY hActiveKey)
{
DWORD dwOption = 0;
BOOL bEnableInterrupts = FALSE;
BOOL bRet = TRUE;
//
// Read in the registry settings first.
//
//dwOption = 0;
//if (AtaGetRegistryValue(m_hDevKey, REG_VALUE_DMAENABLE, &dwOption) && (dwOption == 1))
//{
// m_fDMAActive = TRUE;
//}
dwOption = 0;
if (AtaGetRegistryValue(m_hDevKey, REG_VALUE_UDMAENABLE, &dwOption) && (dwOption == 1))
{
m_fUDMAActive = TRUE;
}
// dwOption = 0;
// if (AtaGetRegistryValue(m_hDevKey, REG_VALUE_MDMA_MODE, &dwOption) )
// {
// m_ulBestMwDmaModeReg = dwOption;
// }
//
// MDMA is currently disabled. Future EP931x chips may not have DMA working.
//
m_ulBestMwDmaModeReg = -1;
dwOption = 0;
if (AtaGetRegistryValue(m_hDevKey, REG_VALUE_UDMA_MODE, &dwOption) )
{
m_ulBestUDmaModeReg = dwOption;
}
dwOption = 0;
if (AtaGetRegistryValue(m_hDevKey, REG_VALUE_DVD, &dwOption) )
{
if(dwOption == 1)
{
m_dwDeviceFlags |= DFLAGS_DEVICE_ISDVD;
}
}
TakeCS();
if (m_dwDeviceFlags & DFLAGS_DEVICE_INITIALIZED)
{
DEBUGMSG( ZONE_INIT, (TEXT("ATAPI:ResetController Skipped - Device !!!\r\n")));
}
else
{
SelectDevice();
if(m_dwDeviceId == 0)
{
if (!(bRet = ResetController(FALSE)))
{
if (!(bRet = ResetController(TRUE)))
{
DEBUGMSG( ZONE_INIT, (TEXT("ATAPI:AtaInitDevice: ResetController failed!!")));
ReleaseCS();
goto Exit;
}
}
}
else
{
AtapiSoftReset();
}
WaitOnBusy(TRUE);
bEnableInterrupts = TRUE;
m_dwDeviceFlags |= DFLAGS_DEVICE_INITIALIZED;
}
ReleaseCS();
//
// Issue Identify Command and process received data.
//
if (!(bRet = Identify()))
{
DEBUGMSG( ZONE_INIT, (TEXT("ATAPI:Identify Command failed !!!\r\n")));
goto Exit;
}
if (bEnableInterrupts)
{
// Enable interrupts
SelectDevice();
WriteDriveController( ATA_CTRL_ENABLE_INTR);
SelectDevice();
WriteAltDriveController(ATA_CTRL_ENABLE_INTR);
EnableInterrupt();
}
#if 0
if (IsAtapiDevice()) {
DEBUGMSG( ZONE_INIT, (TEXT("ATAPI:Atapi Device ...performing soft reset !\r\n")));
AtapiSoftReset();
}
#endif
// Get MediaCheckTime if it is removable device.
if (IsRemoveableDevice()) {
if (!AtaGetRegistryValue(m_hDevKey, REG_VALUE_MEDIACHECKTIME, &m_dwUnitReadyTime)) {
m_dwUnitReadyTime = DEFAULT_MEDIA_CHECK_TIME;
DEBUGMSG( ZONE_INIT, (TEXT("ATAPI:ConfigureDisk MediaCheckTime using default value of %ld\r\n"), m_dwUnitReadyTime));
}
}
DEBUGMSG(ZONE_INIT, (TEXT("ATAPI:Init Device Ready!!!( DevceId; %x )\r\n"), m_dwDeviceId));
//
// Test Code.
//
// TestDisk();
//dwOption = 0;
//if (AtaGetRegistryValue(m_hDevKey, REG_VALUE_SETTINGS, &dwOption))
//{
// if (IsAtapiDevice())
// {
// if (dwOption & ATA_SETTINGS_CDDMA)
// {
// m_fDMAActive = TRUE;
// }
// else
// {
// m_fDMAActive = FALSE;
// }
// }
// else
// {
// if (dwOption & ATA_SETTINGS_HDDMA)
// {
// m_fDMAActive = TRUE;
// }
// else
// {
// m_fDMAActive = FALSE;
// }
// }
// }
Exit:
return bRet;
}
//****************************************************************************
// CDisk::ResetController
//****************************************************************************
// Both disks respond to reset. Use AtapiSoftReset to reset a single device.
//
//
#define ZONE_INIT 0
#define ZONE_RESET 0
BOOL CDisk::ResetController(BOOL bSoftReset)
{
DWORD dwAttempts;
BYTE bStatus;
DEBUGMSG(ZONE_INIT, (TEXT("ATAPI:ResetController entered\r\n")));
// WriteAltDriveController( 0x8);
// Read the status first
bStatus = GetBaseStatus();
RETAILMSG(ZONE_INIT, (TEXT("ATADISK:ResetController - ATA_STATUS = %02X Error=%x!\r\n"), bStatus, GetError()));
//
// We select the secondary device , that way we will get a response through the shadow
// if only the master is connected. Otherwise we will get a response from
// the secondary device
//
WriteAltDriveController(ATA_CTRL_RESET );
// WriteAltDriveController(ATA_CTRL_RESET | ATA_CTRL_ENABLE_INTR);
Sleep(1); //host should hold rest signal at least 5 us.
WriteAltDriveController(ATA_CTRL_ENABLE_INTR);
Sleep(2); // host should check status register when RESET is cleared 2 ms later.
if( WaitForDisc( WAIT_TYPE_BUSY, 200, 1 ) )
RETAILMSG(ZONE_RESET, (TEXT("ATADISK:ResetController Can't get BUSY %x\r\n"), GetBaseStatus() ));
else
RETAILMSG(ZONE_RESET, (TEXT("ATADISK:ResetController get BUSY successfully %x \r\n"), GetBaseStatus() ));
if( WaitForDisc( WAIT_TYPE_READY, 2000, 10) )
RETAILMSG(ZONE_RESET, (TEXT("ATADISK:ResetController Can't get READY %x\r\n"), GetBaseStatus() ));
else
RETAILMSG(ZONE_RESET, (TEXT("ATADISK:ResetController get READY successfully %x \r\n"), GetBaseStatus() ));
if (bSoftReset)
{
DEBUGMSG( ZONE_INIT, (TEXT("ATAPI:ResetController ...performing soft reset !\r\n")));
AtapiSoftReset();
}
else
{
StallExecution(50000);
}
for (dwAttempts = 0; dwAttempts < MAX_RESET_ATTEMPTS; dwAttempts++)
{
bStatus = GetBaseStatus();
if ((bStatus != ATA_STATUS_IDLE) && (bStatus != 0x0))
{
DEBUGMSG( ZONE_INIT, (TEXT("ATAPI::ResetController: Current drive status = 0x%2.2X\r\n"), bStatus));
if (bStatus == 0xFF)
{
SetDriveHead( ATA_HEAD_DRIVE_2);
bStatus = GetBaseStatus();
if ((bStatus != ATA_STATUS_IDLE) && (bStatus != 0x0))
{
DEBUGMSG(ZONE_INIT, (TEXT("ATAPI::ResetController Drive 2 status = 0x%2.2X\r\n"), bStatus));
if (bStatus == 0xFF)
{
DEBUGMSG(ZONE_INIT, (TEXT("ATAPI::ResetController no second device\r\n")));
return FALSE;
}
}
else
{
break;
}
}
StallExecution(50000);
}
else
{
break;
}
}
if (dwAttempts == MAX_RESET_ATTEMPTS)
{
RETAILMSG( ZONE_INIT, (TEXT("ATAPIPCI:AtaResetController no response after %ld reset attempts\r\n"), MAX_RESET_ATTEMPTS));
return FALSE;
}
RETAILMSG( ZONE_RESET, (TEXT("ATAPI:ResetController: Controller reset done\r\n")));
return TRUE;
}
/*------------------------------------------------------------------------------------------*/
BOOL CDisk::Identify()
{
DWORD dwBlockSize;
WORD wDevType;
PUSHORT tempS;
BYTE tempByte;
int k;
TakeCS();
// WaitOnBusy(FALSE);
SelectDevice();
//a command should be sent only when no BUSY & READY.
if( WaitForDisc( WAIT_TYPE_NOT_BUSY, 500,5 ) )
RETAILMSG(ZONE_INIT, (TEXT("ATADISK:Identify Can't get NO BUSY %x device-%d\r\n"), GetBaseStatus(),m_dwDevice ));
else
RETAILMSG(ZONE_INIT, (TEXT("ATADISK:Identify get NO BUSY successfully %x device-%d\r\n"), GetBaseStatus(),m_dwDevice ));
if( WaitForDisc( WAIT_TYPE_READY, 500, 5) )
RETAILMSG(ZONE_INIT, (TEXT("ATADISK:Identify Can't get READY %x device-%d\r\n"), GetBaseStatus(),m_dwDevice ));
else
RETAILMSG(ZONE_INIT, (TEXT("ATADISK:Identify get READY successfully %x device-%d\r\n"), GetBaseStatus(),m_dwDevice ));
//RETAILMSG(1, (TEXT("ATADISK:Identify get READY successfully %x device-%d\r\n"), GetBaseStatus(),m_dwDevice ));
Sleep( 1 ); //this Sleep and the following one are only for delay, if don't do it. some card can't work.
// I don't know why, as the ATA specification. it don't need.
WriteCommand(ATA_CMD_IDENTIFY);
if (WaitOnBusy(FALSE) & ATA_STATUS_ERROR)
{
// Not ATA Device. Try ATAPI !!!.
if (GetError() & ATA_ERROR_ABORTED)
{
//
// Try ATAPI!!
//
SelectDevice();
WriteCommand(ATAPI_CMD_IDENTIFY);
if (WaitOnBusy(FALSE) & ATA_STATUS_ERROR)
{
DEBUGMSG( ZONE_ERROR, (TEXT("ATAPI:Identify failed (Device: %x)\r\n"),m_dwDeviceId));
ReleaseCS();
return(FALSE);
}
}
m_fAtapiDevice = TRUE;
}
//to be sure we get DRQ signal, then read identify data out.
//otherwise, we'll get error identify data, because some data can't be read out.
//and device is in pending DRQ status.
if( WaitForDisc( WAIT_TYPE_DRQ, 1000, 10 ) )
RETAILMSG(ZONE_INIT, (TEXT("ATADISK:Identify Can't get DRQ %x device-%d\r\n"), GetBaseStatus(),m_dwDevice ));
else
RETAILMSG(ZONE_INIT, (TEXT("ATADISK:Identify get DRQ successfully %x device-%d\r\n"), GetBaseStatus(),m_dwDevice ));
//RETAILMSG(1, (TEXT("ATADISK:Identify get DRQ successfully %x device-%d\r\n"), GetBaseStatus(),m_dwDevice ));
Sleep(1);
dwBlockSize = sizeof(IDENTIFY_DATA);
ASSERT( dwBlockSize <= BYTES_PER_SECTOR);
if (m_f16Bit)
{
dwBlockSize /= 2;
ReadWordBuffer( (PWORD)&m_Id, dwBlockSize);
}
else
{
ReadByteBuffer( (PBYTE)&m_Id, dwBlockSize);
}
// Read the rest of data if available !!! And throw it away !!!
//
while (GetAltStatus() & ATA_STATUS_DATA_REQ )
{
if (m_f16Bit)
ReadWord();
else
ReadByte();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -