sdmmc: SdCardDeviceAccessor impl

This commit is contained in:
Michael Scire 2020-10-27 19:33:55 -07:00
parent e3900de6c0
commit 4586dce57b
21 changed files with 1564 additions and 37 deletions

View file

@ -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);

View file

@ -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)

View file

@ -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);

View file

@ -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>

View file

@ -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

View 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);
}

View file

@ -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

View file

@ -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

View file

@ -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 {

View file

@ -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"

View file

@ -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();
}

View file

@ -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"

View file

@ -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"

View file

@ -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

View file

@ -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
}
};
}

View file

@ -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) {

View file

@ -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

View file

@ -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();
}

View file

@ -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"

View 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();
}
}