📄 ep931xide.cpp
字号:
//
void CEP931xDisk::WriteWord(WORD wData)
{
ATAWriteRegister(CSDA_DATA_REG, (ULONG)wData);
}
//****************************************************************************
// CEP931xDisk::ReadWord
//****************************************************************************
//
//
//
WORD CEP931xDisk::ReadWord()
{
return ((WORD)(ATAReadRegister(CSDA_DATA_REG) & 0xFFFF));
}
//****************************************************************************
// CEP931xDisk::WriteByte
//****************************************************************************
//
//
//
void CEP931xDisk::WriteByte(BYTE bData)
{
ATAWriteRegister(CSDA_DATA_REG, (ULONG)bData);
}
//****************************************************************************
// CEP931xDisk::ReadByte
//****************************************************************************
//
//
//
WORD CEP931xDisk::ReadByte()
{
return ((BYTE)(ATAReadRegister(CSDA_DATA_REG) & 0xFF));
}
//****************************************************************************
// CEP931xDisk::WaitForInterrupt
//****************************************************************************
// Waits for the IDE interrupt. This is used for waiting in PIO mode.
//
// dwTimeOut - Time out in mS
//
// Return TRUE - Success
// FALSE - Failure
//
BOOL CEP931xDisk::WaitForInterrupt(DWORD dwTimeOut)
{
BYTE bStatus;
BOOL fRet = TRUE;
DWORD dwRet;
//
// Wait for the IDE interrupt. If it doesn't occur, timeout.
//
dwRet = WaitForSingleObject( m_pPort->m_hIdeIntEvent, dwTimeOut);
//
// If we are currently using DMA, switch to PIO mode to read the
// registers.
//
m_pPort->PIOMode();
if (dwRet == WAIT_TIMEOUT )
{
fRet = FALSE;
}
else if (dwRet != WAIT_OBJECT_0 && dwTimeOut >0)
{
//
// This case is for if we don't use the interrupt.
// Not applicable for us.
//
if (!WaitForDisc( WAIT_TYPE_DRQ, dwTimeOut, 10))
{
fRet = FALSE;
}
}
//
// Ack interrupt!!!!!
//
bStatus = GetBaseStatus();
if (bStatus & ATA_STATUS_ERROR )
{
DEBUGMSG( ZONE_WARNING, (TEXT("CEP931xDisk::WaitforInterrupt bStatus = 0x%02x\n"), (ULONG) bStatus));
bStatus = GetError();
fRet = FALSE;
}
//
// Clear the IDE interrupt.
//
InterruptDone(SYSINTR_IDE);
return fRet;
}
//****************************************************************************
// WaitForDMARQCleared
//****************************************************************************
// Wait for DMARQ to be cleared.
//
//
BOOL WaitForDMARQCleared(ULONG ulTime)
{
BOOL bRet = TRUE;
LARGE_INTEGER liStart, liCurrent;
ULONG ulIdeCtrl;
QueryPerformanceCounter(&liStart);
for(;;)
{
QueryPerformanceCounter(&liCurrent);
ulIdeCtrl = *IDE_CTRL;
if(!(ulIdeCtrl & IDE_CTRL_DMARQ))
{
break;
}
if(ULONG(liCurrent.QuadPart - liStart.QuadPart) > ulTime)
{
bRet = FALSE;
}
}
return bRet;
}
//****************************************************************************
// CEP931xPort::WaitForDmaInterrupt
//****************************************************************************
// Waits for the IDE interrupt. This is used for waiting in PIO mode.
//
// dwTimeOut - Time out in mS
//
// Return TRUE - Success
// FALSE - Failure
//
ULONG CEP931xPort::WaitForDmaInterrupt(DWORD dwTimeOut)
{
BYTE bStatus;
BYTE bError;
BOOL fRet = TRUE;
DWORD dwWaitRet;
ULONG ulRet = DMAWAIT_NOERROR;
ULONG ulMicroSec;
ULONG ulTime = 10000 * 1000;
LARGE_INTEGER liCurrent, liStart;
// LARGE_INTEGER liStart, liCurrent;
// volatile register ULONG ulIdeCtrl;
// volatile register ULONG ulDmaM2MInt;
BOOL b;
b = QueryPerformanceCounter(&m_liTotalStart);
//
// Wait for the IDE interrupt. If it doesn't occur, timeout.
//
dwWaitRet = WaitForMultipleObjects( 2, m_hIstEvent, FALSE, dwTimeOut);
b = QueryPerformanceCounter(&m_liTotalEnd);
//
// Both IDE and DMA interrupts never occured, report an error.
//
if (dwWaitRet == (WAIT_OBJECT_0 + DMA_EVENT))
{
#if 0
if(m_bWaitForDMARQCleared)
{
dwWaitRet = WaitForDMARQCleared(10000)?WAIT_OBJECT_0:WAIT_TIMEOUT;
}
else
{
dwWaitRet = WaitForSingleObject(m_hIstEvent[IDE_EVENT], 100);
//
// If DMARQ is cleared the transfer occured successfully but
// the interrupt never asserted. Use DMARQ from now on.
//
ulIdeCtrl = *IDE_CTRL;
if(!(ulIdeCtrl & IDE_CTRL_DMARQ))
{
m_bWaitForDMARQCleared = 1;
dwWaitRet = WAIT_OBJECT_0;
}
}
#endif // 0
dwWaitRet = WaitForSingleObject(m_hIstEvent[IDE_EVENT], UDMA_IDE_TIMEOUT);
if(dwWaitRet == WAIT_TIMEOUT)
{
//
// The IDE interface is asking for more data.
//
DEBUGMSG
(
ZONE_DMA,
(TEXT("CEP931xPort::WaitForDmaInterrupt DMA transfer completed but IDE interface is requesting to recieve more data.\r\n"))
);
if(!m_fDMARead)
{
//
// DMA Hardware Write bug #1
//
CleanUpDmaUDMAWrite();
ulRet = DMAWAIT_ERROR_WRITE_1;
DEBUGMSG
(
ZONE_DMA,
(TEXT("CEP931xPort::WaitForDmaInterrupt Hit DMA Write Bug #1.\r\n"))
);
RETAILMSG
(
1,
(TEXT("CEP931xPort::WaitForDmaInterrupt Hit DMA Write Bug #1.\r\n"))
);
}
else
{
ulRet = DMAWAIT_ERROR;
}
}
}
else if (dwWaitRet == (WAIT_OBJECT_0 + IDE_EVENT))
{
dwWaitRet = WaitForSingleObject(m_hIstEvent[DMA_EVENT], UDMA_DMA_TIMEOUT);
if(dwWaitRet == WAIT_TIMEOUT)
{
//
// The DMA interface is asking for more data.
//
DEBUGMSG
(
ZONE_DMA,
(TEXT("CEP931xPort::WaitForDmaInterrupt IDE transfer completed but DMA is requesting to send more data.\r\n"))
);
if(!m_fDMARead)
{
// RETAILMSG
// (
// 1,
// (TEXT("CEP931xPort::WaitForDmaInterrupt Hit DMA Write Bug #2.\r\n"))
// );
DEBUGMSG
(
ZONE_DMA,
(TEXT("CEP931xPort::WaitForDmaInterrupt Hit DMA Write Bug #2.\r\n"))
);
//
// If we ever hit write bug #2 use pio mode since we cannot detect
// write bug #2 all of the time.
//
// m_bForcePIO = TRUE;
ulRet = DMAWAIT_ERROR_WRITE_2;
// DumpDmaState();
// DumpIDEState();
}
else
{
//RETAILMSG
//(
// 1,
// (TEXT("CEP931xPort::WaitForDmaInterrupt Hit DMA Read Bug #1.\r\n"))
//);
DEBUGMSG
(
ZONE_DMA,
(TEXT("CEP931xPort::WaitForDmaInterrupt Hit DMA Read Bug #1.\r\n"))
);
ulRet = DMAWAIT_ERROR_READ_1;
}
}
}
else
{
RETAILMSG
(
1,
(TEXT("CEP931xPort::WaitForDmaInterrupt Both IDE and DMA interrupts did not occur.\r\n"))
);
// DEBUGMSG
//(
// ZONE_DMA,
// (TEXT("CEP931xPort::WaitForDmaInterrupt Both IDE and DMA interrupts did not occur.\r\n"))
//);
ulRet = DMAWAIT_ERROR;
}
//
// Switch to PIO mode.
//
PIOMode();
DEBUGMSG
(
ZONE_DMA,
(
TEXT("CEP931xPort::WaitForDmaInterrupt Event = %d, IDE= %d DMA = %d.\r\n"),
ULONG(m_liTotalEnd.QuadPart - m_liTotalStart.QuadPart),
ULONG(m_liIdeEnd.QuadPart - m_liIdeStart.QuadPart),
ULONG(m_liDmaEnd.QuadPart - m_liDmaStart.QuadPart)
)
);
//
// Ack interrupt!!!!!
//
QueryPerformanceCounter(&liStart);
if(ulRet == DMAWAIT_NOERROR)
{
for(;;)
{
QueryPerformanceCounter(&liCurrent);
bStatus = (BYTE) ATAReadRegister(CSDA_STAT_REG) & 0xFF;
if( !(bStatus & (ATA_STATUS_BUSY | ATA_STATUS_DATA_REQ) ))
{
break;
}
ulMicroSec = ULONG(liCurrent.QuadPart - liStart.QuadPart);
if(ulMicroSec > ulTime)
{
ulRet = DMAWAIT_ERROR_BUSY;
break;
}
else if(ulMicroSec > 50000)
{
Sleep(10);
}
else if(ulMicroSec > 5000)
{
Sleep(1);
}
else if(ulMicroSec > 500)
{
Sleep(0);
}
}
}
else
{
bStatus = (BYTE) ATAReadRegister(CSDA_STAT_REG) & 0xFF;
}
//*************************************************************************
// Seagate St340014A has DRQ asserted after the transfer has been completed
// also DMARQ goes high after this read?
//*************************************************************************
//if ((bStatus & ATA_STATUS_ERROR) /* || (bStatus & ATA_STATUS_DATA_REQ ) */ )
if ((bStatus & ATA_STATUS_ERROR) && (ulRet == DMAWAIT_NOERROR) )
{
DEBUGMSG
(
ZONE_WARNING,
(
TEXT("CEP931xPort::WaitForDmaInterrupt bStatus = 0x%04x\n"),
(ULONG) bStatus
)
);
// bStatus = GetError();
bError = (BYTE)ATAReadRegister(CSDA_ERROR_REG);
RETAILMSG
(
1,
(
TEXT("CEP931xPort::WaitForDmaInterrupt bError = 0x%04x\n"),
(ULONG) bStatus
)
);
if(bError & 0x80)
{
ulRet = DMAWAIT_ERROR_CRC;
}
else
{
ulRet = DMAWAIT_ERROR_STATUS;
}
}
return ulRet;
}
//****************************************************************************
// CEP931xDisk::WaitForDmaInterrupt
//****************************************************************************
// Waits for the IDE interrupt. This is used for waiting in PIO mode.
//
// dwTimeOut - Time out in mS
//
// Return TRUE - Success
// FALSE - Failure
//
ULONG CEP931xDisk::WaitForDmaInterrupt(DWORD dwTimeOut)
{
ULONG ulRet;
ulRet = m_pPort->WaitForDmaInterrupt(dwTimeOut);
if(m_pPort->m_fDMARead)
{
m_DmaStatistics.ulDmaTotalRead++;
}
else
{
m_DmaStatistics.ulDmaTotalWrite++;
}
switch(ulRet)
{
case DMAWAIT_NOERROR:
m_DmaStatistics.ulDmaNoError++;
break;
case DMAWAIT_ERROR_BUSY:
m_DmaStatistics.ulDmaBusyError++;
break;
case DMAWAIT_ERROR:
m_DmaStatistics.ulDmaOtherError++;
break;
case DMAWAIT_ERROR_WRITE_1:
m_DmaStatistics.ulDmaWriteBug1++;
break;
case DMAWAIT_ERROR_WRITE_2:
m_DmaStatistics.ulDmaWriteBug2++;
break;
case DMAWAIT_ERROR_RE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -