📄 sdhc.cpp
字号:
BOOL fRegisteredWithBusDriver = FALSE;
BOOL fHardwareInitialized = FALSE;
PHYSICAL_ADDRESS pa;
DEBUGMSG(SDCARD_ZONE_INIT, (L"+CSDIOControllerBase::Init: "
L"Active RegPath: %s\r\n", pszActiveKey
));
m_pCurrentRequest = NULL;
m_pszActiveKey = pszActiveKey; //save the activity key for power mgt
hKeyDevice = OpenDeviceKey(pszActiveKey);
if ( (hKeyDevice == NULL) || !regDevice.Open(hKeyDevice, NULL) ) {
DEBUGMSG(SDCARD_ZONE_ERROR, (L"CSDIOControllerBase::Init: "
L"Failed to open device key\r\n"
));
goto EXIT;
}
// allocate the context - support for 2 Slots - BUT 1 controller
status = SDHCDAllocateContext(1, &m_pHCContext);
if (!SD_API_SUCCESS(status)) {
DEBUGMSG(SDCARD_ZONE_ERROR, (L"CSDIOControllerBase::Init: "
L"Failed to allocate context : 0x%08X\r\n",
status
));
goto EXIT;
}
// Set our extension
m_pHCContext->pHCSpecificContext = this;
if( !GetRegistrySettings(®Device) )
{
DEBUGMSG(SDCARD_ZONE_ERROR, (L"CSDIOControllerBase::Init: "
L"Error reading registry settings\r\n"
));
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto EXIT;
}
// map hardware memory space
pa.QuadPart = OMAP3_MMCHS1_REGS_PA;
m_vpSDIOReg = (OMAP2420_SDIO_REGS*)MmMapIoSpace( pa, sizeof(OMAP2420_SDIO_REGS), FALSE );
if ( !m_vpSDIOReg )
{
DEBUGMSG(SDCARD_ZONE_ERROR, (L"CSDIOControllerBase::Init: "
L"Error allocating MMC controller register\r\n"
));
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto EXIT;
}
pa.QuadPart = OMAP2420_PRCM_REGS_PA;
m_vpPRCMReg = (OMAP2420_PRCM_REGS*)MmMapIoSpace( pa, sizeof(OMAP2420_PRCM_REGS), FALSE );
if ( !m_vpPRCMReg )
{
DEBUGMSG(SDCARD_ZONE_ERROR, (L"CSDIOControllerBase::Init: "
L"Error allocating Power Reset and Clock Managment Registers\r\n"
));
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto EXIT;
}
if( !InitializeHardware() )
{
DEBUGMSG(SDCARD_ZONE_ERROR, (L"CSDIOControllerBase::Init: "
L"Error allocating CD/RW GPIO registers\r\n"
));
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto EXIT;
}
// turn the SDHC controller to fully on!
ClockOn();
this->m_PowerState = D0;
fHardwareInitialized = TRUE;
// Initialize the slot
SoftwareReset(SOFT_RESET_ALL);
Sleep(10); // Allow time for card to power down after a device reset
DumpRegisters();
// Read SD Host Controller Info from register.
if (!InterpretCapabilities())
{
goto EXIT;
}
// now register the host controller
status = SDHCDRegisterHostController(m_pHCContext);
if (!SD_API_SUCCESS(status)) {
DEBUGMSG(SDCARD_ZONE_ERROR, (L"CSDIOControllerBase::Init: "
L"Failed to register host controller: %0x08X\r\n", status
));
goto EXIT;
}
fRegisteredWithBusDriver = TRUE;
// return the controller context
dwRet = (DWORD) this;
EXIT:
if (hKeyDevice) RegCloseKey(hKeyDevice);
if ( (dwRet == 0) && m_pHCContext ) {
FreeHostContext( fRegisteredWithBusDriver, fHardwareInitialized );
}
DEBUGMSG(SDCARD_ZONE_INIT, (L"-CSDIOControllerBase::Init\r\n"));
return dwRet;
}
// Free the host context and associated resources.
VOID CSDIOControllerBase::FreeHostContext( BOOL fRegisteredWithBusDriver, BOOL fHardwareInitialized )
{
DEBUGCHK(m_pHCContext);
ClockOff();
if (fRegisteredWithBusDriver) {
// deregister the host controller
SDHCDDeregisterHostController(m_pHCContext);
}
// unmap hardware memory space
DeinitializeHardware();
if (m_vpSDIOReg) MmUnmapIoSpace((PVOID)m_vpSDIOReg, sizeof(OMAP2420_SDIO_REGS));
if (m_vpPRCMReg) MmUnmapIoSpace((PVOID)m_vpPRCMReg, sizeof(OMAP2420_PRCM_REGS));
m_PowerState = D4;
// cleanup the host context
SDHCDDeleteContext(m_pHCContext);
}
BOOL CSDIOControllerBase::IOControl(
DWORD dwCode,
BYTE *pInBuffer,
DWORD inSize,
BYTE *pOutBuffer,
DWORD outSize,
DWORD *pOutSize)
{
BOOL bRetVal = FALSE;
DEBUGMSG(SDCARD_ZONE_FUNC, (L"+CSDIOControllerBase::IOControl(0x%08x, 0x%08x, %d, 0x%08x, %d, 0x%08x)\r\n",
dwCode, pInBuffer, inSize, pOutBuffer, outSize, pOutSize
));
switch (dwCode) {
// Power management functions.
// Return device specific power capabilities.
case IOCTL_POWER_CAPABILITIES:
{
POWER_CAPABILITIES pc;
// Check arguments.
if ( pOutBuffer == NULL || outSize < sizeof(POWER_CAPABILITIES))
{
DEBUGMSG(SDCARD_ZONE_ERROR, (L"CSDIOControllerBase::IOControl: "
L"IOCTL_POWER_CAPABILITIES Invalid parameter.\r\n"
));
break;
}
// Clear capabilities structure.
memset(&pc, 0, sizeof(POWER_CAPABILITIES));
// Set power capabilities. Supports D0 and D4.
pc.DeviceDx = DX_MASK(D0)|DX_MASK(D4);
DEBUGMSG(SDCARD_ZONE_POWER, (L"CSDIOControllerBase::IOControl: "
L"IOCTL_POWER_CAPABILITIES = 0x%x\r\n", pc.DeviceDx
));
if (CeSafeCopyMemory(pOutBuffer, &pc, sizeof(pc)) == 0)
{
DEBUGMSG(SDCARD_ZONE_ERROR, (L"CSDIOControllerBase::IOControl: "
L"CeSafeCopyMemory Failed\r\n"
));
break;
}
// Update returned data size.
if (pOutSize)
{
*pOutSize = sizeof(pc);
}
bRetVal = TRUE;
break;
}
// Indicate if the device is ready to enter a new device power state.
case IOCTL_POWER_QUERY:
{
DEBUGMSG(SDCARD_ZONE_POWER, (L"CSDIOControllerBase::IOControl: "
L"IOCTL_POWER_QUERY Deprecated Function Called\r\n"
));
bRetVal = FALSE;
break;
}
// Request a change from one device power state to another
// This driver self-manages it's internal power state by controlling
// functional and interface clocks as needed in the Read and Write
// functions rather than waiting for PM to tell it to save power
// So the set calls below just update the power state variable
case IOCTL_POWER_SET:
{
CEDEVICE_POWER_STATE dxState;
// Check arguments.
if (pOutBuffer == NULL || outSize < sizeof(CEDEVICE_POWER_STATE))
{
DEBUGMSG(SDCARD_ZONE_ERROR, (L"CSDIOControllerBase::IOControl: "
L"IOCTL_POWER_SET Invalid parameter.\r\n"
));
break;
}
if (CeSafeCopyMemory(&dxState, pOutBuffer, sizeof(dxState)) == 0) break;
DEBUGMSG(SDCARD_ZONE_POWER, (L"CSDIOControllerBase::IOControl: "
L"IOCTL_POWER_SET = %d.\r\n", dxState
));
// Check for any valid power state.
if (VALID_DX(dxState))
{
// Power off
if ( dxState == D4 )
{
DEBUGMSG(SDCARD_ZONE_POWER, (L"CSDIOControllerBase::IOControl: "
L"IOCTL_POWER_set PowerDown\r\n"
));
//SDHCDPowerUpDown(m_pHCContext, FALSE, FALSE, 0);
this->m_PowerState = dxState;
this->FreeHostContext(TRUE, TRUE);
}
// Power on.
else
{
DEBUGMSG(SDCARD_ZONE_POWER, (L"CSDIOControllerBase::IOControl: "
L"IOCTL_POWER_set PowerUp\r\n"
));
this->m_PowerState = dxState;
this->Init(m_pszActiveKey);
// Notify the SD Bus driver of the PowerUp event
//SDHCDPowerUpDown(m_pHCContext, TRUE, FALSE, 0);
}
bRetVal = TRUE;
}
else
{
DEBUGMSG(SDCARD_ZONE_ERROR, (L"CSDIOControllerBase::IOControl: "
L"IOCTL_POWER_SET invalid power state.\r\n"
));
}
break;
}
// Return the current device power state.
case IOCTL_POWER_GET:
{
// Check arguments.
if (pOutBuffer == NULL || outSize < sizeof(CEDEVICE_POWER_STATE))
{
DEBUGMSG(SDCARD_ZONE_ERROR, (L"CSDIOControllerBase::IOControl: "
L"IOCTL_POWER_GET Invalid parameter.\r\n"
));
break;
}
//Copy current state
if (CeSafeCopyMemory(pOutBuffer, &this->m_PowerState, sizeof(this->m_PowerState)) == 0)
{
DEBUGMSG(SDCARD_ZONE_ERROR, (L"CSDIOControllerBase::IOControl: "
L"CeSafeCopyMemory Failed\r\n"
));
break;
}
// Update returned data size.
if (pOutSize)
{
*pOutSize = sizeof(this->m_PowerState);
}
DEBUGMSG(SDCARD_ZONE_POWER, (L"CSDIOControllerBase::IOControl: "
L"IOCTL_POWER_GET: %d\r\n", this->m_PowerState
));
bRetVal = TRUE;
break;
}
default:
DEBUGMSG(SDCARD_ZONE_ERROR, (L"CSDIOControllerBase::IOControl: "
L"Unknown IOCTL_xxx(0x%0.8X)\r\n", dwCode
));
break;
}
DEBUGMSG(SDCARD_ZONE_FUNC, (L"-CSDIOControllerBase::IOControl(rc = %d)\r\n", bRetVal));
return bRetVal;
}
// Read the registry settings
BOOL CSDIOControllerBase::GetRegistrySettings( CReg *pReg )
{
BOOL fRet = TRUE;
DEBUGCHK(pReg);
// get the controller IST thread priority
m_dwSDIOPriority = pReg->ValueDW(SHC_SDIO_PRIORITY_KEY, SHC_CARD_CONTROLLER_PRIORITY);
// get the card detect IST thread priority
m_dwCDPriority = pReg->ValueDW(SHC_CD_PRIORITY_KEY, SHC_CARD_DETECT_PRIORITY);
// get the max clock frequency from the registry (we allow the registry to override)
m_dwMaxClockRate = pReg->ValueDW(SHC_FREQUENCY_KEY);
if (m_dwMaxClockRate == 0)
{
// No clock frequency specified. Use the highest possible that
// could have been specified so that a working clock divisor
// will be chosen.
m_dwMaxClockRate = STD_HC_MAX_CLOCK_FREQUENCY;
}
else
{
m_dwMaxClockRate = min(m_dwMaxClockRate,
STD_HC_MAX_CLOCK_FREQUENCY);
}
// get the read/write timeout value
m_dwMaxTimeout = pReg->ValueDW(SHC_RW_TIMEOUT_KEY, DEFAULT_TIMEOUT_VALUE);
// get the wakeup sources
m_dwWakeupSources = pReg->ValueDW(SHC_WAKEUP_SOURCES_KEY, 0);
m_dwCurrentWakeupSources = m_dwWakeupSources & (~WAKEUP_SDIO);
return fRet;
}
// Process the capabilities register
BOOL CSDIOControllerBase::InterpretCapabilities()
{
BOOL fRet = TRUE;
// set the host controller name
SDHCDSetHCName(m_pHCContext, L"SDHC");
// set init handler
SDHCDSetControllerInitHandler(m_pHCContext, CSDIOControllerBase::SDHCInitialize);
// set deinit handler
SDHCDSetControllerDeinitHandler(m_pHCContext, CSDIOControllerBase::SDHCDeinitialize);
// set the Send packet handler
SDHCDSetBusRequestHandler(m_pHCContext, CSDIOControllerBase::SDHCBusRequestHandler);
// set the cancel I/O handler
SDHCDSetCancelIOHandler(m_pHCContext, CSDIOControllerBase::SDHCCancelIoHandler);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -