📄 atamain.cpp
字号:
}
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
NULL, // lpClass; not required
NULL, // lpcbClass; lpClass is NULL; hence, NULL
NULL // lpftLastWriteTime; set to NULL
)) {
dwIndex += 1;
dwNewKeySize = (sizeof(szNewKey) / sizeof(TCHAR));
pDskReg = NULL;
// open the DeviceX subkey; copy configuration information from the
// IDE/ATA controller's instance key to the device's DeviceX key
if (ERROR_SUCCESS != RegOpenKeyEx(hDevKey, szNewKey, 0, 0, &hKey)) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!IDE_Init> Failed to open DeviceX subkey; device key(%s)\r\n"
), szDevKey));
goto exit;
}
if (
(NULL == pBus->m_pSecondaryPort) &&
((0 == wcscmp(szNewKey, REG_KEY_SECONDARY_MASTER)) || (0 == wcscmp(szNewKey, REG_KEY_SECONDARY_SLAVE)))
) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!IDE_Init> Secondary channel does not exist, but Device2 and Device3 subkeys exist in %s; ignoring\r\n"
), szDevKey));
dwIndex -= 1;
continue;
}
if (
(0 != wcscmp(szNewKey, REG_KEY_PRIMARY_MASTER)) && (0 != wcscmp(szNewKey, REG_KEY_PRIMARY_SLAVE)) &&
(0 != wcscmp(szNewKey, REG_KEY_SECONDARY_MASTER)) && (0 != wcscmp(szNewKey, REG_KEY_SECONDARY_SLAVE))
) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!IDE_Init> Found bad DeviceX subkey(%s) in device's(%s) key; ignoring\r\n"
), szNewKey, szDevKey));
dwIndex -= 1;
continue;
}
// fetch the device's registry value set
pDskReg = (PDSKREG)LocalAlloc(LPTR, sizeof(DSKREG));
if (!pDskReg) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!IDE_Init> Failed to allocate DSK_ registry value set; device key(%s)\r\n"
), szNewKey));
goto exit;
}
dwUndo |= IDEINIT_UNDO_DEL_REG_DSK;
if (!GetDSKRegistryValueSet(hKey, pDskReg)) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!IDE_Init> Failed to read DSK_ registry value set from registry; device key(%s)\r\n"
), szNewKey));
goto exit;
}
// resolve DeviceX subkey's "DeviceId" to (0, 1), so a CDisk instance can
// reference the correct m_pBus->m_p(Primary, Secondary)Port->(m_pDisk, m_pDskReg)
// array element
dwDeviceId = pDskReg->dwDeviceId; // store the original value
pDskReg->dwDeviceId &= 0x01;
// write the new device ID value back to the device's instance key
if (!AtaSetRegistryValue(hKey, REG_VAL_DSK_DEVICEID, pDskReg->dwDeviceId)) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!IDE_Init> Failed to write %s(%d) DSK_ registry value to device's instance key(%s)\r\n"
), REG_VAL_DSK_DEVICEID, dwDeviceId, szNewKey));
goto exit;
}
// the master and slave CDisk instances of a particular channel have to
// share the port instance associated with the channel; write the heap
// address of the port instance to the device's instance key
if ((0 == wcscmp(szNewKey, REG_KEY_PRIMARY_MASTER)) || (0 == wcscmp(szNewKey, REG_KEY_PRIMARY_SLAVE))) {
// store the DSK_ register value set of the master/slave device in
// the appropriate slot of the port instance
pBus->m_pPrimaryPort->m_pDskReg[pDskReg->dwDeviceId] = pDskReg;
if (!AtaSetRegistryValue(hKey, REG_VALUE_PORT, (DWORD)pBus->m_pPrimaryPort)) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!IDE_Init> Failed to write address of primary port instance to device's(%s) DeviceX subkey(%s)\r\n"
), szDevKey, szNewKey));
RETAILMSG(1, (_T(
"Atapi!IDE_Init> Failed to write address of primary port instance to device's(%s) DeviceX subkey(%s)\r\n"
), szDevKey, szNewKey));
goto exit;
}
}
else if ((0 == wcscmp(szNewKey, REG_KEY_SECONDARY_MASTER)) || (0 == wcscmp(szNewKey, REG_KEY_SECONDARY_SLAVE))) {
// store the DSK_ register value set of the master/slave device in
// the appropriate slot of the port instance
pBus->m_pSecondaryPort->m_pDskReg[pDskReg->dwDeviceId] = pDskReg;
if (!AtaSetRegistryValue(hKey, REG_VALUE_PORT, (DWORD)pBus->m_pSecondaryPort)) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!IDE_Init> Failed to write address of secondary port instance to device's(%s) DeviceX subkey(%s)\r\n"
), szDevKey, szNewKey));
goto exit;
}
}
if (!pBus->m_szDevice[dwDeviceId]) {
// save name of device's full registry key path; when we've finished
// enumerating the "bus", we'll call ActivateDevice against all of
// these paths
pBus->m_szDevice[dwDeviceId] = new TCHAR[wcslen(szDevKey) + wcslen(szNewKey) + 10];
wcscpy(pBus->m_szDevice[dwDeviceId], szDevKey);
wcscat(pBus->m_szDevice[dwDeviceId], L"\\");
wcscat(pBus->m_szDevice[dwDeviceId], szNewKey);
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!IDE_Init> Enumerated IDE/ATA device %s\r\n"
), pBus->m_szDevice[dwDeviceId]));
}
} // while
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!IDE_Init> End of IDE/ATA device enumeration\r\n"
)));
// initialize enumerated devices; it's imperative that we activate the
// channel master before the channel slave
for (dwDeviceId = 0; dwDeviceId < 4; dwDeviceId += 1) {
if (pBus->m_szDevice[dwDeviceId]) {
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!IDE_Init> Activating IDE/ATA device %s\r\n"
), pBus->m_szDevice[dwDeviceId]));
pBus->m_hDevice[dwDeviceId] = ActivateDeviceEx(pBus->m_szDevice[dwDeviceId], NULL, 0, NULL);
}
}
dwUndo &= ~IDEINIT_UNDO_DEL_BUS;
dwUndo &= ~IDEINIT_UNDO_DEL_PORT_PRI;
dwUndo &= ~IDEINIT_UNDO_DEL_PORT_SEC;
exit:;
if (dwUndo & IDEINIT_UNDO_CLS_KEY_ACTIVE) {
RegCloseKey(hActiveKey);
}
if (dwUndo & IDEINIT_UNDO_CLS_KEY_DEVICE) {
RegCloseKey(hDevKey);
}
if (szDevKey) {
LocalFree(szDevKey);
}
if ((NULL != pBus) && (dwUndo & IDEINIT_UNDO_DEL_BUS)) {
delete pBus;
pBus = NULL;
}
return (DWORD)pBus;
}
/*++
IDE_Deinit
This function deallocates the associated IDE/ATA controller ("bus") instance.
Parameters:
dwHandle - pointer to associated bus instance (initially returned by
IDE_Init)
Return:
This function always succeeds.
--*/
EXTERN_C
BOOL
IDE_Deinit(
DWORD dwHandle
)
{
CIDEBUS *pBus = (CIDEBUS *)dwHandle;
DEBUGCHK(pBus != NULL);
delete pBus;
return TRUE;
}
/*++
IDE_Open
This function is not supported.
Parameters:
N/A
Return:
This function always fails.
--*/
EXTERN_C
DWORD
IDE_Open(
HANDLE dwHandle,
DWORD dwAccess,
DWORD dwShareMode
)
{
SetLastError(ERROR_NOT_SUPPORTED);
return NULL;
}
/*++
IDE_Close
This function is not supported.
Parameters:
N/A
Return:
This function always fails.
--*/
EXTERN_C
BOOL
IDE_Close(
DWORD dwHandle
)
{
SetLastError(ERROR_NOT_SUPPORTED);
return FALSE;
}
/*++
IDE_IOControl
This function is not supported.
Parameters:
N/A
Return:
This function always fails.
--*/
EXTERN_C
BOOL
IDE_IOControl(
DWORD dwHandle,
DWORD dwIoControlCode,
PBYTE pInBuf,
DWORD nInBufSize,
PBYTE pOutBuf,
DWORD nOutBufSize,
PDWORD pBytesReturned,
PDWORD pOverlapped
)
{
SetLastError(ERROR_NOT_SUPPORTED);
return FALSE;
}
/*++
DllMain
This function is the main ATAPI.DLL entry point.
Parameters:
hInstance - a handle to the dll; this value is the base address of the DLL
dwReason - the reason for the DLL is being entered
lpReserved - not used
Return:
On success, return true. Otherwise, return false.
--*/
BOOL
WINAPI
DllMain(
HANDLE hInstance,
DWORD dwReason,
LPVOID lpReserved
)
{
switch (dwReason) {
case DLL_PROCESS_ATTACH:
// initialize global data
g_hInstance = (HINSTANCE)hInstance;
InitializeCriticalSection(&g_csMain);
// register debug zones
RegisterDbgZones((HMODULE)hInstance, &dpCurSettings);
DisableThreadLibraryCalls((HMODULE)hInstance);
DEBUGMSG(ZONE_INIT, (_T("ATAPI DLL_PROCESS_ATTACH\r\n")));
break;
case DLL_PROCESS_DETACH:
// deinitialize global data
DeleteCriticalSection(&g_csMain);
DEBUGMSG(ZONE_INIT, (TEXT("ATAPI DLL_PROCESS_DETACH\r\n")));
break;
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -