sdcontrol.c
来自「pxa27x library for windows ce 5.0」· C语言 代码 · 共 1,690 行 · 第 1/5 页
C
1,690 行
if (NULL != pHardwareContext->pClkMgrRegisters) {
MmUnmapIoSpace((PVOID)pHardwareContext->pClkMgrRegisters, sizeof(BULVERDE_CLKMGR_REG));
pHardwareContext->pClkMgrRegisters = NULL;
}
if (NULL != pHardwareContext->pDMARegisters) {
MmUnmapIoSpace((PVOID)pHardwareContext->pDMARegisters, sizeof(BULVERDE_DMA_REG));
pHardwareContext->pDMARegisters = NULL;
}
UnInitializeHardware();
DeleteCriticalSection(&pHardwareContext->ControllerCriticalSection);
return SD_API_STATUS_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////
// SDInitialize - Initialize the the MMC Controller
// Input: pHardwareContext - newly allocated hardware context
//
// Output:
// Return: SD_API_STATUS code
// Notes:
//
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS SDInitialize(PSDCARD_HC_CONTEXT pHCContext)
{
DWORD dwSDIOIrq;
DWORD dwRegVal; // intermediate value
SD_API_STATUS status = SD_API_STATUS_SUCCESS; // intermediate status
DWORD threadID; // thread ID
PSDH_HARDWARE_CONTEXT pHardwareContext; // hardware context
PHYSICAL_ADDRESS Bulverde_GPIO_Base = {BULVERDE_BASE_REG_PA_GPIO};
PHYSICAL_ADDRESS Bulverde_SDMMC_Base = {BULVERDE_BASE_REG_PA_MMC};
PHYSICAL_ADDRESS Bulverde_CLKMGR_Base = {BULVERDE_BASE_REG_PA_CLKMGR};
PHYSICAL_ADDRESS Bulverde_DMA_Base = {BULVERDE_BASE_REG_PA_DMAC};
pHardwareContext = GetExtensionFromHCDContext(PSDH_HARDWARE_CONTEXT, pHCContext);
InitializeCriticalSection(&pHardwareContext->ControllerCriticalSection);
pHardwareContext->fSDIOEnabled = FALSE;
pHardwareContext->fSDIOInterruptPending = FALSE;
pHardwareContext->f4BitMode = FALSE;
pHardwareContext->DevicePresent = FALSE;
if( !InitializeHardware() )
{
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("InitializeHardware:: Error initializing platform specific hardware\r\n")));
return SD_API_STATUS_INSUFFICIENT_RESOURCES;
}
pHardwareContext->pGPIORegisters = (BULVERDE_GPIO_REG*)MmMapIoSpace( Bulverde_GPIO_Base, sizeof(BULVERDE_GPIO_REG), FALSE );
if ( !pHardwareContext->pGPIORegisters )
{
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("InitializeHardware:: Error allocating Bulverde GPIO registers\r\n")));
return SD_API_STATUS_INSUFFICIENT_RESOURCES;
}
pHardwareContext->pSDMMCRegisters = (BULVERDE_MMC_REG*)MmMapIoSpace( Bulverde_SDMMC_Base, sizeof(BULVERDE_MMC_REG), FALSE );
if ( !pHardwareContext->pSDMMCRegisters )
{
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("InitializeHardware:: Error allocating Bulverde SD/MMC registers\r\n")));
goto exitInit;
}
pHardwareContext->pClkMgrRegisters = (BULVERDE_CLKMGR_REG*)MmMapIoSpace( Bulverde_CLKMGR_Base, sizeof(BULVERDE_CLKMGR_REG), FALSE );
if ( !pHardwareContext->pClkMgrRegisters )
{
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("InitializeHardware:: Error allocating Bulverde Clock control registers\r\n")));
goto exitInit;
}
pHardwareContext->pDMARegisters = (BULVERDE_DMA_REG*)MmMapIoSpace( Bulverde_DMA_Base, sizeof(BULVERDE_DMA_REG), FALSE );
if ( !pHardwareContext->pDMARegisters )
{
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("InitializeHardware:: Error allocating Bulverde DMA control registers\r\n")));
goto exitInit;
}
// enable the MMC Unit Clock
dwRegVal = pHardwareContext->pClkMgrRegisters->cken;
dwRegVal |= (1 << 12);
pHardwareContext->pClkMgrRegisters->cken = dwRegVal;
//////////////////////////////////////////////////////////
// Configure GPIO_32 as Alternate Function 2 out (MMC_CLK)
// assume that the MMC_CLK is active-low signal driven
dwRegVal = pHardwareContext->pGPIORegisters->GPCR1;
dwRegVal |= 0x00000001;
pHardwareContext->pGPIORegisters->GPCR1 = dwRegVal;
// change the direction to OUT
dwRegVal = pHardwareContext->pGPIORegisters->GPDR1;
dwRegVal |= 0x00000001;
pHardwareContext->pGPIORegisters->GPDR1 = dwRegVal;
// change to Alternate Function 2
dwRegVal = pHardwareContext->pGPIORegisters->GAFR1_L;
dwRegVal = ( dwRegVal & 0xfffffffc ) | 0x00000002;
pHardwareContext->pGPIORegisters->GAFR1_L = dwRegVal;
//////////////////////////////////////////////////////////
// Configure GPIO_112 as Alternate Function 1 (MMC_CMD)
// assume that the MMC_CLK is active-high signal driven
dwRegVal = pHardwareContext->pGPIORegisters->GPSR3;
dwRegVal |= 0x00010000;
pHardwareContext->pGPIORegisters->GPSR3 = dwRegVal;
// change the direction to OUT
dwRegVal = pHardwareContext->pGPIORegisters->GPDR3;
dwRegVal |= 0x00010000;
pHardwareContext->pGPIORegisters->GPDR3 = dwRegVal;
// change to Alternate Function 1
dwRegVal = pHardwareContext->pGPIORegisters->GAFR3_U;
dwRegVal = ( dwRegVal & 0xfffffffc ) | 0x00000001;
pHardwareContext->pGPIORegisters->GAFR3_U = dwRegVal;
//////////////////////////////////////////////////////////
// Configure GPIO_92 as Alternate Function 1 (MMC_DAT0)
// assume that the MMC_CLK is active-high signal driven
dwRegVal = pHardwareContext->pGPIORegisters->GPSR2;
dwRegVal |= 0x10000000;
pHardwareContext->pGPIORegisters->GPSR2 = dwRegVal;
// change the direction to OUT
dwRegVal = pHardwareContext->pGPIORegisters->GPDR2;
dwRegVal |= 0x10000000;
pHardwareContext->pGPIORegisters->GPDR2 = dwRegVal;
// change to Alternate Function 1
dwRegVal = pHardwareContext->pGPIORegisters->GAFR2_U;
dwRegVal = ( dwRegVal & 0xfcffffff ) | 0x01000000;
pHardwareContext->pGPIORegisters->GAFR2_U = dwRegVal;
//////////////////////////////////////////////////////////
// Configure GPIO_109-GPIO_111 as Alternate Function 1 (MMC_DAT1-MMC_DAT3)
// assume that the MMC_CLK is active-high signal driven
dwRegVal = pHardwareContext->pGPIORegisters->GPSR3;
dwRegVal |= 0x0000e000;
pHardwareContext->pGPIORegisters->GPSR3 = dwRegVal;
// change the direction to OUT
dwRegVal = pHardwareContext->pGPIORegisters->GPDR3;
dwRegVal |= 0x0000e000;
pHardwareContext->pGPIORegisters->GPDR3 = dwRegVal;
// change to Alternate Function 1
dwRegVal = pHardwareContext->pGPIORegisters->GAFR3_L;
dwRegVal = ( dwRegVal & 0x03ffffff ) | 0x54000000;
pHardwareContext->pGPIORegisters->GAFR3_L = dwRegVal;
#ifdef DEBUG
DumpRegisters( pHardwareContext );
DumpGPIORegisters( pHardwareContext );
#endif
// allocate the interrupt event
pHardwareContext->hControllerInterruptEvent = CreateEvent(NULL, FALSE, FALSE,NULL);
if (NULL == pHardwareContext->hControllerInterruptEvent) {
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto exitInit;
}
// convert the hardware SD/MMC controller interrupt IRQ into a logical SYSINTR value
dwSDIOIrq = pHardwareContext->dwSDMMCIrq;
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwSDIOIrq, sizeof(DWORD), &(pHardwareContext->dwSysintrSDMMC), sizeof(DWORD), NULL))
{
// invalid SDIO SYSINTR value!
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("Error obtaining SDIO SYSINTR value!\n")));
pHardwareContext->dwSysintrSDMMC = SYSINTR_UNDEFINED;
goto exitInit;
}
// initialize the interrupt event
if (!InterruptInitialize (pHardwareContext->dwSysintrSDMMC,
pHardwareContext->hControllerInterruptEvent,
NULL,
0)) {
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto exitInit;
}
pHardwareContext->DriverShutdown = FALSE;
// 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;
}
// 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
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?