📄 sdslot.cpp
字号:
// Input: pExternalHCContext - Host controller context that was previously registered
// SlotNumber - Slot Number
// Event - new event
// Output:
// Return: SD_API_STATUS
// Notes:
// A host controller driver calls this api when the slot changes state (i.e.
// device insertion/deletion).
///////////////////////////////////////////////////////////////////////////////
VOID CSDSlot::SlotStateChange(SD_SLOT_EVENT Event)
{
switch (Event) {
case DeviceInterrupting: // We should do interrupt callback at SDHC IST.
case DeviceInserted:
case DeviceEjected:
case SlotDeselectRequest:
case SlotSelectRequest:
case SlotResetRequest:
// post this message to the work item for each slot
PostEvent(Event);
break;
case BusRequestComplete:
ASSERT(FALSE);
break;
default:
DEBUGCHK(FALSE);
}
}
///////////////////////////////////////////////////////////////////////////////
// DelayForPowerUp - Delay for powerup
// Input: pSlot - slot to delay on
//
// Output:
// Notes:
//
///////////////////////////////////////////////////////////////////////////////
VOID CSDSlot::DelayForPowerUp()
{
// delay for power up
if (PowerUpDelay != 0) {
Sleep(PowerUpDelay);
} else {
// powerup delay should be set
DEBUG_CHECK(FALSE, (TEXT("SDBusDriver: Slot Delay is 0!!!\n")));
Sleep(500);
}
}
///////////////////////////////////////////////////////////////////////////////
// SDSetCardInterfaceForSlot - set Card interface for the slot
// Input: pSlot - the slot to set the card interface for
// pSetting - card interface settings
// Output:
// Return: SD_API_STATUS
// Notes:
// this function calls the slot option handler in the host controller
// driver
//
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS CSDSlot::SDSetCardInterfaceForSlot(PSD_CARD_INTERFACE_EX pSetting)
{
SD_API_STATUS status; // intermediate status
DWORD origClockSetting; // original clock setting upon entry
origClockSetting = pSetting->ClockRate;
status = m_SdHost.SlotSetupInterface(m_dwSlotIndex,pSetting);
if (SD_API_SUCCESS(status)) {
if (origClockSetting != pSetting->ClockRate){
DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SDSetCardInterfaceForSlot - HC ClockRate differs desired setting: desired: %d Hz, Actual : %d Hz \n"),
origClockSetting, pSetting->ClockRate));
}
}
return status;
}
///////////////////////////////////////////////////////////////////////////////
// SDGetOperationalVoltageRange - Get the operation voltage range
// Input: OcrValue - OCR bit mask to determine the voltage range
// pSlot - the slot
//
// Output:
// Return: DWORD bit mask for optimal operational voltage
// Notes:
// This function compares the OcrValue against the desired
// voltage range of the slot and the capabilities of the slot
// the operational value (also encoded as an OCR value) is returned
// A value of zero indicates no usable voltage range.
///////////////////////////////////////////////////////////////////////////////
DWORD CSDSlot::SDGetOperationalVoltageRange(DWORD OcrValue)
{
ULONG i; // loop variable
// check to see if the voltages can be supported
if (OcrValue & VoltageWindowMask) {
// check to see if the voltage meets the desired voltage range
if (OcrValue & DesiredVoltageMask) {
DEBUGMSG(SDBUS_ZONE_DEVICE, (TEXT("SDBusDriver: Device Power Range:0x%08X matches HC desired power: 0x%08X \n"),
OcrValue, DesiredVoltageMask));
// returned desired voltage range suggested by host controller
return DesiredVoltageMask;
} else {
// walk through the voltage mask starting at the low end looking for
// a voltage that will work with the OCR value
for (i = 0; i < 32; i++) {
if (OcrValue & VoltageWindowMask & (1 << i)) {
DEBUGMSG(SDBUS_ZONE_DEVICE, (TEXT("SDBusDriver: Device Power Range:0x%08X does not match HC desired power 0x%08X \n"),
OcrValue, DesiredVoltageMask));
DEBUGMSG(SDBUS_ZONE_DEVICE, (TEXT("Using negotiated power range: 0x%08X \n"),
(1 << i)));
// found a match
return (1 << i);
}
}
// this should never happen,
DEBUGCHK(FALSE);
return 0;
}
} else {
return 0;
}
}
///////////////////////////////////////////////////////////////////////////////
// SlotCardSelectDeselect - Select/Deselect the card in teh slot
// Input: SlotIndexWanted - index of slot
// Event - SlotDeselectRequest/SlotSelectRequest/SlotResetRequest
// Output:
// Notes:
///////////////////////////////////////////////////////////////////////////////
BOOL CSDSlot::SlotCardSelectDeselect(SD_SLOT_EVENT Event)
{
SD_API_STATUS status; // intermediate SD status
BOOL retStatus = FALSE; // return status
SD_SET_FEATURE_TYPE CardFeature; // card feature code
// check for a ready device in the slot
if (m_SlotState == Ready) {
CSDDevice *pDevice0 = GetFunctionDevice(0);
if (NULL != pDevice0) {
switch ( Event ) {
case SlotDeselectRequest:
CardFeature = SD_CARD_DESELECT_REQUEST;
break;
case SlotSelectRequest:
CardFeature = SD_CARD_SELECT_REQUEST;
break;
case SlotResetRequest:
CardFeature = SD_CARD_FORCE_RESET;
break;
default:
DEBUG_CHECK(FALSE, (TEXT("SDBusDriver: Unknown Slot Event : %d \n"),Event));
return FALSE;
}
// Call API to request the card to be deselected
status = pDevice0->SDSetCardFeature_I(CardFeature,NULL,0);
pDevice0->DeRef();
retStatus = TRUE;
if(!SD_API_SUCCESS(status)) {
DbgPrintZo(SDCARD_ZONE_ERROR,(TEXT("SDBusDriver: Failed to request the card to be deselected\r\n")));
retStatus = FALSE;
}
}
else {
retStatus = FALSE;
DbgPrintZo(SDCARD_ZONE_INIT, (TEXT("Driver not loaded")));
}
}
else {
retStatus = FALSE;
DbgPrintZo(SDCARD_ZONE_INIT, (TEXT("Empty Slot")));
}
return retStatus;
}
///////////////////////////////////////////////////////////////////////////////
// SelectSlotInterface - select slot interface based on default interface
// information of all devices.
// Input: pSlot - the slot
//
// Output:
// Return: SD_API_STATUS code
// Notes: This function sets the slot's default interface in the slot structure,
// the result interface will fit for all functions of the card.
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS CSDSlot::SelectSlotInterface()
{
// Try slot interface at full speed and 4 bit mode (highest bus mode except High Speed)
memset(&m_SlotInterfaceEx,0, sizeof(m_SlotInterfaceEx));
m_SlotInterfaceEx.InterfaceModeEx.bit.sd4Bit = 1;
#ifdef _MMC_SPEC_42_
/**
* Description : HSMMC slot supports up to 52MHz
*/
m_SlotInterfaceEx.ClockRate = HSMMC_FULL_SPEED_RATE;
#else
m_SlotInterfaceEx.ClockRate = SD_FULL_SPEED_RATE;
#endif
m_SlotLock.Lock();
for (DWORD dwIndex=0; dwIndex<SD_MAXIMUM_DEVICE_PER_SLOT; dwIndex ++) {
CSDDevice * psdDevice = m_pFuncDevice[dwIndex];
// for each device set it's card interface
if (psdDevice) {
#ifdef _MMC_SPEC_42_
/**
* Description : HSMMC Slot supports up to 52MHz
*/
m_SlotInterfaceEx.InterfaceModeEx.bit.hsmmc8Bit = psdDevice->GetCardInterface().InterfaceModeEx.bit.hsmmc8Bit;
#endif
m_SlotInterfaceEx.InterfaceModeEx.bit.sd4Bit = psdDevice->GetCardInterface().InterfaceModeEx.bit.sd4Bit;
m_SlotInterfaceEx.InterfaceModeEx.bit.sdWriteProtected = psdDevice->GetCardInterface().InterfaceModeEx.bit.sdWriteProtected;
if ( psdDevice->GetCardInterface().ClockRate < m_SlotInterfaceEx.ClockRate ) {
m_SlotInterfaceEx.ClockRate = psdDevice->GetCardInterface().ClockRate;
}
}
}
m_SlotLock.Unlock();
return SD_API_STATUS_SUCCESS;
}
BOOL CSDSlot::SDSlotEnableSDIOInterrupts()
{
BOOL fRet = FALSE;
m_SlotLock.Lock();
if (!IsSlotInterruptOn()) {
SD_API_STATUS status = m_SdHost.SlotOptionHandler(m_dwSlotIndex,SDHCDEnableSDIOInterrupts, NULL, 0);
if (SD_API_SUCCESS(status)) {
m_Flags|=SD_SLOT_FLAG_SDIO_INTERRUPTS_ENABLED;
fRet = TRUE;
};
}
m_SlotLock.Unlock();
return fRet;
}
BOOL CSDSlot::SDSlotDisableSDIOInterrupts()
{
BOOL fRet = FALSE;
m_SlotLock.Lock();
if (IsSlotInterruptOn()) {
SD_API_STATUS status = m_SdHost.SlotOptionHandler(m_dwSlotIndex,SDHCDDisableSDIOInterrupts, NULL, 0);
if (SD_API_SUCCESS(status)) {
m_Flags&=~SD_SLOT_FLAG_SDIO_INTERRUPTS_ENABLED;
fRet = TRUE;
};
}
m_SlotLock.Unlock();
return fRet;
}
BOOL CSDSlot::HandleSlotSelectDeselect(SD_SLOT_EVENT SlotEvent)
{
SD_API_STATUS status = SD_API_STATUS_SUCCESS;
SD_CARD_INTERFACE_EX CurrentSlotInterface;
DbgPrintZo(SDBUS_ZONE_DEVICE, (TEXT("CSDSlot: HandleSlotSelectDeselect++: %d \n"),SlotEvent));
// Deselect the card
if ((SlotEvent == SlotResetRequest) || (SlotEvent == SlotDeselectRequest)) {
DbgPrintZo(SDBUS_ZONE_DEVICE, (TEXT("CSDSlot: Deselect the card\n")));
// Update RCA for all devices, start from parent device
for (DWORD dwIndex=0; dwIndex <= SD_MAXIMUM_DEVICE_PER_SLOT && SD_API_SUCCESS(status); dwIndex++) {
CSDDevice * pCurrentDevice = GetFunctionDevice(dwIndex);
if (pCurrentDevice != NULL) {
status = pCurrentDevice->HandleDeviceSelectDeselect(SlotEvent, FALSE);
if (SD_API_SUCCESS(status)) {
pCurrentDevice->NotifyClient(SDCardDeselected);
}
pCurrentDevice->DeRef();
}
}
if (SD_API_SUCCESS(status)) {
m_SlotState = SlotDeselected; // Mark the slot as SlotDeselected to prevent further requests
m_AllocatedPower = 0;
}
else {
DbgPrintZo(SDCARD_ZONE_ERROR, (TEXT("CSDSlot: Failed to deselect card status =%x\n"),status));
}
}
// Select the card
if (SD_API_SUCCESS(status) &&
((SlotEvent == SlotResetRequest) || (SlotEvent == SlotSelectRequest))) {
DbgPrintZo(SDBUS_ZONE_DEVICE, (TEXT("SDBusDriver: Select the card\n")));
// Save the current slot interface
CurrentSlotInterface.InterfaceModeEx = m_SlotInterfaceEx.InterfaceModeEx;
CurrentSlotInterface.ClockRate = m_SlotInterfaceEx.ClockRate;
// set the slot for 1 bit mode
m_SlotInterfaceEx.InterfaceModeEx.bit.sd4Bit = 0 ;
m_SlotInterfaceEx.ClockRate = SD_DEFAULT_CARD_ID_CLOCK_RATE;
// set the card interface for the slot
status = SDSetCardInterfaceForSlot(&m_SlotInterfaceEx);
// Mark slot status as SlotReseting, only this thread can send bus request.
m_SlotState = SlotResetting;
for (DWORD dwIndex=0; dwIndex <= SD_MAXIMUM_DEVICE_PER_SLOT && SD_API_SUCCESS(status); dwIndex++) {
CSDDevice * pCurrentDevice = GetFunctionDevice(dwIndex);
if (pCurrentDevice != NULL) {
status = pCurrentDevice->HandleDeviceSelectDeselect(SlotEvent, TRUE);
pCurrentDevice->DeRef();
}
}
if (SD_API_SUCCESS(status)) {
// Set Slot state as ready
m_SlotState = Ready;
m_SlotInterfaceEx.InterfaceModeEx = CurrentSlotInterface.InterfaceModeEx;
m_SlotInterfaceEx.ClockRate = CurrentSlotInterface.ClockRate;
for (DWORD dwIndex=0; dwIndex <SD_MAXIMUM_DEVICE_PER_SLOT && SD_API_SUCCESS(status); dwIndex++) {
CSDDevice * pDevice = GetFunctionDevice(dwIndex);
if (pDevice) {
status = pDevice->SetCardInterface(&CurrentSlotInterface);
pDevice->DeRef();
}
}
status = SDSetCardInterfaceForSlot(&m_SlotInterfaceEx);
for (DWORD dwIndex = 0 ; dwIndex <SD_MAXIMUM_DEVICE_PER_SLOT && SD_API_SUCCESS(status) ; dwIndex++) {
CSDDevice * pDevice = GetFunctionDevice(dwIndex);
if (pDevice) {
pDevice->NotifyClient(SDCardSelected);
pDevice->DeRef();
}
}
}
}
ASSERT(SD_API_SUCCESS(status));
DbgPrintZo(SDBUS_ZONE_DEVICE, (TEXT("SDBusDriver: HandleSlotSelectDeselect--status =%X\n"),status));
return (SD_API_SUCCESS(status));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -