📄 sdcontrol.cpp
字号:
if (BspSdhcIsSdmaSupported(pHardwareContext->ControllerIndex) == TRUE)
{
// Release DMA Resources
DeInitDMA(pHardwareContext);
}
// free the virtual space allocated for SDHC memory map
if (pHardwareContext->pSDMMCRegisters != NULL)
{
MmUnmapIoSpace(pHardwareContext->pSDMMCRegisters, sizeof(CSP_SDHC_REG));
pHardwareContext->pSDMMCRegisters = NULL;
}
DeleteCriticalSection(&pHardwareContext->ControllerCriticalSection);
DEBUGMSG(ZONE_FUNCTION, (TEXT("-SDDeinitialize: \r\n")));
return SD_API_STATUS_SUCCESS;
}
//------------------------------------------------------------------------------
//
// Function: SDHCancelIoHandler
//
// io cancel handler
//
// Parameters:
// pHostContext[in] - host controller context
// Slot[in] - slot the request is going on
// pRequest[in] - the request to be cancelled
//
// Returns:
// TRUE if the request was cancelled
//
//------------------------------------------------------------------------------
BOOLEAN SDHCancelIoHandler(PSDCARD_HC_CONTEXT pHCContext,
DWORD Slot,
PSD_BUS_REQUEST pRequest)
{
PSDH_HARDWARE_CONTEXT pController;
DEBUGMSG(ZONE_FUNCTION, (TEXT("+SDHCancelIoHandler \n"))) ;
// for now, we should never get here because all requests are non-cancelable
// the hardware supports timeouts so it is impossible for the controller to get stuck
DEBUG_ASSERT(FALSE);
// get our extension
pController = GetExtensionFromHCDContext(PSDH_HARDWARE_CONTEXT, pHCContext);
// --- Stop hardware, cancel the request!
// release the lock before we complete the request
SDHCDReleaseHCLock(pHCContext);
// complete the request with a cancelled status
SDHCDIndicateBusRequestComplete(pHCContext,pRequest, SD_API_STATUS_CANCELED);
DEBUGMSG(ZONE_FUNCTION, (TEXT("-SDHCancelIoHandler \n"))) ;
return TRUE;
}
//------------------------------------------------------------------------------
//
// Function: SDHBusRequestHandler
//
// bus request handler. The request passed in is marked as uncancelable, this function
// has the option of making the outstanding request cancelable
//
// Parameters:
// pHostContext[in] - host controller context
// Slot[in] - slot the request is going on
// pRequest[in] - the request to be cancelled
//
// Returns:
// SD_API_STATUS Code
//
//------------------------------------------------------------------------------
SD_API_STATUS SDHBusRequestHandler(PSDCARD_HC_CONTEXT pHCContext,
DWORD Slot,
PSD_BUS_REQUEST pRequest)
{
PSDH_HARDWARE_CONTEXT pController; // our controller
DWORD cmdatRegister=0; // CMDAT register
// get our extension
pController = GetExtensionFromHCDContext(PSDH_HARDWARE_CONTEXT, pHCContext);
DWORD dwNumBytesToTransfer = pRequest->NumBlocks * pRequest->BlockSize;
// DMA is not used for comands
// DMA is not used for small data transfers (DmaMinTransfer)
// DMA is not used for transfer sizes that are not 32-bit aligned
if ((SD_COMMAND == pRequest->TransferClass) ||
(dwNumBytesToTransfer < (pController->DmaMinTransfer)) ||
(dwNumBytesToTransfer & 0x3))
{
pController->fDMATransfer = FALSE;
}
// Allow platform code to specify if DMA is supported
else
{
pController->fDMATransfer = BspSdhcIsSdmaSupported(pController->ControllerIndex);
}
// Handle for ACMD 42/23. Our SDHC expects no reponse but spec say R1.
//This is used during MX21 SDIO workaround. It might not be used during ARM11 hardware debugging
if ( (pRequest->CommandCode == SD_CMD_LOCK_UNLOCK && pController->fAppCommandSent == TRUE) ||
(pRequest->CommandCode == SD_ACMD_SET_WR_BLOCK_ERASE_COUNT && pController->fAppCommandSent == TRUE))
{
pRequest->CommandResponse.ResponseType = NoResponse;
}
//Set the response type
switch (pRequest->CommandResponse.ResponseType)
{
case NoResponse:
CSP_BITFINS(cmdatRegister, SDHC_CDC_FORMAT, 0);
break;
//ARM11 spec does not have busy bit register set.
//Need to check busy bit Hw implementation and handling.This affects commands with
//response R1b and for SDIOAbort transfers.
case ResponseR1b:
case ResponseR1:
case ResponseR5:
case ResponseR6:
CSP_BITFINS(cmdatRegister, SDHC_CDC_FORMAT, 1);
break;
case ResponseR2:
CSP_BITFINS(cmdatRegister, SDHC_CDC_FORMAT, 2);
break;
case ResponseR3:
case ResponseR4:
// R4 is really same as an R3 response on an MMC controller (non-CRC)
// Note: sdbus send for R4 although specs say R3
CSP_BITFINS(cmdatRegister, SDHC_CDC_FORMAT, 3);
break;
default:
ERRORMSG(ZONE_ERROR, (TEXT("SDHBusRequestHandler failed (Invalid parameter)\n")));
return SD_API_STATUS_INVALID_PARAMETER;
}
// check for Command Only
if ((SD_COMMAND != pRequest->TransferClass))
{
// its a command with a data phase
CSP_BITFINS(cmdatRegister, SDHC_CDC_DE, 1);
}
// check for write
if (SD_WRITE == pRequest->TransferClass)
{
//Indicate that it is write process
CSP_BITFINS(cmdatRegister, SDHC_CDC_WR, 1);
#ifdef SD_R1B_BUSYWAIT_WORKAROUND
pController->CurrTransferReq = SD_WRITE;
#endif
// If transfer can be supported by DMA
if (pController->fDMATransfer == TRUE)
{
if (pController->CurrentDmaReq != pController->DmaReqTx)
{
//Update shared channel to TX
DDKSdmaUpdateSharedChan(pController->ChanSDHC, pController->DmaReqTx);
pController->CurrentDmaReq = pController->DmaReqTx ;
// Set flag to update the DMA channel context
pController->fDmaUpdateContext = TRUE;
}
}
}
else if (SD_READ == pRequest->TransferClass)
{
#ifdef SD_R1B_BUSYWAIT_WORKAROUND
pController->CurrTransferReq = SD_READ;
#endif
// If transfer can be supported by DMA
if (pController->fDMATransfer == TRUE)
{
if (pController->CurrentDmaReq != pController->DmaReqRx)
{
//Update shared channel to RX
DDKSdmaUpdateSharedChan(pController->ChanSDHC, pController->DmaReqRx);
pController->CurrentDmaReq = pController->DmaReqRx ;
// Set flag to update the DMA channel context
pController->fDmaUpdateContext = TRUE;
}
}
}
// Build up scatter-gather list for transfers supported by DMA
if (pController->fDMATransfer == TRUE)
{
// Update DMA channel context if needed
if (pController->fDmaUpdateContext == TRUE)
{
DDKSdmaInitChain(pController->ChanSDHC, pController->Bytes_in_fifo);
pController->fDmaUpdateContext = FALSE;
}
// Map address and check for security violation
LPBYTE pBuffer = (LPBYTE) MapPtrToProcess((LPVOID)pRequest->pBlockBuffer, (HANDLE) GetCurrentProcessId());
if (pBuffer == NULL)
{
// Security violation
ERRORMSG(ZONE_ERROR, (TEXT("SDHBusRequestHandler: MapCaller pointer failed for block buffer\r\n")));
return SD_API_STATUS_ACCESS_VIOLATION;
}
// Use CEDDK macro to calculate the number of physical pages spanned by the mapped buffer in virtual memory
DWORD dwNumPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(pBuffer, dwNumBytesToTransfer);
// Check if we have enough buffer desciptors
if (dwNumPages > SDHC_DMA_BUF_DESC)
{
RETAILMSG(TRUE, (_T("WARNING: SDHBusRequestHandler: Buffer descriptors exhausted. Falling back to CPU transfers.\r\n")));
pController->fDMATransfer = FALSE;
}
else
{
// Use LockPages to translate the mapped buffer in virtual memory into an array of physical pages. These
// physical pages will be used to build up a scatter-gather list for the DMA
DWORD physPages[SDHC_DMA_BUF_DESC];
int fOptions = ((SD_WRITE == pRequest->TransferClass) ? LOCKFLAG_READ : LOCKFLAG_WRITE);
if (!LockPages(pBuffer, dwNumBytesToTransfer, physPages, fOptions))
{
// Security violation
ERRORMSG(ZONE_ERROR, (TEXT("SDHBusRequestHandler: LockPages failed for block buffer\r\n")));
return SD_API_STATUS_ACCESS_VIOLATION;
}
// Assume no bytes will be left stranded in the FIFO
pController->DmaStrandedBytes = 0;
DWORD dwTempPtr = (DWORD) pBuffer;
DWORD dwTempLen = dwNumBytesToTransfer;
DWORD currentDesc = 0;
// Traverse the physical pages returned by LockPages and build up a scatter-gather list for the DMA
for(DWORD i = 0; (i < dwNumPages) && (dwTempLen > 0) && pController->fDMATransfer; i++)
{
// Check for invaild physical pages
DEBUGCHK(physPages[i] != 0);
// Physical addresses returned from LockPages must be shifted to get start address of page
DWORD dwPhys = physPages[i] << UserKInfo[KINX_PFN_SHIFT];
// Offset into physical page is determined using lower bits of virtual address
DWORD dwOffset = dwTempPtr & (UserKInfo[KINX_PAGESIZE] - 1);
// Size for scatter-gather list item will be minimum of:
// - length of physical page minus buffer offset
// - remaining length of buffer
DWORD dwSize = UserKInfo[KINX_PAGESIZE] - dwOffset;
if(dwSize > dwTempLen)
{
dwSize = dwTempLen;
}
// Calculate physical address for scatter-gather list item
dwPhys += dwOffset;
// Track progress of traversal through virtual buffer
dwTempLen -= dwSize;
dwTempPtr += dwSize;
DWORD dwFlags;
// If we are done creating the scatter-gather list,
if(dwTempLen == 0)
{
// To avoid leaving data stranded in the SDHC FIFO, we must
// make the last buffer descriptor a multiple of the FIFO
// watermark (16 bytes for 1-bit, 64 bytes for 4-bit).
// We keep track of the number of bytes that would
// be stranded by the DMA and read them out
// with the CPU
pController->DmaStrandedBytes = dwSize & (pController->Bytes_in_fifo - 1);
dwSize -= pController->DmaStrandedBytes;
dwFlags = DDK_DMA_FLAGS_INTR | DDK_DMA_FLAGS_WRAP;
}
else if (dwTempLen < pController->Bytes_in_fifo)
{
pController->DmaStrandedBytes = dwTempLen;
dwTempLen = 0;
dwFlags = DDK_DMA_FLAGS_INTR | DDK_DMA_FLAGS_WRAP;
}
// Else we need more scatter-gather list entries, set the
// buffer descriptor continue flag
else
{
dwFlags = DDK_DMA_FLAGS_CONT;
}
// DMA cannot handle unaligned sizes and data pointers
if ((dwSize & 0x3) || (dwPhys & 0x3))
{
pController->fDMATransfer = FALSE;
continue;
}
#ifdef SDHC_SDMA_VERBOSE
if (SD_WRITE == pRequest->TransferClass)
RETAILMSG(TRUE, (_T("SD_WRITE: DDKSdmaSetBufDesc-SG (BD[%d], flags = 0x%x, addr = 0x%x, size = %d\r\n"), currentDesc, dwFlags, dwPhys, dwSize));
else
RETAILMSG(TRUE, (_T("SD_READ: DDKSdmaSetBufDesc-SG (BD[%d], flags = 0x%x, addr = 0x%x, size = %d\r\n"), currentDesc, dwFlags, dwPhys, dwSize));
#endif
// Add new buffer descriptor to DMA chain
DDKSdmaSetBufDesc(pController->ChanSDHC,
currentDesc,
dwFlags,
dwPhys,
0,
DDK_DMA_ACCESS_32BIT,
(UINT16) dwSize);
++currentDesc;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -