📄 diskmain.cpp
字号:
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));
}
}
if (m_pPort->m_pDskReg[m_dwDeviceId]->dwEnableUDMA && ( m_Id.UltraDMASupport & 0x3f))
{
for(int i=5;i>=0;i--) {
//RETAILMSG(1, (_T("### ATA-Disk supports UDMA to 0x%x 0x%x\r\n"), i,m_dwCurrentUDMAMode));
if(m_Id.UltraDMASupport & (0x01<<i)) {
m_dwCurrentUDMAMode = (i > 4) ? 4 : i;
break;
}
}
SetPioMode(PIO0);
SetUdmaMode();
RETAILMSG(1, (_T("### ATA-Disk supports UDMA to 0x%x 0x%x\r\n"), m_Id.UltraDMASupport,m_dwCurrentUDMAMode));
m_pPort->m_pDskReg[m_dwDeviceId]->dwEnablePDMA = FALSE;
}
else
{
SetPioMode(m_Id.AdvancedPIOxferreserved);
m_pPort->m_pDskReg[m_dwDeviceId]->dwEnableUDMA = FALSE;;
}
fRet = TRUE;
exit:;
return fRet;
}
// ----------------------------------------------------------------------------
// Function: ResetController
// Implement ATA/ATAPI-6 R3B 9.2 (Software reset protocol)
//
// Parameters:
// bSoftReset -
// ----------------------------------------------------------------------------
BOOL
CDisk::ResetController(
BOOL bSoftReset // ignore
)
{
DWORD dwAttempts = 0;
BYTE bStatus = 0;
BOOL fRet = FALSE;
// we have to negate the RESET signal for 5 microseconds before we assert it
WriteAltDriveController(0x00);
::StallExecution(25);
// Set_SRST
// --------
// to enter Set_SRST state, set SRST in the Device Control register to one;
// this will assert the RESET signal and reset both devices on the current
// channel
WriteAltDriveController(0x04); // 0x04 == SRST
// remain in this state for at least 5 microseconds; i.e., assert RESET signal
// for at least 5 microseconds
// if this is a hardware reset, then assert RESET signal for at least 25
// microseconds
::StallExecution(25); // this should be CEDDK implementation
// Clear_wait
// ----------
// clear SRST in the Device Control register, i.e., negate RESET signal
WriteAltDriveController(0x00);
// remain in this state for at least 2 milliseconds
Sleep(5);
HSR2_Check_status:;
// Check_status
// ------------
// read the Status or Alternate Status register
// if BSY is set to one, then re-enter this state
// if BSY is cleared to zero, check the ending status in the Error register
// and the signature (9.12) and transition to Host_Idle
bStatus = GetAltStatus(); // read Status register
if (bStatus & 0x80) {
// BSY is set to one, re-enter this state
DEBUGMSG(ZONE_INIT, (TEXT(
"Atapi!CDisk::ResetController> Device is busy; %u seconds remaining\r\n"
), (m_pPort->m_pController->m_pIdeReg->dwSoftResetTimeout - dwAttempts)));
Sleep(1000);
dwAttempts += 1;
// a device has at most 31 seconds to complete a software reset; we'll use 3 seconds
if (dwAttempts == m_pPort->m_pController->m_pIdeReg->dwSoftResetTimeout) {
DEBUGMSG(ZONE_INIT, (TEXT("Atapi!CDisk::ResetController> Timeout\r\n")));
goto exit;
}
goto HSR2_Check_status;
}
DEBUGMSG(ZONE_INIT, (TEXT(
"Atapi!CDisk::ResetController> Device is ready\r\n"
)));
// BSY is cleared to zero, check the ending status in the Error register
// and the signature
// TODO: Check the signature (9.12)
// if ERR bit set to one, then the reset failed
bStatus = GetAltStatus(); // read Status register
if (bStatus & 0x01) {
// ERR is set to one
// the bits in the Error register are valid, but the Error register
// doesn't provide any useful information in the case of SRST failing
DEBUGMSG(ZONE_INIT, (TEXT(
"Atapi!CDisk::ResetController> SRST failed\r\n"
)));
// TODO: Recover from error
goto exit;
}
fRet = TRUE;
exit:;
return fRet;
}
// ----------------------------------------------------------------------------
// Function: AtapiSoftReset
// Issue ATAPI SOFT RESET command
//
// Parameters:
// None
// ----------------------------------------------------------------------------
void
CDisk::AtapiSoftReset(
)
{
WriteCommand(ATAPI_CMD_SOFT_RESET);
WaitForDisc(WAIT_TYPE_NOT_BUSY, 400);
WaitForDisc(WAIT_TYPE_READY, 500);
}
// ----------------------------------------------------------------------------
// Function: IsDevicePresent
// Determine whether a device is present on the channel
//
// Parameters:
// None
//
// Notes:
// If a device is present on a channel, then the device's associated
// Error register is populated with 0x1. If a device is not present on
// a channel, then the device's associated Error register is populated
// with 0xa or 0xb, for master or slave, respectively.
// ----------------------------------------------------------------------------
BOOL
CDisk::IsDevicePresent(
)
{
BYTE bError;
BYTE bStatus;
// determine which device to select (i.e., which device this device is)
if ((m_dwDevice == 0) || (m_dwDevice == 2) ) {
// select device 0
ATA_WRITE_BYTE(m_pATAReg + m_dwDrvHeadOffset, ATA_HEAD_DRIVE_1);
}
else {
// select device 1
ATA_WRITE_BYTE(m_pATAReg + m_dwDrvHeadOffset, ATA_HEAD_DRIVE_2);
}
// read Status register
bStatus = GetAltStatus();
// read Error register
bError = GetError();
// test Error register
if (bError == 0x1) {
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CDisk::IsDevicePresent> Device %d is present\r\n"
), m_dwDevice));
return TRUE;
}
RETAILMSG(1, (_T(
"Atapi!CDisk::IsDevicePresent> Device %d is not present; Error register(0x%x)\r\n"
), m_dwDevice, bError));
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CDisk::IsDevicePresent> Device %d is not present; Error register(0x%x)\r\n"
), m_dwDevice, bError));
return FALSE;
}
// ----------------------------------------------------------------------------
// Function: SendExecuteDeviceDiagnostic
// Implement ATA/ATAPI-6 R3B 9.10 (Device diagnostic protocol)
//
// Parameters:
// pbDiagnosticCode - diagnostic code returned by controller in Error
// register as a result of issuing EXECUTE DEVICE
// DIAGNOSTIC (8.11)
//
// pfIsAtapi - whether device is an ATAPI device
// ----------------------------------------------------------------------------
BOOL
CDisk::SendExecuteDeviceDiagnostic(
PBYTE pbDiagnosticCode,
PBOOL pfIsAtapi
)
{
BYTE bStatus = 0;
DWORD dwWaitAttempts = 1200;
BOOL fReadSignature = FALSE;
PREFAST_DEBUGCHK(NULL != pbDiagnosticCode);
PREFAST_DEBUGCHK(NULL != pfIsAtapi);
// HI4:HED0, write command
WaitOnBusy(FALSE);
WriteCommand(0x90); // EXECUTE DEVICE DIAGNOSTIC command code
// HED0:Wait, wait for at least 2 milliseconds; see following Sleep(5)
// HED2:Check_Status, wait on BSY=0
while (1) {
Sleep(5); // wait 5 milliseconds
bStatus = GetAltStatus(); // get status
// test error
if (bStatus & ATA_STATUS_ERROR) {
// error
DEBUGMSG(ZONE_ERROR, (TEXT(
"Atapi!CDisk::SendExecuteDeviceDiagnostic> Device failed to process command\r\n"
), m_dwDeviceId));
break;
}
// test BSY=0
if (!(bStatus & ATA_STATUS_BUSY)) break;
// retry
if (dwWaitAttempts-- == 0) {
DEBUGMSG(ZONE_ERROR, (TEXT(
"Atapi!CDisk::SendExecuteDeviceDiagnostic> No response; assuming channel is empty\r\n"
), m_dwDeviceId));
break; // return FALSE;
}
}
// inspect result of diagnosis (table 26, 8.11); select self
SelectDevice();
*pbDiagnosticCode = GetError();
if ((m_dwDevice == 0) || (m_dwDevice == 0)) {
// device 0 (master)
if (*pbDiagnosticCode == 0x01) {
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CDisk::SendExecuteDeviceDiagnostic> Device 0 passed, Device 1 passed or not present\r\n"
)));
RETAILMSG(1, (_T(
"Atapi!CDisk::SendExecuteDeviceDiagnostic> Device 0 passed, Device 1 passed or not present\r\n"
)));
fReadSignature = TRUE; // read signature to determine if we're ATA or ATAPI
}
else if (*pbDiagnosticCode == 0x00 || (0x02 <= *pbDiagnosticCode && *pbDiagnosticCode <= 0x7F)) {
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CDisk::SendExecuteDeviceDiagnostic> Device 0 failed, Device 1 passed or not present\r\n"
)));
RETAILMSG(1, (_T(
"111Atapi!CDisk::SendExecuteDeviceDiagnostic> Device 0 1failed, Device 1 passed or not present\r\n"
)));
}
else if (*pbDiagnosticCode == 0x81) {
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CDisk::SendExecuteDeviceDiagnostic> Device 0 passed, Device 1 failed\r\n"
)));
RETAILMSG(1, (_T(
"Atapi!CDisk::SendExecuteDeviceDiagnostic> Device 0 passed, Device 1 failed\r\n"
)));
fReadSignature = TRUE; // read signature to determine if we're ATA or ATAPI
}
else if (*pbDiagnosticCode == 0x80 || (0x82 <= *pbDiagnosticCode && *pbDiagnosticCode <= 0xFF)) {
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CDisk::SendExecuteDeviceDiagnostic> Device 0 failed, Device 1 failed\r\n"
)));
RETAILMSG(1, (_T(
"Atapi!CDisk::SendExecuteDeviceDiagnostic> Device 0 failed, Device 1 failed\r\n"
)));
}
else {
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CDisk::SendExecuteDeviceDiagnostic> Unknown diagnostic code(0x%x)\r\n"
), *pbDiagnosticCode));
RETAILMSG(1, (_T(
"Atapi!CDisk::SendExecuteDeviceDiagnostic> Unknown diagnostic code(0x%x)\r\n"
), *pbDiagnosticCode));
}
}
else {
// device 1 (slave)
if (*pbDiagnosticCode == 0x01) {
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CDisk::SendExecuteDeviceDiagnostic> Device 1 passed\r\n"
)));
fReadSignature = TRUE; // read signature to determine if we're ATA or ATAPI
}
else if (*pbDiagnosticCode == 0x00 || (0x02 <= *pbDiagnosticCode && *pbDiagnosticCode <= 0x7F)) {
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CDisk::SendExecuteDeviceDiagnostic> Device 1 failed\r\n"
)));
}
else {
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CDisk::SendExecuteDeviceDiagnostic> Unknown diagnostic code(0x%x)\r\n"
), *pbDiagnosticCode));
}
}
if (fReadSignature) {
// we passed; read signature to determine if it's ATA or ATAPI
// test for ATA
if (
ATA_READ_BYTE(m_pATAReg + m_dwSectNumOffset) == 0x01 &&
ATA_READ_BYTE(m_pATAReg + m_dwByteCountLowOffset) == 0x00 &&
ATA_READ_BYTE(m_pATAReg + m_dwByteCountHighOffset) == 0x00 // &&
// ATA_READ_BYTE(m_pATAReg + m_dwDrvHeadOffset) == 0x00 &&
// ATA_READ_BYTE(m_pATAReg + m_dwSectCntReasonOffset) == 0x01 &&
) {
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CDisk::SendExecuteDeviceDiagnostic> ATA device\r\n"
)));
*pfIsAtapi = FALSE;
}
// test for ATAPI
else if (
ATA_READ_BYTE(m_pATAReg + m_dwSectNumOffset) == 0x01 &&
ATA_READ_BYTE(m_pATAReg + m_dwByteCountLowOffset) == 0x14 &&
ATA_READ_BYTE(m_pATAReg + m_dwByteCountHighOffset) == 0xEB // &&
// ATA_READ_BYTE(m_pATAReg + m_dwDrvHeadOffset) == 0x00 &&
// ATA_READ_BYTE(m_pATAReg + m_dwSectCntReasonOffset) == 0x01 &&
) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -