sdcontrol.c
来自「该BSP是基于PXA270+WINCE的BSP」· C语言 代码 · 共 1,659 行 · 第 1/5 页
C
1,659 行
goto exitInit;
}
if( pHardwareContext->dwDmaChannel != 0xffffffff )
{
// allocate the DMA interrupt event
pHardwareContext->hDMAInterruptEvent = CreateEvent(NULL, FALSE, FALSE,NULL);
if( pHardwareContext->dwDmaSysIntr == SYSINTR_UNDEFINED )
{
// convert the hardware DMA controller interrupt IRQ into a logical SYSINTR value
DWORD dwDMAIrq = pHardwareContext->dwDmaIRQ;
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwDMAIrq, sizeof(DWORD), &(pHardwareContext->dwDmaSysIntr), sizeof(DWORD), NULL))
{
// invalid SDIO SYSINTR value!
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("Error obtaining DMA SYSINTR value!\n")));
pHardwareContext->dwDmaSysIntr = SYSINTR_UNDEFINED;
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto exitInit;
}
}
// allocate the DMA data & descriptors buffers
if( pHardwareContext->dwDmaBufferSize )
{
DMA_ADAPTER_OBJECT dmaAdapter;
dmaAdapter.ObjectSize = sizeof(dmaAdapter);
dmaAdapter.InterfaceType = Internal;
dmaAdapter.BusNumber = 0;
pHardwareContext->pDMABuffer = (PBYTE)HalAllocateCommonBuffer( &dmaAdapter,
pHardwareContext->dwDmaBufferSize,
&pHardwareContext->pDMABufferPhys,
FALSE );
if( pHardwareContext->pDMABuffer == NULL )
{
DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SHCDriver: - Unable to allocate memory for DMA buffers!\r\n")));
pHardwareContext->dwDmaBufferSize = 0;
}
else
{ // allocate DMA descriptors
DWORD dwDescriptorsSize = pHardwareContext->dwDmaBufferSize / pHardwareContext->systemInfo.dwPageSize;
if( pHardwareContext->dwDmaBufferSize % pHardwareContext->systemInfo.dwPageSize )
{
dwDescriptorsSize++;
}
dwDescriptorsSize *= sizeof(DMADescriptorChannelType);
pHardwareContext->pDMADescriptors = (volatile DMADescriptorChannelType*)HalAllocateCommonBuffer( &dmaAdapter,
dwDescriptorsSize,
&pHardwareContext->pDMADescriptorsPhys,
FALSE );
if( pHardwareContext->pDMADescriptors == NULL )
{
DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SHCDriver: - Unable to allocate memory for DMA descriptors!\r\n")));
HalFreeCommonBuffer( &dmaAdapter,
pHardwareContext->dwDmaBufferSize,
pHardwareContext->pDMABufferPhys,
pHardwareContext->pDMABuffer,
FALSE );
pHardwareContext->pDMABuffer = NULL;
pHardwareContext->dwDmaBufferSize = 0;
}
}
}
// install the DMA ISR handler
if( pHardwareContext->wszDmaIsrDll[0] )
{
GIISR_INFO Info;
PVOID PhysAddr;
DWORD inIoSpace = 0; // io space
PHYSICAL_ADDRESS DmaRegisterAddress = {DMA_INTERRUPT_REGISTER, 0};
pHardwareContext->hDMAIsrHandler = LoadIntChainHandler(pHardwareContext->wszDmaIsrDll,
pHardwareContext->wszDmaIsrHandler,
(BYTE)pHardwareContext->dwDmaIRQ);
if (pHardwareContext->hDMAIsrHandler == NULL) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("LoadIntChainHandler (%s, %s, %d) failed!\r\n"),
pHardwareContext->wszDmaIsrDll,
pHardwareContext->wszDmaIsrHandler,
(BYTE)pHardwareContext->dwDmaIRQ));
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto exitInit;
}
if (!BusTransBusAddrToStatic(pHardwareContext->hBusAccessHandle, Internal, 0, DmaRegisterAddress, sizeof(DWORD), &inIoSpace, &PhysAddr)) {
DEBUGMSG(SDCARD_ZONE_ERROR, (L"SDHC: Failed TransBusAddrToStatic\r\n"));
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto exitInit;
}
DEBUGMSG(SDCARD_ZONE_INIT, (L"SDHC: Installed ISR handler, Dll = '%s', Handler = '%s', Irq = %d, PhysAddr = 0x%x\r\n",
pHardwareContext->wszDmaIsrDll, pHardwareContext->wszDmaIsrHandler, pHardwareContext->dwDmaIRQ, PhysAddr));
// Set up ISR handler
Info.SysIntr = pHardwareContext->dwDmaSysIntr;
Info.CheckPort = TRUE;
Info.PortIsIO = FALSE;
Info.UseMaskReg = FALSE;
Info.PortAddr = (DWORD)PhysAddr;
Info.PortSize = sizeof(DWORD);
Info.Mask = 1 << pHardwareContext->dwDmaChannel;
if (!KernelLibIoControl(pHardwareContext->hDMAIsrHandler, IOCTL_GIISR_INFO, &Info, sizeof(Info), NULL, 0, NULL)) {
DEBUGMSG(SDCARD_ZONE_ERROR, (L"SDHC: KernelLibIoControl call failed.\r\n"));
}
}
// initialize the DMA interrupt event
if (!InterruptInitialize (pHardwareContext->dwDmaSysIntr,
pHardwareContext->hDMAInterruptEvent,
NULL,
0)) {
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto exitInit;
}
// create the interrupt thread for controller interrupts
pHardwareContext->hDmaInterruptThread = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)SDDMAIstThread,
pHardwareContext,
0,
&threadID);
if (NULL == pHardwareContext->hDmaInterruptThread) {
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto exitInit;
}
}
// create the interrupt thread for controller interrupts
pHardwareContext->hControllerInterruptThread = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)SDControllerIstThread,
pHardwareContext,
0,
&threadID);
if (NULL == pHardwareContext->hControllerInterruptThread) {
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto exitInit;
}
if (!SetupCardDetectIST(pHardwareContext))
{
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
}
exitInit:
if (!SD_API_SUCCESS(status)) {
// just call the deinit handler directly to cleanup
SDDeinitialize(pHCContext);
}
return status;
}
///////////////////////////////////////////////////////////////////////////////
// SDHCancelIoHandler - io cancel handler
// Input: pHostContext - host controller context
// Slot - slot the request is going on
// pRequest - the request to be cancelled
//
// Output:
// Return: TRUE if the request was cancelled
// Notes:
//
//
///////////////////////////////////////////////////////////////////////////////
BOOLEAN SDHCancelIoHandler(PSDCARD_HC_CONTEXT pHCContext,
DWORD Slot,
PSD_BUS_REQUEST pRequest)
{
PSDH_HARDWARE_CONTEXT pController;
// 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);
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
// SDHBusRequestHandler - bus request handler
// Input: pHostContext - host controller context
// Slot - slot the request is going on
// pRequest - the request
//
// Output:
// Return: SD_API_STATUS Code
// Notes: The request passed in is marked as uncancelable, this function
// has the option of making the outstanding request cancelable
//
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS SDHBusRequestHandler(PSDCARD_HC_CONTEXT pHCContext,
DWORD Slot,
PSD_BUS_REQUEST pRequest)
{
BOOL fExtraDelay = FALSE;
PSDH_HARDWARE_CONTEXT pController; // our controller
DWORD cmdatRegister; // CMDAT register
DbgPrintZo(SDCARD_ZONE_FUNC, (TEXT("SDHBusRequestHandler - CMD: 0x%02X DATA: 0x%08X, TC: %d\n"),
pRequest->CommandCode, pRequest->CommandArgument, pRequest->TransferClass));
// get our extension
pController = GetExtensionFromHCDContext(PSDH_HARDWARE_CONTEXT, pHCContext);
DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("SDHBusRequestHandler - CMD: 0x%02X DATA: 0x%08X, TC: %d\n"),
pRequest->CommandCode, pRequest->CommandArgument, pRequest->TransferClass));
// stop the clock
SDClockOff(pController);
// set the command
WRITE_MMC_REGISTER_DWORD(pController, MMC_CMD, pRequest->CommandCode);
// set the argument, high part
WRITE_MMC_REGISTER_DWORD(pController, MMC_ARGH, (pRequest->CommandArgument >> 16));
// set the argument, high part
WRITE_MMC_REGISTER_DWORD(pController, MMC_ARGL, (pRequest->CommandArgument & 0x0000FFFF));
switch (pRequest->CommandResponse.ResponseType) {
case NoResponse:
cmdatRegister = MMC_CMDAT_RESPONSE_NONE;
break;
case ResponseR1b:
// response1 with busy signalling
cmdatRegister = MMC_CMDAT_RESPONSE_R1 | MMC_CMDAT_EXPECT_BUSY;
break;
case ResponseR1:
case ResponseR5:
case ResponseR6:
// on an MMC controller R5 and R6 are really just an R1 response (CRC protected)
cmdatRegister = MMC_CMDAT_RESPONSE_R1;
break;
case ResponseR2:
cmdatRegister = MMC_CMDAT_RESPONSE_R2;
break;
case ResponseR3:
case ResponseR4:
// R4 is really same as an R3 response on an MMC controller (non-CRC)
cmdatRegister = MMC_CMDAT_RESPONSE_R3;
break;
default:
DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("SDHBusRequestHandler failed (Invalid parameter)\n")));
return SD_API_STATUS_INVALID_PARAMETER;
}
pController->fDMATransfer = FALSE;
pController->fDMATransferCancelled = FALSE;
// check for Command Only
if ((SD_COMMAND == pRequest->TransferClass)) {
// set the length of the block
WRITE_MMC_REGISTER_DWORD(pController, MMC_BLKLEN, 0);
// set the number of blocks
WRITE_MMC_REGISTER_DWORD(pController, MMC_NOB, 0);
} else {
// its a command with a data phase
cmdatRegister |= MMC_CMDAT_DATA_EN;
// set the buffer index to the end of the buffer
pRequest->HCParam = 0;
// set the length of the block
WRITE_MMC_REGISTER_DWORD(pController, MMC_BLKLEN, pRequest->BlockSize);
// set the number of blocks
WRITE_MMC_REGISTER_DWORD(pController, MMC_NOB, pRequest->NumBlocks);
// check for write
if (TRANSFER_IS_WRITE(pRequest)) {
cmdatRegister |= MMC_CMDAT_DATA_WRITE;
}
// check to see if we can use DMA for data transfer
if( PrepareDmaTransfer( pController, pRequest ) )
{
cmdatRegister |= MMC_CMDAT_DMA_ENABLE;
pController->fDMATransfer = TRUE;
}
}
// check to see if we need to append the 80 clocks (i.e. this is the first transaction)
if (pController->SendInitClocks) {
pController->SendInitClocks = FALSE;
cmdatRegister |= MMC_CMDAT_INIT;
fExtraDelay = TRUE;
}
// check to see if we need to enable the SDIO interrupt checking
if (pController->fSDIOEnabled) {
cmdatRegister |= MMC_CMDAT_SDIO_INT_EN;
}
// check to see if we need to enable wide bus (4 bit) data transfer mode
if (pController->f4BitMode) {
cmdatRegister |= MMC_CMDAT_SD_4DAT;
}
// write the CMDAT register
WRITE_MMC_REGISTER_DWORD(pController, MMC_CMDAT, cmdatRegister);
DbgPrintZo(SDH_SEND_ZONE, (TEXT("SDHBusRequestHandler - CMDAT Reg: 0x%08X, CMD:%d \n"),
cmdatRegister, pRequest->CommandCode));
// set the the response timeout
WRITE_MMC_REGISTER_DWORD(pController, MMC_RESTO, SDH_DEFAULT_RESPONSE_TIMEOUT_CLOCKS);
// set the data receive timeout
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?