📄 ep931xide.cpp
字号:
if(m_hThreadWaitEvent)
{
CloseHandle(m_hThreadWaitEvent);
m_hThreadWaitEvent = 0;
}
//
// Close the IDE and the DMA events handles.
//
if(m_hDmaIntEvent)
{
InterruptDisable(SYSINTR_DMA_M2M0);
CloseHandle(m_hDmaIntEvent);
m_hDmaIntEvent = 0;
}
if(m_hIdeIntEvent)
{
InterruptDisable(SYSINTR_IDE);
CloseHandle(m_hIdeIntEvent);
m_hIdeIntEvent = 0;
}
//
// Close the handles for the Ist Events.
//
if(m_hIstEvent[DMA_EVENT])
{
CloseHandle(m_hIstEvent[DMA_EVENT]);
m_hIstEvent[DMA_EVENT] = 0;
}
if(m_hIstEvent[IDE_EVENT])
{
CloseHandle(m_hIstEvent[IDE_EVENT]);
m_hIstEvent[IDE_EVENT] = 0;
}
DeleteCriticalSection( &m_CriticalSection);
}
//****************************************************************************
// CEP931xPort::SetupDMAInit
//****************************************************************************
// Sets up the dma controller and prepares the DMA buffers from INIT.
//
//
BOOL CEP931xPort::SetupDMAInit ()
{
return TRUE;
}
//****************************************************************************
// CEP931xPort::SetupDMA
//****************************************************************************
// Sets up the dma controller and prepares the DMA buffers.
//
//
BOOL CEP931xPort::SetupDMA
(
PSG_BUF pSgBuf,
DWORD dwSgCount,
BOOL fRead,
ULONG ulCurrentMode
)
{
BOOL fLockRet;
ULONG ulDmaCount;
ULONG ulIDESource, ulIDEDest;
ULONG ulBuffer;
LPBYTE pBuffer;
BOOL fPagesLocked;
DWORD PFNs[16];
ULONG ulPage, ulNumPages;
ULONG ulPageSize = UserKInfo[KINX_PAGESIZE];
DWORD dwAlignMask = 3;
volatile ULONG ulDumbCntrlRead;
DEBUGMSG
(
ZONE_DMA,
(
TEXT("ATAPI:SetupDMA Request = %s SgCount=%ld\r\n"),
fRead ? TEXT("Read") : TEXT("Write"),
dwSgCount
)
);
//
// Stop any DMA that is occuring.
//
m_pulDmaBase[M2M_CTRL>>2] = 0;
//* * * Read back the control register to allow hardware state
//* * * machines to transition.
ulDumbCntrlRead = m_pulDmaBase[M2M_CTRL>>2];
//
// Lets save off the DMA information.
//
m_pDMASgBuf = pSgBuf;
m_dwDMASgCount = dwSgCount;
m_fDMARead = fRead;
m_fAligned = TRUE;
m_ulCurrentMode = ulCurrentMode;
//
// Check if either the buffer or the buffer length is unaligned. If the buffers are not
//
if(dwSgCount ==1 && !((ULONG)pSgBuf[0].sb_buf & dwAlignMask) && !(pSgBuf[0].sb_len & dwAlignMask))
{
//
// Map the pointer to the process so that we have a valid pointer in our process.
//
m_pucDmaBuffer = pSgBuf[0].sb_buf;//(LPBYTE)MapCallerPtr(pSgBuf[0].sb_buf, pSgBuf[0].sb_len);
// m_pucDmaBuffer = (LPBYTE)MapPtrToProcess(pSgBuf[0].sb_buf, GetCallerProcess());
//
// Lock the pages for reading or writing.
//
fPagesLocked = LockPages
(
m_pucDmaBuffer,
pSgBuf[0].sb_len,
PFNs,
fRead ? LOCKFLAG_WRITE : LOCKFLAG_READ
);
//
// If the function succeds, Check to make sure that the pages are physically contiguous.
// If they are not then do the unaligned buffer case.
//
if(fPagesLocked)
{
ulNumPages =1 + ((ULONG(m_pucDmaBuffer) + pSgBuf[0].sb_len - 1) >> m_ulPageShift) -
( ULONG(m_pucDmaBuffer) >> m_ulPageShift);
for(ulPage = 0; ulPage< (ulNumPages - 1); ulPage++)
{
if(PFNs[ulPage] !=PFNs[ulPage + 1])
{
m_fAligned = FALSE;
break;
}
}
//
// If it is aligned then calculate the current physical address.
//
if(m_fAligned )
{
//* * * UserKInfo[KINX_PFN_SHIFT].
m_ulDmaPhysBuff = PFNs[0] + ((ULONG)m_pucDmaBuffer & (ulPageSize -1));
m_ulDmaCount = pSgBuf[0].sb_len;
}
else
{
//
// Unlock the pages and free the Mapped pointer.
//
fLockRet = UnlockPages
(
m_pucDmaBuffer,
pSgBuf[0].sb_len
);
ASSERT(fLockRet);
}
}
}
else
{
m_fAligned = FALSE;
}
//
// If the pSgBuf are unaligned copy the entire buffer to our buffer.
//
if(!m_fAligned )
{
DEBUGMSG( ZONE_DMA, (TEXT("ATAPI:SetupDMA Unaligned copy in SetupDMA.\r\n")));
ulDmaCount = 0;
for (ulBuffer = 0; ulBuffer < dwSgCount; ulBuffer++)
{
if(!fRead)
{
if (pSgBuf[ulBuffer].sb_len >0x8000 || pSgBuf[ulBuffer].sb_len <=0 || pBuffer == NULL || m_pucStaticBuffer == NULL)
{
DEBUGMSG
(
ZONE_DMA,
(
TEXT("ATAPI:SetupDMA pSgBuf[ulBuffer].sb_len was %ld * * *\r\n"),
pSgBuf[ulBuffer].sb_len
)
);
}
pBuffer = pSgBuf[ulBuffer].sb_buf;//(LPBYTE)MapCallerPtr(pSgBuf[ulBuffer].sb_buf, pSgBuf[ulBuffer].sb_len);
// pBuffer = (LPBYTE)MapPtrToProcess(pSgBuf[ulBuffer].sb_buf, GetCallerProcess());
memcpy(m_pucStaticBuffer + ulDmaCount, pBuffer, pSgBuf[ulBuffer].sb_len);
}
ulDmaCount+= pSgBuf[ulBuffer].sb_len;
}
m_ulDmaCount = ulDmaCount;
m_pucDmaBuffer = m_pucStaticBuffer;
m_ulDmaPhysBuff = m_ulStaticPhysBuff;
}
//
// Setup DMA controller.
// Check to make sure that this bit change cannot occur in one write.
//
// m_pulDmaBase[M2M_CTRL>>2] |= M2M_CTRL_DONEINTEN;
// m_pulDmaBase[M2M_CTRL>>2] |= M2M_CTRL_BWC_FULLTRANS;
// m_pulDmaBase[M2M_CTRL>>2] |= M2M_CTRL_PW_WORD;
// m_pulDmaBase[M2M_CTRL>>2] |= M2M_CTRL_TM_SOFTINIT;
// m_pulDmaBase[M2M_CTRL>>2] |= M2M_CTRL_ETDP_AHIGH_OUTPUT;
// m_pulDmaBase[M2M_CTRL>>2] |= M2M_CTRL_DREQP_HIGHLEVEL;
// m_pulDmaBase[M2M_CTRL>>2] |= M2M_CTRL_RSS_INTIDE;
// m_pulDmaBase[M2M_CTRL>>2] |= M2M_CTRL_NO_HDSK;
// * * * CAMSDB - Test for proper DMA channel setup. (START)
// DumbCntrlRead = m_pulDmaBase[M2M_CTRL>>2]; //* * * According to SPEC>
// * * * CAMSDB - Test for proper DMA channel setup. (END)
m_ulDmaCtrlReg = M2M_CTRL_DONEINTEN |
M2M_CTRL_BWC_FULLTRANS |
M2M_CTRL_PW_WORD |
M2M_CTRL_ETDP_AHIGH_OUTPUT |
M2M_CTRL_DREQP_HIGHLEVEL |
M2M_CTRL_RSS_INTIDE |
M2M_CTRL_NO_HDSK;
//
// Setup the DMA ctrl register.
//
if(fRead)
{
m_ulDmaCtrlReg |= M2M_CTRL_SAH | M2M_CTRL_TM_HARDINITP2M;
}
else
{
m_ulDmaCtrlReg |= M2M_CTRL_DAH | M2M_CTRL_TM_HARDINITM2P;
}
//
// Setup the source and destination with there proper values.
//
switch(m_ulCurrentMode)
{
// EP931x rev E1 doesn't support UWDMA
/* case MWDMA_MODE0:
case MWDMA_MODE1:
case MWDMA_MODE2:
m_ulDmaCtrlReg |= (fRead?3:3)<<M2M_CTRL_PWSC_SHIFT;
ulIDESource = 0x800a001C; // IDE_MDMADATAIN
ulIDEDest = 0x800a0018; // IDE_UDMADATAOUT
break;
*/
case UDMA_MODE0:
case UDMA_MODE1:
case UDMA_MODE2:
case UDMA_MODE3:
// case UDMA_MODE4:
//* * * The timing below is the only reliable one that will work.
//* * * More research needs to be done as to why...(START)
m_ulDmaCtrlReg |= (fRead?1:2)<<M2M_CTRL_PWSC_SHIFT;
ulIDESource = 0x800a0024; // IDE_UDMADATAIN
ulIDEDest = 0x800a0020; // IDE_UDMADATAOUT
break;
default:
DEBUGMSG
(
1,
(
TEXT("ATAPI:SetupDMA EP9312 unsupported dma mode.\r\n")
)
);
break;
}
//
// Write out the DMA control register, then read it back to
// make sure that it takes effect.
//
m_pulDmaBase[M2M_CTRL>>2] = m_ulDmaCtrlReg;
ulDumbCntrlRead = m_pulDmaBase[M2M_CTRL>>2];
//
// Clear the status register.
//
m_pulDmaBase[M2M_STATUS>>2] = 0;
//
// Bit definitions are the same for Udma and Mdma.
//
if(fRead)
{
m_pulDmaBase[M2M_SAR_BASE0>>2] = ulIDESource;
m_pulDmaBase[M2M_DAR_BASE0>>2] = m_ulDmaPhysBuff;
//
// Write the extra data to location zero for now.
//
//m_pulDmaBase[M2M_SAR_BASE1>>2] = ulIDESource;
//m_pulDmaBase[M2M_DAR_BASE1>>2] = 0;
}
else
{
m_pulDmaBase[M2M_SAR_BASE0>>2] = m_ulDmaPhysBuff;
m_pulDmaBase[M2M_DAR_BASE0>>2] = ulIDEDest;
//
// Write the extra data to location zero for now.
//
// m_pulDmaBase[M2M_SAR_BASE1>>2] = 0;
// m_pulDmaBase[M2M_DAR_BASE1>>2] = ulIDEDest;
}
//
// Figure out the number of bytes to transfer. Round up.
//
//* * * This is needed for MDMA modes for CD/DVD drives.
//* * * Probably not needed anymore...
// if (m_ulDmaCount >= 0x10000)
// m_ulDmaCount = 0xFFFC;
m_pulDmaBase[M2M_BCR0>>2] = m_ulDmaCount;
// m_pulDmaBase[M2M_BCR1>>2] = 8;
return TRUE;
}
//****************************************************************************
// CEP931xPort::BeginDMA
//****************************************************************************
// Begins the DMA engine.
//
//
BOOL CEP931xPort::BeginDMA(BOOL fRead)
{
// volatile register ULONG ulIdeCtrl;
// volatile register ULONG ulDMAStatReg;
// ULONG BusyDMARQCount = 0;
// DWORD TimeOut = 2, DMAREQLowCount = 0, DMAREQWentLow = 0; //* * * Was 10
volatile ULONG ulDumbCntrlRead;
DEBUGMSG
(
ZONE_DMA,
(
TEXT("ATAPI:BeginDMA\r\n")
)
);
//
// If the we are reading/writing directly to the memory buffers, we must
// flush the data cache.
//
//
if(m_fAligned)
{
#if (_WIN32_WCE>=420)
//
// If we are running on Windows CE 4.2 flush the only the
// portion of the cache that we need.
//
// If we are writing to the hard drive, have the cache write
// its contents to memory.
//
// If we are reading the hard drive, write to memory and
// discard the data in the cache.
//
CacheRangeFlush
(
m_pucDmaBuffer,
m_ulDmaCount,
fRead? CACHE_SYNC_DISCARD: CACHE_SYNC_WRITEBACK
);
#else
CacheSync(CACHE_SYNC_DISCARD);
#endif // 0
}
//
// Original code waited for Busy to be 0 or for DMARQ is 1.
// I am not sure if I need to do this also.
//
//
// Check to see if there is data in the UDMA write buffer.
//
if(!(*IDE_UDMAWFST & 0x100) && !m_fDMARead)
{
DumpIDEState();
DumpDmaState();
}
//
// Setup the DMA control register and clear the start bit.
//
m_pulDmaBase[M2M_CTRL>>2] = m_ulDmaCtrlReg |= M2M_CTRL_ENABLE;
ulDumbCntrlRead= m_pulDmaBase[M2M_CTRL>>2];
//
// Make sure there are no glitches involving CS0 or CS1 and STOP/DIOWn
// when switching modes: deassert CS0 and CS1.
//
*IDE_CTRL |= IDE_CTRL_CS0 | IDE_CTRL_CS1;
switch(m_ulCurrentMode)
{
// EP931x rev E1 doesn't support UWDMA
/* case MWDMA_MODE0:
*IDE_CFG = IDE_CFG_IDEEN | IDE_CFG_MDMAEN | (0<<IDE_CFG_MODE_SHIFT);
*IDE_MDMAOP = (fRead? 0: IDE_MDMAOP_RWOP);
*IDE_MDMAOP |= IDE_MDMAOP_MEN ;
break;
case MWDMA_MODE1:
*IDE_CFG = IDE_CFG_IDEEN | IDE_CFG_MDMAEN | (1<<IDE_CFG_MODE_SHIFT);
*IDE_MDMAOP = (fRead? 0: IDE_MDMAOP_RWOP);
*IDE_MDMAOP |= IDE_MDMAOP_MEN ;
break;
case MWDMA_MODE2:
*IDE_CFG = IDE_CFG_IDEEN | IDE_CFG_MDMAEN | (2<<IDE_CFG_MODE_SHIFT);
*IDE_MDMAOP = (fRead? 0: IDE_MDMAOP_RWOP);
*IDE_MDMAOP |= IDE_MDMAOP_MEN ;
break;
*/
case UDMA_MODE0:
*IDE_CFG = IDE_CFG_IDEEN | IDE_CFG_UDMAEN | (0<<IDE_CFG_MODE_SHIFT);
*IDE_UDMAOP = (fRead? 0: IDE_UDMAOP_RWOP);
*IDE_UDMAOP |=IDE_UDMAOP_MEN ;
break;
case UDMA_MODE1:
*IDE_CFG = IDE_CFG_IDEEN | IDE_CFG_UDMAEN | (1<<IDE_CFG_MODE_SHIFT);
*IDE_UDMAOP = (fRead? 0: IDE_UDMAOP_RWOP);
*IDE_UDMAOP |=IDE_UDMAOP_MEN ;
break;
case UDMA_MODE2:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -