📄 atamain.cpp
字号:
Return:
On success, return handle to "open" CDisk instance; this handle is the
same as dwHandle. Otherwise, return null.
--*/
EXTERN_C
DWORD
DSK_Open(
HANDLE dwHandle,
DWORD dwAccess,
DWORD dwShareMode
)
{
CDisk *pDisk = (CDisk *)dwHandle;
EnterCriticalSection(&g_csMain);
// validate the CDisk instance
if (!AtaIsValidDisk(pDisk)) {
pDisk = NULL;
}
LeaveCriticalSection(&g_csMain);
// if the CDisk instance is valid, then open; open just increments the
// instance's open count
if (pDisk) {
pDisk->Open();
}
return (DWORD)pDisk;
}
/*++
DSK_Close
This function closes a CDisk instance.
Parameters:
dwHandle - pointer to associated CDisk instance (initially returned by
DSK_Init)
Return:
On success, return true. Otherwise, return false.
--*/
EXTERN_C
BOOL
DSK_Close(
DWORD dwHandle
)
{
CDisk *pDisk = (CDisk *)dwHandle;
EnterCriticalSection(&g_csMain);
// validate the CDisk instance
if (!AtaIsValidDisk(pDisk)) {
pDisk = NULL;
}
LeaveCriticalSection(&g_csMain);
// if CDisk instance is valid, then close; close just decrements the
// instance's open count
if (pDisk) {
pDisk->Close();
}
return (pDisk != NULL);
}
/*++
DSK_IOControl
This function processes an IOCTL_DISK_Xxx/DISK_IOCTL_Xxx I/O control.
Parameters:
dwHandle - pointer to associated CDisk instance (initially returned by
DSK_Init)
dwIOControlCode - I/O control to perform
pInBuf - pointer to buffer containing the input data of the I/O control
nInBufSize - size of pInBuf (bytes)
pOutBuf - pointer to buffer that is to receive the output data of the
I/O control
nOutBufSize - size of pOutBuf (bytes)
pBytesReturned - pointer to DWORD that is to receive the size (bytes) of the
output data of the I/O control
pOverlapped - ignored
Return:
On success, return true. Otherwise, return false.
--*/
EXTERN_C
BOOL
DSK_IOControl(
DWORD dwHandle,
DWORD dwIoControlCode,
PBYTE pInBuf,
DWORD nInBufSize,
PBYTE pOutBuf,
DWORD nOutBufSize,
PDWORD pBytesReturned,
PDWORD pOverlapped)
{
CDisk *pDisk = (CDisk *)dwHandle;
BOOL fRet = FALSE;
if (OEM_CERTIFY_TRUST != PSLGetCallerTrust()) {
SetLastError(ERROR_ACCESS_DENIED);
return FALSE;
}
EnterCriticalSection(&g_csMain);
// validate CDisk instance
if (!AtaIsValidDisk(pDisk)) {
pDisk = NULL;
}
LeaveCriticalSection(&g_csMain);
if (!pDisk) {
return FALSE;
}
// DISK_IOCTL_INITIALIZED is a deprecated IOCTL; what does PostInit do?
if (dwIoControlCode == DISK_IOCTL_INITIALIZED) {
fRet = pDisk->PostInit((PPOST_INIT_BUF)pInBuf);
}
else {
IOREQ IOReq;
// build I/O request structure
memset(&IOReq, 0, sizeof(IOReq));
IOReq.dwCode = dwIoControlCode;
IOReq.pInBuf = pInBuf;
IOReq.dwInBufSize = nInBufSize;
IOReq.pOutBuf = pOutBuf;
IOReq.dwOutBufSize = nOutBufSize;
IOReq.pBytesReturned = pBytesReturned;
IOReq.hProcess = GetCallerProcess();
// perform I/O control
__try {
fRet = pDisk->PerformIoctl(&IOReq);
} __except(EXCEPTION_EXECUTE_HANDLER) {
fRet = FALSE;
SetLastError(ERROR_GEN_FAILURE);
}
}
return fRet;
}
/*++
DSK_PowerUp
This function resumes the device.
Parameters:
None
Return:
On success, return true. Otherwise, return false.
--*/
EXTERN_C
VOID
DSK_PowerUp(
VOID
)
{
EnterCriticalSection(&g_csMain);
CDisk *pDisk = g_pDiskRoot;
// iterate through the global CDisk list and direct each CDisk instance to
// power up its associated device
while (pDisk) {
pDisk->PowerUp();
pDisk = pDisk->m_pNextDisk;
}
LeaveCriticalSection(&g_csMain);
}
/*++
DSK_PowerDown
This function suspends a device.
Parameters:
None
Return:
On success, return true. Otherwise, return false.
--*/
EXTERN_C
VOID
DSK_PowerDown(
VOID
)
{
EnterCriticalSection(&g_csMain);
CDisk *pDisk = g_pDiskRoot;
// iterate through the global CDisk list and direct each CDist instance to
// power down its associated device
while (pDisk) {
pDisk->PowerDown();
pDisk = pDisk->m_pNextDisk;
}
LeaveCriticalSection(&g_csMain);
}
/*++
IDE_Init
This function is called as a result of a bus driver enumerating an IDE/ATA
controller.
Each IDE/ATA controller is a "bus". An IDE/ATA controller contains at most
two channels, and each channel can contain a master and a slave device.
An IDE/ATA controller's instance key will typically contain the following
subkeys: Device0, Device1, Device2, and Device3. Device0 is the master
device on the primary channel. Device1 is the slave device on the primary
channel. Device2 is the master device on the secondary channel. Device3
is the slave device on the secondary.
This function is responsible for searching the driver's instance key for
DeviceX subkeys and calling ActivateDevice on each DeviceX subkey found.
The call to ActivateDevice will eventually enter DSK_Init. DSK_Init is
responsible for creating a CDisk instance to associate with a device. If a
device is present and intialization succeeds, then DSK_Init will succeed.
Parameters:
dwContext - pointer to string containing the registry path to the active key
of the IDE/ATA controller; the active key contains a key to the IDE/ATA
controller's instance key, which stores all of the IDE/ATA controller's
configuration information
Return:
On success, return handle to IDE/ATA controller (for identification); this
handle is passed to all subsequent IDE_Xxx calls. Otherwise, return null.
--*/
#define IDEINIT_UNDO_CLS_KEY_ACTIVE 0x01
#define IDEINIT_UNDO_CLS_KEY_DEVICE 0x02
#define IDEINIT_UNDO_DEL_BUS 0x04
#define IDEINIT_UNDO_DEL_PORT_PRI 0x08
#define IDEINIT_UNDO_DEL_PORT_SEC 0x10
#define IDEINIT_UNDO_DEL_REG_IDE 0x20
#define IDEINIT_UNDO_DEL_REG_DSK 0x40
EXTERN_C
DWORD
IDE_Init(
DWORD dwContext
)
{
DWORD dwUndo = 0; // undo bitset
PTSTR szActiveKey = (PTSTR)dwContext; // name of IDE/ATA controller's active key
HKEY hActiveKey; // handle to IDE/ATA controller's active key
PTSTR szDevKey = NULL; // name of IDE/ATA controller's instance key
HKEY hDevKey; // handle to IDE/ATA controller's instance key
PDSKREG pDskReg; // ATA/ATAPI device's registry value set
CIDEBUS *pBus = NULL; // return
// open the IDE/ATA controllers's active key
if ((ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, szActiveKey, 0, 0, &hActiveKey)) || (!hActiveKey)) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!IDE_Init> Failed to open IDE/ATA controller's active key(%s)\r\n"
), szActiveKey));
goto exit;
}
dwUndo |= IDEINIT_UNDO_CLS_KEY_ACTIVE;
DUMPREGKEY(ZONE_INIT, szActiveKey, hActiveKey);
// fetch the name of the IDE/ATA controller's instance key and open it
if (!(hDevKey = AtaLoadRegKey(hActiveKey, &szDevKey)) || !szDevKey) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!IDE_Init> Failed to fetch/open IDE/ATA controller's instance key from active key(%s)\r\n"
), szActiveKey));
goto exit;
}
dwUndo |= IDEINIT_UNDO_CLS_KEY_DEVICE;
DUMPREGKEY(ZONE_INIT, szDevKey, hDevKey);
// instantiate an IDE/ATA controller ("bus") object
if (!(pBus = new CIDEBUS)) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!IDE_Init> Failed to instantiate IDE/ATA controller bus object; device key(%s)\r\n"
), szDevKey));
goto exit;
}
dwUndo |= IDEINIT_UNDO_DEL_BUS;
// instantiate primary channel port object
pBus->m_pPrimaryPort = new CPort(pBus);
if (!pBus->m_pPrimaryPort) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!IDE_Init> Failed to allocate port for primary channel; device key(%s)\r\n"
), szDevKey));
goto exit;
}
dwUndo |= IDEINIT_UNDO_DEL_PORT_PRI;
// instantiate secondary channel port object
pBus->m_pSecondaryPort = new CPort(pBus);
if (!pBus->m_pSecondaryPort) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!IDE_Init> Failed to allocate port for secondary channel; device key(%s)\r\n"
), szDevKey));
goto exit;
}
dwUndo |= IDEINIT_UNDO_DEL_PORT_SEC;
// configure port instances based on I/O window information in registry
if (!GetIoPort(hDevKey, szDevKey, pBus)) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!IDE_Init> Bad I/O window information; device key(%s)\r\n"
), szDevKey));
goto exit;
}
// fetch IDE/ATA controller registry value set (i.e., registry configuration)
pBus->m_pIdeReg = (PIDEREG)LocalAlloc(LPTR, sizeof(IDEREG));
if (!pBus->m_pIdeReg) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!IDE_Init> Failed to allocate IDE_ registry value set; device key(%s)\r\n"
), szDevKey));
goto exit;
}
dwUndo |= IDEINIT_UNDO_DEL_REG_IDE;
if (!GetIDERegistryValueSet(hDevKey, pBus->m_pIdeReg)) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!IDE_Init> Failed to read IDE_ registry value set from registry; device key(%s)\r\n"
), szDevKey));
goto exit;
}
// assign IRQs
pBus->m_pPrimaryPort->m_dwIrq = pBus->m_pIdeReg->dwIrq;
pBus->m_pSecondaryPort->m_dwIrq = pBus->m_pIdeReg->dwIrq;
// if IDE/ATA controller is legacy ISA/PCI, then IRQ of secondary channel is
// (IRQ of primary channel + 1); otherwise, the primary and secondary
// channels must share an interrupt and employ an ISR
if (pBus->m_pIdeReg->dwLegacy) {
pBus->m_pSecondaryPort->m_dwIrq =pBus->m_pPrimaryPort->m_dwIrq + 1;
}
// no SysIntr provided; we have to map IRQ to SysIntr ourselves; note that,
// even if the primary and secondary channels share an IRQ, each channel is
// required to have its own IRQ-SysIntr mapping
if (!pBus->m_pIdeReg->dwSysIntr) {
DWORD dwReturned = 0;
if (!KernelIoControl(
IOCTL_HAL_TRANSLATE_IRQ,
(LPVOID)&pBus->m_pPrimaryPort->m_dwIrq, sizeof(DWORD),
(LPVOID)&pBus->m_pPrimaryPort->m_dwSysIntr, sizeof(DWORD),
&dwReturned
)) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!IDE_Init> Failed to map IRQ(%d) to SysIntr for primary channel of device(%s)\r\n"
), pBus->m_pPrimaryPort->m_dwIrq, szDevKey));
//goto exit;
}
// even if primary and secondary channels use the same IRQ, we need two
// separate SysIntr mappings
if (pBus->m_pSecondaryPort->m_fInitialized) {
if (!KernelIoControl(
IOCTL_HAL_TRANSLATE_IRQ,
(LPVOID)&pBus->m_pSecondaryPort->m_dwIrq, sizeof(DWORD),
(LPVOID)&pBus->m_pSecondaryPort->m_dwSysIntr, sizeof(DWORD),
&dwReturned
)) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!IDE_Init> Failed to map IRQ(%d) to SysIntr for secondary channel on device(%s)\r\n"
), pBus->m_pSecondaryPort->m_dwIrq, szDevKey));
//goto exit;
}
}
}
else {
DWORD dwReturned = 0;
// the SysIntr corresponds to the primary channel; we need to request
// a separate SysIntr for the secondary channel
pBus->m_pPrimaryPort->m_dwSysIntr = pBus->m_pIdeReg->dwSysIntr;
if (pBus->m_pSecondaryPort->m_fInitialized) {
if (!KernelIoControl(
IOCTL_HAL_TRANSLATE_IRQ,
(LPVOID)&pBus->m_pSecondaryPort->m_dwIrq, sizeof(DWORD),
(LPVOID)&pBus->m_pSecondaryPort->m_dwSysIntr, sizeof(DWORD),
&dwReturned
)) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!IDE_Init> Failed to map IRQ(%d) to SysIntr for secondary channel on device(%s)\r\n"
), pBus->m_pSecondaryPort->m_dwIrq, szDevKey));
//goto exit;
}
}
}
// if this IDE/ATA controller only has a single channel, e.g., PC Card,
// then destroy the secondary channel's port
DEBUGCHK(pBus->m_pPrimaryPort->m_fInitialized);
if (!pBus->m_pSecondaryPort->m_fInitialized) {
delete pBus->m_pSecondaryPort;
pBus->m_pSecondaryPort = NULL;
dwUndo &= ~IDEINIT_UNDO_DEL_PORT_SEC;
}
// IDE/ATA "bus" enumeration; scan the current IDE/ATA controller's instance
// key for DeviceX subkeys
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!IDE_Init> Start of IDE/ATA device enumeration\r\n"
)));
DWORD dwIndex = 0; // index of next DeviceX subkey to fetch/enumerate
HKEY hKey; // handle to DeviceX subkey
TCHAR szNewKey[MAX_PATH]; // name of DeviceX subkey
DWORD dwNewKeySize; // size of name of DeviceX subkey
DWORD dwDeviceId; // "DeviceId" read from DeviceX subkey and resolved to 0, 1
dwNewKeySize = (sizeof(szNewKey) / sizeof(TCHAR));
while (
ERROR_SUCCESS == RegEnumKeyEx(
hDevKey, // IDE/ATA controller's instance key
dwIndex, // index of the subkey to fetch
szNewKey, // name of subkey (e.g., "Device0")
&dwNewKeySize, // size of name of subkey
NULL, // lpReserved; set to NULL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -