?? diskmain.cpp
字號:
//
// 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>
/*++
Module Name:
diskmain.cpp
Abstract:
Base ATA/ATAPI device abstraction.
Revision History:
--*/
static HANDLE g_hTestUnitReadyThread = NULL;
// ----------------------------------------------------------------------------
// Function: CDisk
// Constructor
//
// Parameters:
// None
// ----------------------------------------------------------------------------
CDisk::CDisk(
)
{
// empty
}
// ----------------------------------------------------------------------------
// Function: CDisk
// Constructor
//
// Parameters:
// hKey -
// ----------------------------------------------------------------------------
CDisk::CDisk(
HKEY hKey
)
{
m_dwDeviceFlags = 0;
m_pNextDisk = NULL;
m_pATAReg = NULL;
m_pATARegAlt = NULL;
m_dwDevice = 0;
m_hDevKey = hKey;
m_dwDeviceId = 0;
m_dwPort = 0;
m_f16Bit = FALSE;
m_fAtapiDevice = FALSE;
m_fInterruptSupported = FALSE;
m_szDiskName = NULL;
m_fDMAActive = FALSE;
m_dwOpenCount = 0;
m_dwUnitReadyTime = 0;
m_dwStateFlag = 0;
m_dwLastCheckTime = 0;
m_dwStride = 1;
m_pDiskPower = NULL;
m_rgbDoubleBuffer = NULL;
m_pPort = NULL;
// init generic structures
InitializeCriticalSection(&m_csDisk);
memset(&m_Id, 0, sizeof(IDENTIFY_DATA));
memset(&m_DiskInfo, 0, sizeof(DISK_INFO));
memset(&m_InqData, 0, sizeof(INQUIRY_DATA));
}
// ----------------------------------------------------------------------------
// Function: ~CDisk
// Destructor
//
// Parameters:
// None
// ----------------------------------------------------------------------------
CDisk::~CDisk(
)
{
if (m_hDevKey) {
RegCloseKey(m_hDevKey);
}
if(m_pDiskPower != NULL) {
delete m_pDiskPower;
}
DeleteCriticalSection(&m_csDisk);
// deallocate double buffer, if present
if (NULL != m_rgbDoubleBuffer) {
LocalFree((HLOCAL)m_rgbDoubleBuffer);
}
}
// ----------------------------------------------------------------------------
// Function: StallExecution
// Stall execution for the specified period of time
//
// Parameters:
// dwTime -
// ----------------------------------------------------------------------------
void
CDisk::StallExecution(
DWORD dwTime
)
{
if ((dwTime >= 100) && (m_dwDeviceFlags & DFLAGS_DEVICE_CDROM)) {
Sleep (dwTime / 100);
}
else {
::StallExecution(dwTime * 10);
}
}
#define HELPER_
// These functions should be inlined or converted to macros
void CDisk::TakeCS() { EnterCriticalSection(&m_csDisk); }
void CDisk::ReleaseCS() { LeaveCriticalSection(&m_csDisk); }
void CDisk::Open() { InterlockedIncrement((LONG *)&m_dwOpenCount); }
void CDisk::Close() { InterlockedDecrement((LONG *)&m_dwOpenCount); }
BOOL CDisk::IsAtapiDevice() { return m_fAtapiDevice; }
BOOL CDisk::IsCDRomDevice() { return (((m_Id.GeneralConfiguration >> 8) & 0x1f) == ATA_IDDEVICE_CDROM); }
BOOL CDisk::IsDVDROMDevice() { return TRUE; }
BOOL CDisk::IsDiskDevice() { return (((m_Id.GeneralConfiguration >> 8) & 0x1f) == ATA_IDDEVICE_DISK); }
BOOL CDisk::IsRemoveableDevice() { return (m_Id.GeneralConfiguration & IDE_IDDATA_REMOVABLE); }
BOOL CDisk::IsDMASupported() { return ((m_Id.Capabilities & IDENTIFY_CAPABILITIES_DMA_SUPPORTED) && m_fDMAActive); }
BOOL CDisk::IsDRQTypeIRQ() { return ((m_Id.GeneralConfiguration >> 5) & 0x0003) == ATA_DRQTYPE_INTRQ; }
WORD CDisk::GetPacketSize() { return m_Id.GeneralConfiguration & 0x0003 ? 16 : 12; }
BOOL CDisk::IsValidCommandSupportInfo() { return ((m_Id.CommandSetSupported2 & (1 << 14)) && !(m_Id.CommandSetSupported2 & (1 << 15))); }
BOOL CDisk::IsWriteCacheSupported() { return ((m_Id.CommandSetSupported1 & COMMAND_SET_WRITE_CACHE_SUPPORTED) && IsValidCommandSupportInfo()); }
BOOL CDisk::IsPMSupported() { return (m_Id.CommandSetSupported1 & COMMAND_SET_POWER_MANAGEMENT_SUPPORTED && IsValidCommandSupportInfo()); }
BOOL CDisk::IsPMEnabled() { return (IsPMSupported() && (m_Id.CommandSetFeatureEnabled1 & COMMAND_SET_POWER_MANAGEMENT_ENABLED)); }
// These functions are called (1x) in atamain and should be inlined
void CDisk::SetActiveKey(TCHAR *szActiveKey)
{
wcsncpy(m_szActiveKey, szActiveKey, MAX_PATH - 1);
m_szActiveKey[MAX_PATH - 1] = 0;
}
void CDisk::SetDeviceKey(TCHAR *szDeviceKey)
{
wcsncpy(m_szDeviceKey, szDeviceKey, MAX_PATH - 1);
m_szDeviceKey[MAX_PATH - 1] = 0;
}
#define _HELPER
// ----------------------------------------------------------------------------
// Function: InitController
// Reset the controller and determine whether a device is present on the
// channel; if a device is present, then query and store its capabilities
//
// Parameters:
// fForce -
// ----------------------------------------------------------------------------
BOOL
CDisk::InitController(
BOOL fForce
)
{
BOOL bRet = TRUE;
// if the controller has not already been reset, then perform a soft-reset
// to enable the channel
if (!(m_dwDeviceFlags & DFLAGS_DEVICE_INITIALIZED)) {
// perform a soft-reset on the controller; if we don't do this, then
// we won't be able to detect whether or not devices are present on the
// channel
bRet = ResetController(FALSE);
if (!bRet) {
goto exit;
}
// if interrupt is supported, enable interrupt
if (m_fInterruptSupported) {
SelectDevice();
WriteAltDriveController(ATA_CTRL_ENABLE_INTR);
EnableInterrupt();
}
}
// issue IDENTIFY DEVICE and/or IDENTIFY PACKET DEVICE
bRet = Identify();
if (!bRet) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!CDisk::InitController> Device did not respond to identify\r\n"
)));
goto exit;
}
else {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!CDisk::InitController> Device responded to identify\r\n"
)));
m_dwDeviceFlags |= DFLAGS_DEVICE_INITIALIZED;
}
exit:;
return bRet;
}
// ----------------------------------------------------------------------------
// Function: ConfigureRegisterBlock
// This function is called by DSK_Init before any other CDisk function to
// set up the register block.
//
// Parameters:
// dwStride -
// ----------------------------------------------------------------------------
VOID
CDisk::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;
m_dwAltStatusOffset = ATA_REG_ALT_STATUS_CS1 * dwStride;
m_dwAltDrvCtrl = ATA_REG_DRV_CTRL_CS1 * dwStride;
}
// ----------------------------------------------------------------------------
// Function: Init
// This function is called by the IDE/ATA controller enumerator to trigger
// the initialization of a device
//
// Parameters:
// hActiveKey -
// ----------------------------------------------------------------------------
BOOL
CDisk::Init(
HKEY hActiveKey
)
{
BOOL fRet = FALSE;
// replicate CDisk::ReadRegistry
m_dwWaitCheckIter = m_pPort->m_pController->m_pIdeReg->dwStatusPollCycles;
m_dwWaitSampleTimes = m_pPort->m_pController->m_pIdeReg->dwStatusPollsPerCycle;
m_dwWaitStallTime = m_pPort->m_pController->m_pIdeReg->dwStatusPollCyclePause;
m_dwDiskIoTimeOut = DEFAULT_DISK_IO_TIME_OUT;
// replicate CDisk::ReadSettings
m_dwUnitReadyTime = DEFAULT_MEDIA_CHECK_TIME;
// if DMA=2 and this is not an ATAPI device, then we'll set m_fDMAActive in Identify
if (1 == m_pPort->m_pDskReg[m_dwDeviceId]->dwDMA) { // 0=PIO, 1=DMA, 2=ATA DMA only
m_fDMAActive = TRUE;
}
m_dwDMAAlign = m_pPort->m_pController->m_pIdeReg->dwDMAAlignment;
// m_dwDeviceFlags |= DFLAGS_DEVICE_ISDVD; this is ignored
if (m_pPort->m_pDskReg[m_dwDeviceId]->dwInterruptDriven) {
m_fInterruptSupported = TRUE;
}
// initialize controller
if (!InitController(TRUE)) {
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CDisk::Init> Failed to initialize device\r\n"
)));
goto exit;
}
// set write cache mode, if write cache mode supported
if (m_Id.CommandSetSupported1 & 0x20) {
if (SetWriteCacheMode(m_pPort->m_pDskReg[m_dwDeviceId]->dwWriteCache)) {
if (m_pPort->m_pDskReg[m_dwDeviceId]->dwWriteCache) {
m_dwDeviceFlags |= DFLAGS_USE_WRITE_CACHE;
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CDisk::Init> Enabled write cache\r\n"
)));
}
else {
m_dwDeviceFlags &= ~DFLAGS_USE_WRITE_CACHE;
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CDisk::Init> Disabled on device write cache\r\n"
)));
}
}
else {
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CDisk::Init> Failed to set write cache mode\r\n"
)));
}
}
// set read look-ahead, if read look-ahead supported
if ((m_Id.CommandSetSupported1 & 0x40) && m_pPort->m_pDskReg[m_dwDeviceId]->dwLookAhead) {
if (SetLookAhead()) {
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CDisk::Init> Enabled read look-ahead\r\n"
)));
}
else {
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CDisk::Init> Failed to enable read look-ahead\r\n"
)));
}
}
// set transfer mode, if a specific transfer mode was specified in the
// device's instance key
BYTE bTransferMode = (BYTE)m_pPort->m_pDskReg[m_dwDeviceId]->dwTransferMode;
if (0xFF != bTransferMode) {
if (0x00 == bTransferMode) {
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CDisk::Init> Selecting PIO default mode(0x%x)\r\n"
), bTransferMode));
}
else if (0x01 == bTransferMode) {
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CDisk::Init> Selecting PIO default mode(0x%x); disabled IORDY\r\n"
), bTransferMode));
}
else if ((bTransferMode & 0xF8) == 0x08) {
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CDisk::Init> Selecting PIO flow control mode %d (0x%x)\r\n"
), (bTransferMode & 0x08), bTransferMode));
}
else if ((bTransferMode & 0xF0) == 0x20) {
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CDisk::Init> Selecting Multi-word DMA mode %d (0x%x)\r\n"
), bTransferMode, bTransferMode));
}
else if ((bTransferMode & 0xF0) == 0x40) {
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CDisk::Init> Selecting Ultra DMA mode %d (0x%x)\r\n"
), bTransferMode, bTransferMode));
}
else {
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CDisk::Init> Unknown transfer mode(0x%x)\r\n"
), bTransferMode));
}
// @bTransferMode is a valid transfer mode
if (!SetTransferMode(bTransferMode)) {
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CDisk::Init> Failed to set transfer mode(0x%x)\r\n"
), bTransferMode));
}
}
fRet = TRUE;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -