mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2025-01-03 11:11:14 +00:00
sdmmc: SdCardDeviceAccessor impl
This commit is contained in:
parent
e3900de6c0
commit
4586dce57b
21 changed files with 1564 additions and 37 deletions
|
@ -21,8 +21,8 @@ namespace ams::sdmmc_test {
|
|||
|
||||
constexpr inline const uintptr_t PMC = secmon::MemoryRegionPhysicalDevicePmc.GetAddress();
|
||||
|
||||
constexpr inline auto Port = sdmmc::Port_Mmc0;
|
||||
alignas(8) constinit u8 g_mmc_work_buffer[sdmmc::MmcWorkBufferSize];
|
||||
constexpr inline auto Port = sdmmc::Port_SdCard0;
|
||||
alignas(8) constinit u8 g_sd_work_buffer[sdmmc::SdCardWorkBufferSize];
|
||||
|
||||
constexpr inline u32 SectorIndex = 0;
|
||||
constexpr inline u32 SectorCount = 2;
|
||||
|
@ -55,31 +55,28 @@ namespace ams::sdmmc_test {
|
|||
sdmmc::Initialize(Port);
|
||||
DEBUG[0] = 1;
|
||||
|
||||
sdmmc::SetMmcWorkBuffer(Port, g_mmc_work_buffer, sizeof(g_mmc_work_buffer));
|
||||
sdmmc::SetSdCardWorkBuffer(Port, g_sd_work_buffer, sizeof(g_sd_work_buffer));
|
||||
DEBUG[0] = 2;
|
||||
|
||||
Result result = sdmmc::Activate(Port);
|
||||
DEBUG[0] = 3;
|
||||
CheckResult(result);
|
||||
|
||||
/* Select user data partition. */
|
||||
result = sdmmc::SelectMmcPartition(Port, sdmmc::MmcPartition_UserData);
|
||||
DEBUG[0] = 4;
|
||||
CheckResult(result);
|
||||
PmcMainReboot();
|
||||
|
||||
/* Read the first two sectors from disk. */
|
||||
void * const sector_dst = reinterpret_cast<void *>(0x40038000);
|
||||
result = sdmmc::Read(sector_dst, SectorCount * sdmmc::SectorSize, Port, SectorIndex, SectorCount);
|
||||
DEBUG[0] = 5;
|
||||
DEBUG[0] = 4;
|
||||
CheckResult(result);
|
||||
|
||||
/* Get the connection status. */
|
||||
sdmmc::SpeedMode speed_mode;
|
||||
sdmmc::BusWidth bus_width;
|
||||
result = sdmmc::CheckMmcConnection(std::addressof(speed_mode), std::addressof(bus_width), Port);
|
||||
result = sdmmc::CheckSdCardConnection(std::addressof(speed_mode), std::addressof(bus_width), Port);
|
||||
|
||||
/* Save status for debug. */
|
||||
DEBUG[0] = 6;
|
||||
DEBUG[0] = 5;
|
||||
DEBUG[1] = result.GetValue();
|
||||
DEBUG[2] = static_cast<u32>(speed_mode);
|
||||
DEBUG[3] = static_cast<u32>(bus_width);
|
||||
|
|
|
@ -140,9 +140,9 @@ ATMOSPHERE_GCH_IDENTIFIER ?= ams_placeholder_gch_identifier
|
|||
# Rules for compiling pre-compiled headers
|
||||
#---------------------------------------------------------------------------------
|
||||
%.hpp.gch/$(ATMOSPHERE_GCH_IDENTIFIER): %.hpp | %.hpp.gch
|
||||
$(SILENTMSG) Precompiling $(notdir $<) for $(ATMOSPHERE_GCH_IDENTIFIER)
|
||||
@echo Precompiling $(notdir $<) for $(ATMOSPHERE_GCH_IDENTIFIER)
|
||||
$(SILENTCMD)$(CXX) -w -x c++-header -MMD -MP -MQ$@ -MF $(DEPSDIR)/$(notdir $*).d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)
|
||||
|
||||
%.hpp.gch: %.hpp
|
||||
$(SILENTMSG) Precompiling $(notdir $<)
|
||||
@echo Precompiling $(notdir $<)
|
||||
$(SILENTCMD)$(CXX) -w -x c++-header -MMD -MP -MQ$@ -MF $(DEPSDIR)/$(notdir $*).d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)
|
||||
|
|
|
@ -21,6 +21,7 @@ namespace ams::sdmmc {
|
|||
|
||||
R_DEFINE_NAMESPACE_RESULT_MODULE(24);
|
||||
|
||||
R_DEFINE_ERROR_RESULT(NoDevice, 1);
|
||||
R_DEFINE_ERROR_RESULT(NotActivated, 2);
|
||||
R_DEFINE_ERROR_RESULT(DeviceRemoved, 3);
|
||||
R_DEFINE_ERROR_RESULT(NotAwakened, 4);
|
||||
|
@ -57,20 +58,32 @@ namespace ams::sdmmc {
|
|||
R_DEFINE_ERROR_RESULT(DeviceStatusWpEraseSkip, 62);
|
||||
R_DEFINE_ERROR_RESULT(DeviceStatusEraseReset, 63);
|
||||
R_DEFINE_ERROR_RESULT(DeviceStatusSwitchError, 64);
|
||||
R_DEFINE_ERROR_RESULT(UnexpectedDeviceState, 72);
|
||||
R_DEFINE_ERROR_RESULT(UnexpectedDeviceCsdValue, 73);
|
||||
R_DEFINE_ERROR_RESULT(AbortTransactionSoftwareTimeout, 74);
|
||||
R_DEFINE_ERROR_RESULT(CommandInhibitCmdSoftwareTimeout, 75);
|
||||
R_DEFINE_ERROR_RESULT(CommandInhibitDatSoftwareTimeout, 76);
|
||||
R_DEFINE_ERROR_RESULT(BusySoftwareTimeout, 77);
|
||||
R_DEFINE_ERROR_RESULT(IssueTuningCommandSoftwareTimeout, 78);
|
||||
R_DEFINE_ERROR_RESULT(TuningFailed, 79);
|
||||
R_DEFINE_ERROR_RESULT(MmcInitializationSoftwareTimeout, 80);
|
||||
R_DEFINE_ERROR_RESULT(MmcNotSupportExtendedCsd, 81);
|
||||
R_DEFINE_ERROR_RESULT(UnexpectedMmcExtendedCsdValue, 82);
|
||||
R_DEFINE_ERROR_RESULT(MmcEraseSoftwareTimeout, 83);
|
||||
R_DEFINE_ERROR_RESULT(SdCardNotReadyToVoltageSwitch, 96);
|
||||
R_DEFINE_ERROR_RESULT(SdCardNotCompleteVoltageSwitch, 97);
|
||||
R_DEFINE_ERROR_RESULT(UnexpectedDeviceState, 72);
|
||||
R_DEFINE_ERROR_RESULT(UnexpectedDeviceCsdValue, 73);
|
||||
R_DEFINE_ERROR_RESULT(AbortTransactionSoftwareTimeout, 74);
|
||||
R_DEFINE_ERROR_RESULT(CommandInhibitCmdSoftwareTimeout, 75);
|
||||
R_DEFINE_ERROR_RESULT(CommandInhibitDatSoftwareTimeout, 76);
|
||||
R_DEFINE_ERROR_RESULT(BusySoftwareTimeout, 77);
|
||||
R_DEFINE_ERROR_RESULT(IssueTuningCommandSoftwareTimeout, 78);
|
||||
R_DEFINE_ERROR_RESULT(TuningFailed, 79);
|
||||
R_DEFINE_ERROR_RESULT(MmcInitializationSoftwareTimeout, 80);
|
||||
R_DEFINE_ERROR_RESULT(MmcNotSupportExtendedCsd, 81);
|
||||
R_DEFINE_ERROR_RESULT(UnexpectedMmcExtendedCsdValue, 82);
|
||||
R_DEFINE_ERROR_RESULT(MmcEraseSoftwareTimeout, 83);
|
||||
R_DEFINE_ERROR_RESULT(SdCardValidationError, 84);
|
||||
R_DEFINE_ERROR_RESULT(SdCardInitializationSoftwareTimeout, 85);
|
||||
R_DEFINE_ERROR_RESULT(SdCardGetValidRcaSoftwareTimeout, 86);
|
||||
R_DEFINE_ERROR_RESULT(UnexpectedSdCardAcmdDisabled, 87);
|
||||
R_DEFINE_ERROR_RESULT(SdCardNotSupportSwitchFunctionStatus, 88);
|
||||
R_DEFINE_ERROR_RESULT(UnexpectedSdCardSwitchFunctionStatus, 89);
|
||||
R_DEFINE_ERROR_RESULT(SdCardNotSupportAccessMode, 90);
|
||||
R_DEFINE_ERROR_RESULT(SdCardNot4BitBusWidthAtUhsIMode, 91);
|
||||
R_DEFINE_ERROR_RESULT(SdCardNotSupportSdr104AndSdr50, 92);
|
||||
R_DEFINE_ERROR_RESULT(SdCardCannotSwitchAccessMode, 93);
|
||||
R_DEFINE_ERROR_RESULT(SdCardFailedSwitchAccessMode, 94);
|
||||
R_DEFINE_ERROR_RESULT(SdCardUnacceptableCurrentConsumption, 95);
|
||||
R_DEFINE_ERROR_RESULT(SdCardNotReadyToVoltageSwitch, 96);
|
||||
R_DEFINE_ERROR_RESULT(SdCardNotCompleteVoltageSwitch, 97);
|
||||
|
||||
R_DEFINE_ERROR_RANGE(HostControllerUnexpected, 128, 158);
|
||||
R_DEFINE_ERROR_RESULT(InternalClockStableSoftwareTimeout, 129);
|
||||
|
|
|
@ -24,3 +24,4 @@
|
|||
#include <vapours/sdmmc/sdmmc_build_config.hpp>
|
||||
#include <vapours/sdmmc/sdmmc_common.hpp>
|
||||
#include <vapours/sdmmc/sdmmc_mmc.hpp>
|
||||
#include <vapours/sdmmc/sdmmc_sd_card.hpp>
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
//#define AMS_SDMMC_USE_OS_TIMER
|
||||
#define AMS_SDMMC_USE_UTIL_TIMER
|
||||
//#define AMS_SDMMC_ENABLE_MMC_HS400
|
||||
//#define AMS_SDMMC_ENABLE_SD_UHS_I
|
||||
//#define AMS_SDMMC_SET_PLLC4_BASE
|
||||
//#define AMS_SDMMC_USE_SD_CARD_DETECTOR
|
||||
|
||||
|
@ -47,6 +48,7 @@
|
|||
//#define AMS_SDMMC_USE_OS_TIMER
|
||||
#define AMS_SDMMC_USE_UTIL_TIMER
|
||||
//#define AMS_SDMMC_ENABLE_MMC_HS400
|
||||
//#define AMS_SDMMC_ENABLE_SD_UHS_I
|
||||
//#define AMS_SDMMC_SET_PLLC4_BASE
|
||||
//#define AMS_SDMMC_USE_SD_CARD_DETECTOR
|
||||
|
||||
|
@ -61,6 +63,7 @@
|
|||
#define AMS_SDMMC_USE_OS_TIMER
|
||||
//#define AMS_SDMMC_USE_UTIL_TIMER
|
||||
#define AMS_SDMMC_ENABLE_MMC_HS400
|
||||
#define AMS_SDMMC_ENABLE_SD_UHS_I
|
||||
#define AMS_SDMMC_SET_PLLC4_BASE
|
||||
#define AMS_SDMMC_USE_SD_CARD_DETECTOR
|
||||
|
||||
|
|
53
libraries/libvapours/include/vapours/sdmmc/sdmmc_sd_card.hpp
Normal file
53
libraries/libvapours/include/vapours/sdmmc/sdmmc_sd_card.hpp
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours/sdmmc/sdmmc_build_config.hpp>
|
||||
|
||||
namespace ams::sdmmc {
|
||||
|
||||
enum SdCardSwitchFunction {
|
||||
SdCardSwitchFunction_CheckSupportedFunction = 0,
|
||||
SdCardSwitchFunction_CheckDefault = 1,
|
||||
SdCardSwitchFunction_CheckHighSpeed = 2,
|
||||
SdCardSwitchFunction_CheckSdr50 = 3,
|
||||
SdCardSwitchFunction_CheckSdr104 = 4,
|
||||
SdCardSwitchFunction_CheckDdr50 = 5,
|
||||
};
|
||||
|
||||
constexpr inline size_t SdCardScrSize = 0x08;
|
||||
constexpr inline size_t SdCardSwitchFunctionStatusSize = 0x40;
|
||||
constexpr inline size_t SdCardSdStatusSize = 0x40;
|
||||
|
||||
constexpr inline size_t SdCardWorkBufferSize = SdCardSdStatusSize;
|
||||
|
||||
void SetSdCardWorkBuffer(Port port, void *buffer, size_t buffer_size);
|
||||
void PutSdCardToSleep(Port port);
|
||||
void AwakenSdCard(Port port);
|
||||
Result GetSdCardProtectedAreaCapacity(u32 *out_num_sectors, Port port);
|
||||
Result GetSdCardScr(void *dst, size_t dst_size, Port port);
|
||||
Result GetSdCardSwitchFunctionStatus(void *dst, size_t dst_size, Port port, SdCardSwitchFunction switch_function);
|
||||
Result GetSdCardCurrentConsumption(u16 *out_current_consumption, Port port, SpeedMode speed_mode);
|
||||
Result GetSdCardSdStatus(void *dst, size_t dst_size, Port port);
|
||||
|
||||
Result CheckSdCardConnection(SpeedMode *out_speed_mode, BusWidth *out_bus_width, Port port);
|
||||
|
||||
bool IsSdCardInserted(Port port);
|
||||
bool IsSdCardRemoved(Port port);
|
||||
|
||||
void RegisterSdCardDetectionEventCallback(Port port, DeviceDetectionEventCallback callback, void *arg);
|
||||
void UnregisterSdCardDetectionEventCallback(Port port);
|
||||
|
||||
}
|
|
@ -15,6 +15,10 @@
|
|||
*/
|
||||
#if defined(ATMOSPHERE_IS_STRATOSPHERE)
|
||||
#include <stratosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_MESOSPHERE)
|
||||
#include <mesosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_EXOSPHERE)
|
||||
#include <exosphere.hpp>
|
||||
#else
|
||||
#include <vapours.hpp>
|
||||
#endif
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
*/
|
||||
#if defined(ATMOSPHERE_IS_STRATOSPHERE)
|
||||
#include <stratosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_MESOSPHERE)
|
||||
#include <mesosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_EXOSPHERE)
|
||||
#include <exosphere.hpp>
|
||||
#else
|
||||
#include <vapours.hpp>
|
||||
#endif
|
||||
|
|
|
@ -13,7 +13,15 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#if defined(ATMOSPHERE_IS_STRATOSPHERE)
|
||||
#include <stratosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_MESOSPHERE)
|
||||
#include <mesosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_EXOSPHERE)
|
||||
#include <exosphere.hpp>
|
||||
#else
|
||||
#include <vapours.hpp>
|
||||
#endif
|
||||
#include "sdmmc_base_device_accessor.hpp"
|
||||
|
||||
namespace ams::sdmmc::impl {
|
||||
|
|
|
@ -13,7 +13,15 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#if defined(ATMOSPHERE_IS_STRATOSPHERE)
|
||||
#include <stratosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_MESOSPHERE)
|
||||
#include <mesosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_EXOSPHERE)
|
||||
#include <exosphere.hpp>
|
||||
#else
|
||||
#include <vapours.hpp>
|
||||
#endif
|
||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||
#include "sdmmc_device_detector.hpp"
|
||||
|
||||
|
|
|
@ -13,7 +13,15 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#if defined(ATMOSPHERE_IS_STRATOSPHERE)
|
||||
#include <stratosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_MESOSPHERE)
|
||||
#include <mesosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_EXOSPHERE)
|
||||
#include <exosphere.hpp>
|
||||
#else
|
||||
#include <vapours.hpp>
|
||||
#endif
|
||||
#include "sdmmc_mmc_device_accessor.hpp"
|
||||
#include "sdmmc_timer.hpp"
|
||||
|
||||
|
@ -231,7 +239,7 @@ namespace ams::sdmmc::impl {
|
|||
/* Be prepared to wait up to 1.5 seconds to change state. */
|
||||
ManualTimer timer(1500);
|
||||
while (true) {
|
||||
/* Gte the ocr, and check if we're done. */
|
||||
/* Get the ocr, and check if we're done. */
|
||||
u32 ocr;
|
||||
R_TRY(this->IssueCommandSendOpCond(std::addressof(ocr), bus_power));
|
||||
if ((ocr & OcrCardPowerUpStatus) != 0) {
|
||||
|
@ -467,7 +475,7 @@ namespace ams::sdmmc::impl {
|
|||
if (R_SUCCEEDED(result)) {
|
||||
/* If we previously failed to start up the device, log the error correction. */
|
||||
if (i != 0) {
|
||||
BaseDeviceAccessor::PushErrorLog(true, "S %d %d:0", this->max_bus_width, this->max_speed_mode, 0);
|
||||
BaseDeviceAccessor::PushErrorLog(true, "S %d %d:0", this->max_bus_width, this->max_speed_mode);
|
||||
BaseDeviceAccessor::IncrementNumActivationErrorCorrections();
|
||||
}
|
||||
|
||||
|
@ -586,7 +594,7 @@ namespace ams::sdmmc::impl {
|
|||
return;
|
||||
}
|
||||
|
||||
/* Wake the device, it we need to.*/
|
||||
/* Wake the host controller, if we need to.*/
|
||||
if (this->mmc_device.IsActive()) {
|
||||
const Result result = BaseDeviceAccessor::GetHostController()->Awaken();
|
||||
if (R_FAILED(result)) {
|
||||
|
@ -594,6 +602,7 @@ namespace ams::sdmmc::impl {
|
|||
}
|
||||
}
|
||||
|
||||
/* Wake the device. */
|
||||
this->mmc_device.Awaken();
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,15 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#if defined(ATMOSPHERE_IS_STRATOSPHERE)
|
||||
#include <stratosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_MESOSPHERE)
|
||||
#include <mesosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_EXOSPHERE)
|
||||
#include <exosphere.hpp>
|
||||
#else
|
||||
#include <vapours.hpp>
|
||||
#endif
|
||||
#include "sdmmc_port_mmc0.hpp"
|
||||
#include "sdmmc_select_sdmmc_controller.hpp"
|
||||
|
||||
|
|
|
@ -13,7 +13,15 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#if defined(ATMOSPHERE_IS_STRATOSPHERE)
|
||||
#include <stratosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_MESOSPHERE)
|
||||
#include <mesosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_EXOSPHERE)
|
||||
#include <exosphere.hpp>
|
||||
#else
|
||||
#include <vapours.hpp>
|
||||
#endif
|
||||
#include "sdmmc_port_mmc0.hpp"
|
||||
#include "sdmmc_select_sdmmc_controller.hpp"
|
||||
#include "sdmmc_base_device_accessor.hpp"
|
||||
|
|
|
@ -13,8 +13,16 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#if defined(ATMOSPHERE_IS_STRATOSPHERE)
|
||||
#include <stratosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_MESOSPHERE)
|
||||
#include <mesosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_EXOSPHERE)
|
||||
#include <exosphere.hpp>
|
||||
#else
|
||||
#include <vapours.hpp>
|
||||
#include "sdmmc_port_mmc0.hpp"
|
||||
#endif
|
||||
#include "sdmmc_port_sd_card0.hpp"
|
||||
#include "sdmmc_select_sdmmc_controller.hpp"
|
||||
|
||||
|
||||
|
@ -24,6 +32,19 @@ namespace ams::sdmmc::impl {
|
|||
|
||||
SdmmcControllerForPortSdCard0 g_sd_card0_host_controller;
|
||||
|
||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||
|
||||
constexpr inline u32 SdCard0DebounceMilliSeconds = 128;
|
||||
DeviceDetector g_sd_card0_detector(gpio::DeviceCode_SdCd, gpio::GpioValue_Low, SdCard0DebounceMilliSeconds);
|
||||
|
||||
SdCardDeviceAccessor g_sd_card0_device_accessor(std::addressof(g_sd_card0_host_controller), std::addressof(g_sd_card0_detector));
|
||||
|
||||
#else
|
||||
|
||||
SdCardDeviceAccessor g_sd_card0_device_accessor(std::addressof(g_sd_card0_host_controller));
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -31,4 +52,12 @@ namespace ams::sdmmc::impl {
|
|||
return std::addressof(g_sd_card0_host_controller);
|
||||
}
|
||||
|
||||
IDeviceAccessor *GetDeviceAccessorOfPortSdCard0() {
|
||||
return std::addressof(g_sd_card0_device_accessor);
|
||||
}
|
||||
|
||||
SdCardDeviceAccessor *GetSdCardDeviceAccessorOfPortSdCard0() {
|
||||
return std::addressof(g_sd_card0_device_accessor);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -17,9 +17,206 @@
|
|||
#include <vapours.hpp>
|
||||
#include "sdmmc_base_device_accessor.hpp"
|
||||
|
||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||
#include "sdmmc_device_detector.hpp"
|
||||
#endif
|
||||
|
||||
namespace ams::sdmmc::impl {
|
||||
|
||||
/* TODO */
|
||||
struct SdCardDeviceAccessor;
|
||||
class SdCardDevice : public BaseDevice {
|
||||
private:
|
||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||
mutable os::EventType removed_event;
|
||||
#endif
|
||||
u16 rca;
|
||||
bool is_valid_rca;
|
||||
bool is_uhs_i_mode;
|
||||
public:
|
||||
SdCardDevice() : rca(0) {
|
||||
this->OnDeactivate();
|
||||
}
|
||||
|
||||
virtual void Deactivate() override {
|
||||
this->OnDeactivate();
|
||||
BaseDevice::Deactivate();
|
||||
}
|
||||
|
||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||
virtual os::EventType *GetRemovedEvent() const override {
|
||||
return std::addressof(this->removed_event);
|
||||
}
|
||||
#elif defined(AMS_SDMMC_USE_OS_EVENTS)
|
||||
virtual os::EventType *GetRemovedEvent() const override {
|
||||
/* Mmc can't be removed. */
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual DeviceType GetDeviceType() const override {
|
||||
return DeviceType_SdCard;
|
||||
}
|
||||
|
||||
virtual u16 GetRca() const override {
|
||||
AMS_ABORT_UNLESS(this->is_valid_rca);
|
||||
return this->rca;
|
||||
}
|
||||
|
||||
void OnDeactivate() {
|
||||
this->is_valid_rca = false;
|
||||
this->is_uhs_i_mode = false;
|
||||
}
|
||||
|
||||
void SetRca(u16 v) {
|
||||
this->rca = v;
|
||||
this->is_valid_rca = true;
|
||||
}
|
||||
|
||||
void SetOcrAndHighCapacity(u32 ocr);
|
||||
|
||||
void SetUhsIMode(bool en) {
|
||||
this->is_uhs_i_mode = en;
|
||||
}
|
||||
|
||||
bool IsUhsIMode() const {
|
||||
return this->is_uhs_i_mode;
|
||||
}
|
||||
};
|
||||
|
||||
enum SdCardApplicationCommandIndex : std::underlying_type<CommandIndex>::type {
|
||||
SdApplicationCommandIndex_SetBusWidth = 6,
|
||||
|
||||
SdApplicationCommandIndex_SdStatus = 13,
|
||||
|
||||
SdApplicationCommandIndex_SendNumWriteBlocks = 22,
|
||||
SdApplicationCommandIndex_SetWriteBlockEraseCount = 23,
|
||||
|
||||
SdApplicationCommandIndex_SdSendOpCond = 41,
|
||||
SdApplicationCommandIndex_SetClearCardDetect = 42,
|
||||
|
||||
SdApplicationCommandIndex_SendScr = 51,
|
||||
};
|
||||
|
||||
enum SwitchFunctionAccessMode {
|
||||
SwitchFunctionAccessMode_Default = 0,
|
||||
SwitchFunctionAccessMode_HighSpeed = 1,
|
||||
SwitchFunctionAccessMode_Sdr50 = 2,
|
||||
SwitchFunctionAccessMode_Sdr104 = 3,
|
||||
SwitchFunctionAccessMode_Ddr50 = 4,
|
||||
};
|
||||
|
||||
class SdCardDeviceAccessor : public BaseDeviceAccessor {
|
||||
private:
|
||||
SdCardDevice sd_card_device;
|
||||
void *work_buffer;
|
||||
size_t work_buffer_size;
|
||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||
DeviceDetector *sd_card_detector;
|
||||
#endif
|
||||
BusWidth max_bus_width;
|
||||
SpeedMode max_speed_mode;
|
||||
bool is_initialized;
|
||||
private:
|
||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||
void RemovedCallback();
|
||||
|
||||
static void RemovedCallbackEntry(void *arg) {
|
||||
static_cast<SdCardDeviceAccessor *>(arg)->RemovedCallback();
|
||||
}
|
||||
#endif
|
||||
|
||||
Result IssueCommandSendRelativeAddr(u16 *out_rca) const;
|
||||
Result IssueCommandSendIfCond() const;
|
||||
Result IssueCommandCheckSupportedFunction(void *dst, size_t dst_size) const;
|
||||
Result IssueCommandSwitchAccessMode(void *dst, size_t dst_size, bool set_function, SwitchFunctionAccessMode access_mode) const;
|
||||
Result IssueCommandVoltageSwitch() const;
|
||||
Result IssueCommandAppCmd(DeviceState expected_state, u32 ignore_mask = 0) const;
|
||||
Result IssueCommandSetBusWidth4Bit() const;
|
||||
Result IssueCommandSdStatus(void *dst, size_t dst_size) const;
|
||||
Result IssueCommandSendOpCond(u32 *out_ocr, bool spec_under_2, bool uhs_i_supported) const;
|
||||
Result IssueCommandClearCardDetect() const;
|
||||
Result IssueCommandSendScr(void *dst, size_t dst_size) const;
|
||||
|
||||
Result EnterUhsIMode();
|
||||
Result ChangeToReadyState(bool spec_under_2, bool uhs_i_supported);
|
||||
Result ChangeToStbyStateAndGetRca();
|
||||
Result SetMemoryCapacity(const void *csd);
|
||||
Result GetScr(void *dst, size_t dst_size) const;
|
||||
Result ExtendBusWidth(BusWidth max_bw, u8 sd_bw);
|
||||
Result SwitchAccessMode(SwitchFunctionAccessMode access_mode, void *wb, size_t wb_size);
|
||||
Result ExtendBusSpeedAtUhsIMode(SpeedMode max_sm, void *wb, size_t wb_size);
|
||||
Result ExtendBusSpeedAtNonUhsIMode(SpeedMode max_sm, bool spec_under_1_1, void *wb, size_t wb_size);
|
||||
Result GetSdStatus(void *dst, size_t dst_size) const;
|
||||
Result StartupSdCardDevice(BusWidth max_bw, SpeedMode max_sm, void *wb, size_t wb_size);
|
||||
|
||||
void TryDisconnectDat3PullUpResistor() const;
|
||||
protected:
|
||||
virtual Result OnActivate() override;
|
||||
virtual Result OnReadWrite(u32 sector_index, u32 num_sectors, void *buf, size_t buf_size, bool is_read) override;
|
||||
virtual Result ReStartup() override;
|
||||
public:
|
||||
virtual void Initialize() override;
|
||||
virtual void Finalize() override;
|
||||
virtual Result Activate() override;
|
||||
virtual Result GetSpeedMode(SpeedMode *out_speed_mode) const override;
|
||||
public:
|
||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||
explicit SdCardDeviceAccessor(IHostController *hc, DeviceDetector *dd) : BaseDeviceAccessor(hc), sd_card_detector(dd)
|
||||
#else
|
||||
explicit SdCardDeviceAccessor(IHostController *hc) : BaseDeviceAccessor(hc)
|
||||
#endif
|
||||
{
|
||||
this->work_buffer = nullptr;
|
||||
this->work_buffer_size = 0;
|
||||
this->max_bus_width = BusWidth_4Bit;
|
||||
this->max_speed_mode = SpeedMode_SdCardSdr104;
|
||||
this->is_initialized = false;
|
||||
}
|
||||
|
||||
void SetSdCardWorkBuffer(void *wb, size_t wb_size) {
|
||||
this->work_buffer = wb;
|
||||
this->work_buffer_size = wb_size;
|
||||
}
|
||||
|
||||
void PutSdCardToSleep();
|
||||
void AwakenSdCard();
|
||||
Result GetSdCardProtectedAreaCapacity(u32 *out_num_sectors) const;
|
||||
Result GetSdCardScr(void *dst, size_t dst_size) const;
|
||||
Result GetSdCardSwitchFunctionStatus(void *dst, size_t dst_size, SdCardSwitchFunction switch_function) const;
|
||||
Result GetSdCardCurrentConsumption(u16 *out_current_consumption, SpeedMode speed_mode) const;
|
||||
Result GetSdCardSdStatus(void *dst, size_t dst_size) const;
|
||||
|
||||
bool IsSdCardInserted() {
|
||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||
return this->sd_card_detector->IsInserted();
|
||||
#else
|
||||
AMS_ABORT("IsSdCardInserted without SdCardDetector");
|
||||
#endif
|
||||
}
|
||||
|
||||
bool IsSdCardRemoved() {
|
||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||
return this->sd_card_device.IsRemoved();
|
||||
#else
|
||||
AMS_ABORT("IsSdCardRemoved without SdCardDetector");
|
||||
#endif
|
||||
}
|
||||
|
||||
void RegisterSdCardDetectionEventCallback(DeviceDetectionEventCallback cb, void *arg) {
|
||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||
return this->sd_card_detector->RegisterDetectionEventCallback(cb, arg);
|
||||
#else
|
||||
AMS_UNUSED(cb, arg);
|
||||
AMS_ABORT("RegisterSdCardDetectionEventCallback without SdCardDetector");
|
||||
#endif
|
||||
}
|
||||
|
||||
void UnregisterSdCardDetectionEventCallback() {
|
||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||
return this->sd_card_detector->UnregisterDetectionEventCallback();
|
||||
#else
|
||||
AMS_ABORT("UnregisterSdCardDetectionEventCallback without SdCardDetector");
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -13,7 +13,15 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#if defined(ATMOSPHERE_IS_STRATOSPHERE)
|
||||
#include <stratosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_MESOSPHERE)
|
||||
#include <mesosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_EXOSPHERE)
|
||||
#include <exosphere.hpp>
|
||||
#else
|
||||
#include <vapours.hpp>
|
||||
#endif
|
||||
#include "sdmmc_sd_host_standard_controller.hpp"
|
||||
#include "sdmmc_timer.hpp"
|
||||
|
||||
|
@ -392,9 +400,9 @@ namespace ams::sdmmc::impl {
|
|||
|
||||
Result SdHostStandardController::CheckAndClearInterruptStatus(volatile u16 *out_normal_int_status, u16 wait_mask) {
|
||||
/* Read the statuses. */
|
||||
volatile u16 normal_int_status = this->registers->normal_int_status;
|
||||
volatile u16 error_int_status = this->registers->error_int_status;
|
||||
volatile u16 auto_cmd_err_status = this->registers->acmd12_err;
|
||||
volatile u16 normal_int_status = reg::Read(this->registers->normal_int_status);
|
||||
volatile u16 error_int_status = reg::Read(this->registers->error_int_status);
|
||||
volatile u16 auto_cmd_err_status = reg::Read(this->registers->acmd12_err);
|
||||
|
||||
/* Set the output status, if necessary. */
|
||||
if (out_normal_int_status != nullptr) {
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
*/
|
||||
#if defined(ATMOSPHERE_IS_STRATOSPHERE)
|
||||
#include <stratosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_MESOSPHERE)
|
||||
#include <mesosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_EXOSPHERE)
|
||||
#include <exosphere.hpp>
|
||||
#else
|
||||
#include <vapours.hpp>
|
||||
#endif
|
||||
|
|
|
@ -13,7 +13,15 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#if defined(ATMOSPHERE_IS_STRATOSPHERE)
|
||||
#include <stratosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_MESOSPHERE)
|
||||
#include <mesosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_EXOSPHERE)
|
||||
#include <exosphere.hpp>
|
||||
#else
|
||||
#include <vapours.hpp>
|
||||
#endif
|
||||
#include "impl/sdmmc_i_host_controller.hpp"
|
||||
#include "impl/sdmmc_i_device_accessor.hpp"
|
||||
#include "impl/sdmmc_clock_reset_controller.hpp"
|
||||
|
@ -30,7 +38,7 @@ namespace ams::sdmmc {
|
|||
impl::IHostController *host_controller = nullptr;
|
||||
switch (port) {
|
||||
case Port_Mmc0: host_controller = impl::GetHostControllerOfPortMmc0(); break;
|
||||
//TODO: case Port_SdCard0: host_controller = impl::GetHostControllerOfPortSdCard0(); break;
|
||||
case Port_SdCard0: host_controller = impl::GetHostControllerOfPortSdCard0(); break;
|
||||
//TODO: case Port_GcAsic0: host_controller = impl::GetHostControllerOfPortGcAsic0(); break;
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
|
@ -45,7 +53,7 @@ namespace ams::sdmmc {
|
|||
impl::IDeviceAccessor *device_accessor = nullptr;
|
||||
switch (port) {
|
||||
case Port_Mmc0: device_accessor = impl::GetDeviceAccessorOfPortMmc0(); break;
|
||||
//TODO: case Port_SdCard0: device_accessor = impl::GetDeviceAccessorOfPortSdCard0(); break;
|
||||
case Port_SdCard0: device_accessor = impl::GetDeviceAccessorOfPortSdCard0(); break;
|
||||
//TODO: case Port_GcAsic0: device_accessor = impl::GetDeviceAccessorOfPortGcAsic0(); break;
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
|
|
|
@ -13,7 +13,15 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#if defined(ATMOSPHERE_IS_STRATOSPHERE)
|
||||
#include <stratosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_MESOSPHERE)
|
||||
#include <mesosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_EXOSPHERE)
|
||||
#include <exosphere.hpp>
|
||||
#else
|
||||
#include <vapours.hpp>
|
||||
#endif
|
||||
#include "impl/sdmmc_mmc_device_accessor.hpp"
|
||||
#include "impl/sdmmc_port_mmc0.hpp"
|
||||
#include "impl/sdmmc_port_sd_card0.hpp"
|
||||
|
|
103
libraries/libvapours/source/sdmmc/sdmmc_sd_card.cpp
Normal file
103
libraries/libvapours/source/sdmmc/sdmmc_sd_card.cpp
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#if defined(ATMOSPHERE_IS_STRATOSPHERE)
|
||||
#include <stratosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_MESOSPHERE)
|
||||
#include <mesosphere.hpp>
|
||||
#elif defined(ATMOSPHERE_IS_EXOSPHERE)
|
||||
#include <exosphere.hpp>
|
||||
#else
|
||||
#include <vapours.hpp>
|
||||
#endif
|
||||
#include "impl/sdmmc_sd_card_device_accessor.hpp"
|
||||
#include "impl/sdmmc_port_mmc0.hpp"
|
||||
#include "impl/sdmmc_port_sd_card0.hpp"
|
||||
#include "impl/sdmmc_port_gc_asic0.hpp"
|
||||
|
||||
namespace ams::sdmmc {
|
||||
|
||||
namespace {
|
||||
|
||||
impl::SdCardDeviceAccessor *GetSdCardDeviceAccessor(Port port) {
|
||||
/* Get the accessor. */
|
||||
impl::SdCardDeviceAccessor *sd_card_device_accessor = nullptr;
|
||||
switch (port) {
|
||||
case Port_SdCard0: sd_card_device_accessor = impl::GetSdCardDeviceAccessorOfPortSdCard0(); break;
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
|
||||
/* Ensure it's valid */
|
||||
AMS_ABORT_UNLESS(sd_card_device_accessor != nullptr);
|
||||
return sd_card_device_accessor;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SetSdCardWorkBuffer(Port port, void *buffer, size_t buffer_size) {
|
||||
return GetSdCardDeviceAccessor(port)->SetSdCardWorkBuffer(buffer, buffer_size);
|
||||
}
|
||||
|
||||
void PutSdCardToSleep(Port port) {
|
||||
return GetSdCardDeviceAccessor(port)->PutSdCardToSleep();
|
||||
}
|
||||
|
||||
void AwakenSdCard(Port port) {
|
||||
return GetSdCardDeviceAccessor(port)->AwakenSdCard();
|
||||
}
|
||||
|
||||
Result GetSdCardProtectedAreaCapacity(u32 *out_num_sectors, Port port) {
|
||||
return GetSdCardDeviceAccessor(port)->GetSdCardProtectedAreaCapacity(out_num_sectors);
|
||||
}
|
||||
|
||||
Result GetSdCardScr(void *dst, size_t dst_size, Port port) {
|
||||
return GetSdCardDeviceAccessor(port)->GetSdCardScr(dst, dst_size);
|
||||
}
|
||||
|
||||
Result GetSdCardSwitchFunctionStatus(void *dst, size_t dst_size, Port port, SdCardSwitchFunction switch_function) {
|
||||
return GetSdCardDeviceAccessor(port)->GetSdCardSwitchFunctionStatus(dst, dst_size, switch_function);
|
||||
}
|
||||
|
||||
Result GetSdCardCurrentConsumption(u16 *out_current_consumption, Port port, SpeedMode speed_mode) {
|
||||
return GetSdCardDeviceAccessor(port)->GetSdCardCurrentConsumption(out_current_consumption, speed_mode);
|
||||
}
|
||||
|
||||
Result GetSdCardSdStatus(void *dst, size_t dst_size, Port port) {
|
||||
return GetSdCardDeviceAccessor(port)->GetSdCardSdStatus(dst, dst_size);
|
||||
}
|
||||
|
||||
Result CheckSdCardConnection(SpeedMode *out_speed_mode, BusWidth *out_bus_width, Port port) {
|
||||
return GetSdCardDeviceAccessor(port)->CheckConnection(out_speed_mode, out_bus_width);
|
||||
}
|
||||
|
||||
bool IsSdCardInserted(Port port) {
|
||||
return GetSdCardDeviceAccessor(port)->IsSdCardInserted();
|
||||
}
|
||||
|
||||
bool IsSdCardRemoved(Port port) {
|
||||
return GetSdCardDeviceAccessor(port)->IsSdCardRemoved();
|
||||
}
|
||||
|
||||
|
||||
void RegisterSdCardDetectionEventCallback(Port port, DeviceDetectionEventCallback callback, void *arg) {
|
||||
return GetSdCardDeviceAccessor(port)->RegisterSdCardDetectionEventCallback(callback, arg);
|
||||
}
|
||||
|
||||
void UnregisterSdCardDetectionEventCallback(Port port) {
|
||||
return GetSdCardDeviceAccessor(port)->UnregisterSdCardDetectionEventCallback();
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in a new issue