📄 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-2007 Freescale Semiconductor, Inc. All Rights Reserved.
// THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
// AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT
//
//-----------------------------------------------------------------------------
//
// File: sdcontrol.cpp
//
// Implementation of SDHC common Device Driver
//
// This file implements common SDHC functions
// This driver is still pending to PMIC integration.
//------------------------------------------------------------------------------
#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>
#include "csp.h"
#include "sdhc.h"
/*******************************************************************************
GLOBAL OR STATIC VARIABLES
*******************************************************************************/
/*******************************************************************************
STATIC FUNCTION PROTOTYPES
*******************************************************************************/
static DWORD SDControllerIstThread(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 BOOL Drivstrset(DWORD dwIndex);
static void SoftwareReset(PSDH_HARDWARE_CONTEXT pController, BOOL bResetClock);
static void SetHardwarePowerState(PSDH_HARDWARE_CONTEXT pHc, CEDEVICE_POWER_STATE ds);
static void ResetCard(SDH_HARDWARE_CONTEXT *pController);
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 DWORD SDControllerBusyWaitResponse(PSDH_HARDWARE_CONTEXT pHCDevice);
#if DMA
static BOOL InitDMA(PSDH_HARDWARE_CONTEXT pController) ;
static BOOL DeInitDMA(PSDH_HARDWARE_CONTEXT pController) ;
#endif //DMA
static BOOL SetupCardDetectIST(PSDH_HARDWARE_CONTEXT pHardwareContext) ;
static void CleanupCardDetectIST(PSDH_HARDWARE_CONTEXT pHardwareContext);
static void DumpRegisters(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
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);
// Map Virtual Address
pHardwareContext->pSDMMCRegisters = (PCSP_SDHC_REG) MmMapIoSpace(pHardwareContext->phySDHCAddr, sizeof(CSP_SDHC_REG), FALSE);
if (pHardwareContext->pSDMMCRegisters == NULL)
{
ERRORMSG(ZONE_ERROR, (TEXT("SDInitialize: MmMapIoSpace failed!\r\n")));
goto exitInit;
}
//driving strength SDHC
Drivstrset(pHardwareContext->ControllerIndex);
//Turn off the voltage regulator to the slot
BSPSlotVoltageOff(pHardwareContext->ControllerIndex);
//Set slot voltage
BSPSetVoltageSlot(pHardwareContext->ControllerIndex, 0) ;
//Stopt clock gating mode
BSPSdhcSetClockGatingMode(FALSE, pHardwareContext->ControllerIndex) ;
//Setup GPIO
BspSdhcSetGPIO(pHardwareContext->ControllerIndex);
//Reset the controller
SoftwareReset(pHardwareContext, TRUE);
#if DMA
// Initialize DMA
if (!InitDMA(pHardwareContext))
{
ERRORMSG(ZONE_ERROR, (TEXT("MMCSD_DMAInit: cannot init DMA!\r\n")));
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto exitInit;
}
#endif //DMA
//Create interrupt event
pHardwareContext->hControllerInterruptEvent = CreateEvent(NULL, FALSE, FALSE,NULL);
if (NULL == pHardwareContext->hControllerInterruptEvent)
{
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;
}
//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;
}
// Create interrupt thread for card detection
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);
}
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;
}
// clean up card detection IST and free card insertion interrupt
CleanupCardDetectIST(pHardwareContext);
// Release SYSINTR
KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &(pHardwareContext->dwSysintrSDHC),
sizeof(DWORD), NULL, 0, NULL);
pHardwareContext->dwSysintrSDHC = (DWORD)SYSINTR_UNDEFINED;
// free controller interrupt event
if (NULL != pHardwareContext->hControllerInterruptEvent)
{
CloseHandle(pHardwareContext->hControllerInterruptEvent);
pHardwareContext->hControllerInterruptEvent = NULL;
}
#if DMA
// Release DMA Resources
DeInitDMA(pHardwareContext);
#endif //DMA
// free the virtual space allocated for SDHC1 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: SDControllerBusyWaitResponse
//
// Thread for SDHC/MMC Controller driver which busy waits for controller to be ready
// in order to invoke next commands
//
// Parameters:
// pHCDevice[in] - the controller instance
//
// Returns:
// Thread exit code
//
//------------------------------------------------------------------------------
DWORD SDControllerBusyWaitResponse(PSDH_HARDWARE_CONTEXT pHCDevice)
{
DWORD cmdatRegister=0, cmdArg = 0; // CMDAT register
PSD_BUS_REQUEST pRequest;
SD_API_STATUS status = SD_API_STATUS_SUCCESS;
LONG ii; // loop variable
USHORT responseBuffer[SDH_RESPONSE_FIFO_DEPTH - 5]; // response buffer
SD_CARD_STATUS CardStatus = 0, CardState = 0;
PUCHAR tempBuffer = NULL;
CHAR retryCount =0;
DEBUGMSG(ZONE_FUNCTION, (TEXT("+SDControllerBusyWaitResponse for SDHC/MMC Controller driver\r\n")));
retryCount = DEFAULT_BUS_REQUEST_RETRY_COUNT;
pRequest = SDHCDGetAndLockCurrentRequest(pHCDevice->pHCContext, 0);
cmdArg = (((DWORD)((SDDCGetClientDeviceFromHandle(pRequest->hDevice))->RelativeAddress)) << 16);
do
{
status = SD_API_STATUS_SUCCESS;
if (CardState != CardStatus)
{
DEBUGMSG (ZONE_INFO,(TEXT("SDControllerBusyWaitResponse: Sleeping before issuing next Status cmd\r\n")));
Sleep (0);
}
CardState = CardStatus;
DEBUGMSG(ZONE_INFO, (TEXT("SDControllerBusyWaitResponse: Sending Status Command %d\r\n"), retryCount));
CardState = SD_STATUS_CURRENT_STATE_TRAN;
CSP_BITFINS(cmdatRegister, SDHC_CDC_FORMAT, 1);
// check to see if we need to enable wide bus (4 bit) data transfer mode
CSP_BITFINS(cmdatRegister, SDHC_CDC_BW, pHCDevice->BusWidthSetting);
// clear all status
OUTREG32(&pHCDevice->pSDMMCRegisters->STATUS, 0xFFFFFFFF);
// set the command
INSREG32BF(&pHCDevice->pSDMMCRegisters->CMD, SDHC_CMD_CMD, SD_CMD_SEND_STATUS);
// set the argument
OUTREG32(&pHCDevice->pSDMMCRegisters->ARG, cmdArg);
// write the CMDAT register
OUTREG32(&pHCDevice->pSDMMCRegisters->CMD_DAT_CONT, cmdatRegister);
//start clock
//SetClock(pHCDevice, TRUE);
while (!EXTREG32BF(&pHCDevice->pSDMMCRegisters->STATUS, SDHC_SR_ECR))
Sleep (0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -