📄 sdhc.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) 2002 BSQUARE Corporation. All rights reserved.
// DO NOT REMOVE --- BEGIN EXTERNALLY DEVELOPED SOURCE CODE ID 40973--- DO NOT REMOVE
// SDHC controller driver implementation
#include "SDCardDDK.h"
#include "SDHC.h"
#ifndef SHIP_BUILD
#define STR_MODULE _T("CSDHCBase::")
#define SETFNAME(name) LPCTSTR pszFname = STR_MODULE name _T(":")
#else
#define SETFNAME(name)
#endif
#ifdef DEBUG
#define MAKE_OPTION_STRING(x) _T(#x)
const LPCTSTR CSDHCBase::sc_rgpszOptions[SDHCDSlotOptionCount] = {
MAKE_OPTION_STRING(SDHCDSetSlotPower),
MAKE_OPTION_STRING(SDHCDSetSlotInterface),
MAKE_OPTION_STRING(SDHCDEnableSDIOInterrupts),
MAKE_OPTION_STRING(SDHCDDisableSDIOInterrupts),
MAKE_OPTION_STRING(SDHCDAckSDIOInterrupt),
MAKE_OPTION_STRING(SDHCDGetWriteProtectStatus),
MAKE_OPTION_STRING(SDHCDQueryBlockCapability),
MAKE_OPTION_STRING(SDHCDSetClockStateDuringIdle),
MAKE_OPTION_STRING(SDHCDSetSlotPowerState),
MAKE_OPTION_STRING(SDHCDGetSlotPowerState),
MAKE_OPTION_STRING(SDHCDWakeOnSDIOInterrupts),
MAKE_OPTION_STRING(SDHCDGetSlotInfo),
};
#endif
CSDHCBase::CSDHCBase(
)
: m_regDevice()
{
m_hBusAccess = NULL;
m_cSlots = 0;
m_pSlots = NULL;
m_pSlotInfos = NULL;
m_pHCDContext = NULL;
m_interfaceType = InterfaceTypeUndefined;
m_dwBusNumber = INVALID_BUS_NUMBER;
m_hISRHandler = NULL;
m_dwSysIntr = SYSINTR_UNDEFINED;
m_dwPriority = 0;
m_hevInterrupt = NULL;
m_htIST = NULL;
m_cpsCurrent = D0;
m_fHardwareInitialized = FALSE;
m_fRegisteredWithBusDriver = FALSE;
m_fDriverShutdown = FALSE;
m_fInterruptInitialized = FALSE;
}
CSDHCBase::~CSDHCBase(
)
{
// We call PreDeinit just in case we are not being destroyed by
// a call to SHC_PreDeinit.
PreDeinit();
if (m_fHardwareInitialized) {
DeinitializeHardware();
}
if (m_pHCDContext) {
// Cleanup the host context
SDHCDDeleteContext(m_pHCDContext);
}
if (m_pSlots) delete [] m_pSlots;
if (m_pSlotInfos) LocalFree(m_pSlotInfos);
if (m_hBusAccess) CloseBusAccessHandle(m_hBusAccess);
}
BOOL
CSDHCBase::Init(
LPCTSTR pszActiveKey
)
{
BOOL fRet = FALSE;
SD_API_STATUS status;
HKEY hkDevice = NULL;
hkDevice = OpenDeviceKey(pszActiveKey);
if (!hkDevice || !m_regDevice.Open(hkDevice, _T(""))) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHC: Failed to open device key\n")));
goto EXIT;
}
// Get a handle to our parent bus.
m_hBusAccess = CreateBusAccessHandle(pszActiveKey);
if (m_hBusAccess == NULL) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHC: Could not get handle to parent\n")));
goto EXIT;
}
m_cSlots = DetermineSlotCount();
if (m_cSlots == 0) {
goto EXIT;
}
ValidateSlotCount();
RETAILMSG(0,(TEXT("CSDHCBase::Init m_cSlots=%d\n"),m_cSlots)); // jylee
m_pSlotInfos = (PSDHC_SLOT_INFO) LocalAlloc(LPTR,
sizeof(SDHC_SLOT_INFO) * m_cSlots);
if (m_pSlotInfos == NULL) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHC Failed to allocate slot info objects\n")));
goto EXIT;
}
status = SDHCDAllocateContext(m_cSlots, &m_pHCDContext);
if (!SD_API_SUCCESS(status)) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHC Failed to allocate context : 0x%08X \n"),
status));
goto EXIT;
}
// Set our extension
m_pHCDContext->pHCSpecificContext = this;
if (!InitializeHardware()) {
goto EXIT;
}
RETAILMSG(0,(TEXT("AllocateSlotObjects\n")));
// Allocate slot objects
m_pSlots = AllocateSlotObjects(m_cSlots);
if (m_pSlots == NULL) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHC Failed to allocate slot objects\n")));
goto EXIT;
}
// Initialize the slots
for (DWORD dwSlot = 0; dwSlot < m_cSlots; ++dwSlot) {
PSDHC_SLOT_INFO pSlotInfo = &m_pSlotInfos[dwSlot];
PCSDHCSlotBase pSlot = GetSlot(dwSlot);
RETAILMSG(0,(TEXT("pSlot->Init\n")));
RETAILMSG(0,(TEXT("pSlotInfo->pucRegisters : 0x%x\r\n"),pSlotInfo->pucRegisters));
if (!pSlot->Init(dwSlot, pSlotInfo->pucRegisters, m_pHCDContext,
m_dwSysIntr, m_hBusAccess, m_interfaceType, m_dwBusNumber, &m_regDevice)) {
goto EXIT;
}
}
// set the host controller name
SDHCDSetHCName(m_pHCDContext, TEXT("HSMMC"));
// set init handler
SDHCDSetControllerInitHandler(m_pHCDContext, CSDHCBase::SDHCInitialize);
// set deinit handler
SDHCDSetControllerDeinitHandler(m_pHCDContext, CSDHCBase::SDHCDeinitialize);
// set the Send packet handler
SDHCDSetBusRequestHandler(m_pHCDContext, CSDHCBase::SDHCBusRequestHandler);
// set the cancel I/O handler
SDHCDSetCancelIOHandler(m_pHCDContext, CSDHCBase::SDHCCancelIoHandler);
// set the slot option handler
SDHCDSetSlotOptionHandler(m_pHCDContext, CSDHCBase::SDHCSlotOptionHandler);
// These values must be set before calling SDHCDRegisterHostController()
// because they are used during that call.
m_dwPriority = m_regDevice.ValueDW(SDHC_PRIORITY_KEY, SDHC_CARD_CONTROLLER_PRIORITY);
RETAILMSG(0,(TEXT("SDHCDRegisterHostController\n"))); // jylee
// now register the host controller
status = SDHCDRegisterHostController(m_pHCDContext);
if (!SD_API_SUCCESS(status)) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHC Failed to register host controller: %0x08X \n"),
status));
goto EXIT;
}
m_fRegisteredWithBusDriver = TRUE;
fRet = TRUE;
RETAILMSG(0,(TEXT("CSDHCBase::Init Finished.\n"))); // jylee
EXIT:
if (hkDevice) RegCloseKey(hkDevice);
return fRet;
}
SD_API_STATUS
CSDHCBase::Start()
{
SD_API_STATUS status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
m_fDriverShutdown = FALSE;
// allocate the interrupt event
m_hevInterrupt = CreateEvent(NULL, FALSE, FALSE,NULL);
if (NULL == m_hevInterrupt) {
goto EXIT;
}
// initialize the interrupt event
RETAILMSG(0,(_T("CSDHCBase::Start() m_dwSysIntr = %x\r\n"), m_dwSysIntr)); // jylee
if (!InterruptInitialize (m_dwSysIntr, m_hevInterrupt, NULL, 0)) {
goto EXIT;
}
m_fInterruptInitialized = TRUE;
// create the interrupt thread for controller interrupts
m_htIST = CreateThread(NULL, 0, ISTStub, this, 0, NULL);
if (NULL == m_htIST) {
goto EXIT;
}
for (DWORD dwSlot = 0; dwSlot < m_cSlots; ++dwSlot) {
PCSDHCSlotBase pSlot = GetSlot(dwSlot);
status = pSlot->Start();
if (!SD_API_SUCCESS(status)) {
goto EXIT;
}
}
// wake up the interrupt thread to check the slot
::SetInterruptEvent(m_dwSysIntr);
status = SD_API_STATUS_SUCCESS;
EXIT:
if (!SD_API_SUCCESS(status)) {
// Clean up
Stop();
}
RETAILMSG(0,(_T("CSDHCBase::-Start() status = %x\r\n"), status)); // jylee
return status;
}
SD_API_STATUS
CSDHCBase::Stop()
{
// Mark for shutdown
m_fDriverShutdown = TRUE;
if (m_fInterruptInitialized) {
KernelIoControl(IOCTL_HAL_DISABLE_WAKE, &m_dwSysIntr, sizeof(m_dwSysIntr),
NULL, 0, NULL);
InterruptDisable(m_dwSysIntr);
}
// Clean up controller IST
if (m_htIST) {
// Wake up the IST
SetEvent(m_hevInterrupt);
WaitForSingleObject(m_htIST, INFINITE);
CloseHandle(m_htIST);
m_htIST = NULL;
}
// free controller interrupt event
if (m_hevInterrupt) {
CloseHandle(m_hevInterrupt);
m_hevInterrupt = NULL;
}
for (DWORD dwSlot = 0; dwSlot < m_cSlots; ++dwSlot) {
PCSDHCSlotBase pSlot = GetSlot(dwSlot);
pSlot->Stop();
}
return SD_API_STATUS_SUCCESS;
}
SD_API_STATUS
CSDHCBase::SlotOptionHandler(
DWORD dwSlot,
SD_SLOT_OPTION_CODE sdOption,
PVOID pData,
DWORD cbData
)
{
SD_API_STATUS status = SD_API_STATUS_SUCCESS;
BOOL fCallSlotsHandler = TRUE;
Lock();
Validate();
PCSDHCSlotBase pSlot = GetSlot(dwSlot);
DEBUGCHK(sdOption < dim(sc_rgpszOptions));
DEBUGCHK(sc_rgpszOptions[sdOption] != NULL);
DEBUGMSG(SDCARD_ZONE_INFO, (_T("CSDHCBase::SlotOptionHandler(%u, %s)\n"),
dwSlot, sc_rgpszOptions[sdOption]));
switch (sdOption) {
case SDHCDSetSlotPower: {
if (cbData != sizeof(DWORD)) {
status = SD_API_STATUS_INVALID_PARAMETER;
}
break;
}
case SDHCDSetSlotInterface: {
if (cbData != sizeof(SD_CARD_INTERFACE)) {
status = SD_API_STATUS_INVALID_PARAMETER;
}
break;
}
case SDHCDEnableSDIOInterrupts:
case SDHCDDisableSDIOInterrupts:
case SDHCDAckSDIOInterrupt:
if (pData || cbData != 0) {
status = SD_API_STATUS_INVALID_PARAMETER;
}
break;
case SDHCDGetWriteProtectStatus: {
if (cbData != sizeof(SD_CARD_INTERFACE)) {
status = SD_API_STATUS_INVALID_PARAMETER;
}
break;
}
case SDHCDQueryBlockCapability: {
if (cbData != sizeof(SD_HOST_BLOCK_CAPABILITY)) {
status = SD_API_STATUS_INVALID_PARAMETER;
}
break;
}
case SDHCDSetSlotPowerState: {
if (cbData != sizeof(CEDEVICE_POWER_STATE)) {
status = SD_API_STATUS_INVALID_PARAMETER;
}
PCEDEVICE_POWER_STATE pcps = (PCEDEVICE_POWER_STATE) pData;
if (*pcps < m_cpsCurrent) {
// Move controller to higher power state initially since
// it will need to be powered for the slot to access
// registers.
SetControllerPowerState(*pcps);
}
status = pSlot->SlotOptionHandler(sdOption, pData, cbData);
// Set the power state based on current conditions. Note that
// the slot may have gone to a state different from what was
// requested.
CEDEVICE_POWER_STATE cps = DetermineRequiredControllerPowerState();
SetControllerPowerState(cps);
fCallSlotsHandler = FALSE;
break;
}
case SDHCDGetSlotPowerState: {
if (cbData != sizeof(CEDEVICE_POWER_STATE)) {
status = SD_API_STATUS_INVALID_PARAMETER;
}
break;
}
case SDHCDWakeOnSDIOInterrupts: {
if (cbData != sizeof(BOOL)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -