📄 sdcontrol.cpp
字号:
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on
// your install media.
//
//------------------------------------------------------------------------------
//
// Copyright (C) 2004, Motorola Inc. All Rights Reserved
//
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//
// Copyright (C) 2004, 2005, 2006 Freescale Semiconductor, Inc. All Rights Reserved
// THIS SOURCE CODE IS CONFIDENTIAL AND PROPRIETARY AND MAY NOT
// BE USED OR DISTRIBUTED WITHOUT THE WRITTEN PERMISSION OF
// FREESCALE SEMICONDUCTOR, INC.
//
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//
// File: sdcontrol.cpp
//
// Implementation of SDHC common Device Driver
//
// This file implements common SDHC functions
// This driver is still pending to PMIC integration. During driver power down and power up,
// hardware reset is not implemented yet.
//------------------------------------------------------------------------------
#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>
#include "mxarm11.h"
#include "sdhc.h"
#include "sdbusdriver.h"
/*******************************************************************************
GLOBAL OR STATIC VARIABLES
*******************************************************************************/
/*******************************************************************************
STATIC FUNCTION PROTOTYPES
*******************************************************************************/
static DWORD SDControllerIstThread(PSDH_HARDWARE_CONTEXT pHCDevice);
static DWORD SDControllerBusyResponseThread(PSDH_HARDWARE_CONTEXT pHCDevice);
static void IndicateBusRequestComplete(PSDH_HARDWARE_CONTEXT pController,
PSD_BUS_REQUEST pRequest,
SD_API_STATUS status);
static BOOL HandleCommandComplete(PSDH_HARDWARE_CONTEXT pController);
static BOOL HandleTransferDone(PSDH_HARDWARE_CONTEXT pController);
static void SetRate(PSDH_HARDWARE_CONTEXT pHc, PDWORD pRate, BOOL fSetNewRate);
static void SetClock(PSDH_HARDWARE_CONTEXT pController, BOOL Start) ;
static void SoftwareReset(PSDH_HARDWARE_CONTEXT pController, BOOL bResetClock);
static void SetHardwarePowerState(PSDH_HARDWARE_CONTEXT pHc, CEDEVICE_POWER_STATE ds);
static void ProcessCardInsertion(void *pContext);
static void ProcessCardRemoval(void *pContext);
static void InitGlobals(PSDH_HARDWARE_CONTEXT pController);
static inline BOOL TransferIsSDIOAbort(PSD_BUS_REQUEST pRequest);
static BOOL InitDMA(PSDH_HARDWARE_CONTEXT pController) ;
static BOOL DeInitDMA(PSDH_HARDWARE_CONTEXT pController) ;
static BOOL SetupCardPresenceDetect(PSDH_HARDWARE_CONTEXT pHardwareContext) ;
static void SDCardPresenceDetect(void *pContext);
static void CleanupCardPresenceDetect(PSDH_HARDWARE_CONTEXT pHardwareContext);
static void DumpRegisters(PSDH_HARDWARE_CONTEXT pHc);
static void DumpStatusRegister(PSDH_HARDWARE_CONTEXT pHc);
/*******************************************************************************
EXPORTED FUNCTIONS
*******************************************************************************/
//------------------------------------------------------------------------------
//
// Function: SDInitialize
//
// Initialize the the MMC Controller
//
// Parameters:
// pHardwareContext[in] - newly allocated hardware context
//
// Returns:
// SD_API_STATUS code
//
//------------------------------------------------------------------------------
SD_API_STATUS SDInitialize(PSDCARD_HC_CONTEXT pHCContext)
{
SD_API_STATUS status = SD_API_STATUS_SUCCESS; // intermediate status
PHYSICAL_ADDRESS phyAddr;
PSDH_HARDWARE_CONTEXT pHardwareContext; // hardware context
pHardwareContext = GetExtensionFromHCDContext(PSDH_HARDWARE_CONTEXT, pHCContext);
DEBUGMSG(ZONE_FUNCTION, (TEXT("+SDInitialize: Initialize the SDHC\r\n")));
InitializeCriticalSection(&pHardwareContext->ControllerCriticalSection);
// Init globals
InitGlobals(pHardwareContext);
if (pHardwareContext->ControllerIndex == 1)
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("SDInitialize: Controller 1\r\n")));
//Virtual memory mapping
phyAddr.QuadPart = CSP_BASE_REG_PA_SDHC1 ;
}
else if (pHardwareContext->ControllerIndex == 2)
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("SDInitialize: Controller 2\r\n")));
//Virtual memory mapping
phyAddr.QuadPart = CSP_BASE_REG_PA_SDHC2 ;
}
else
{
ERRORMSG(ZONE_ERROR, (TEXT("SDInitialize: We only have 2 controllers!!\r\n")));
goto exitInit;
}
#if !VPMX31
//Start SDHC BSP specific initialization
if (!BSPSdhcInit(pHardwareContext->ControllerIndex))
{
ERRORMSG(ZONE_ERROR, (TEXT("BSPSdhcInit FAIL!\r\n")));
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto exitInit;
}
#endif //VPMX31
// Power off the card slot to save power
BSPSetVoltageSlot(pHardwareContext->ControllerIndex, 0);
// cut the clocks to the controller to save power
BSPSdhcSetClockGatingMode(FALSE, pHardwareContext->ControllerIndex);
//Setup IOMUX
BspSdhcSetIOMux(pHardwareContext->ControllerIndex);
//Get IRQ and DMA channels for SDHC
pHardwareContext->dwIrqSDHC = BspSdhcGetIrq(pHardwareContext->ControllerIndex);
pHardwareContext->DmaReqTx = (DDK_DMA_REQ)BspSdhcGetSdmaChannelTx(pHardwareContext->ControllerIndex);
pHardwareContext->DmaReqRx = (DDK_DMA_REQ)BspSdhcGetSdmaChannelRx(pHardwareContext->ControllerIndex);
// Map Virtual Address
pHardwareContext->pSDMMCRegisters = (PCSP_SDHC_REG) MmMapIoSpace(phyAddr, sizeof(CSP_SDHC_REG), FALSE);
if (pHardwareContext->pSDMMCRegisters == NULL)
{
ERRORMSG(ZONE_ERROR, (TEXT("SDInitialize: MmMapIoSpace failed!\r\n")));
goto exitInit;
}
if (BspSdhcIsSdmaSupported(pHardwareContext->ControllerIndex) == TRUE)
{
RETAILMSG(1, (TEXT("SDHC: DMA Support Enabled for Controller %d\r\n"), pHardwareContext->ControllerIndex));
// Initialize DMA
if (!InitDMA(pHardwareContext))
{
ERRORMSG(ZONE_ERROR, (TEXT("MMCSD_DMAInit: cannot init DMA!\r\n")));
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto exitInit;
}
}
else
{
RETAILMSG(1, (TEXT("SDHC: DMA Support Disabled for Controller %d\r\n"), pHardwareContext->ControllerIndex));
}
// controller clock gating between cmds is supported only for memory cards. This decision is taken later.
pHardwareContext->fClockGatingSupported = FALSE;
pHardwareContext->fClockGatedOff = TRUE; // controller clocks are not enabled here
// Setup card detection mechanism
if (!SetupCardPresenceDetect(pHardwareContext))
{
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto exitInit;
}
//Create interrupt event
pHardwareContext->hControllerInterruptEvent = CreateEvent(NULL, FALSE, FALSE,NULL);
if (NULL == pHardwareContext->hControllerInterruptEvent)
{
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto exitInit;
}
#ifdef SD_R1B_BUSYWAIT_WORKAROUND
//Create busy wait event
pHardwareContext->hControllerBusyEvent = CreateEvent(NULL, FALSE, FALSE,NULL);
if (NULL == pHardwareContext->hControllerBusyEvent)
{
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto exitInit;
}
// Initialize SDControllerBusyResponseThread() to handle busy response commands
DWORD busyThreadID;
// create the interrupt thread for controller interrupts
pHardwareContext->hControllerBusyResponseThread= CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)
SDControllerBusyResponseThread,
pHardwareContext,
0,
&busyThreadID);
if (NULL == pHardwareContext->hControllerBusyResponseThread)
{
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto exitInit;
}
#endif
//driver not shutting down
pHardwareContext->DriverShutdown = FALSE;
// Initialize SDControllerIstThread() to handle interrupt generated by Host Controller
DWORD threadID;
// 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;
}
// Translate IRQ to SYSINTR
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &(pHardwareContext->dwIrqSDHC),
sizeof(pHardwareContext->dwIrqSDHC), &(pHardwareContext->dwSysintrSDHC),
sizeof(pHardwareContext->dwSysintrSDHC), NULL))
{
ERRORMSG(ZONE_ERROR,(TEXT("%s: Request SYSINTR failed\r\n"), __WFUNCTION__));
goto exitInit;
}
//Initialize interrupt
if (!InterruptInitialize(pHardwareContext->dwSysintrSDHC,
pHardwareContext->hControllerInterruptEvent, NULL, 0))
{
ERRORMSG(ZONE_ERROR,(TEXT("%s: Interrupt initialization failed! \r\n"), __WFUNCTION__));
goto exitInit;
}
exitInit:
if (!SD_API_SUCCESS(status))
{
// just call the deinit handler directly to cleanup
SDDeinitialize(pHCContext);
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("-SDInitialize: Initialize the the MMC Controller\r\n")));
return status;
}
//------------------------------------------------------------------------------
//
// Function: SDDeInitialize
//
// Deinitialize the the MMC Controller
//
// Parameters:
// pHCContext[in] - Host controller context
//
// Returns:
// SD_API_STATUS code
//
//------------------------------------------------------------------------------
SD_API_STATUS SDDeinitialize(PSDCARD_HC_CONTEXT pHCContext)
{
PSDH_HARDWARE_CONTEXT pHardwareContext; // hardware context
DEBUGMSG(ZONE_FUNCTION, (TEXT("+SDDeinitialize: \r\n")));
pHardwareContext = GetExtensionFromHCDContext(PSDH_HARDWARE_CONTEXT, pHCContext);
// make sure all interrupt sources are disabled
InterruptDisable(pHardwareContext->dwSysintrSDHC);
// Indicate shutdown to threads
pHardwareContext->DriverShutdown = TRUE;
// clean up controller IST
if (NULL != pHardwareContext->hControllerInterruptThread)
{
// wake up the IST
SetEvent(pHardwareContext->hControllerInterruptEvent);
CloseHandle(pHardwareContext->hControllerInterruptThread);
pHardwareContext->hControllerInterruptThread = NULL;
}
#ifdef SD_R1B_BUSYWAIT_WORKAROUND
// clean up controller busy wait thread
if (NULL != pHardwareContext->hControllerBusyResponseThread)
{
// wake up the busy wait thread
SetEvent(pHardwareContext->hControllerBusyEvent);
CloseHandle(pHardwareContext->hControllerBusyResponseThread);
pHardwareContext->hControllerBusyResponseThread = NULL;
// free controller interrupt event
if (NULL != pHardwareContext->hControllerBusyEvent)
{
CloseHandle(pHardwareContext->hControllerBusyEvent);
pHardwareContext->hControllerBusyEvent = NULL;
}
}
#endif
// clean up card detection IST and free card insertion interrupt
CleanupCardPresenceDetect(pHardwareContext);
// Release SYSINTR
KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &(pHardwareContext->dwSysintrSDHC),
sizeof(DWORD), NULL, 0, NULL);
pHardwareContext->dwSysintrSDHC = SYSINTR_UNDEFINED;
// free controller interrupt event
if (NULL != pHardwareContext->hControllerInterruptEvent)
{
CloseHandle(pHardwareContext->hControllerInterruptEvent);
pHardwareContext->hControllerInterruptEvent = NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -