📄 sdcontrol.c
字号:
SD_API_STATUS SDInitialize(PSDCARD_HC_CONTEXT pHCContext)
{
DWORD dwSDIOIrq;
SD_API_STATUS status = SD_API_STATUS_SUCCESS; // intermediate status
DWORD threadID; // thread ID
PSDH_HARDWARE_CONTEXT pHardwareContext; // hardware context
PHYSICAL_ADDRESS SDMMC_Base = {PXA255_BASE_REG_PA_MMC};
PHYSICAL_ADDRESS DMA_Base = {PXA255_BASE_REG_PA_DMAC};
pHardwareContext = GetExtensionFromHCDContext(PSDH_HARDWARE_CONTEXT, pHCContext);
InitializeCriticalSection(&pHardwareContext->ControllerCriticalSection);
pHardwareContext->fSDIOEnabled = FALSE;
pHardwareContext->fSDIOInterruptPending = 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->pSDMMCRegisters = (MMC_REG_T *)MmMapIoSpace( SDMMC_Base, 0x400, FALSE );
if ( !pHardwareContext->pSDMMCRegisters )
{
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("InitializeHardware:: Error allocating SD/MMC registers\r\n")));
goto exitInit;
}
pHardwareContext->pDMARegisters = (DMAC_REG_T *)MmMapIoSpace( DMA_Base, 0x400, FALSE );
if ( !pHardwareContext->pDMARegisters )
{
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("InitializeHardware:: Error allocating DMA control registers\r\n")));
goto exitInit;
}
#ifdef DEBUG
DumpRegisters( 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
pController->pSDMMCRegisters->CMD = pRequest->CommandCode;
// set the argument, high part
pController->pSDMMCRegisters->ARGH = (pRequest->CommandArgument >> 16);
// set the argument, high part
pController->pSDMMCRegisters->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
pController->pSDMMCRegisters->BLKLE = 0;
// set the number of blocks
pController->pSDMMCRegisters->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
pController->pSDMMCRegisters->BLKLE = pRequest->BlockSize;
// set the number of blocks
pController->pSDMMCRegisters->NOB = pRequest->NumBlocks;
// check for write
if (TRANSFER_IS_WRITE(pRequest)) {
cmdatRegister |= MMC_CMDAT_DATA_WRITE;
}
}
// 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;
}
// write the CMDAT register
pController->pSDMMCRegisters->CMDAT = cmdatRegister;
DbgPrintZo(SDH_SEND_ZONE, (TEXT("SDHBusRequestHandler - CMDAT Reg: 0x%08X, CMD:%d \n"),
cmdatRegister, pRequest->CommandCode));
// set the the response timeout
pController->pSDMMCRegisters->RESTO = SDH_DEFAULT_RESPONSE_TIMEOUT_CLOCKS;
// set the data receive timeout
pController->pSDMMCRegisters->RDTO = SDH_DEFAULT_DATA_TIMEOUT_CLOCKS;
SetCurrentState(pController, CommandSend);
// turn on just the command complete interrupt
END_CMD_INTERRUPT_ON(pController);
// turn on the clock
SDClockOn(pController);
#if DEBUG
{
DWORD mmcStatus;
mmcStatus = pController->pSDMMCRegisters->STAT;
if (mmcStatus & 0x0000003F) {
// these errors should be cleared
DbgPrintZo(SDCARD_ZONE_ERROR,
(TEXT("********* SDHBusRequestHandler - MMC Status did not clear : 0x%08X \n"),
(mmcStatus & 0x0000003F)));
}
}
#endif
DbgPrintZo(SDH_SEND_ZONE, (TEXT("SDHBusRequestHandler - Request Sent\n")));
return SD_API_STATUS_PENDING;
}
///////////////////////////////////////////////////////////////////////////////
// SDHSlotOptionHandler - handler for slot option changes
// Input: pHostContext - host controller context
// SlotNumber - the slot the change is being applied to
// Option - the option code
// pData - data associated with the option
// OptionSize - size of option data
// Output:
// Return: SD_API_STATUS code
// Notes:
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS SDHSlotOptionHandler(PSDCARD_HC_CONTEXT pHCContext,
DWORD SlotNumber,
SD_SLOT_OPTION_CODE Option,
PVOID pData,
ULONG OptionSize)
{
SD_API_STATUS status = SD_API_STATUS_SUCCESS; // status
PSDH_HARDWARE_CONTEXT pController; // the controller
PSD_HOST_BLOCK_CAPABILITY pBlockCaps; // queried block capabilities
// get our extension
pController = GetExtensionFromHCDContext(PSDH_HARDWARE_CONTEXT, pHCContext);
switch (Option) {
case SDHCDSetSlotPower:
DbgPrintZo(SDCARD_ZONE_INIT,
(TEXT("SDHSlotOptionHandler - called - SetSlotPower : 0x%08X \n"),
*((PDWORD)pData)));
break;
case SDHCDSetSlotInterface:
DbgPrintZo(SDCARD_ZONE_INIT,
(TEXT("SDHSlotOptionHandler - called - SetSlotInterface : Clock Setting: %d \n"),
((PSD_CARD_INTERFACE)pData)->ClockRate));
if (SD_INTERFACE_SD_MMC_1BIT ==
((PSD_CARD_INTERFACE)pData)->InterfaceMode) {
DbgPrintZo(SDCARD_ZONE_INIT,
(TEXT("SDHSlotOptionHandler - called - SetSlotInterface : setting for 1 bit mode \n")));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -