📄 atamx31.cpp
字号:
DDKIomuxGetPadConfig(DDK_IOMUX_PAD_CSI_D15, &slew, &drive, &mode, &trig, &pull);
DDKIomuxSetPadConfig(DDK_IOMUX_PAD_CSI_D15, DDK_IOMUX_PAD_SLEW_FAST,DDK_IOMUX_PAD_DRIVE_MAX, mode, trig, pull);
DDKIomuxGetPadConfig(DDK_IOMUX_PAD_CSI_MCLK, &slew, &drive, &mode, &trig, &pull);
DDKIomuxSetPadConfig(DDK_IOMUX_PAD_CSI_MCLK, DDK_IOMUX_PAD_SLEW_FAST,DDK_IOMUX_PAD_DRIVE_MAX, mode, trig, pull);
DDKIomuxGetPadConfig(DDK_IOMUX_PAD_CSI_VSYNC, &slew, &drive, &mode, &trig, &pull);
DDKIomuxSetPadConfig(DDK_IOMUX_PAD_CSI_VSYNC, DDK_IOMUX_PAD_SLEW_FAST,DDK_IOMUX_PAD_DRIVE_MAX, mode, trig, pull);
DDKIomuxGetPadConfig(DDK_IOMUX_PAD_CSI_HSYNC, &slew, &drive, &mode, &trig, &pull);
DDKIomuxSetPadConfig(DDK_IOMUX_PAD_CSI_HSYNC, DDK_IOMUX_PAD_SLEW_FAST,DDK_IOMUX_PAD_DRIVE_MAX, mode, trig, pull);
DDKIomuxGetPadConfig(DDK_IOMUX_PAD_CSI_PIXCLK, &slew, &drive, &mode, &trig, &pull);
DDKIomuxSetPadConfig(DDK_IOMUX_PAD_CSI_PIXCLK, DDK_IOMUX_PAD_SLEW_FAST,DDK_IOMUX_PAD_DRIVE_MAX, mode, trig, pull);
DDKIomuxGetPadConfig(DDK_IOMUX_PAD_I2C_CLK, &slew, &drive, &mode, &trig, &pull);
DDKIomuxSetPadConfig(DDK_IOMUX_PAD_I2C_CLK, DDK_IOMUX_PAD_SLEW_FAST,DDK_IOMUX_PAD_DRIVE_MAX, mode, trig, pull);
DDKIomuxGetPadConfig(DDK_IOMUX_PAD_I2C_DAT, &slew, &drive, &mode, &trig, &pull);
DDKIomuxSetPadConfig(DDK_IOMUX_PAD_I2C_DAT, DDK_IOMUX_PAD_SLEW_FAST,DDK_IOMUX_PAD_DRIVE_MAX, mode, trig, pull);
}
bRet = TRUE;
exit:
return bRet;
}
// ----------------------------------------------------------------------------
// Function: InitializePort
// Initialize ATA Port
//
// Parameters:
// None
// Returns:
// Returns TRUE if successful, otherwise returns FALSE.
// ----------------------------------------------------------------------------
BOOL CMX31Disk::InitializePort(void)
{
PHYSICAL_ADDRESS phyAddr;
BOOL bRet = FALSE;
DEBUGMSG(ZONE_FUNC, (_T("CMX31Disk: InitializePort+")));
if(g_pVAtaReg == NULL)
{
phyAddr.QuadPart = BSP_BASE_REG_PA_PBC_BASE;
g_pPBC = (PCSP_PBC_REGS) MmMapIoSpace(phyAddr, sizeof(CSP_PBC_REGS), FALSE);
if (g_pPBC == NULL)
{
DEBUGMSG(ZONE_ERROR, (TEXT("CMX31Disk: MmMapIoSpace failed!\r\n")));
goto exit;
}
phyAddr.QuadPart = CSP_BASE_REG_PA_ATA_CTRL;
g_pVAtaReg = (PCSP_ATA_REG) MmMapIoSpace(phyAddr, sizeof(CSP_ATA_REG), FALSE);
// Check if virtual mapping failed
if (g_pVAtaReg == NULL)
{
DEBUGMSG(ZONE_ERROR, (TEXT("CMX31Disk: MmMapIoSpace failed!\r\n")));
goto exit;
}
m_pATAReg = (PBYTE) (g_pVAtaReg);
m_pATARegAlt = (PBYTE) (g_pVAtaReg);
ConfigureRegisterBlock(4);
DDKClockSetGatingMode(DDK_CLOCK_GATE_INDEX_ATA, DDK_CLOCK_GATE_MODE_ENABLED_ALL);
ConfigureIOMUXPad(0);
SetTimingRegisters(0, PIO_MODE, CLOCK_PERIOD);
SetTimingRegisters(0, MDMA_MODE, CLOCK_PERIOD);
SetTimingRegisters(0, UDMA_MODE, CLOCK_PERIOD);
OUTREG8(&g_pVAtaReg->ATAControl, 0x00);
Sleep(20);
OUTREG8(&g_pVAtaReg->ATAControl, 0x40);
Sleep(20);
}
bRet = TRUE;
exit:;
DEBUGMSG(ZONE_FUNC, (_T("CMX31Disk: InitializePort-")));
return bRet;
}
// ----------------------------------------------------------------------------
// Function: ShowRegisters
// Print current ATA registers
//
// Parameters:
// None
// Returns:
// None
// ----------------------------------------------------------------------------
void CMX31Disk::ShowRegisters(UCHAR usel)
{
if(usel & 0x01)
{
DEBUGMSG(ZONE_INIT, (_T("ATAReg: ATA_TIME_CONFIG0 %p,0x%08x\n"), &g_pVAtaReg->ATA_TIME_CONFIG0, INREG32(&g_pVAtaReg->ATA_TIME_CONFIG0)));
DEBUGMSG(ZONE_INIT, (_T("ATAReg: ATA_TIME_CONFIG1 %p,0x%08x\n"), &g_pVAtaReg->ATA_TIME_CONFIG1, INREG32(&g_pVAtaReg->ATA_TIME_CONFIG1)));
DEBUGMSG(ZONE_INIT, (_T("ATAReg: ATA_TIME_CONFIG2 %p,0x%08x\n"), &g_pVAtaReg->ATA_TIME_CONFIG2, INREG32(&g_pVAtaReg->ATA_TIME_CONFIG2)));
DEBUGMSG(ZONE_INIT, (_T("ATAReg: ATA_TIME_CONFIG3 %p,0x%08x\n"), &g_pVAtaReg->ATA_TIME_CONFIG3, INREG32(&g_pVAtaReg->ATA_TIME_CONFIG3)));
DEBUGMSG(ZONE_INIT, (_T("ATAReg: ATA_TIME_CONFIG4 %p,0x%08x\n"), &g_pVAtaReg->ATA_TIME_CONFIG4, INREG32(&g_pVAtaReg->ATA_TIME_CONFIG4)));
DEBUGMSG(ZONE_INIT, (_T("ATAReg: ATA_TIME_CONFIG5 %p,0x%08x\n"), &g_pVAtaReg->ATA_TIME_CONFIG5, INREG32(&g_pVAtaReg->ATA_TIME_CONFIG5)));
DEBUGMSG(ZONE_INIT, (_T("ATAReg: ATAControl %p,0x%02x\n"), &g_pVAtaReg->ATAControl, INREG8(&g_pVAtaReg->ATAControl)));
DEBUGMSG(ZONE_INIT, (_T("ATAReg: InterruptPending %p,0x%02x\n"), &g_pVAtaReg->InterruptPending, INREG8(&g_pVAtaReg->InterruptPending)));
}
if(usel & 0x02)
{
}
}
#ifdef USE_SDMA
// ----------------------------------------------------------------------------
// Function: SetupDMA
// Setup DMA transfer
//
// Parameters:
// pSgBuf -
// dwSgCount -
// fRead -
// ----------------------------------------------------------------------------
BOOL CMX31Disk::SetupDMA(PSG_BUF pSgBuf, DWORD dwSgCount, BOOL fRead)
{
UINT8 chan = fRead ? DmaChanATARx : DmaChanATATx;
BOOL rc = TRUE;
#ifdef USE_SDMA_SG_LIST
BOOL fAlign = TRUE;
#else
BOOL fAlign = FALSE;
#endif
DWORD dwLockedPages = 0;
DWORD dwSize;
// get the total size for this transfer in bytes
m_dwTransferSize = 0;
for(DWORD i = 0; i < dwSgCount; i++)
m_dwTransferSize+=pSgBuf[i].sb_len;
DEBUGMSG(ZONE_FUNC, (_T("CMX31Disk::SetupDMA(%d, %d)+\n"), fRead, m_dwTransferSize * BYTES_PER_SECTOR));
m_pDMASgBuf = pSgBuf;
m_dwAlignedSgCount = 0;
m_dwAlignedDescCount = 0;
m_dwAlignedSgBytes = 0;
m_DMAChan = chan;
OUTREG8(&g_pVAtaReg->ATAControl, 0x40);
DWORD currentSg = 0;
DWORD currentDesc = 0;
DWORD pdwPages[ATA_MAX_DESC_COUNT];
// For each ATA watermark aligned scatter/gather buffer
while((currentSg < dwSgCount) && fAlign)
{
// Map address and check for security violation
LPBYTE pBuffer = (LPBYTE)MapCallerPtr((LPVOID)pSgBuf[currentSg].sb_buf, pSgBuf[currentSg].sb_len);
if (pSgBuf[currentSg].sb_buf != NULL && pBuffer == NULL)
{
// security violation
ERRORMSG(ZONE_ERROR, (TEXT(
"CMX31Disk::SetupDMA> Failed to map pointer to caller\r\n"
)));
rc = FALSE;
goto cleanUp;
}
if (!LockPages(pBuffer,pSgBuf[currentSg].sb_len,pdwPages, fRead ? LOCKFLAG_WRITE : LOCKFLAG_READ))
{
DEBUGMSG(ZONE_ERROR, (TEXT(
"CMX31Disk::SetupDMA> LockPages failed\r\n"
)));
// Try to fall back to copy using aligned buffer
fAlign = FALSE;
break;
}
else
{
// Keep track of how many pages we have locked so we can
// unlock them if we encounter a failure
dwLockedPages++;
}
DWORD dwMaxPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(pSgBuf[currentSg].sb_buf,pSgBuf[currentSg].sb_len);
DWORD dwTempLen = pSgBuf[currentSg].sb_len;
DWORD dwTempPtr = (DWORD)pBuffer;
for(DWORD i = 0; (i < dwMaxPages) && (dwTempLen > 0) && fAlign; i++)
{
// try and rule out broken values
DEBUGCHK(pdwPages[i] != 0);
DWORD dwPhys = pdwPages[i] << UserKInfo[KINX_PFN_SHIFT]; // get the start address of pages
DWORD dwOffset = dwTempPtr & (UserKInfo[KINX_PAGESIZE] - 1); // offset into page, if any
dwSize = UserKInfo[KINX_PAGESIZE] - dwOffset;
if(dwSize > dwTempLen)
dwSize = dwTempLen;
dwPhys += dwOffset;
dwTempLen -= dwSize;
dwTempPtr += dwSize;
// If we have any unaligned SG pages, perform remainder of transfer
// using a copy into an aligned buffer. We require the buffers to
// be cache line aligned to prevent coherency problems that may
// result from concurrent accesses to cache line data that is
// "shared" between the DMA and the CPU
if (fRead && ((dwSize & CACHE_LINE_SIZE_MASK) || (dwPhys & CACHE_LINE_SIZE_MASK)))
{
//DEBUGMSG(ZONE_FUNC, (_T("CMX31Disk::SetupDMA unaligned page (sg = %d, page = %d, size = %d\r\n"), currentSg, i, dwSize));
UnlockPages(pBuffer,pSgBuf[currentSg].sb_len);
--dwLockedPages;
fAlign = FALSE;
}
else if(!fRead && ((dwSize & 0x3) || (dwPhys & 0x3)))
{
UnlockPages(pBuffer,pSgBuf[currentSg].sb_len);
--dwLockedPages;
fAlign = FALSE;
}
else
{
// if we're at the end to enable the intr flag
DWORD dwFlags;
if(dwTempLen == 0 && (currentSg == (dwSgCount - 1)))
dwFlags = DDK_DMA_FLAGS_INTR | DDK_DMA_FLAGS_WRAP;
else
dwFlags = DDK_DMA_FLAGS_CONT;
//RETAILMSG(TRUE, (_T("DDKSdmaSetBufDesc-SG (BD[%d], chan = %d, flags = 0x%x, size = %d\r\n"), currentDesc, chan, dwFlags, dwSize));
// add new descriptor to chain
DDKSdmaSetBufDesc(chan, currentDesc, dwFlags, dwPhys,
0, DDK_DMA_ACCESS_32BIT, (WORD)dwSize);
++currentDesc;
}
}
if (fAlign)
{
// Keep track of the aligned SG buffers. If we encounter a
// a misaligned length while walking through the current
// SG buffer pages, we will punt the remainder of the list back to
// MapDMABuffers implementation
m_dwAlignedSgBytes += pSgBuf[currentSg].sb_len;
m_dwAlignedDescCount = currentDesc;
m_dwAlignedSgCount = ++currentSg;
}
}
if (!fAlign)
{
if (fRead)
{
dwSize = m_dwTransferSize - m_dwAlignedSgBytes;
}
else
{
dwSize = MoveDMABuffer(pSgBuf, m_dwAlignedSgCount, dwSgCount, fRead);
DEBUGCHK(dwSize == (m_dwTransferSize - m_dwAlignedSgBytes));
}
DEBUGCHK(!(dwSize & (ATA_DMA_WATERMARK - 1)));
//RETAILMSG(TRUE, (_T("DDKSdmaSetBufDesc (BD[%d], chan = %d, flags = 0x%x, size = %d\r\n"), dwAlignedDescCount, chan, DDK_DMA_FLAGS_INTR | DDK_DMA_FLAGS_WRAP, dwSize));
// Set number of bytes to transfer
DDKSdmaSetBufDesc(chan, m_dwAlignedDescCount,
DDK_DMA_FLAGS_INTR | DDK_DMA_FLAGS_WRAP,
PhysDMABufferAddr.LowPart, 0, DDK_DMA_ACCESS_32BIT,
(WORD)(dwSize));
}
DDKSdmaStartChan(chan);
// set fifo alarm to 16 halfwords, midway
OUTREG8(&g_pVAtaReg->FIFOAlarm, ATA_DMA_WATERMARK/2) ;
OUTREG8(&g_pVAtaReg->InterruptClear, 0xff);
OUTREG8(&g_pVAtaReg->InterruptEnable, 0x80);
cleanUp:
if(!rc)
{
// Unlock any previous locked page ranges
for(DWORD i = 0; i < dwLockedPages; i++)
{
LPBYTE pUnlockBuffer = (LPBYTE)MapCallerPtr((LPVOID)pSgBuf[i].sb_buf, pSgBuf[i].sb_len);
UnlockPages(pUnlockBuffer,pSgBuf[i].sb_len);
}
}
return rc;
}
// ----------------------------------------------------------------------------
// Function: BeginDMA
// Begin DMA transfer
//
// Parameters:
// fRead -
// ----------------------------------------------------------------------------
BOOL
CMX31Disk::BeginDMA(
BOOL fRead
)
{
DEBUGMSG(ZONE_FUNC, (_T("CMX31Disk::BeginDMA+\n")));
if (m_dwAlignedSgCount > 0)
{
CacheSync(CACHE_SYNC_DISCARD);
}
fSDMAIntrEnable = TRUE;
BYTE bTransferMode = (BYTE)m_pPort->m_pDskReg[m_dwDeviceId]->dwTransferMode;
switch(bTransferMode)
{
case 0x20: // MDMA_MODE:
case 0x21:
case 0x22:
OUTREG8(&g_pVAtaReg->ATAControl, fRead ? 0xd8 : 0xea);
break;
case 0x40: // UDMA_MODE:
case 0x41:
case 0x42:
case 0x43:
case 0x44:
case 0x45:
OUTREG8(&g_pVAtaReg->ATAControl, fRead ? 0xdc : 0xee);
break;
}
DEBUGMSG(ZONE_FUNC, (_T("CMX31Disk::BeginDMA-\n")));
return TRUE;
}
// ----------------------------------------------------------------------------
// Function: EndDMA
// End DMA transfer
//
// Parameters:
// None
// ----------------------------------------------------------------------------
BOOL
CMX31Disk::EndDMA(
)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -