📄 sdhcslot.h
字号:
//
// 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) 2002 BSQUARE Corporation. All rights reserved.
// DO NOT REMOVE --- BEGIN EXTERNALLY DEVELOPED SOURCE CODE ID 40973--- DO NOT REMOVE
#ifndef _SDHCSLOT_DEFINED
#define _SDHCSLOT_DEFINED
#include "SDCardDDK.h"
#include <SDHCD.h>
#include <ceddk.h>
#include "SDHCRegs.h"
#define SDHC_MAX_POWER_SUPPLY_RAMP_UP 250 // SD Phys Layer 6.6
#define SDHC_POWER_UP_DELAY_KEY _T("PowerUpDelay")
#define SDHC_WAKEUP_SOURCES_KEY _T("DefaultWakeupSources")
#define SDHC_CAN_WAKE_ON_INT_KEY _T("AllowWakeOnSDIOInterrupts")
#define SDHC_FREQUENCY_KEY _T("BaseClockFrequency")
#define SDHC_TIMEOUT_FREQUENCY_KEY _T("TimeoutClockFrequency")
#define SDHC_TIMEOUT_KEY _T("TimeoutInMS")
#define CRC_DEBUG 0
typedef class CSDHCSlotBase {
public:
// Constructor - only initializes the member data. True initialization
// occurs in Init().
CSDHCSlotBase();
virtual ~CSDHCSlotBase();
// Perform basic initialization including initializing the hardware
// so that the capabilities register can be read.
virtual BOOL Init(DWORD dwSlot, volatile BYTE *pbRegisters,
PSDCARD_HC_CONTEXT pHCDContext, DWORD dwSysIntr, HANDLE hBusAccess,
INTERFACE_TYPE interfaceType, DWORD dwBusNumber, CReg *pregDevice);
// Second stage of hardware initialization. Complete slot configuration
// and enable interrupts.
virtual SD_API_STATUS Start();
// Signals card removal disables the slot.
virtual SD_API_STATUS Stop();
// Process a slot option call.
virtual SD_API_STATUS SlotOptionHandler(SD_SLOT_OPTION_CODE sdOption,
PVOID pData, DWORD cbData);
// Get this slot's power state.
virtual CEDEVICE_POWER_STATE GetPowerState() { return m_cpsCurrent; }
// What power state is required upon power up?
virtual CEDEVICE_POWER_STATE GetPowerUpRequirement() { return m_cpsAtPowerDown; }
// Called when the device is suspending.
virtual VOID PowerDown();
// Called when the device is resuming.
virtual VOID PowerUp();
// Start this bus request.
virtual SD_API_STATUS BusRequestHandler(PSD_BUS_REQUEST pRequest);
// Returns TRUE if the interrupt routine needs servicing, say at
// initialization to see if a card is present.
virtual BOOL NeedsServicing() { return m_fCheckSlot; }
// Handle a slot interrupt. Also called when NeedsServicing() returns TRUE.
virtual VOID HandleInterrupt();
BOOL IsOnlySDIOInterrupt();
// Called by the controller to get the controller interrupt register.
inline WORD ReadControllerInterrupts() {
return ReadWord(SDHC_NORMAL_INT_STATUS);
}
protected:
// What is this slot's maximum clock rate?
virtual DWORD DetermineMaxClockRate();
// What is this slot's maximum block length?
virtual DWORD DetermineMaxBlockLen();
// What should this slot use for timeout control?
virtual DWORD DetermineTimeoutControl();
// What are the default wakeup sources?
virtual DWORD DetermineWakeupSources();
// Set the slot voltage.
virtual VOID SetVoltage(DWORD dwVddSetting);
// Set the bus width and clock rate.
virtual VOID SetInterface(PSD_CARD_INTERFACE pInterface);
// Set this slot's power state.
virtual VOID SetPowerState(CEDEVICE_POWER_STATE cpsNew);
// Get the capabilities register.
virtual SSDHC_CAPABILITIES GetCapabilities() {
SSDHC_CAPABILITIES caps;
caps.dw = ReadDword(SDHC_CAPABILITIES);
return caps;
}
// Fill in the slot info structure.
virtual SD_API_STATUS GetSlotInfo(PSDCARD_HC_SLOT_INFO pSlotInfo);
// Get the desired Vdd window.
virtual DWORD GetDesiredVddWindow();
// Get the max Vdd window.
virtual DWORD GetMaxVddWindow();
// Is the card write-protected?
virtual BOOL IsWriteProtected() {
return ((ReadDword(SDHC_PRESENT_STATE) & STATE_WRITE_PROTECT) == STATE_WRITE_PROTECT);
}
// Enable/disable SDIO card interrupts.
virtual VOID EnableSDIOInterrupts(BOOL fEnable);
// How much extra time in ms for initial clocks is needed upon
// insertion of a card for the power supply ramp up?
virtual DWORD GetPowerSupplyRampUpMs() {
return m_pregDevice->ValueDW(SDHC_POWER_UP_DELAY_KEY,
SDHC_MAX_POWER_SUPPLY_RAMP_UP);
}
// Register access routines. These are not virtual so that we get
// good inline read/write perf.
template <class T>
inline VOID WriteReg (DWORD dwOffset, T tValue) {
CheckRegOffset(dwOffset, sizeof(T));
volatile T *ptRegister = (volatile T *) (m_pbRegisters + dwOffset);
*ptRegister = tValue;
}
template <class T>
inline T ReadReg (DWORD dwOffset) {
CheckRegOffset(dwOffset, sizeof(T));
volatile T *ptRegister = (volatile T *) (m_pbRegisters + dwOffset);
return *ptRegister;
}
inline BYTE ReadByte (DWORD dwOffset) {
return ReadReg<BYTE>(dwOffset);
}
inline VOID WriteByte (DWORD dwOffset, BYTE bValue) {
WriteReg(dwOffset, bValue);
}
inline WORD ReadWord (DWORD dwOffset) {
return ReadReg<WORD>(dwOffset);
}
inline VOID WriteWord (DWORD dwOffset, WORD wValue) {
WriteReg(dwOffset, wValue);
}
inline DWORD ReadDword (DWORD dwOffset) {
return ReadReg<DWORD>(dwOffset);
}
inline VOID WriteDword(DWORD dwOffset, DWORD dwValue) {
WriteReg(dwOffset, dwValue);
}
// Interrupt handling methods
virtual VOID HandleRemoval(BOOL fCancelRequest);
virtual VOID HandleInsertion();
virtual BOOL HandleCommandComplete();
virtual VOID HandleErrors();
virtual VOID HandleTransferDone();
virtual VOID HandleReadReady();
virtual VOID HandleWriteReady();
virtual VOID HandleDma();
// Determines if DMA can be used for this request taking alignment
// requirements and capabilities into account.
virtual BOOL UseDmaForRequest(PSD_BUS_REQUEST pRequest);
// Allocates a physical buffer for DMA.
virtual PVOID AllocPhysBuffer(size_t cb, PDWORD pdwPhysAddr);
// Frees the physical buffer.
virtual VOID FreePhysBuffer(PVOID pv);
// Place the slot into the desired power state.
virtual VOID SetHardwarePowerState(CEDEVICE_POWER_STATE cpsNew);
// Performs the actual enabling/disabling of SDIO card interrupts.
virtual VOID DoEnableSDIOInterrupts(BOOL fEnable);
// Perform the desired reset and wait for completion. Returns FALSE
// if there is a timeout.
virtual BOOL SoftwareReset(BYTE bResetBits);
// Keep reading the register using (*pfnReadReg)(dwRegOffset) until
// value & tMask == tWaitForEqual.
template<class T>
BOOL WaitForReg(
T (CSDHCSlotBase::*pfnReadReg)(DWORD),
DWORD dwRegOffset,
T tMask,
T tWaitForEqual,
DWORD dwTimeout = 1000
);
// Turn the LED on or off.
virtual VOID EnableLED(BOOL fEnable);
// Calls SDHCDIndicateSlotStateChange.
virtual VOID IndicateSlotStateChange(SD_SLOT_EVENT sdEvent);
// Calls SDHCDGetAndLockCurrentRequest.
virtual PSD_BUS_REQUEST GetAndLockCurrentRequest();
// Calls SDHCDPowerUpDown.
virtual VOID PowerUpDown(BOOL fPowerUp, BOOL fKeepPower);
// Calls SDHCDIndicateBusRequestComplete.
virtual VOID IndicateBusRequestComplete(PSD_BUS_REQUEST pRequest, SD_API_STATUS status);
// Finds the closest rate that is *pdwRate or lower. Stores the
// actual rate in *pdwRate.
virtual VOID SetClockRate(PDWORD pdwRate);
// Turn on the SD clock according to the clock divisor found
// in SetClockRate().
virtual VOID SDClockOn();
// Turn off the SD clock.
virtual VOID SDClockOff();
// Determine the Vdd windows from the capabilities register.
virtual DWORD DetermineVddWindows();
// Set an interrupt event.
virtual VOID SetInterruptEvent() { ::SetInterruptEvent(m_dwSysIntr); }
#ifdef DEBUG
// Print out the standard host register set.
virtual VOID DumpRegisters();
// Validate the member data.
virtual VOID Validate();
// Verify that the desired register accesses are properly aligned.
VOID CheckRegOffset(DWORD dwOffset, DWORD dwRegSize) {
DEBUGCHK( (dwOffset % dwRegSize) == 0);
DEBUGCHK(dwOffset < sizeof(SSDHC_REGISTERS));
DEBUGCHK( (dwOffset + dwRegSize) <= sizeof(SSDHC_REGISTERS));
}
#else
// These routines do nothing in non-debug builds.
inline VOID DumpRegisters() {}
inline VOID Validate() {}
inline VOID CheckRegOffset(DWORD dwOffset, DWORD dwRegSize) {}
#endif
CReg *m_pregDevice; // pointer to device registry key
DWORD m_dwSlot; // physical slot number
volatile BYTE *m_pbRegisters; // memory-mapped registers
PSDCARD_HC_CONTEXT m_pHCDContext; // host context
DWORD m_dwSysIntr; // system interrupt
HANDLE m_hBusAccess; // bus parent
INTERFACE_TYPE m_interfaceType; // interface of the controller
DWORD m_dwBusNumber; // bus number of the controller
DWORD m_dwVddWindows; // supported VDD windows
DWORD m_dwMaxClockRate; // maximum clock rate
DWORD m_dwTimeoutControl; // timeout control value
DWORD m_dwMaxBlockLen; // maximum block length
PBYTE m_pbDmaBuffer; // virtual address of DMA buffer
DWORD m_paDmaBuffer; // physical address of DMA buffer
WORD m_wRegClockControl; // register value of Clock Control
WORD m_wIntSignals; // saved int signals for powerup
CEDEVICE_POWER_STATE m_cpsCurrent; // current power state
CEDEVICE_POWER_STATE m_cpsAtPowerDown; // power state at PowerDown()
DWORD m_dwDefaultWakeupControl; // wakeup source list
BYTE m_bWakeupControl; // current wakeup interrupts
BOOL isSDIOInterrupt;
#ifdef DEBUG
DWORD m_dwReadyInts; // number of Read/WriteReady interrupts that have occurred
#endif DEBUG
BOOL m_fCommandCompleteOccurred; // has the Command Complete occurred for the current transfer?
BOOL m_fSleepsWithPower : 1; // keep power in PowerDown()?
BOOL m_fPowerUpDisabledInts : 1; // did PowerUp disable SDIO card interrupts?
BOOL m_fIsPowerManaged : 1; // is the power manager handling us?
BOOL m_fSDIOInterruptsEnabled : 1; // are SDIO card interrupts enabled?
BOOL m_fCardPresent : 1; // is a card present
BOOL m_fAutoCMD12Success : 1; // AutoCMD12 success
BOOL m_fCheckSlot : 1; // does HandleInterrupt() need to be run?
BOOL m_fCanWakeOnSDIOInterrupts : 1; // can wake on SDIO interrupts
BOOL m_f4BitMode : 1; // 4 bit bus mode?
BOOL m_fFakeCardRemoval : 1; // should we simulate card removal?
#ifdef NEW_POWER_MANAGEMENT
// 2007.08.29 D.Baek
// Sleep/Wakeup Support
BOOL m_fWhileWakeup : 1; // dose it initialze a card after wakeup? 070822 hsjang
HANDLE m_hWaitForEndofWakeup;
#endif
} *PCSDHCSlotBase;
#define CB_DMA_BUFFER 0x30000 // 512KB buffer 0x20000//128KB buffer
#define CB_DMA_PAGE 0x30000 // we program DMA for 512KB pages // 0x1000 // we program DMA for 4KB pages
#define TRANSFER_IS_WRITE(pRequest) (SD_WRITE == (pRequest)->TransferClass)
#define TRANSFER_IS_READ(pRequest) (SD_READ == (pRequest)->TransferClass)
#define TRANSFER_IS_COMMAND_ONLY(pRequest) (SD_COMMAND == (pRequest)->TransferClass)
#define TRANSFER_SIZE(pRequest) ((pRequest)->BlockSize * (pRequest)->NumBlocks)
#define SDHC_DEFAULT_TIMEOUT 2000 // 2 seconds
// Is this request an SDIO abort (CMD52, Function 0, I/O Abort Reg)?
inline
BOOL
TransferIsSDIOAbort(
PSD_BUS_REQUEST pRequest
)
{
PREFAST_DEBUGCHK(pRequest);
BOOL fRet = FALSE;
if (pRequest->CommandCode == SD_CMD_IO_RW_DIRECT) {
if (IO_RW_DIRECT_ARG_FUNC(pRequest->CommandArgument) == 0) {
if (IO_RW_DIRECT_ARG_ADDR(pRequest->CommandArgument) == SD_IO_REG_IO_ABORT) {
fRet = TRUE;
}
}
}
return fRet;
}
#endif // _SDHCSLOT_DEFINED
// DO NOT REMOVE --- END EXTERNALLY DEVELOPED SOURCE CODE ID --- DO NOT REMOVE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -