📄 atamain.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.
//
//------------------------------------------------------------------------------
//
// 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: atamain.cpp
//
// IDE/ATA and ATA/ATAPI are stream interface drivers.
//
//------------------------------------------------------------------------------
#include <windows.h>
#include <atamx27.h>
// DLL instance handle; differentiate this driver from other ATAPI instances
// (what other buses?)
HINSTANCE g_hInstance;
// List of active devices/disks
CDisk *g_pDiskRoot = NULL;
// Protect global variables
CRITICAL_SECTION g_csMain;
// Debug
extern "C" BOOL RegisterDbgZones(HMODULE hMod, LPDBGPARAM lpdbgparam);
// Definitions
typedef CDisk *(* POBJECTFUNCTION)(HKEY hKey);
//------------------------------------------------------------------------------
//
// Function : CPort
// CPort Constructor
// Parameters:
// void
// Return:
// void
//
//------------------------------------------------------------------------------
CPort::CPort()
{
InitializeCriticalSection(&m_csPort);
// initialize flags
m_fInitialized = 0;
m_dwFlag = 0;
// initialize I/O ports
m_dwRegBase = 0;
m_dwRegAlt = 0;
m_dwBMR = 0;
m_dwBMRStatic = 0;
// initialize interrupt data
m_hIRQEvent = NULL;
m_hThread = NULL;
m_dwSysIntr = SYSINTR_NOP;
m_dwSysIntrRX = SYSINTR_NOP;
m_dwSysIntrTX = SYSINTR_NOP;
m_dwIrq = IRQ_ATA;
}
//------------------------------------------------------------------------------
//
// Function : ~CPort
// CPort Destructor
// Parameters:
// void
// Return:
// void
//
//------------------------------------------------------------------------------
CPort::~CPort(
)
{
DeleteCriticalSection(&m_csPort);
// unmap ATA channel's I/O windows
if (m_dwRegBase) {
MmUnmapIoSpace((LPVOID)m_dwRegBase, ATA_REG_LENGTH);
}
if (m_dwRegAlt) {
MmUnmapIoSpace((LPVOID)m_dwRegAlt, ATA_REG_LENGTH);
}
if (m_dwBMR) {
MmUnmapIoSpace((LPVOID)m_dwBMR, 16);
}
// close interrupt event handle
if (m_hIRQEvent) {
CloseHandle(m_hIRQEvent);
}
// close interrupt thread
if (m_hThread) {
CloseHandle(m_hThread);
}
// disable interrupt
if (m_dwSysIntr != SYSINTR_NOP) {
InterruptDisable(m_dwSysIntr);
}
// disable interrupt
if (m_dwSysIntrRX != SYSINTR_NOP) {
InterruptDisable(m_dwSysIntrRX);
}
// disable interrupt
if (m_dwSysIntrTX != SYSINTR_NOP) {
InterruptDisable(m_dwSysIntrTX);
}
// free DSK_ registry value set
if (m_pDskReg[0]) {
LocalFree(m_pDskReg[0]);
}
if (m_pDskReg[1]) {
LocalFree(m_pDskReg[1]);
}
}
//------------------------------------------------------------------------------
//
// Function : TakeCS
// Acquire exclusive access to IDE/ATA channel's I/O window
// Parameters:
// void
// Return:
// void
//
//------------------------------------------------------------------------------
VOID
CPort::TakeCS(
)
{
EnterCriticalSection(&m_csPort);
}
//------------------------------------------------------------------------------
//
// Function : ReleaseCS
// Release exclusive access to IDE/ATA channel's I/O window
// Parameters:
// void
// Return:
// void
//
//------------------------------------------------------------------------------
VOID
CPort::ReleaseCS(
)
{
LeaveCriticalSection(&m_csPort);
}
//------------------------------------------------------------------------------
//
// Function : AtaLoadRegKey
// Write I/O window and interrupt data to debug output
//
// Parameters:
// void
// Return:
// void
//
//------------------------------------------------------------------------------
VOID
CPort::PrintInfo(
)
{
DEBUGMSG(ZONE_INIT, (TEXT("dwRegBase = %08X\r\n"), m_dwRegBase));
DEBUGMSG(ZONE_INIT, (TEXT("dwRegAlt = %08X\r\n"), m_dwRegAlt));
DEBUGMSG(ZONE_INIT, (TEXT("dwSysIntr = %08X\r\n"), m_dwSysIntr));
DEBUGMSG(ZONE_INIT, (TEXT("dwIrq = %08X\r\n"), m_dwIrq));
}
//------------------------------------------------------------------------------
//
// Function : AtaLoadRegKey
// This function is used by an Xxx_Init function to fetch the name of
// and return a handle to the instance/device ("Key") key from an
// Active key
// Parameters:
// hActiveKey : handle to DSK active Key
// pszDevKey : pointer to device key
// Return:
// return handle to DSK active key, otherwise return NULL handle.
//
//------------------------------------------------------------------------------
HKEY
AtaLoadRegKey(
HKEY hActiveKey,
TCHAR **pszDevKey
)
{
DWORD dwValueType; // registry value type
DWORD dwValueLength = 0; // registry value length
PTSTR szDeviceKey = NULL; // name of device key; value associated with "Key"
HKEY hDeviceKey = NULL; // handle to device key; handle to "Key"
// query the value of "Key" with @dwValueLength=0, to determine the actual
// length of the value (so as to allocate the exact amount of memory)
if (ERROR_SUCCESS == RegQueryValueEx(hActiveKey, DEVLOAD_DEVKEY_VALNAME, NULL, &dwValueType, NULL, &dwValueLength)) {
// allocate just enough memory to store the value of "Key"
szDeviceKey = (PTSTR)LocalAlloc(LPTR, dwValueLength);
if (szDeviceKey) {
// read the actual value of "Key" and null terminate the target buffer
RegQueryValueEx(hActiveKey, DEVLOAD_DEVKEY_VALNAME, NULL, &dwValueType, (PBYTE)szDeviceKey, &dwValueLength);
DEBUGCHK(dwValueLength != 0);
szDeviceKey[(dwValueLength / sizeof(TCHAR)) - 1] = 0;
// open the device key
if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, szDeviceKey, 0, 0, &hDeviceKey)) {
DEBUGMSG(ZONE_INIT, (_T(
"AtaLoadRegyKey> Failed to open %s\r\n"
), szDeviceKey));
hDeviceKey = NULL;
}
}
}
if (!hDeviceKey) {
if (szDeviceKey) {
LocalFree(szDeviceKey);
}
*pszDevKey = NULL;
}
else {
*pszDevKey = szDeviceKey;
}
return hDeviceKey;
}
//------------------------------------------------------------------------------
//
// Function : AtaIsValidDisk
// This function is used to determine whether a target disk instance
// is valid
// Parameters:
// pDisk : Pointer Cdisk object
//
// Return:
// On success return true, Otherwise return flase.
//
//------------------------------------------------------------------------------
BOOL
AtaIsValidDisk(
CDisk *pDisk
)
{
CDisk *pTemp = g_pDiskRoot;
while (pTemp) {
if (pTemp == pDisk) {
return TRUE;
}
pTemp = pTemp->m_pNextDisk;
}
return FALSE;
}
//------------------------------------------------------------------------------
//
// Function : AtaGetRegistryResources
// This function is used to fetch an IDE/ATA channel's I/O window from
// its instance key; this function recovers gracefully if an OEM has a
// proprietary registry configuration that doesn't specify bus type or
// bus number
// Parameters:
// hDevKey : Handle to active device key
// pdwi : Pointer to window info
//
// Return:
// On success return true, Otherwise return flase.
//
//------------------------------------------------------------------------------
BOOL
AtaGetRegistryResources(
HKEY hDevKey,
PDDKWINDOWINFO pdwi
)
{
DEBUGCHK(pdwi != NULL);
if (!pdwi) {
return FALSE;
}
// fetch I/O window information
pdwi->cbSize = sizeof(*pdwi);
if (ERROR_SUCCESS != ::DDKReg_GetWindowInfo(hDevKey, pdwi)) {
return FALSE;
}
// if interface not specified, then assume PCI
if (pdwi->dwInterfaceType == InterfaceTypeUndefined) {
DEBUGMSG(ZONE_WARNING, (_T(
"Ata!AtaGetRegistryResources> bus type not specified, using PCI as default\r\n"
)));
pdwi->dwInterfaceType = PCIBus;
}
return TRUE;
}
//------------------------------------------------------------------------------
//
// Function : GetDSKRegistryValueSet
// This function reads the DSK registry value set from the IDE/ATA
// controller's registry key
//
// Parameters:
// hDSKInstanceKey : Active registry instance key
// pDskReg : Pointer to registry value structure.
//
// Return:
// On success return true, Otherwise return flase.
//
//------------------------------------------------------------------------------
BOOL
GetDSKRegistryValueSet(
HKEY hDSKInstanceKey,
PDSKREG pDskReg
)
{
BOOL fRet;
// fetch device ID
fRet = AtaGetRegistryValue(hDSKInstanceKey, REG_VAL_DSK_DEVICEID, &pDskReg->dwDeviceId);
if (!fRet) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Ata!GetDSKRegistryValueSet> Failed to read %s from DSK instance key\r\n"
), REG_VAL_DSK_DEVICEID));
return FALSE;
}
if (!((0 <= pDskReg->dwDeviceId) && (pDskReg->dwDeviceId <= 3))) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Ata!GetDSKRegistryValueSet> Bad value(%d) for %s in DSK instance key; valid: {0, 1, 2, 3}\r\n"
), pDskReg->dwDeviceId, REG_VAL_DSK_DEVICEID));
return FALSE;
}
// fetch interrupt driven I/O boolean
fRet = AtaGetRegistryValue(hDSKInstanceKey, REG_VAL_DSK_INTERRUPTDRIVEN, &pDskReg->dwInterruptDriven);
if (!fRet) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Ata!GetDSKRegistryValueSet> Failed to read %s from DSK instance key\r\n"
), REG_VAL_DSK_INTERRUPTDRIVEN));
return FALSE;
}
if (pDskReg->dwInterruptDriven >= 2) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Ata!GetDSKRegistryValueSet> Bad value(%d) for %s in DSK instance key; valid: {0, 1}\r\n"
), pDskReg->dwInterruptDriven, REG_VAL_DSK_INTERRUPTDRIVEN));
return FALSE;
}
// fetch DMA triple
fRet = AtaGetRegistryValue(hDSKInstanceKey, REG_VAL_DSK_DMA, &pDskReg->dwDMA);
if (!fRet) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Ata!GetDSKRegistryValueSet> Failed to read %s from DSK instance key\r\n"
), REG_VAL_DSK_DMA));
return FALSE;
}
if (pDskReg->dwDMA >= 0x03) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Ata!GetDSKRegistryValueSet> Bad value(%d) for %s in DSK instance key; valid: {0=no DMA, 1 or 2=MDMA/UDMA}\r\n"
), pDskReg->dwDMA, REG_VAL_DSK_DMA));
return FALSE;
}
// fetch double buffer size
fRet = AtaGetRegistryValue(hDSKInstanceKey, REG_VAL_DSK_DOUBLEBUFFERSIZE, &pDskReg->dwDoubleBufferSize);
if (!fRet) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Ata!GetDSKRegistryValueSet> Failed to read %s from DSK instance key\r\n"
), REG_VAL_DSK_DOUBLEBUFFERSIZE));
return FALSE;
}
if (
(pDskReg->dwDoubleBufferSize < REG_VAL_DSK_DOUBLEBUFFERSIZE_MIN) ||
(pDskReg->dwDoubleBufferSize > REG_VAL_DSK_DOUBLEBUFFERSIZE_MAX)
) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Ata!GetDSKRegistryValueSet> Bad value(%d) for %s in DSK instance key; valid: {%d, ..., %d}\r\n"
), pDskReg->dwDoubleBufferSize, REG_VAL_DSK_DOUBLEBUFFERSIZE, REG_VAL_DSK_DOUBLEBUFFERSIZE_MIN, REG_VAL_DSK_DOUBLEBUFFERSIZE_MAX));
return FALSE;
}
// fetch DRQ data block size; this has to be validated by a sub-class
fRet = AtaGetRegistryValue(hDSKInstanceKey, REG_VAL_DSK_DRQDATABLOCKSIZE, &pDskReg->dwDrqDataBlockSize);
if (!fRet) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Ata!GetDSKRegistryValueSet> Failed to read %s from DSK instance key\r\n"
), REG_VAL_DSK_DRQDATABLOCKSIZE));
return FALSE;
}
// fetch write cache boolean
fRet = AtaGetRegistryValue(hDSKInstanceKey, REG_VAL_DSK_WRITECACHE, &pDskReg->dwWriteCache);
if (!fRet) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Ata!GetDSKRegistryValueSet> Failed to read %s from DSK instance key\r\n"
), REG_VAL_DSK_WRITECACHE));
return FALSE;
}
if (pDskReg->dwWriteCache >= 2) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Ata!GetDSKRegistryValueSet> Bad value(%d) for %s in DSK instance key; valid: {0, 1}\r\n"
), pDskReg->dwWriteCache, REG_VAL_DSK_WRITECACHE));
return FALSE;
}
// fetch look-ahead boolean
fRet = AtaGetRegistryValue(hDSKInstanceKey, REG_VAL_DSK_LOOKAHEAD, &pDskReg->dwLookAhead);
if (!fRet) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Ata!GetDSKRegistryValueSet> Failed to read %s from DSK instance key\r\n"
), REG_VAL_DSK_LOOKAHEAD));
return FALSE;
}
if (pDskReg->dwLookAhead >= 2) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Ata!GetDSKRegistryValueSet> Bad value(%d) for %s in DSK instance key; valid: {0, 1}\r\n"
), pDskReg->dwLookAhead, REG_VAL_DSK_LOOKAHEAD));
return FALSE;
}
// fetch transfer mode
fRet = AtaGetRegistryValue(hDSKInstanceKey, REG_VAL_DSK_TRANSFERMODE, &pDskReg->dwTransferMode);
if (!fRet) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Ata!GetDSKRegistryValueSet> Failed to read %s from DSK instance key\r\n"
), REG_VAL_DSK_TRANSFERMODE));
return FALSE;
}
// fetch IORDY Enable
fRet = AtaGetRegistryValue(hDSKInstanceKey, REG_VAL_DSK_IORDYENABLE, &pDskReg->dwIORDYEnable);
if (!fRet) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Ata!GetDSKRegistryValueSet> Failed to read %s from DSK instance key\r\n"
), REG_VAL_DSK_IORDYENABLE));
return FALSE;
}
return TRUE;
}
//------------------------------------------------------------------------------
//
// Function : DSK_Init
// This function is called as a result of IDE_Init calling ActivateDevice on
// HKLM\Drivers\@BUS\@IDEAdapter\DeviceX, to initialize a master or slave
// device on a particular IDE/ATA channel of a particular IDE/ATA controller.
// That is, an "IDE" driver is a bus driver for devices to one its IDE/ATA
// controller's channels.
//
// This function is responsible for creating a CDisk instance to associate
// with a device. This function reads the "Object" value from its instance
// key to determine which CDisk (sub)type to instantiate and calls Init on the
// CDisk instance to initialize the device. If the device is not present, then
// Init will fail. The "Object" value maps to a function that creates an
// instance of the target CDisk (sub)type.
//
// Note that this driver model is convoluted. A CDisk (sub)type instance
// corresponds to both an IDE/ATA controller and an ATA/ATAPI device.
//
// Parameters:
// dwContext - pointer to string containing the registry path to the active key
// of the associated device; the active key contains a key to the device's instance
// key, which stores all of the device's configuration information
//
// Return:
// On success, return handle to device (to identify device); this handle is
// passed to all subsequent DSK_Xxx calls. Otherwise, return null.
//
//------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -