📄 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>
#include <bsp_cfg.h>
/*++
Module Name:
diskmain.cpp
Abstract:
Base ATA/ATAPI device abstraction.
Revision History:
--*/
// 48-bit LBA support
#define ATA_CMD_FLUSH_CACHE_EXT 0xEA
#define ATA_CMD_READ_DMA_EXT 0x25
#define ATA_CMD_READ_DMA_QUEUED_EXT 0x26
#define ATA_CMD_READ_LOG_EXT 0x2F
#define ATA_CMD_READ_MULTIPLE_EXT 0x29
#define ATA_CMD_READ_NATIVE_MAX_ADDRESS_EXT 0x27
#define ATA_CMD_READ_SECTOR_EXT 0x24
#define ATA_CMD_READ_VERIFY_SECTOR 0x42
#define ATA_CMD_SET_MAX_ADDRESS_EXT 0x37
#define ATA_CMD_WRITE_DMA_EXT 0x35
#define ATA_CMD_DMA_QUEUED_EXT 0x36
#define ATA_CMD_WRITE_LOG_EXT 0x3F
#define ATA_CMD_WRITE_MULTIPLE_EXT 0x39
#define ATA_CMD_WRITE_SECTOR_EXT 0x34
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_fUseLBA48 = 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));
m_dwCurrentUDMAMode = 0;
}
// ----------------------------------------------------------------------------
// 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);
}
if (m_pPort->m_pDskReg[m_dwDeviceId]->dwEnablePDMA)
{
HalFreeCommonBuffer( NULL, 0, m_DMAPhyaddress, m_pDMAVirtualAddress, FALSE );
}
}
// ----------------------------------------------------------------------------
// 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 (TRUE || !(m_dwDeviceFlags & DFLAGS_DEVICE_INITIALIZED)) { // for Wakeup 070625 Hsjang
// 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"
)));
RETAILMSG(1, (_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;
}
if (m_pPort->m_pDskReg[m_dwDeviceId]->dwEnablePDMA)
{
DMA_ADAPTER_OBJECT dmaAdapter;
dmaAdapter.ObjectSize = sizeof(dmaAdapter);
dmaAdapter.InterfaceType = Internal;
dmaAdapter.BusNumber = 0;
m_pDMAVirtualAddress= (PBYTE)HalAllocateCommonBuffer( &dmaAdapter, m_pPort->m_pDskReg[m_dwDeviceId]->dwDoubleBufferSize, &m_DMAPhyaddress, FALSE );
}
// set write cache mode, if write cache mode supported
//SetPioMode(m_Id.AdvancedPIOxferreserved);
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"
)));
RETAILMSG(1, (_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"
)));
RETAILMSG(1, (_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"
)));
RETAILMSG(1, (_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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -