📄 atapiromi.cpp
字号:
m_vpEBIRegs = (volatile S3C2450_MATRIX_REG *)VirtualAlloc(0, sizeof(S3C2450_MATRIX_REG), MEM_RESERVE, PAGE_NOACCESS);
if (m_vpEBIRegs == NULL)
{
RETAILMSG(1,(TEXT("For m_vpATAPIRegs : VirtualAlloc failed error code %d\r\n"),GetLastError()));
return FALSE;
}
else
{
if (!VirtualCopy((PVOID)m_vpEBIRegs, (PVOID)(S3C2450_BASE_REG_PA_MATRIX>> 8),
sizeof(S3C2450_MATRIX_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))
{
RETAILMSG(1,(TEXT("For INTRregs: VirtualCopy failed EBI!\r\n")));
return FALSE;
}
}
m_vpEBIRegs->EBICON |= (1<<10)|(1<<9); // bank3_cfg->CF,bank2_cfg->CF
m_vpIOPORTRegs->GPGCON &= ~(0x3ff<<22);
m_vpIOPORTRegs->GPGCON |= (3<<30)|(3<<28)|(1<<26)|(3<<24)|(3<<22); //nCARD_PWREN, RESET_CF,nRE3G_CF,nINPACK,nIREQ_CF
#if (BSP_TYPE == BSP_SMDK2443)
m_vpIOPORTRegs->GPADAT = 0x1aa8a; // GPA10 RDATA_OEN setting
#elif (BSP_TYPE == BSP_SMDK2450)
m_vpIOPORTRegs->GPACON |= (1<<27)|(1<<11)|(1<<14)|(1<<13);// nWE_CF,nOE_CF,nRCS3,nRCS2 enable //S3C2450X01
// m_vpIOPORTRegs->GPACON &= ~(0x1<<10); // GPA10 RDATA_OEN setting
#endif // (BSP_TYPE == BSP_SMDK2443)
m_vpIOPORTRegs->MISCCR &=(~(1<<30)); // card detect when card is detected ,the bit should be '0'.
m_vpIOPORTRegs->GPADAT &=~(0x1<<13);
Sleep(2);
*((UINT32 *)(m_pATAReg + MUX_REG)) = 0x07;
Sleep(2);
*((UINT32 *)(m_pATAReg + MUX_REG)) = 0x03;
Sleep(2);
*((UINT32 *)(m_pATAReg + MUX_REG)) = 0x01;
Sleep(500);
*((UINT32 *)(m_pATAReg + ATA_PIO_TIME)) = 0x1C238;
*((UINT32 *)(m_pATAReg + ATA_UDMA_TIME)) = 0x20B1362 ;
*((UINT32 *)(m_pATAReg + ATA_IRQ)) |= 0x1f;
*((UINT32 *)(m_pATAReg + ATA_IRQ_MASK)) |= 0x1f;
*((UINT32 *)(m_pATAReg + ATA_CONTROL)) |= 0x1;
Sleep(200);
// this function is called for the master and slave on this channel; if
// this has already been called, then exit
if (m_pPort->m_pDskReg[m_dwDeviceId]->dwInterruptDriven || m_pPort->m_pDskReg[m_dwDeviceId]->dwEnableUDMA)
{
if (m_pPort->m_hIRQEvent) {
m_dwDeviceFlags |= DFLAGS_DEVICE_INITIALIZED;
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T("atapiRomi already initialized\n")));
return TRUE;
}
// create interrupt event
if (NULL == (m_pPort->m_hIRQEvent = CreateEvent(NULL, FALSE, FALSE, NULL))) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!CRomiDisk::ConfigPort> Failed to create interrupt event for device(%d)\r\n"
), m_dwDeviceId));
return FALSE;
}
// associate interrupt event with IRQ
if (!InterruptInitialize(
m_pPort->m_dwSysIntr,
m_pPort->m_hIRQEvent,
NULL,
0)
) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!CRomiDisk::ConfigPort> Failed to initialize interrupt(SysIntr(%d)) for device(%d)\r\n"
), m_pPort->m_dwSysIntr, m_dwDeviceId));
return FALSE;
}
}
return RetValue;
//WriteDriveHeadReg(0x40);
}
// ----------------------------------------------------------------------------
// Function: TranslateAddress
// Translate a system address to a bus address for the DMA controller
//
// Parameters:
// pdwAddr -
// ----------------------------------------------------------------------------
BOOL
CRomiDisk::TranslateAddress(
PDWORD pdwAddr
)
{
// translate a system address to a bus address for the DMA bus controller
PHYSICAL_ADDRESS SystemLogicalAddress, TransLogicalAddress;
DWORD dwBus;
// fetch bus number/type
// if (m_pPort->m_pCNTRL != NULL) {
// dwBus = m_pPort->m_pCNTRL->m_dwBus;
// }
// else {
// dwBus = 0;
// }
dwBus = m_pPort->m_pController->m_dwi.dwBusNumber;
// translate address
SystemLogicalAddress.HighPart = 0;
SystemLogicalAddress.LowPart = *pdwAddr;
if (!HalTranslateSystemAddress(PCIBus, dwBus, SystemLogicalAddress, &TransLogicalAddress)) {
return FALSE;
}
*pdwAddr = TransLogicalAddress.LowPart;
return TRUE;
}
// ----------------------------------------------------------------------------
// Function: SetupDMA
// Prepare DMA transfer
//
// Parameters:
// pSgBuf -
// dwSgCount -
// fRead -
// ----------------------------------------------------------------------------
BOOL
CRomiDisk::SetupDMA(
PSG_BUF pSgBuf,
DWORD dwSgCount,
BOOL fRead
)
{
DWORD dwAlignMask = m_dwDMAAlign - 1;
DWORD dwPageMask = UserKInfo[KINX_PAGESIZE] - 1;
DWORD iPage = 0, iPFN, iBuffer;
BOOL fUnalign = FALSE;
DMA_ADAPTER_OBJECT Adapter;
Adapter.ObjectSize = sizeof(DMA_ADAPTER_OBJECT);
Adapter.InterfaceType = (INTERFACE_TYPE)m_pPort->m_pController->m_dwi.dwInterfaceType;
Adapter.BusNumber = m_pPort->m_pController->m_dwi.dwBusNumber;
DEBUGMSG(ZONE_DMA, (_T(
"Atapi!CRomiDisk::SetupDMA> Request(%s), SgCount(%d)\r\n"
), fRead ? (_T("Read")) : (_T("Write")), dwSgCount));
// disable bus master
WriteBMCommand(0);
if (!m_pPRD) {
m_pPRD = (PDMATable)HalAllocateCommonBuffer(&Adapter,
UserKInfo[KINX_PAGESIZE], (PPHYSICAL_ADDRESS)&m_pPRDPhys, FALSE);
if (!m_pPRD) {
goto ExitFailure;
}
}
// m_pPhysList tracks pages used for DMA buffers when the scatter/gather
// buffer is unaligned
if (!m_pPhysList) {
m_pPhysList = (PPhysTable)VirtualAlloc(m_pStartMemory, UserKInfo[KINX_PAGESIZE], MEM_COMMIT, PAGE_READWRITE);
if (!m_pPhysList) {
goto ExitFailure;
}
// allocate the minimum number of fixed pages
for (DWORD i = 0; i < MIN_PHYS_PAGES; i++) {
PHYSICAL_ADDRESS PhysicalAddress = {0};
m_pPhysList[i].pVirtualAddress = (LPBYTE)HalAllocateCommonBuffer(&Adapter,
UserKInfo[KINX_PAGESIZE], &PhysicalAddress, FALSE);
m_pPhysList[i].pPhysicalAddress = (LPBYTE)PhysicalAddress.QuadPart;
if (!m_pPhysList[i].pVirtualAddress) {
goto ExitFailure;
}
}
}
m_dwPhysCount = 0;
// m_pSGCopy tracks the mapping between scatter/gather buffers and DMA
// buffers when the scatter/gather buffer is unaligned and we are reading,
// so we can copy the read data back to the scatter/gather buffer; when the
// scatter/gather buffer is aligned, m_pSGCopy tracks the scatter/gather
// buffers of a particular DMA transfer, so we can unlock the buffers at
// completion
if (!m_pSGCopy) {
m_pSGCopy = (PSGCopyTable)VirtualAlloc(
m_pStartMemory + UserKInfo[KINX_PAGESIZE],
UserKInfo[KINX_PAGESIZE],
MEM_COMMIT,
PAGE_READWRITE);
if (!m_pSGCopy) {
goto ExitFailure;
}
}
m_dwSGCount = 0;
if (!m_pPFNs) {
m_pPFNs = (PDWORD)VirtualAlloc(
m_pStartMemory + 2*UserKInfo[KINX_PAGESIZE],
UserKInfo[KINX_PAGESIZE],
MEM_COMMIT,
PAGE_READWRITE);
if (!m_pPFNs) {
goto ExitFailure;
}
}
// determine whether the a buffer or the buffer length is unaligned
for (iBuffer = 0; iBuffer < dwSgCount; iBuffer++) {
if (
((DWORD)pSgBuf[iBuffer].sb_buf & dwAlignMask) ||
((DWORD)pSgBuf[iBuffer].sb_len & dwAlignMask)
) {
fUnalign = TRUE;
break;
}
}
if (fUnalign) {
DWORD dwCurPageOffset = 0;
for (iBuffer = 0; iBuffer < dwSgCount; iBuffer++) {
// Map address and check for security violation
LPBYTE pBuffer = (LPBYTE)MapCallerPtr((LPVOID)pSgBuf[iBuffer].sb_buf, pSgBuf[iBuffer].sb_len);
if (pSgBuf[iBuffer].sb_buf != NULL && pBuffer == NULL) {
// security violation
DEBUGMSG(ZONE_ERROR, (TEXT(
"Atapi!CRomiDisk::SetupDMA> Failed to map pointer to caller\r\n"
)));
goto ExitFailure;
}
DWORD dwBufferLeft = pSgBuf[iBuffer].sb_len;
while (dwBufferLeft) {
DWORD dwBytesInCurPage = UserKInfo[KINX_PAGESIZE] - dwCurPageOffset;
DWORD dwBytesToTransfer = (dwBufferLeft > dwBytesInCurPage) ? dwBytesInCurPage : dwBufferLeft;
// allocate a new page, if necessary
if ((dwCurPageOffset == 0) && (m_dwPhysCount >= MIN_PHYS_PAGES)) {
PHYSICAL_ADDRESS PhysicalAddress = {0};
m_pPhysList[m_dwPhysCount].pVirtualAddress = (LPBYTE)HalAllocateCommonBuffer(
&Adapter, UserKInfo[KINX_PAGESIZE], &PhysicalAddress, FALSE);
m_pPhysList[m_dwPhysCount].pPhysicalAddress = (LPBYTE)PhysicalAddress.QuadPart;
if (!m_pPhysList[m_dwPhysCount].pVirtualAddress) {
goto ExitFailure;
}
}
if (fRead) {
// prepare a scatter/gather copy entry on read, so we can
// copy data from the DMA buffer to the scatter/gather
// buffer after this DMA transfer is complete
m_pSGCopy[m_dwSGCount].pSrcAddress = m_pPhysList[m_dwPhysCount].pVirtualAddress + dwCurPageOffset;
m_pSGCopy[m_dwSGCount].pDstAddress = pBuffer;
m_pSGCopy[m_dwSGCount].dwSize = dwBytesToTransfer;
m_dwSGCount++;
}
else {
memcpy(m_pPhysList[m_dwPhysCount].pVirtualAddress + dwCurPageOffset, pBuffer, dwBytesToTransfer);
}
// if this buffer is larger than the space remaining on the page,
// then finish processing this page by setting @dwCurPageOffset<-0
if (dwBufferLeft >= dwBytesInCurPage) {
dwCurPageOffset = 0;
}
else {
dwCurPageOffset += dwBytesToTransfer;
}
// have we finished a page? (i.e., offset was reset or this is the last buffer)
if ((dwCurPageOffset == 0) || (iBuffer == (dwSgCount - 1))) {
// add this to the PRD table
m_pPRD[m_dwPhysCount].physAddr = (DWORD)m_pPhysList[m_dwPhysCount].pPhysicalAddress;
m_pPRD[m_dwPhysCount].size = dwCurPageOffset ? (USHORT)dwCurPageOffset : (USHORT)UserKInfo[KINX_PAGESIZE];
m_pPRD[m_dwPhysCount].EOTpad = 0;
m_dwPhysCount++;
}
// update transfer
dwBufferLeft -= dwBytesToTransfer;
pBuffer += dwBytesToTransfer;
}
}
m_pPRD[m_dwPhysCount - 1].EOTpad = 0x8000;
}
else {
DWORD dwTotalBytes = 0;
for (iBuffer = 0; iBuffer < dwSgCount; iBuffer++) {
// Map address and check for security violation
LPBYTE pBuffer = (LPBYTE)MapCallerPtr((LPVOID)pSgBuf[iBuffer].sb_buf, pSgBuf[iBuffer].sb_len);
if (pSgBuf[iBuffer].sb_buf != NULL && pBuffer == NULL) {
// security violation
DEBUGMSG(ZONE_ERROR, (TEXT(
"Atapi!CRomiDisk::SetupDMA> Failed to map pointer to caller\r\n"
)));
goto ExitFailure;
}
// determine the number of bytes remaining to be placed in PRD
dwTotalBytes = pSgBuf[iBuffer].sb_len;
if (!LockPages (
pBuffer,
dwTotalBytes,
m_pPFNs,
fRead ? LOCKFLAG_WRITE : LOCKFLAG_READ)
) {
goto ExitFailure;
}
// add a scatter/gather copy entry for the area we lock, so that
// we can unlock it when we are finished
m_pSGCopy[m_dwSGCount].pSrcAddress = pBuffer;
m_pSGCopy[m_dwSGCount].pDstAddress = 0;
m_pSGCopy[m_dwSGCount].dwSize = dwTotalBytes;
m_dwSGCount++;
iPFN = 0;
while (dwTotalBytes) {
DWORD dwBytesToTransfer = UserKInfo[KINX_PAGESIZE];
if ((DWORD)pBuffer & dwPageMask) {
// the buffer is not page aligned; use up the next page
// boundary
dwBytesToTransfer = UserKInfo[KINX_PAGESIZE] - ((DWORD)pBuffer & dwPageMask);
}
if (dwTotalBytes < dwBytesToTransfer) {
// use what remains
dwBytesToTransfer = dwTotalBytes;
}
m_pPRD[iPage].physAddr = (m_pPFNs[iPFN] << UserKInfo[KINX_PFN_SHIFT]) + ((DWORD)pBuffer & dwPageMask);
if (!TranslateAddress(&m_pPRD[iPage].physAddr)) {
goto ExitFailure;
}
m_pPRD[iPage].size = (USHORT)dwBytesToTransfer;
m_pPRD[iPage].EOTpad = 0;
iPage++;
iPFN++;
// update transfer
pBuffer += dwBytesToTransfer;
dwTotalBytes -= dwBytesToTransfer;
}
}
m_dwPhysCount = 0;
m_pPRD[iPage-1].EOTpad = 0x8000;
}
return TRUE;
ExitFailure:
DEBUGCHK(0);
// clean up
// FreeDMABuffers();
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -