📄 ep931xide.cpp
字号:
*IDE_CFG = IDE_CFG_IDEEN | IDE_CFG_UDMAEN | (2<<IDE_CFG_MODE_SHIFT);
*IDE_UDMAOP = (fRead? 0: IDE_UDMAOP_RWOP);
*IDE_UDMAOP |=IDE_UDMAOP_MEN ;
break;
case UDMA_MODE3:
*IDE_CFG = IDE_CFG_IDEEN | IDE_CFG_UDMAEN | (3<<IDE_CFG_MODE_SHIFT);
*IDE_UDMAOP = (fRead? 0: IDE_UDMAOP_RWOP);
*IDE_UDMAOP |=IDE_UDMAOP_MEN ;
break;
//EP931x rev E1 supports up to UDMA mode 3.
/* case UDMA_MODE4:
*IDE_CFG = IDE_CFG_IDEEN | IDE_CFG_UDMAEN | (4<<IDE_CFG_MODE_SHIFT);
*IDE_UDMAOP = (fRead? 0: IDE_UDMAOP_RWOP);
*IDE_UDMAOP |=IDE_UDMAOP_MEN ;
break;
*/
default:
DEBUGMSG
(
1,
(
TEXT("ATAPI:BeginDMA EP9312 unsupported dma mode.\r\n")
)
);
break;
}
//
// The IDE controller is now using DMA.
//
m_bDMAState = TRUE;
//
// Make sure that the Ide event has not fired.
// For some reason this event is usually set.
//
ResetEvent(m_hIstEvent[IDE_EVENT]);
ResetEvent(m_hIstEvent[DMA_EVENT]);
//
// Tell the DMA thread to start waiting for the DMA event.
//
PulseEvent(m_hThreadWaitEvent);
return TRUE;
}
//****************************************************************************
// CEP931xPort::DmaIst
//****************************************************************************
// Allows us to signal the WaitforDMA when a DMA interrupt event
// occurs.
//
//
DWORD CEP931xPort::DmaIst(LPVOID lpParameter)
{
CEP931xPort *t = (CEP931xPort *)lpParameter;
for(;;)
{
WaitForSingleObject(t->m_hThreadWaitEvent, INFINITE);
if(t->m_bThreadExit)
break;
//
// This enables the interrupt.
//
InterruptDone(SYSINTR_DMA_M2M0);
QueryPerformanceCounter(&t->m_liDmaStart);
WaitForSingleObject(t->m_hDmaIntEvent, INFINITE);
QueryPerformanceCounter(&t->m_liDmaEnd);
//
// Signal the other thread that dma event has occured.
//
SetEvent(t->m_hIstEvent[DMA_EVENT]);
}
return 0;
}
//****************************************************************************
// CEP931xPort::WaitOnDMARQ
//****************************************************************************
// Waits for DMARQ to be Asserted
//
//
BOOL CEP931xPort::WaitOnDMARQ(ULONG ulTime)
{
LARGE_INTEGER liStart, liCurrent;
BOOL bRet = TRUE;
ULONG ulIdeCtrl;
ULONG ulMicroSec;
// BYTE bStatus;
QueryPerformanceCounter(&liStart);
// bStatus = BYTE(ATAReadRegister(CSDA_ALT_STAT_REG) & 0xFF);
DELAY_100NS
DELAY_100NS
for(;;)
{
QueryPerformanceCounter(&liCurrent);
ulIdeCtrl = *IDE_CTRL;
if (ulIdeCtrl & IDE_CTRL_DMARQ)
{
break;
// bStatus = BYTE(ATAReadRegister(CSDA_STAT_REG) & 0xFF);
// if(((bStatus & (ATA_STATUS_BUSY| ATA_STATUS_DATA_REQ)) == ATA_STATUS_BUSY ) ||
// ((bStatus & (ATA_STATUS_BUSY| ATA_STATUS_DATA_REQ)) == ATA_STATUS_DATA_REQ))
// if((bStatus & (ATA_STATUS_BUSY| ATA_STATUS_DATA_REQ)) == ATA_STATUS_DATA_REQ)
// {
// }
}
ulMicroSec = ULONG(liCurrent.QuadPart - liStart.QuadPart);
if(ulMicroSec > ulTime)
{
bRet = FALSE;
break;
}
else if(ulMicroSec > 50000)
{
Sleep(10);
}
else if(ulMicroSec > 5000)
{
Sleep(1);
}
else if(ulMicroSec > 500)
{
Sleep(0);
}
}
return bRet;
}
//****************************************************************************
// CEP931xPort::WaitOnDMARQForCD
//****************************************************************************
// Waits for DMARQ to be Asserted the CD version.
// CD may seek for up to a second while spinning up the drive. Should
// perform a sleep to not degrade system performance.
//
// ulTime - Max Time to wait in Milliseconds.
//
BOOL CEP931xPort::WaitOnDMARQForCD(ULONG ulTime)
{
BOOL bRet = TRUE;
ULONG ulIdeCtrl;
BYTE bStatus;
const ULONG ulMaxSleepTime= 5;
ULONG ulSleepTime;
ULONG ulCount;
bStatus = BYTE(ATAReadRegister(CSDA_ALT_STAT_REG) & 0xFF);
ulCount = 0;
ulSleepTime = 0;
do
{
ulIdeCtrl = *IDE_CTRL;
bStatus = BYTE(ATAReadRegister(CSDA_STAT_REG) & 0xFF);
if ( (ulIdeCtrl & IDE_CTRL_DMARQ) &&
(((bStatus & (ATA_STATUS_BUSY| ATA_STATUS_DATA_REQ)) == ATA_STATUS_BUSY ) ||
((bStatus & (ATA_STATUS_BUSY| ATA_STATUS_DATA_REQ)) == ATA_STATUS_DATA_REQ)) )
{
break;
}
//
// Sleep with increasing delay. If the to wait is very short.
// the sleep delay is small. If the drive has to spin up
// we can give the system more time to perform other tasks.
//
Sleep(ulSleepTime);
ulCount +=ulSleepTime;
if(ulSleepTime< ulMaxSleepTime)
ulSleepTime++;
} while( ulCount <ulTime);
return bRet;
}
//****************************************************************************
// CEP931xPort::IDEIst
//****************************************************************************
// Allows us to signal the WaitforDMA function when an IDE interrupt event
// occurs.
//
//
DWORD CEP931xPort::IdeIst(LPVOID lpParameter)
{
CEP931xPort *t = (CEP931xPort *)lpParameter;
for(;;)
{
WaitForSingleObject(t->m_hThreadWaitEvent, INFINITE);
if(t->m_bThreadExit)
break;
//
// This enables the interrupt.
//
InterruptDone(SYSINTR_IDE);
QueryPerformanceCounter(&t->m_liIdeStart);
WaitForSingleObject(t->m_hIdeIntEvent, INFINITE);
QueryPerformanceCounter(&t->m_liIdeEnd);
//
// Signal the other thread that IDE event has occured.
//
SetEvent(t->m_hIstEvent[IDE_EVENT]);
}
return 0;
}
//****************************************************************************
// CEP931xPort::EndDMA
//****************************************************************************
// End the DMA
//
//
BOOL CEP931xPort::EndDMA()
{
volatile BYTE bStatus;
DEBUGMSG
(
ZONE_DMA,
(
TEXT("ATAPI:EndDMA\r\n")
)
);
// Clear the IDE IRQ.
bStatus = (BYTE)(ATAReadRegister(CSDA_STAT_REG) & 0xFF);
//
// Clear the M2M DMA interrupt register.
//
m_pulDmaBase[M2M_INT>>2] = 0;
//
// Disable the DMA channel.
//
m_pulDmaBase[M2M_CTRL>>2] = 0;
return TRUE;
}
//****************************************************************************
// CEP931xPort::CleanUpDmaUDMAWrite
//****************************************************************************
// This routine sends bytes until the UDMA write transaction is finished.
//
//
void CEP931xPort::CleanUpDmaUDMAWrite( void)
{
LARGE_INTEGER liStart, liCurrent;
ULONG ulCount;
ULONG ulIdeCtrl, ulIdeUdmaStatus;
BOOL b;
//
// Clear the status register.
//
m_pulDmaBase[M2M_INT>>2] = 0;
//
// Disable the DMA channel.
//
m_pulDmaBase[M2M_CTRL>>2] = 0;
for(ulCount = 0 ; ulCount < 20 ; ulCount ++)
{
//
// If we get an IDE interrupt we don't need to write any more data.
//
ulIdeCtrl = *IDE_CTRL;
if(ulIdeCtrl & IDE_CTRL_INTRQ)
{
break;
}
//
// Wait for a request from the IDE state machine.
//
b = QueryPerformanceCounter(&liStart);
for(;;)
{
b = QueryPerformanceCounter(&liCurrent);
ulIdeUdmaStatus = *IDE_UDMASTATUS;
if(ulIdeUdmaStatus & UDMASTATUS_DMAIDE)
break;
if(ULONG(liCurrent.QuadPart - liStart.QuadPart) > 1000)
break;
}
//
// Send a byte out the IDE interface.
//
*IDE_UDMADATAOUT = 0x1234;
}
}
//****************************************************************************
// CEP931xDisk::AbortDMA
//****************************************************************************
// Aborts the DMA after the DMA has started.
//
//
BOOL CEP931xPort::AbortDMA()
{
volatile BYTE bStatus;
BOOL fRet;
DEBUGMSG
(
ZONE_DMA,
(
TEXT("ATAPI:AbortDMA\r\n")
)
);
//
// Clear the IDE IRQ.
//
bStatus = (BYTE)(ATAReadRegister(CSDA_STAT_REG) & 0xFF);
//
// Clear the status register.
//
m_pulDmaBase[M2M_INT>>2] = 0;
//
// Disable the DMA channel.
//
m_pulDmaBase[M2M_CTRL>>2] = 0;
//
// Unlock the Buffers and free the mapped pointers.
//
if(m_fAligned)
{
fRet = UnlockPages
(
m_pucDmaBuffer,
m_ulDmaCount
);
ASSERT(fRet);
}
return TRUE;
}
//****************************************************************************
// CEP931xDisk::CompleteDMA
//****************************************************************************
// Completes the DMA and cleans up the buffers.
//
//
BOOL CEP931xPort::CompleteDMA(PSG_BUF pSgBuf, DWORD dwSgCount, BOOL fRead)
{
ULONG ulDmaCount;
ULONG ulBuffer;
LPBYTE pBuffer;
BOOL fRet = TRUE;
// LARGE_INTEGER liStart, liCurrent, liEnd;
DEBUGMSG
(
ZONE_DMA,
(
TEXT("ATAPI:CompleteDMA\r\n")
)
);
//
// Unlock the Buffers and free the mapped pointers.
//
if(m_fAligned)
{
fRet = UnlockPages
(
m_pucDmaBuffer,
m_ulDmaCount
);
ASSERT(fRet);
}
//
// If the pSgBuf are unaligned, copy the entire buffer to our buffer.
//
else if(!m_fAligned && fRead)
{
ulDmaCount = 0;
for (ulBuffer = 0; ulBuffer < dwSgCount; ulBuffer++)
{
pBuffer = pSgBuf[ulBuffer].sb_buf;//(LPBYTE)MapCallerPtr(pSgBuf[ulBuffer].sb_buf, pSgBuf[ulBuffer].sb_len);
// pBuffer = (LPBYTE)MapPtrToProcess(pSgBuf[ulBuffer].sb_buf, GetCallerProcess());
if (pSgBuf[ulBuffer].sb_len >0x8000 || pSgBuf[ulBuffer].sb_len <=0 || pBuffer == NULL || m_pucDmaBuffer == NULL)
{
if (pSgBuf[ulBuffer].sb_len >0x8000 || pSgBuf[ulBuffer].sb_len <0)
{
// DEBUGMSG( ZONE_DMA, (TEXT("CEP931xPort::CompleteDMA pSgBuf[ulBuffer].sb_len was %ld.\r\n"),pSgBuf[ulBuffer].sb_len));
pSgBuf[ulBuffer].sb_len = 0;
}
if (m_pucDmaBuffer == NULL)
{
DEBUGMSG( ZONE_DMA, (TEXT("CEP931xPort::CompleteDMA m_pucDmaBuffer was NULL.\r\n")));
}
if (pBuffer == NULL)
{
DEBUGMSG( ZONE_DMA, (TEXT("CEP931xPort::CompleteDMA pBuffer was NULL.\r\n")));
}
}
else
{
// DEBUGMSG( ZONE_DMA, (TEXT("CEP931xPort::CompleteDMA About to check and possibly do memcopy.\r\n")));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -