📄 atamx27.cpp
字号:
//
// Parameters:
// fRead -
// ----------------------------------------------------------------------------
BOOL CMX27Disk::BeginDMA(BOOL fRead)
{
UINT8 chan = fRead ? DmaChanATARx : DmaChanATATx;
DEBUGMSG(ZONE_FUNC, (_T("CMX27Disk::BeginDMA+\n")));
if (m_dwAlignedSgCount > 0)
{
CacheSync(CACHE_SYNC_DISCARD);
}
fDMAIntrEnable = TRUE;
BYTE bTransferMode = (BYTE)m_pPort->m_pDskReg[m_dwDeviceId]->dwTransferMode;
switch(bTransferMode)
{
case 0x20: // MDMA_MODE:
case 0x21:
case 0x22:
OUTREG32(&g_pVAtaReg->ATAControl, fRead ? 0xd8 : 0xea);
break;
case 0x40: // UDMA_MODE:
case 0x41:
case 0x42:
case 0x43:
case 0x44:
case 0x45:
OUTREG32(&g_pVAtaReg->ATAControl, fRead ? 0xdc : 0xee);
break;
}
DEBUGMSG(ZONE_FUNC, (_T("CMX27Disk::BeginDMA-\n")));
return TRUE;
}
// ----------------------------------------------------------------------------
// Function: EndDMA
// End DMA transfer
//
// Parameters:
// None
// ----------------------------------------------------------------------------
BOOL CMX27Disk::EndDMA()
{
DEBUGMSG(ZONE_FUNC, (_T("CMX27Disk::EndDMA+\n")));
DDKDmacDisableChannelIntr(m_DMAChan);
DDKDmacStopChan(m_DMAChan);
DDKDmacClearChannelIntr(m_DMAChan);
// unlock any previous locked page ranges
for(DWORD i = 0; i < m_dwAlignedSgCount; i++)
{
LPBYTE pBuffer = (LPBYTE)m_pDMASgBuf[i].sb_buf;
UnlockPages(pBuffer,m_pDMASgBuf[i].sb_len);
}
fDMAIntrEnable = FALSE;
return TRUE;
}
// ----------------------------------------------------------------------------
// Function: AbortDMA
// Abort DMA transfer
//
// Parameters:
// None
// ----------------------------------------------------------------------------
BOOL
CMX27Disk::AbortDMA(
)
{
DEBUGMSG(ZONE_FUNC, (_T("CMX27Disk::AbortDMA+\n")));
fDMAIntrEnable = FALSE;
return EndDMA();
}
// ----------------------------------------------------------------------------
// Function: MoveDMABuffer
// Move data from s/g buffer to DMA buffer or vice versa
//
// Parameters:
// fRead -
//
// ----------------------------------------------------------------------------
DWORD CMX27Disk::MoveDMABuffer(PSG_BUF pSgBuf, DWORD dwSgIndex, DWORD dwSgCount, BOOL fRead)
{
DEBUGMSG(ZONE_FUNC, (_T("CMX27Disk::MoveDMABuffer(%d)+\n"), dwSgCount));
DWORD dwOffset = 0;
DWORD dwEnd = dwSectorsToTransfer * BYTES_PER_SECTOR - m_dwAlignedSgBytes;
for ( ; dwSgIndex < dwSgCount; dwSgIndex++)
{
LPBYTE pBuffer = NULL;
//WINCE500 Map address and check for security violation
// pBuffer = (LPBYTE)MapCallerPtr((LPVOID)pSgBuf[dwSgIndex].sb_buf, pSgBuf[dwSgIndex].sb_len);
// if (pSgBuf[dwSgIndex].sb_buf != NULL && pBuffer == NULL)
//WINCE600 Map address and check for security violation
if (FAILED(CeOpenCallerBuffer((PVOID*)&pBuffer, pSgBuf[dwSgIndex].sb_buf, pSgBuf[dwSgIndex].sb_len, fRead ? ARG_O_PTR : ARG_I_PTR, FALSE)))
{
DEBUGMSG(ZONE_ERROR, (TEXT("CMX27Disk::MoveDMABuffer> CeOpenCallerBuffer(pDestMarshalled=0x%08x,pSrcUnmarshalled=0x%08x) failed!\r\n"),pBuffer, pSgBuf[dwSgIndex].sb_buf));
dwOffset = 0;
goto cleanUp;
}
DWORD dwSize = pSgBuf[dwSgIndex].sb_len;
if((dwSize + dwOffset) > dwEnd)
dwSize = dwEnd - dwOffset;
if (fRead)
{
memcpy(pBuffer, pVirtDMABufferAddr + dwOffset, dwSize);
DEBUGMSG(ZONE_FUNC, (_T("MEMREAD %d\r\n"), dwSize));
}
else
{
memcpy(pVirtDMABufferAddr + dwOffset, pBuffer, dwSize);
//DEBUGMSG(ZONE_FUNC, (_T("MEMWRITE %d\r\n"), dwSize));
}
if (FAILED(CeCloseCallerBuffer((PVOID)pBuffer, pSgBuf[dwSgIndex].sb_buf, pSgBuf[dwSgIndex].sb_len, fRead ? ARG_O_PTR : ARG_I_PTR)))
{
DEBUGMSG(ZONE_ERROR, (TEXT("CMX27Disk::MoveDMABuffer> CeCloseCallerBuffer(pDestMarshalled=0x%08x,pSrcUnmarshalled=0x%08x) failed!\r\n"),pBuffer, pSgBuf[dwSgIndex].sb_buf));
}
dwOffset += dwSize;
}
cleanUp:
return dwOffset;
}
// ----------------------------------------------------------------------------
// Function: CompleteDMA
// Complete DMA transfer
//
// Parameters:
// pSgBuf -
// dwSgCount -
// fRead -
// ----------------------------------------------------------------------------
BOOL CMX27Disk::CompleteDMA(PSG_BUF pSgBuf, DWORD dwSgCount, BOOL fRead)
{
DEBUGMSG(ZONE_FUNC, (_T("CMX27Disk::CompleteDMA+\n")));
fDMAIntrEnable = FALSE;
if(fRead)
{
if (m_dwAlignedSgCount != dwSgCount)
{
DWORD dwSize = MoveDMABuffer(pSgBuf, m_dwAlignedSgCount, dwSgCount, fRead);
DEBUGCHK(dwSize == (dwSectorsToTransfer * BYTES_PER_SECTOR - m_dwAlignedSgBytes));
}
}
return TRUE;
}
//------------------------------------------------------------------------------
//
// Function: MapDMABuffers
//
// Allocate and map DMA buffer
//
// Parameters:
// pController[in] - hardware context
//
// Returns:
// Returns TRUE if successful, otherwise returns FALSE.
//
//------------------------------------------------------------------------------
BOOL CMX27Disk::MapDMABuffers(void)
{
DMA_ADAPTER_OBJECT Adapter;
DEBUGMSG(ZONE_FUNC,(_T("CMX27Disk::MapDMABuffers+\r\n")));
pVirtDMABufferAddr = NULL;
memset(&Adapter, 0, sizeof(DMA_ADAPTER_OBJECT));
Adapter.InterfaceType = Internal;
Adapter.ObjectSize = sizeof(DMA_ADAPTER_OBJECT);
// Allocate a block of virtual memory (physically contiguous) for the DMA buffers.
pVirtDMABufferAddr = (PBYTE)HalAllocateCommonBuffer(&Adapter, (ATA_DMA_BUFFER_SIZE)
, &(PhysDMABufferAddr), FALSE);
if (pVirtDMABufferAddr == NULL)
{
DEBUGMSG(ZONE_ERROR, (TEXT("ATA_MX27:MapDMABuffers() - Failed to allocate DMA buffer.\r\n")));
return(FALSE);
}
DEBUGMSG(ZONE_FUNC,(_T("CMX27Disk::MapDMABuffers-\r\n")));
return(TRUE);
}
//------------------------------------------------------------------------------
//
// Function: UnmapDMABuffers
//
// This function unmaps the DMA buffers previously mapped with the
// MapDMABuffers function.
//
// Parameters:
// pController[in] - hardware context
//
// Returns:
// Returns TRUE if successful, otherwise returns FALSE.
//
//------------------------------------------------------------------------------
BOOL CMX27Disk::UnmapDMABuffers(void)
{
PHYSICAL_ADDRESS phyAddr;
DEBUGMSG(ZONE_FUNC,(_T("CMX27Disk::UnmapDMABuffers+\r\n")));
if(pVirtDMABufferAddr)
{
// Logical address parameter is ignored
phyAddr.QuadPart = 0;
HalFreeCommonBuffer(NULL, 0, phyAddr, (PVOID)pVirtDMABufferAddr, FALSE);
}
return TRUE;
}
//------------------------------------------------------------------------------
//
// Function: DeinitChannelDMA
//
// This function deinitializes the DMA channel for output.
//
// Parameters:
// pController[in] - hardware context
//
// Returns:
// Returns TRUE if successful, otherwise returns FALSE.
//
//------------------------------------------------------------------------------
BOOL CMX27Disk::DeinitChannelDMA(void)
{
if (DmaChanATARx != 0)
{
DDKDmacReleaseChan(DmaChanATARx);
DmaChanATARx = 0;
}
if (DmaChanATATx != 0)
{
DDKDmacReleaseChan(DmaChanATATx);
DmaChanATATx = 0;
}
return TRUE;
}
//------------------------------------------------------------------------------
//
// Function: InitChannelDMA
//
// This function initializes the DMA channel for output.
//
// Parameters:
//
// Returns:
// Returns TRUE if successful, otherwise returns FALSE.
//
//------------------------------------------------------------------------------
BOOL CMX27Disk::InitChannelDMA(void)
{
DMAC_CHANNEL_CFG gDMAC_InputData;
BOOL rc = FALSE;
DEBUGMSG(ZONE_FUNC,(_T("CMX27Disk::InitChannelDMA+\r\n")));
// Check if DMA buffer has been allocated
if (!PhysDMABufferAddr.LowPart || !pVirtDMABufferAddr)
{
DEBUGMSG(ZONE_ERROR, (_T("ERROR:InitChannelDMA: Invalid DMA buffer physical address.\r\n")));
goto cleanUp;
}
// 2.1. Request Channel for RX
DEBUGMSG(ZONE_DMA, (TEXT("InitDMA: Request ATA RX DMA channel\r\n")));
DmaChanATARx = DDKDmacRequestChan(DmaReqRx);
// 2.2. Configure channel for RX
DEBUGMSG(1, (TEXT("InitDMA: Bind ATA RX DMA channel\r\n")));
gDMAC_InputData.SrcAddr = (UINT32)(CSP_BASE_REG_PA_ATA + ATA_FIFO_DATA_16_OFFSET);
gDMAC_InputData.DstAddr = (UINT32)(PhysDMABufferAddr.QuadPart);
gDMAC_InputData.DataSize = ATA_DMA_BUFFER_SIZE;
gDMAC_InputData.DstMode = DMAC_TRANSFER_MODE_LINEAR_MEMORY;
gDMAC_InputData.SrcMode = DMAC_TRANSFER_MODE_FIFO ;
gDMAC_InputData.MemDirIncrease = TRUE ;
gDMAC_InputData.SrcSize = DMAC_TRANSFER_SIZE_16BIT ;
gDMAC_InputData.DstSize = DMAC_TRANSFER_SIZE_32BIT ;
gDMAC_InputData.RepeatType = DMAC_REPEAT_DISABLED;
gDMAC_InputData.ExtReqEnable = TRUE ;
gDMAC_InputData.ReqSrc = DMAC_REQUEST_ATA_RCV_FIFO ;
gDMAC_InputData.ReqTimeout = FALSE ;
gDMAC_InputData.BurstLength = 32; // 16 byte burst length
if (DDKDmacConfigureChan(DmaChanATARx, &gDMAC_InputData) != DmaChanATARx) {
DEBUGMSG(ZONE_ERROR, (TEXT("Bind ATA RX DMA channel failed!\r\n")));
goto cleanUp;
}
//
// 3. Configure DMA for ATA TX
//
// 3.1. Request Channel for TX
DEBUGMSG(1, (TEXT("InitDMA: Request ATA TX DMA channel\r\n")));
DmaChanATATx = DDKDmacRequestChan(DmaReqTx);
// 3.2. Configure DMA for TX
DEBUGMSG(ZONE_DMA, (TEXT("InitDMA: Bind ATA TX DMA channel\r\n")));
gDMAC_InputData.DstAddr = (UINT32)(CSP_BASE_REG_PA_ATA + ATA_FIFO_DATA_16_OFFSET);
gDMAC_InputData.SrcAddr = (UINT32)(PhysDMABufferAddr.QuadPart);
gDMAC_InputData.DataSize = ATA_DMA_BUFFER_SIZE ;
gDMAC_InputData.DstMode = DMAC_TRANSFER_MODE_FIFO ;
gDMAC_InputData.SrcMode = DMAC_TRANSFER_MODE_LINEAR_MEMORY ;
gDMAC_InputData.MemDirIncrease = TRUE ;
gDMAC_InputData.DstSize = DMAC_TRANSFER_SIZE_16BIT ;
gDMAC_InputData.SrcSize = DMAC_TRANSFER_SIZE_32BIT ;
gDMAC_InputData.RepeatType = DMAC_REPEAT_DISABLED;
gDMAC_InputData.ExtReqEnable = TRUE ;
gDMAC_InputData.ReqSrc = DMAC_REQUEST_ATA_TX_FIFO ;
gDMAC_InputData.ReqTimeout = FALSE ;
gDMAC_InputData.BurstLength = 32; //16 byte burst length
if (DDKDmacConfigureChan(DmaChanATATx, &gDMAC_InputData) != DmaChanATATx) {
DEBUGMSG(ZONE_ERROR, (TEXT("Bind ATA TX DMA channel failed!\r\n")));
goto cleanUp;
}
// Clear intr
DDKDmacClearChannelIntr(DmaChanATATx);
DDKDmacClearChannelIntr(DmaChanATARx);
rc = TRUE;
cleanUp:
if (!rc)
{
DeinitChannelDMA();
}
DEBUGMSG(ZONE_DMA,(_T("CMX27Disk::InitChannelDMA-\r\n")));
return rc;
}
//------------------------------------------------------------------------------
//
// Function: InitDMA
//
// Performs DMA channel intialization
//
// Parameters:
// pController[in] - hardware context
//
// Returns:
// Returns TRUE if successful, otherwise returns FALSE.
//
//------------------------------------------------------------------------------
BOOL CMX27Disk::InitDMA(void)
{
DEBUGMSG(ZONE_FUNC, (TEXT("CMX27Disk::InitDMA+\r\n")));
BSPATADMAChanAlloc(&DmaReqTx, &DmaReqRx);
// Map the DMA buffers into driver's virtual address space
if(!MapDMABuffers())
{
DEBUGMSG(ZONE_ERROR, (TEXT("ATA_MX27:InitDMA() - Failed to map DMA buffers.\r\n")));
return FALSE;
}
// Initialize the output DMA
if (!InitChannelDMA())
{
DEBUGMSG(ZONE_ERROR, (TEXT("ATA_MX27:InitDMA() - Failed to initialize output DMA.\r\n")));
return FALSE;
}
DEBUGMSG(ZONE_FUNC, (TEXT("CMX27Disk::InitDMA-\r\n")));
return TRUE ;
}
BOOL CMX27Disk::DeInitDMA(void)
{
if(!DeinitChannelDMA())
{
DEBUGMSG(ZONE_ERROR, (TEXT("ATA_MX27:DeinitChannelDMA() - Failed to deinitialize DMA.\r\n")));
return FALSE;
}
if(!UnmapDMABuffers())
{
DEBUGMSG(ZONE_ERROR, (TEXT("ATA_MX27:UnmapDMABuffers() - Failed to Unmap DMA buffers\r\n")));
return FALSE;
}
return TRUE ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -