diff --git a/exosphere/program/source/secmon_setup.cpp b/exosphere/program/source/secmon_setup.cpp
index b5580c1b2..5e33002b8 100644
--- a/exosphere/program/source/secmon_setup.cpp
+++ b/exosphere/program/source/secmon_setup.cpp
@@ -648,7 +648,7 @@ namespace ams::secmon {
reg::Read (MC + MC_SMMU_TLB_CONFIG);
/* Flush the entire page table cache, and read TLB_CONFIG to ensure the flush takes. */
- reg::Write(MC + MC_SMMU_PTC_FLUSH, 0);
+ reg::Write(MC + MC_SMMU_PTC_FLUSH_0, 0);
reg::Read (MC + MC_SMMU_TLB_CONFIG);
/* Flush the entire translation lookaside buffer, and read TLB_CONFIG to ensure the flush takes. */
@@ -907,7 +907,7 @@ namespace ams::secmon {
reg::Write(MC + MC_SMMU_PPCS1_ASID, MC_REG_BITS_ENUM(SMMU_PPCS1_ASID_PPCS1_SMMU_ENABLE, ENABLE), MC_REG_BITS_VALUE(SMMU_PPCS1_ASID_PPCS1_ASID, BpmpAsid));
/* Flush the entire page table cache, and read TLB_CONFIG to ensure the flush takes. */
- reg::Write(MC + MC_SMMU_PTC_FLUSH, 0);
+ reg::Write(MC + MC_SMMU_PTC_FLUSH_0, 0);
reg::Read (MC + MC_SMMU_TLB_CONFIG);
/* Flush the entire translation lookaside buffer, and read TLB_CONFIG to ensure the flush takes. */
diff --git a/exosphere/program/source/smc/secmon_mc_access_table_data.inc b/exosphere/program/source/smc/secmon_mc_access_table_data.inc
index 5b97b8f3f..9d75169d7 100644
--- a/exosphere/program/source/smc/secmon_mc_access_table_data.inc
+++ b/exosphere/program/source/smc/secmon_mc_access_table_data.inc
@@ -22,7 +22,7 @@ SetRegisterAllowed(MC_SMMU_CONFIG); /* 0x010 */
SetRegisterAllowed(MC_SMMU_PTB_ASID); /* 0x01C */
SetRegisterAllowed(MC_SMMU_PTB_DATA); /* 0x020 */
SetRegisterAllowed(MC_SMMU_TLB_FLUSH); /* 0x030 */
-SetRegisterAllowed(MC_SMMU_PTC_FLUSH); /* 0x034 */
+SetRegisterAllowed(MC_SMMU_PTC_FLUSH_0); /* 0x034 */
SetRegisterAllowed(MC_EMEM_CFG); /* 0x050 */
SetRegisterAllowed(MC_EMEM_ADR_CFG); /* 0x054 */
SetRegisterAllowed(MC_EMEM_ARB_CFG); /* 0x090 */
@@ -53,7 +53,7 @@ SetRegisterAllowed(MC_SMMU_DCB_ASID); /* 0x244 */
SetRegisterAllowed(MC_SMMU_HC_ASID); /* 0x250 */
SetRegisterAllowed(MC_SMMU_HDA_ASID); /* 0x254 */
SetRegisterAllowed(MC_SMMU_ISP2_ASID); /* 0x258 */
-SetRegisterAllowed(MC_SMMU_NVENC_ASID); /* 0x264 */
+SetRegisterAllowed(MC_SMMU_MSENC_NVENC_ASID); /* 0x264 */
SetRegisterAllowed(MC_SMMU_NV_ASID); /* 0x268 */
SetRegisterAllowed(MC_SMMU_NV2_ASID); /* 0x26C */
SetRegisterAllowed(MC_SMMU_PPCS_ASID); /* 0x270 */
diff --git a/exosphere/sdmmc_test/Makefile b/exosphere/sdmmc_test/Makefile
new file mode 100644
index 000000000..4bfed891e
--- /dev/null
+++ b/exosphere/sdmmc_test/Makefile
@@ -0,0 +1,108 @@
+#---------------------------------------------------------------------------------
+# Define the atmosphere board and cpu
+#---------------------------------------------------------------------------------
+export ATMOSPHERE_BOARD := nx-hac-001
+export ATMOSPHERE_CPU := arm7tdmi
+
+#---------------------------------------------------------------------------------
+# pull in common atmosphere configuration
+#---------------------------------------------------------------------------------
+include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../../libraries/config/templates/exosphere.mk
+
+#---------------------------------------------------------------------------------
+# no real need to edit anything past this point unless you need to add additional
+# rules for different file extensions
+#---------------------------------------------------------------------------------
+ifneq ($(BUILD),$(notdir $(CURDIR)))
+#---------------------------------------------------------------------------------
+
+export OUTPUT := $(CURDIR)/$(TARGET)
+export TOPDIR := $(CURDIR)
+export DEPSDIR := $(CURDIR)/$(BUILD)
+
+export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
+ $(foreach dir,$(DATA),$(CURDIR)/$(dir))
+
+CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
+CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
+SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
+
+#---------------------------------------------------------------------------------
+# use CXX for linking C++ projects, CC for standard C
+#---------------------------------------------------------------------------------
+ifeq ($(strip $(CPPFILES)),)
+#---------------------------------------------------------------------------------
+ export LD := $(CC)
+#---------------------------------------------------------------------------------
+else
+#---------------------------------------------------------------------------------
+ export LD := $(CXX)
+#---------------------------------------------------------------------------------
+endif
+#---------------------------------------------------------------------------------
+
+export OFILES_BIN := $(addsuffix .o,$(BINFILES))
+export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
+export OFILES := $(OFILES_BIN) $(OFILES_SRC)
+export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(subst -,_,$(BINFILES))))
+
+export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
+ $(foreach dir,$(LIBDIRS),-I$(dir)/include) \
+ -I.
+
+export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib -L$(dir)/$(ATMOSPHERE_LIBRARY_DIR))
+
+.PHONY: $(BUILD) clean all
+
+#---------------------------------------------------------------------------------
+all: $(BUILD) check_libexo
+
+$(BUILD): check_libexo
+ @[ -d $@ ] || mkdir -p $@
+ @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
+
+check_libexo:
+ @$(MAKE) --no-print-directory -C ../../libraries/libexosphere arm
+
+#---------------------------------------------------------------------------------
+clean:
+ @echo clean ...
+ @rm -fr $(BUILD) $(OUTPUT).bin $(OUTPUT).elf *.lz4
+
+#---------------------------------------------------------------------------------
+else
+.PHONY: all
+
+DEPENDS := $(OFILES:.o=.d)
+
+#---------------------------------------------------------------------------------
+# main targets
+#---------------------------------------------------------------------------------
+all : $(OUTPUT).bin
+
+$(OUTPUT).bin : $(OUTPUT).elf
+ $(OBJCOPY) -S -O binary --set-section-flags .bss=alloc,load,contents $< $@
+ @echo built ... $(notdir $@)
+
+$(OUTPUT).elf : $(OFILES) ../../../libraries/libexosphere/$(ATMOSPHERE_LIBRARY_DIR)/libexosphere.a
+
+%.elf:
+ @echo linking $(notdir $@)
+ $(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
+ @$(NM) -CSn $@ > $(notdir $*.lst)
+
+$(OFILES_SRC) : $(HFILES_BIN)
+
+#---------------------------------------------------------------------------------
+# you need a rule like this for each extension you use as binary data
+#---------------------------------------------------------------------------------
+%.bin.o %_bin.h: %.bin
+#---------------------------------------------------------------------------------
+ @echo $(notdir $<)
+ @$(bin2o)
+
+-include $(DEPENDS)
+
+#---------------------------------------------------------------------------------------
+endif
+#---------------------------------------------------------------------------------------
diff --git a/exosphere/sdmmc_test/sdmmc_test.ld b/exosphere/sdmmc_test/sdmmc_test.ld
new file mode 100644
index 000000000..181d33330
--- /dev/null
+++ b/exosphere/sdmmc_test/sdmmc_test.ld
@@ -0,0 +1,194 @@
+OUTPUT_ARCH(arm)
+ENTRY(_ZN3ams10sdmmc_test5StartEv)
+
+MEMORY
+{
+ NULL : ORIGIN = 0, LENGTH = 4K
+ test_fw : ORIGIN = 0x40010000, LENGTH = 32K
+}
+
+
+SECTIONS
+{
+ /* =========== CODE section =========== */
+ PROVIDE(__start__ = ORIGIN(test_fw));
+ . = __start__;
+ __code_start = . ;
+
+ .crt0 :
+ {
+ KEEP (*(.crt0 .crt0.*))
+ . = ALIGN(8);
+ } >test_fw
+
+ .vectors :
+ {
+ KEEP (*(.vectors .vectors.*))
+ . = ALIGN(8);
+ } >test_fw
+
+ .text :
+ {
+ *(.text.unlikely .text.*_unlikely .text.unlikely.*)
+ *(.text.exit .text.exit.*)
+ *(.text.startup .text.startup.*)
+ *(.text.hot .text.hot.*)
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ . = ALIGN(8);
+ } >test_fw
+
+ .init :
+ {
+ KEEP( *(.init) )
+ . = ALIGN(8);
+ } >test_fw
+
+ .plt :
+ {
+ *(.plt)
+ *(.iplt)
+ . = ALIGN(8);
+ } >test_fw
+
+ .fini :
+ {
+ KEEP( *(.fini) )
+ . = ALIGN(8);
+ } >test_fw
+
+
+ /* =========== RODATA section =========== */
+ . = ALIGN(8);
+ __rodata_start = . ;
+
+ .rodata :
+ {
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ . = ALIGN(8);
+ } >test_fw
+
+ .eh_frame_hdr : { __eh_frame_hdr_start = .; *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) __eh_frame_hdr_end = .; } >test_fw
+ .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } >test_fw
+ .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } >test_fw
+ .gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } >test_fw
+
+ .hash : { *(.hash) } >test_fw
+
+ /* =========== DATA section =========== */
+ . = ALIGN(8);
+ __data_start = . ;
+
+ .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } >test_fw
+ .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } >test_fw
+ .gnu_extab : ONLY_IF_RW { *(.gnu_extab*) } >test_fw
+ .exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } >test_fw
+
+ .preinit_array ALIGN(8) :
+ {
+ PROVIDE (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE (__preinit_array_end = .);
+ } >test_fw
+
+ .init_array ALIGN(8) :
+ {
+ PROVIDE (__init_array_start = .);
+ KEEP (*(SORT(.init_array.*)))
+ KEEP (*(.init_array))
+ PROVIDE (__init_array_end = .);
+ } >test_fw
+
+ .fini_array ALIGN(8) :
+ {
+ PROVIDE (__fini_array_start = .);
+ KEEP (*(.fini_array))
+ KEEP (*(SORT(.fini_array.*)))
+ PROVIDE (__fini_array_end = .);
+ } >test_fw
+
+ .ctors ALIGN(8) :
+ {
+ KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ } >test_fw
+
+ .dtors ALIGN(8) :
+ {
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ } >test_fw
+
+ __got_start__ = .;
+
+ .got : { *(.got) *(.igot) } >test_fw
+ .got.plt : { *(.got.plt) *(.igot.plt) } >test_fw
+
+ __got_end__ = .;
+
+ .data ALIGN(8) :
+ {
+ *(.data .data.* .gnu.linkonce.d.*)
+ SORT(CONSTRUCTORS)
+ } >test_fw
+
+ __bss_start__ = .;
+ .bss ALIGN(8) :
+ {
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ . = ALIGN(16);
+ } >test_fw
+ __bss_end__ = .;
+
+ __end__ = ABSOLUTE(.) ;
+
+ __total_size__ = (__end__ - __start__);
+
+ __stack_top__ = 0x40031000;
+ __stack_bottom__ = 0x40030000;
+
+ /* ==================
+ ==== Metadata ====
+ ================== */
+
+ /* Discard sections that difficult post-processing */
+ /DISCARD/ : { *(.group .comment .note .interp) }
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+}
\ No newline at end of file
diff --git a/exosphere/sdmmc_test/sdmmc_test.specs b/exosphere/sdmmc_test/sdmmc_test.specs
new file mode 100644
index 000000000..72d846e06
--- /dev/null
+++ b/exosphere/sdmmc_test/sdmmc_test.specs
@@ -0,0 +1,7 @@
+%rename link old_link
+
+*link:
+%(old_link) -T %:getenv(TOPDIR /sdmmc_test.ld) --gc-sections --nmagic -nostdlib -nostartfiles
+
+*startfile:
+crti%O%s crtbegin%O%s
diff --git a/exosphere/sdmmc_test/source/sdmmc_test_main.cpp b/exosphere/sdmmc_test/source/sdmmc_test_main.cpp
new file mode 100644
index 000000000..c7da95715
--- /dev/null
+++ b/exosphere/sdmmc_test/source/sdmmc_test_main.cpp
@@ -0,0 +1,146 @@
+/*
+ * 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 .
+ */
+#include
+
+namespace ams::sdmmc_test {
+
+ namespace {
+
+ constexpr inline const uintptr_t PMC = secmon::MemoryRegionPhysicalDevicePmc.GetAddress();
+
+ 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;
+
+ NORETURN void PmcMainReboot() {
+ /* Write enable to MAIN_RESET. */
+ reg::Write(PMC + APBDEV_PMC_CNTRL, PMC_REG_BITS_ENUM(CNTRL_MAIN_RESET, ENABLE));
+
+ /* Wait forever until we're reset. */
+ AMS_INFINITE_LOOP();
+ }
+
+ void CheckResult(const Result result) {
+ volatile u32 * const DEBUG = reinterpret_cast(0x4003C000);
+ if (R_FAILED(result)) {
+ DEBUG[1] = result.GetValue();
+ PmcMainReboot();
+ }
+ }
+
+ }
+
+ void Main() {
+ /* Perform butchered hwinit. */
+ /* TODO: replace with simpler, non-C logic. */
+ /* nx_hwinit(); */
+
+ /* Clear output buffer for debug. */
+ std::memset((void *)0x40038000, 0xAA, 0x400);
+
+ /* Normally, these pins get configured by boot sysmodule during initial pinmux config. */
+ /* However, they're required to access the SD card. */
+ {
+ const uintptr_t apb_misc = dd::QueryIoMapping(0x70000000, 0x4000);
+
+ reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_CLK, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
+ PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
+ PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_DOWN),
+ PINMUX_REG_BITS_ENUM(AUX_SDMMC1_CLK_PM, SDMMC1));
+
+ reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_CMD, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
+ PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
+ PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
+ PINMUX_REG_BITS_ENUM(AUX_SDMMC1_CMD_PM, SDMMC1));
+
+ reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_DAT3, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
+ PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
+ PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
+ PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT3_PM, SDMMC1));
+
+ reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_DAT2, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
+ PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
+ PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
+ PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT2_PM, SDMMC1));
+
+ reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_DAT1, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
+ PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
+ PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
+ PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT1_PM, SDMMC1));
+
+ reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_DAT0, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
+ PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
+ PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
+ PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT0_PM, SDMMC1));
+
+ reg::ReadWrite(apb_misc + PINMUX_AUX_DMIC3_CLK, PINMUX_REG_BITS_ENUM(AUX_E_OD, DISABLE),
+ PINMUX_REG_BITS_ENUM(AUX_E_INPUT, DISABLE),
+ PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
+ PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT0_PM, RSVD2));
+ }
+
+ /* Debug signaler. */
+ volatile u32 * const DEBUG = reinterpret_cast(0x4003C000);
+ DEBUG[0] = 0;
+ DEBUG[1] = 0xAAAAAAAA;
+
+ /* Initialize sdmmc library. */
+ sdmmc::Initialize(Port);
+ DEBUG[0] = 1;
+
+ 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);
+
+ /* Read the first two sectors from disk. */
+ void * const sector_dst = reinterpret_cast(0x40038000);
+ result = sdmmc::Read(sector_dst, SectorCount * sdmmc::SectorSize, Port, SectorIndex, SectorCount);
+ DEBUG[0] = 4;
+ CheckResult(result);
+
+ /* Get the connection status. */
+ sdmmc::SpeedMode speed_mode;
+ sdmmc::BusWidth bus_width;
+ result = sdmmc::CheckSdCardConnection(std::addressof(speed_mode), std::addressof(bus_width), Port);
+
+ /* Save status for debug. */
+ DEBUG[0] = 5;
+ DEBUG[1] = result.GetValue();
+ DEBUG[2] = static_cast(speed_mode);
+ DEBUG[3] = static_cast(bus_width);
+
+ /* Perform a reboot. */
+ PmcMainReboot();
+ }
+
+ NORETURN void ExceptionHandler() {
+ PmcMainReboot();
+ }
+
+}
+
+namespace ams::diag {
+
+ void AbortImpl() {
+ sdmmc_test::ExceptionHandler();
+ }
+
+}
diff --git a/exosphere/sdmmc_test/source/sdmmc_test_start.s b/exosphere/sdmmc_test/source/sdmmc_test_start.s
new file mode 100644
index 000000000..69c1204f7
--- /dev/null
+++ b/exosphere/sdmmc_test/source/sdmmc_test_start.s
@@ -0,0 +1,37 @@
+/*
+ * 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 .
+ */
+
+.section .crt0.text._ZN3ams10sdmmc_test5StartEv, "ax", %progbits
+.align 3
+.global _ZN3ams10sdmmc_test5StartEv
+_ZN3ams10sdmmc_test5StartEv:
+ /* Switch to system mode, mask all interrupts, clear all flags */
+ msr cpsr_cxsf, #0xDF
+
+ /* Set the stack pointer. */
+ ldr sp, =__stack_top__
+
+ /* Set our link register to the exception handler. */
+ ldr lr, =_ZN3ams10sdmmc_test16ExceptionHandlerEv
+
+ /* Call init array functions. */
+ bl __libc_init_array
+
+ /* Invoke main. */
+ b _ZN3ams10sdmmc_test4MainEv
+
+ /* Infinite loop. */
+ 2: b 2b
\ No newline at end of file
diff --git a/exosphere/warmboot/source/warmboot_start.s b/exosphere/warmboot/source/warmboot_start.s
index 18070e04a..dc6a56c2e 100644
--- a/exosphere/warmboot/source/warmboot_start.s
+++ b/exosphere/warmboot/source/warmboot_start.s
@@ -30,7 +30,7 @@ _ZN3ams8warmboot5StartEv:
/* Invoke main. */
ldr r0, =_metadata
- bl _ZN3ams8warmboot4MainEPKNS0_8MetadataE
+ b _ZN3ams8warmboot4MainEPKNS0_8MetadataE
/* Infinite loop. */
1: b 1b
\ No newline at end of file
diff --git a/libraries/config/common.mk b/libraries/config/common.mk
index d5bf46fbb..1ca25d415 100644
--- a/libraries/config/common.mk
+++ b/libraries/config/common.mk
@@ -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)
diff --git a/libraries/libexosphere/arm.mk b/libraries/libexosphere/arm.mk
index f82386e0f..a9b50909c 100644
--- a/libraries/libexosphere/arm.mk
+++ b/libraries/libexosphere/arm.mk
@@ -112,6 +112,7 @@ $(OFILES) : $(GCH_FILES)
$(OFILES_SRC) : $(HFILES_BIN)
libc.o: CFLAGS += -fno-builtin -fno-lto
+libgcc_division.arch.arm.o: CFLAGS += -fno-builtin -fno-lto
#---------------------------------------------------------------------------------
%_bin.h %.bin.o : %.bin
diff --git a/libraries/libexosphere/include/exosphere.hpp b/libraries/libexosphere/include/exosphere.hpp
index d7403cbf5..5fe60639c 100644
--- a/libraries/libexosphere/include/exosphere.hpp
+++ b/libraries/libexosphere/include/exosphere.hpp
@@ -17,7 +17,6 @@
#include
#include
-#include
#include
#include
#include
@@ -41,4 +40,3 @@
#include
#include
#include
-#include
\ No newline at end of file
diff --git a/libraries/libexosphere/include/exosphere/tegra.hpp b/libraries/libexosphere/include/exosphere/tegra.hpp
deleted file mode 100644
index 7f988871f..000000000
--- a/libraries/libexosphere/include/exosphere/tegra.hpp
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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 .
- */
-#pragma once
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
diff --git a/libraries/libexosphere/include/exosphere/util.hpp b/libraries/libexosphere/include/exosphere/util.hpp
index 088033e7c..ce31b63ea 100644
--- a/libraries/libexosphere/include/exosphere/util.hpp
+++ b/libraries/libexosphere/include/exosphere/util.hpp
@@ -20,14 +20,6 @@ namespace ams::util {
void SetRegisterAddress(uintptr_t address);
- u32 GetMicroSeconds();
- void WaitMicroSeconds(int us);
-
void ClearMemory(void *ptr, size_t size);
- template requires std::integral && std::integral
- constexpr T DivideUp(T x, U y) {
- return (x + (y - 1)) / y;
- }
-
}
\ No newline at end of file
diff --git a/libraries/libexosphere/source/libc/libexo_cxx.cpp b/libraries/libexosphere/source/libc/libexo_cxx.cpp
new file mode 100644
index 000000000..64efc6786
--- /dev/null
+++ b/libraries/libexosphere/source/libc/libexo_cxx.cpp
@@ -0,0 +1,27 @@
+/*
+ * 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 .
+ */
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* cxx implementation details to be stubbed here, as needed. */
+void __cxa_pure_virtual() { AMS_ABORT("pure virtual function call"); }
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
diff --git a/libraries/libexosphere/source/libc/libgcc_division.arch.arm.c b/libraries/libexosphere/source/libc/libgcc_division.arch.arm.c
new file mode 100644
index 000000000..22bc673a1
--- /dev/null
+++ b/libraries/libexosphere/source/libc/libgcc_division.arch.arm.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2014, STMicroelectronics International N.V.
+ */
+
+/*
+ * Form ABI specifications:
+ * int __aeabi_idiv(int numerator, int denominator);
+ * unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator);
+ *
+ * typedef struct { int quot; int rem; } idiv_return;
+ * typedef struct { unsigned quot; unsigned rem; } uidiv_return;
+ *
+ * __value_in_regs idiv_return __aeabi_idivmod(int numerator,
+ * int *denominator);
+ * __value_in_regs uidiv_return __aeabi_uidivmod(unsigned *numerator,
+ * unsigned denominator);
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* struct qr - stores qutient/remainder to handle divmod EABI interfaces. */
+struct qr {
+ unsigned q; /* computed quotient */
+ unsigned r; /* computed remainder */
+ unsigned q_n; /* specficies if quotient shall be negative */
+ unsigned r_n; /* specficies if remainder shall be negative */
+};
+
+static void uint_div_qr(unsigned numerator, unsigned denominator,
+ struct qr *qr);
+
+/* returns in R0 and R1 by tail calling an asm function */
+unsigned __aeabi_uidivmod(unsigned numerator, unsigned denominator);
+
+unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator);
+
+/* returns in R0 and R1 by tail calling an asm function */
+signed __aeabi_idivmod(signed numerator, signed denominator);
+
+signed __aeabi_idiv(signed numerator, signed denominator);
+
+/*
+ * __ste_idivmod_ret_t __aeabi_idivmod(signed numerator, signed denominator)
+ * Numerator and Denominator are received in R0 and R1.
+ * Where __ste_idivmod_ret_t is returned in R0 and R1.
+ *
+ * __ste_uidivmod_ret_t __aeabi_uidivmod(unsigned numerator,
+ * unsigned denominator)
+ * Numerator and Denominator are received in R0 and R1.
+ * Where __ste_uidivmod_ret_t is returned in R0 and R1.
+ */
+#ifdef __GNUC__
+signed ret_idivmod_values(signed quotient, signed remainder);
+unsigned ret_uidivmod_values(unsigned quotient, unsigned remainder);
+#else
+#error "Compiler not supported"
+#endif
+
+static void division_qr(unsigned n, unsigned p, struct qr *qr)
+{
+ unsigned i = 1, q = 0;
+ if (p == 0) {
+ qr->r = 0xFFFFFFFF; /* division by 0 */
+ return;
+ }
+
+ while ((p >> 31) == 0) {
+ i = i << 1; /* count the max division steps */
+ p = p << 1; /* increase p until it has maximum size*/
+ }
+
+ while (i > 0) {
+ q = q << 1; /* write bit in q at index (size-1) */
+ if (n >= p)
+ {
+ n -= p;
+ q++;
+ }
+ p = p >> 1; /* decrease p */
+ i = i >> 1; /* decrease remaining size in q */
+ }
+ qr->r = n;
+ qr->q = q;
+}
+
+static void uint_div_qr(unsigned numerator, unsigned denominator, struct qr *qr)
+{
+
+ division_qr(numerator, denominator, qr);
+
+ /* negate quotient and/or remainder according to requester */
+ if (qr->q_n)
+ qr->q = -qr->q;
+ if (qr->r_n)
+ qr->r = -qr->r;
+}
+
+unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator)
+{
+ struct qr qr = { .q_n = 0, .r_n = 0 };
+
+ uint_div_qr(numerator, denominator, &qr);
+
+ return qr.q;
+}
+
+unsigned __aeabi_uidivmod(unsigned numerator, unsigned denominator)
+{
+ struct qr qr = { .q_n = 0, .r_n = 0 };
+
+ uint_div_qr(numerator, denominator, &qr);
+
+ return ret_uidivmod_values(qr.q, qr.r);
+}
+
+signed __aeabi_idiv(signed numerator, signed denominator)
+{
+ struct qr qr = { .q_n = 0, .r_n = 0 };
+
+ if (((numerator < 0) && (denominator > 0)) ||
+ ((numerator > 0) && (denominator < 0)))
+ qr.q_n = 1; /* quotient shall be negate */
+ if (numerator < 0) {
+ numerator = -numerator;
+ qr.r_n = 1; /* remainder shall be negate */
+ }
+ if (denominator < 0)
+ denominator = -denominator;
+
+ uint_div_qr(numerator, denominator, &qr);
+
+ return qr.q;
+}
+
+signed __aeabi_idivmod(signed numerator, signed denominator)
+{
+ struct qr qr = { .q_n = 0, .r_n = 0 };
+
+ if (((numerator < 0) && (denominator > 0)) ||
+ ((numerator > 0) && (denominator < 0)))
+ qr.q_n = 1; /* quotient shall be negate */
+ if (numerator < 0) {
+ numerator = -numerator;
+ qr.r_n = 1; /* remainder shall be negate */
+ }
+ if (denominator < 0)
+ denominator = -denominator;
+
+ uint_div_qr(numerator, denominator, &qr);
+
+ return ret_idivmod_values(qr.q, qr.r);
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
\ No newline at end of file
diff --git a/libraries/libexosphere/source/libc/libgcc_division_asm.arch.arm.s b/libraries/libexosphere/source/libc/libgcc_division_asm.arch.arm.s
new file mode 100644
index 000000000..a0acbace0
--- /dev/null
+++ b/libraries/libexosphere/source/libc/libgcc_division_asm.arch.arm.s
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2014, STMicroelectronics International N.V.
+ */
+
+/*
+ * signed ret_idivmod_values(signed quot, signed rem);
+ * return quotient and remaining the EABI way (regs r0,r1)
+ */
+.section .text.ret_idivmod_values, "ax", %progbits
+.globl ret_idivmod_values
+.align 0
+.syntax unified
+ret_idivmod_values:
+ bx lr
+.type ret_idivmod_values, %function
+.size ret_idivmod_values, .-ret_idivmod_values
+
+/*
+ * unsigned ret_uidivmod_values(unsigned quot, unsigned rem);
+ * return quotient and remaining the EABI way (regs r0,r1)
+ */
+.section .text.ret_uidivmod_values, "ax", %progbits
+.globl ret_uidivmod_values
+.align 0
+.syntax unified
+ret_uidivmod_values:
+ bx lr
+.type ret_uidivmod_values, %function
+.size ret_uidivmod_values, .-ret_uidivmod_values
diff --git a/libraries/libexosphere/source/libc/libgcc_thumb_case.arch.arm.s b/libraries/libexosphere/source/libc/libgcc_thumb_case.arch.arm.s
new file mode 100644
index 000000000..2658ad61b
--- /dev/null
+++ b/libraries/libexosphere/source/libc/libgcc_thumb_case.arch.arm.s
@@ -0,0 +1,35 @@
+/* Copyright (C) 1995-2018 Free Software Foundation, Inc.
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3, or (at your option) any
+later version.
+This file is distributed in the hope that 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.
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+. */
+
+
+.section .text.__gnu_thumb1_case_uqi, "ax", %progbits
+.globl __gnu_thumb1_case_uqi
+.align 0
+.thumb_func
+.syntax unified
+__gnu_thumb1_case_uqi:
+ push {r1}
+ mov r1, lr
+ lsrs r1, r1, #1
+ lsls r1, r1, #1
+ ldrb r1, [r1, r0]
+ lsls r1, r1, #1
+ add lr, lr, r1
+ pop {r1}
+ bx lr
+.type __gnu_thumb1_case_uqi, %function
+.size __gnu_thumb1_case_uqi, .-__gnu_thumb1_case_uqi
diff --git a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_device_page_table.cpp b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_device_page_table.cpp
index aa05ae0a7..0557bb305 100644
--- a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_device_page_table.cpp
+++ b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_device_page_table.cpp
@@ -14,7 +14,6 @@
* along with this program. If not, see .
*/
#include
-#include "kern_mc_registers.hpp"
#if defined(MESOSPHERE_BUILD_FOR_DEBUGGING) || defined(MESOSPHERE_BUILD_FOR_AUDITING)
#define MESOSPHERE_ENABLE_MEMORY_CONTROLLER_INTERRUPT
diff --git a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_sleep_manager.cpp b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_sleep_manager.cpp
index da7f1f6ad..913137d5f 100644
--- a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_sleep_manager.cpp
+++ b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_sleep_manager.cpp
@@ -78,13 +78,11 @@ namespace ams::kern::board::nintendo::nx {
void WaitOtherCpuPowerOff() {
constexpr u64 PmcPhysicalAddress = 0x7000E400;
- constexpr u64 APBDEV_PMC_PWRGATE_STATUS = PmcPhysicalAddress + 0x38;
-
constexpr u32 PWRGATE_STATUS_CE123_MASK = ((1u << 3) - 1) << 9;
u32 value;
do {
- bool res = smc::ReadWriteRegister(std::addressof(value), APBDEV_PMC_PWRGATE_STATUS, 0, 0);
+ bool res = smc::ReadWriteRegister(std::addressof(value), PmcPhysicalAddress + APBDEV_PMC_PWRGATE_STATUS, 0, 0);
MESOSPHERE_ASSERT(res);
} while ((value & PWRGATE_STATUS_CE123_MASK) != 0);
}
diff --git a/libraries/libmesosphere/source/board/nintendo/nx/kern_lps_driver.cpp b/libraries/libmesosphere/source/board/nintendo/nx/kern_lps_driver.cpp
index b6c232a05..e3f8755c9 100644
--- a/libraries/libmesosphere/source/board/nintendo/nx/kern_lps_driver.cpp
+++ b/libraries/libmesosphere/source/board/nintendo/nx/kern_lps_driver.cpp
@@ -19,11 +19,7 @@
#include "kern_bpmp_api.hpp"
#include "kern_atomics_registers.hpp"
-#include "kern_clkrst_registers.hpp"
-#include "kern_evp_registers.hpp"
-#include "kern_flow_registers.hpp"
#include "kern_ictlr_registers.hpp"
-#include "kern_pmc_registers.hpp"
#include "kern_sema_registers.hpp"
namespace ams::kern::board::nintendo::nx::lps {
diff --git a/libraries/libmesosphere/source/board/nintendo/nx/kern_mc_registers.hpp b/libraries/libmesosphere/source/board/nintendo/nx/kern_mc_registers.hpp
deleted file mode 100644
index edd925ee2..000000000
--- a/libraries/libmesosphere/source/board/nintendo/nx/kern_mc_registers.hpp
+++ /dev/null
@@ -1,526 +0,0 @@
-/*
- * 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 .
- */
-#pragma once
-
-#define MC_INTSTATUS 0x0
-#define MC_INTMASK 0x4
-#define MC_ERR_STATUS 0x8
-#define MC_ERR_ADR 0xc
-#define MC_SMMU_CONFIG 0x10
-#define MC_SMMU_TLB_CONFIG 0x14
-#define MC_SMMU_PTC_CONFIG 0x18
-#define MC_SMMU_PTB_ASID 0x1c
-#define MC_SMMU_PTB_DATA 0x20
-#define MC_SMMU_TLB_FLUSH 0x30
-#define MC_SMMU_PTC_FLUSH_0 0x34
-#define MC_SMMU_PTC_FLUSH_1 0x9b8
-#define MC_SMMU_ASID_SECURITY 0x38
-#define MC_SMMU_ASID_SECURITY_1 0x3c
-#define MC_SMMU_ASID_SECURITY_2 0x9e0
-#define MC_SMMU_ASID_SECURITY_3 0x9e4
-#define MC_SMMU_ASID_SECURITY_4 0x9e8
-#define MC_SMMU_ASID_SECURITY_5 0x9ec
-#define MC_SMMU_ASID_SECURITY_6 0x9f0
-#define MC_SMMU_ASID_SECURITY_7 0x9f4
-#define MC_SMMU_AFI_ASID 0x238
-#define MC_SMMU_AVPC_ASID 0x23c
-#define MC_SMMU_DC_ASID 0x240
-#define MC_SMMU_DCB_ASID 0x244
-#define MC_SMMU_HC_ASID 0x250
-#define MC_SMMU_HDA_ASID 0x254
-#define MC_SMMU_ISP2_ASID 0x258
-#define MC_SMMU_MSENC_NVENC_ASID 0x264
-#define MC_SMMU_NV_ASID 0x268
-#define MC_SMMU_NV2_ASID 0x26c
-#define MC_SMMU_PPCS_ASID 0x270
-#define MC_SMMU_SATA_ASID 0x274
-#define MC_SMMU_VDE_ASID 0x27c
-#define MC_SMMU_VI_ASID 0x280
-#define MC_SMMU_VIC_ASID 0x284
-#define MC_SMMU_XUSB_HOST_ASID 0x288
-#define MC_SMMU_XUSB_DEV_ASID 0x28c
-#define MC_SMMU_TSEC_ASID 0x294
-#define MC_SMMU_PPCS1_ASID 0x298
-#define MC_SMMU_DC1_ASID 0xa88
-#define MC_SMMU_SDMMC1A_ASID 0xa94
-#define MC_SMMU_SDMMC2A_ASID 0xa98
-#define MC_SMMU_SDMMC3A_ASID 0xa9c
-#define MC_SMMU_SDMMC4A_ASID 0xaa0
-#define MC_SMMU_ISP2B_ASID 0xaa4
-#define MC_SMMU_GPU_ASID 0xaa8
-#define MC_SMMU_GPUB_ASID 0xaac
-#define MC_SMMU_PPCS2_ASID 0xab0
-#define MC_SMMU_NVDEC_ASID 0xab4
-#define MC_SMMU_APE_ASID 0xab8
-#define MC_SMMU_SE_ASID 0xabc
-#define MC_SMMU_NVJPG_ASID 0xac0
-#define MC_SMMU_HC1_ASID 0xac4
-#define MC_SMMU_SE1_ASID 0xac8
-#define MC_SMMU_AXIAP_ASID 0xacc
-#define MC_SMMU_ETR_ASID 0xad0
-#define MC_SMMU_TSECB_ASID 0xad4
-#define MC_SMMU_TSEC1_ASID 0xad8
-#define MC_SMMU_TSECB1_ASID 0xadc
-#define MC_SMMU_NVDEC1_ASID 0xae0
-#define MC_SMMU_TRANSLATION_ENABLE_0 0x228
-#define MC_SMMU_TRANSLATION_ENABLE_1 0x22c
-#define MC_SMMU_TRANSLATION_ENABLE_2 0x230
-#define MC_SMMU_TRANSLATION_ENABLE_3 0x234
-#define MC_SMMU_TRANSLATION_ENABLE_4 0xb98
-#define MC_PCFIFO_CLIENT_CONFIG0 0xdd0
-#define MC_PCFIFO_CLIENT_CONFIG1 0xdd4
-#define MC_PCFIFO_CLIENT_CONFIG2 0xdd8
-#define MC_PCFIFO_CLIENT_CONFIG3 0xddc
-#define MC_PCFIFO_CLIENT_CONFIG4 0xde0
-#define MC_EMEM_CFG 0x50
-#define MC_EMEM_ADR_CFG 0x54
-#define MC_EMEM_ADR_CFG_DEV0 0x58
-#define MC_EMEM_ADR_CFG_DEV1 0x5c
-#define MC_EMEM_ADR_CFG_CHANNEL_MASK 0x60
-#define MC_EMEM_ADR_CFG_BANK_MASK_0 0x64
-#define MC_EMEM_ADR_CFG_BANK_MASK_1 0x68
-#define MC_EMEM_ADR_CFG_BANK_MASK_2 0x6c
-#define MC_SECURITY_CFG0 0x70
-#define MC_SECURITY_CFG1 0x74
-#define MC_SECURITY_CFG3 0x9bc
-#define MC_SECURITY_RSV 0x7c
-#define MC_EMEM_ARB_CFG 0x90
-#define MC_EMEM_ARB_OUTSTANDING_REQ 0x94
-#define MC_EMEM_ARB_TIMING_RCD 0x98
-#define MC_EMEM_ARB_TIMING_RP 0x9c
-#define MC_EMEM_ARB_TIMING_RC 0xa0
-#define MC_EMEM_ARB_TIMING_RAS 0xa4
-#define MC_EMEM_ARB_TIMING_FAW 0xa8
-#define MC_EMEM_ARB_TIMING_RRD 0xac
-#define MC_EMEM_ARB_TIMING_RAP2PRE 0xb0
-#define MC_EMEM_ARB_TIMING_WAP2PRE 0xb4
-#define MC_EMEM_ARB_TIMING_R2R 0xb8
-#define MC_EMEM_ARB_TIMING_W2W 0xbc
-#define MC_EMEM_ARB_TIMING_R2W 0xc0
-#define MC_EMEM_ARB_TIMING_W2R 0xc4
-#define MC_EMEM_ARB_TIMING_RFCPB 0x6c0
-#define MC_EMEM_ARB_TIMING_CCDMW 0x6c4
-#define MC_EMEM_ARB_REFPB_HP_CTRL 0x6f0
-#define MC_EMEM_ARB_REFPB_BANK_CTRL 0x6f4
-#define MC_EMEM_ARB_DA_TURNS 0xd0
-#define MC_EMEM_ARB_DA_COVERS 0xd4
-#define MC_EMEM_ARB_MISC0 0xd8
-#define MC_EMEM_ARB_MISC1 0xdc
-#define MC_EMEM_ARB_MISC2 0xc8
-#define MC_EMEM_ARB_RING1_THROTTLE 0xe0
-#define MC_EMEM_ARB_RING3_THROTTLE 0xe4
-#define MC_EMEM_ARB_NISO_THROTTLE 0x6b0
-#define MC_EMEM_ARB_OVERRIDE 0xe8
-#define MC_EMEM_ARB_RSV 0xec
-#define MC_CLKEN_OVERRIDE 0xf4
-#define MC_TIMING_CONTROL_DBG 0xf8
-#define MC_TIMING_CONTROL 0xfc
-#define MC_STAT_CONTROL 0x100
-#define MC_STAT_STATUS 0x104
-#define MC_STAT_EMC_CLOCK_LIMIT 0x108
-#define MC_STAT_EMC_CLOCK_LIMIT_MSBS 0x10c
-#define MC_STAT_EMC_CLOCKS 0x110
-#define MC_STAT_EMC_CLOCKS_MSBS 0x114
-#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_LO 0x118
-#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_LO 0x158
-#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_HI 0x11c
-#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_HI 0x15c
-#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_UPPER 0xa20
-#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_UPPER 0xa24
-#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_LO 0x198
-#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_LO 0x1a8
-#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_HI 0x19c
-#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_HI 0x1ac
-#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_UPPER 0xa28
-#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_UPPER 0xa2c
-#define MC_STAT_EMC_FILTER_SET0_ASID 0x1a0
-#define MC_STAT_EMC_FILTER_SET1_ASID 0x1b0
-#define MC_STAT_EMC_FILTER_SET0_SLACK_LIMIT 0x120
-#define MC_STAT_EMC_FILTER_SET1_SLACK_LIMIT 0x160
-#define MC_STAT_EMC_FILTER_SET0_CLIENT_0 0x128
-#define MC_STAT_EMC_FILTER_SET1_CLIENT_0 0x168
-#define MC_STAT_EMC_FILTER_SET0_CLIENT_1 0x12c
-#define MC_STAT_EMC_FILTER_SET1_CLIENT_1 0x16c
-#define MC_STAT_EMC_FILTER_SET0_CLIENT_2 0x130
-#define MC_STAT_EMC_FILTER_SET1_CLIENT_2 0x170
-#define MC_STAT_EMC_FILTER_SET0_CLIENT_3 0x134
-#define MC_STAT_EMC_FILTER_SET0_CLIENT_4 0xb88
-#define MC_STAT_EMC_FILTER_SET1_CLIENT_3 0x174
-#define MC_STAT_EMC_FILTER_SET1_CLIENT_4 0xb8c
-#define MC_STAT_EMC_SET0_COUNT 0x138
-#define MC_STAT_EMC_SET0_COUNT_MSBS 0x13c
-#define MC_STAT_EMC_SET1_COUNT 0x178
-#define MC_STAT_EMC_SET1_COUNT_MSBS 0x17c
-#define MC_STAT_EMC_SET0_SLACK_ACCUM 0x140
-#define MC_STAT_EMC_SET0_SLACK_ACCUM_MSBS 0x144
-#define MC_STAT_EMC_SET1_SLACK_ACCUM 0x180
-#define MC_STAT_EMC_SET1_SLACK_ACCUM_MSBS 0x184
-#define MC_STAT_EMC_SET0_HISTO_COUNT 0x148
-#define MC_STAT_EMC_SET0_HISTO_COUNT_MSBS 0x14c
-#define MC_STAT_EMC_SET1_HISTO_COUNT 0x188
-#define MC_STAT_EMC_SET1_HISTO_COUNT_MSBS 0x18c
-#define MC_STAT_EMC_SET0_MINIMUM_SLACK_OBSERVED 0x150
-#define MC_STAT_EMC_SET1_MINIMUM_SLACK_OBSERVED 0x190
-#define MC_STAT_EMC_SET0_IDLE_CYCLE_COUNT 0x1b8
-#define MC_STAT_EMC_SET0_IDLE_CYCL_COUNT_MSBS 0x1bc
-#define MC_STAT_EMC_SET1_IDLE_CYCLE_COUNT 0x1c8
-#define MC_STAT_EMC_SET1_IDLE_CYCL_COUNT_MSBS 0x1cc
-#define MC_STAT_EMC_SET0_IDLE_CYCLE_PARTITION_SELECT 0x1c0
-#define MC_STAT_EMC_SET1_IDLE_CYCLE_PARTITION_SELECT 0x1d0
-#define MC_CLIENT_HOTRESET_CTRL 0x200
-#define MC_CLIENT_HOTRESET_CTRL_1 0x970
-#define MC_CLIENT_HOTRESET_STATUS 0x204
-#define MC_CLIENT_HOTRESET_STATUS_1 0x974
-#define MC_EMEM_ARB_ISOCHRONOUS_0 0x208
-#define MC_EMEM_ARB_ISOCHRONOUS_1 0x20c
-#define MC_EMEM_ARB_ISOCHRONOUS_2 0x210
-#define MC_EMEM_ARB_ISOCHRONOUS_3 0x214
-#define MC_EMEM_ARB_ISOCHRONOUS_4 0xb94
-#define MC_EMEM_ARB_HYSTERESIS_0 0x218
-#define MC_EMEM_ARB_HYSTERESIS_1 0x21c
-#define MC_EMEM_ARB_HYSTERESIS_2 0x220
-#define MC_EMEM_ARB_HYSTERESIS_3 0x224
-#define MC_EMEM_ARB_HYSTERESIS_4 0xb84
-#define MC_EMEM_ARB_DHYSTERESIS_0 0xbb0
-#define MC_EMEM_ARB_DHYSTERESIS_1 0xbb4
-#define MC_EMEM_ARB_DHYSTERESIS_2 0xbb8
-#define MC_EMEM_ARB_DHYSTERESIS_3 0xbbc
-#define MC_EMEM_ARB_DHYSTERESIS_4 0xbc0
-#define MC_EMEM_ARB_DHYST_CTRL 0xbcc
-#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_0 0xbd0
-#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_1 0xbd4
-#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_2 0xbd8
-#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_3 0xbdc
-#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_4 0xbe0
-#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_5 0xbe4
-#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_6 0xbe8
-#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_7 0xbec
-#define MC_RESERVED_RSV 0x3fc
-#define MC_DISB_EXTRA_SNAP_LEVELS 0x408
-#define MC_APB_EXTRA_SNAP_LEVELS 0x2a4
-#define MC_AHB_EXTRA_SNAP_LEVELS 0x2a0
-#define MC_USBD_EXTRA_SNAP_LEVELS 0xa18
-#define MC_ISP_EXTRA_SNAP_LEVELS 0xa08
-#define MC_AUD_EXTRA_SNAP_LEVELS 0xa10
-#define MC_MSE_EXTRA_SNAP_LEVELS 0x40c
-#define MC_GK2_EXTRA_SNAP_LEVELS 0xa40
-#define MC_A9AVPPC_EXTRA_SNAP_LEVELS 0x414
-#define MC_FTOP_EXTRA_SNAP_LEVELS 0x2bc
-#define MC_JPG_EXTRA_SNAP_LEVELS 0xa3c
-#define MC_HOST_EXTRA_SNAP_LEVELS 0xa14
-#define MC_SAX_EXTRA_SNAP_LEVELS 0x2c0
-#define MC_DIS_EXTRA_SNAP_LEVELS 0x2ac
-#define MC_VICPC_EXTRA_SNAP_LEVELS 0xa1c
-#define MC_HDAPC_EXTRA_SNAP_LEVELS 0xa48
-#define MC_AVP_EXTRA_SNAP_LEVELS 0x2a8
-#define MC_USBX_EXTRA_SNAP_LEVELS 0x404
-#define MC_PCX_EXTRA_SNAP_LEVELS 0x2b8
-#define MC_SD_EXTRA_SNAP_LEVELS 0xa04
-#define MC_DFD_EXTRA_SNAP_LEVELS 0xa4c
-#define MC_VE_EXTRA_SNAP_LEVELS 0x2d8
-#define MC_GK_EXTRA_SNAP_LEVELS 0xa00
-#define MC_VE2_EXTRA_SNAP_LEVELS 0x410
-#define MC_SDM_EXTRA_SNAP_LEVELS 0xa44
-#define MC_VIDEO_PROTECT_BOM 0x648
-#define MC_VIDEO_PROTECT_SIZE_MB 0x64c
-#define MC_VIDEO_PROTECT_BOM_ADR_HI 0x978
-#define MC_VIDEO_PROTECT_REG_CTRL 0x650
-#define MC_ERR_VPR_STATUS 0x654
-#define MC_ERR_VPR_ADR 0x658
-#define MC_VIDEO_PROTECT_VPR_OVERRIDE 0x418
-#define MC_VIDEO_PROTECT_VPR_OVERRIDE1 0x590
-#define MC_IRAM_BOM 0x65c
-#define MC_IRAM_TOM 0x660
-#define MC_IRAM_ADR_HI 0x980
-#define MC_IRAM_REG_CTRL 0x964
-#define MC_EMEM_CFG_ACCESS_CTRL 0x664
-#define MC_TZ_SECURITY_CTRL 0x668
-#define MC_EMEM_ARB_OUTSTANDING_REQ_RING3 0x66c
-#define MC_EMEM_ARB_OUTSTANDING_REQ_NISO 0x6b4
-#define MC_EMEM_ARB_RING0_THROTTLE_MASK 0x6bc
-#define MC_EMEM_ARB_NISO_THROTTLE_MASK 0x6b8
-#define MC_EMEM_ARB_NISO_THROTTLE_MASK_1 0xb80
-#define MC_SEC_CARVEOUT_BOM 0x670
-#define MC_SEC_CARVEOUT_SIZE_MB 0x674
-#define MC_SEC_CARVEOUT_ADR_HI 0x9d4
-#define MC_SEC_CARVEOUT_REG_CTRL 0x678
-#define MC_ERR_SEC_STATUS 0x67c
-#define MC_ERR_SEC_ADR 0x680
-#define MC_PC_IDLE_CLOCK_GATE_CONFIG 0x684
-#define MC_STUTTER_CONTROL 0x688
-#define MC_RESERVED_RSV_1 0x958
-#define MC_DVFS_PIPE_SELECT 0x95c
-#define MC_AHB_PTSA_MIN 0x4e0
-#define MC_AUD_PTSA_MIN 0x54c
-#define MC_MLL_MPCORER_PTSA_RATE 0x44c
-#define MC_RING2_PTSA_RATE 0x440
-#define MC_USBD_PTSA_RATE 0x530
-#define MC_USBX_PTSA_MIN 0x528
-#define MC_USBD_PTSA_MIN 0x534
-#define MC_APB_PTSA_MAX 0x4f0
-#define MC_JPG_PTSA_RATE 0x584
-#define MC_DIS_PTSA_MIN 0x420
-#define MC_AVP_PTSA_MAX 0x4fc
-#define MC_AVP_PTSA_RATE 0x4f4
-#define MC_RING1_PTSA_MIN 0x480
-#define MC_DIS_PTSA_MAX 0x424
-#define MC_SD_PTSA_MAX 0x4d8
-#define MC_MSE_PTSA_RATE 0x4c4
-#define MC_VICPC_PTSA_MIN 0x558
-#define MC_PCX_PTSA_MAX 0x4b4
-#define MC_ISP_PTSA_RATE 0x4a0
-#define MC_A9AVPPC_PTSA_MIN 0x48c
-#define MC_RING2_PTSA_MAX 0x448
-#define MC_AUD_PTSA_RATE 0x548
-#define MC_HOST_PTSA_MIN 0x51c
-#define MC_MLL_MPCORER_PTSA_MAX 0x454
-#define MC_SD_PTSA_MIN 0x4d4
-#define MC_RING1_PTSA_RATE 0x47c
-#define MC_JPG_PTSA_MIN 0x588
-#define MC_HDAPC_PTSA_MIN 0x62c
-#define MC_AVP_PTSA_MIN 0x4f8
-#define MC_JPG_PTSA_MAX 0x58c
-#define MC_VE_PTSA_MAX 0x43c
-#define MC_DFD_PTSA_MAX 0x63c
-#define MC_VICPC_PTSA_RATE 0x554
-#define MC_GK_PTSA_MAX 0x544
-#define MC_VICPC_PTSA_MAX 0x55c
-#define MC_SDM_PTSA_MAX 0x624
-#define MC_SAX_PTSA_RATE 0x4b8
-#define MC_PCX_PTSA_MIN 0x4b0
-#define MC_APB_PTSA_MIN 0x4ec
-#define MC_GK2_PTSA_MIN 0x614
-#define MC_PCX_PTSA_RATE 0x4ac
-#define MC_RING1_PTSA_MAX 0x484
-#define MC_HDAPC_PTSA_RATE 0x628
-#define MC_MLL_MPCORER_PTSA_MIN 0x450
-#define MC_GK2_PTSA_MAX 0x618
-#define MC_AUD_PTSA_MAX 0x550
-#define MC_GK2_PTSA_RATE 0x610
-#define MC_ISP_PTSA_MAX 0x4a8
-#define MC_DISB_PTSA_RATE 0x428
-#define MC_VE2_PTSA_MAX 0x49c
-#define MC_DFD_PTSA_MIN 0x638
-#define MC_FTOP_PTSA_RATE 0x50c
-#define MC_A9AVPPC_PTSA_RATE 0x488
-#define MC_VE2_PTSA_MIN 0x498
-#define MC_USBX_PTSA_MAX 0x52c
-#define MC_DIS_PTSA_RATE 0x41c
-#define MC_USBD_PTSA_MAX 0x538
-#define MC_A9AVPPC_PTSA_MAX 0x490
-#define MC_USBX_PTSA_RATE 0x524
-#define MC_FTOP_PTSA_MAX 0x514
-#define MC_HDAPC_PTSA_MAX 0x630
-#define MC_SD_PTSA_RATE 0x4d0
-#define MC_DFD_PTSA_RATE 0x634
-#define MC_FTOP_PTSA_MIN 0x510
-#define MC_SDM_PTSA_RATE 0x61c
-#define MC_AHB_PTSA_RATE 0x4dc
-#define MC_SMMU_SMMU_PTSA_MAX 0x460
-#define MC_RING2_PTSA_MIN 0x444
-#define MC_SDM_PTSA_MIN 0x620
-#define MC_APB_PTSA_RATE 0x4e8
-#define MC_MSE_PTSA_MIN 0x4c8
-#define MC_HOST_PTSA_RATE 0x518
-#define MC_VE_PTSA_RATE 0x434
-#define MC_AHB_PTSA_MAX 0x4e4
-#define MC_SAX_PTSA_MIN 0x4bc
-#define MC_SMMU_SMMU_PTSA_MIN 0x45c
-#define MC_ISP_PTSA_MIN 0x4a4
-#define MC_HOST_PTSA_MAX 0x520
-#define MC_SAX_PTSA_MAX 0x4c0
-#define MC_VE_PTSA_MIN 0x438
-#define MC_GK_PTSA_MIN 0x540
-#define MC_MSE_PTSA_MAX 0x4cc
-#define MC_DISB_PTSA_MAX 0x430
-#define MC_DISB_PTSA_MIN 0x42c
-#define MC_SMMU_SMMU_PTSA_RATE 0x458
-#define MC_VE2_PTSA_RATE 0x494
-#define MC_GK_PTSA_RATE 0x53c
-#define MC_PTSA_GRANT_DECREMENT 0x960
-#define MC_LATENCY_ALLOWANCE_AVPC_0 0x2e4
-#define MC_LATENCY_ALLOWANCE_AXIAP_0 0x3a0
-#define MC_LATENCY_ALLOWANCE_XUSB_1 0x380
-#define MC_LATENCY_ALLOWANCE_ISP2B_0 0x384
-#define MC_LATENCY_ALLOWANCE_SDMMCAA_0 0x3bc
-#define MC_LATENCY_ALLOWANCE_SDMMCA_0 0x3b8
-#define MC_LATENCY_ALLOWANCE_ISP2_0 0x370
-#define MC_LATENCY_ALLOWANCE_SE_0 0x3e0
-#define MC_LATENCY_ALLOWANCE_ISP2_1 0x374
-#define MC_LATENCY_ALLOWANCE_DC_0 0x2e8
-#define MC_LATENCY_ALLOWANCE_VIC_0 0x394
-#define MC_LATENCY_ALLOWANCE_DCB_1 0x2f8
-#define MC_LATENCY_ALLOWANCE_NVDEC_0 0x3d8
-#define MC_LATENCY_ALLOWANCE_DCB_2 0x2fc
-#define MC_LATENCY_ALLOWANCE_TSEC_0 0x390
-#define MC_LATENCY_ALLOWANCE_DC_2 0x2f0
-#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0AB 0x694
-#define MC_LATENCY_ALLOWANCE_PPCS_1 0x348
-#define MC_LATENCY_ALLOWANCE_XUSB_0 0x37c
-#define MC_LATENCY_ALLOWANCE_PPCS_0 0x344
-#define MC_LATENCY_ALLOWANCE_TSECB_0 0x3f0
-#define MC_LATENCY_ALLOWANCE_AFI_0 0x2e0
-#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0B 0x698
-#define MC_LATENCY_ALLOWANCE_DC_1 0x2ec
-#define MC_LATENCY_ALLOWANCE_APE_0 0x3dc
-#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0C 0x6a0
-#define MC_LATENCY_ALLOWANCE_A9AVP_0 0x3a4
-#define MC_LATENCY_ALLOWANCE_GPU2_0 0x3e8
-#define MC_LATENCY_ALLOWANCE_DCB_0 0x2f4
-#define MC_LATENCY_ALLOWANCE_HC_1 0x314
-#define MC_LATENCY_ALLOWANCE_SDMMC_0 0x3c0
-#define MC_LATENCY_ALLOWANCE_NVJPG_0 0x3e4
-#define MC_LATENCY_ALLOWANCE_PTC_0 0x34c
-#define MC_LATENCY_ALLOWANCE_ETR_0 0x3ec
-#define MC_LATENCY_ALLOWANCE_MPCORE_0 0x320
-#define MC_LATENCY_ALLOWANCE_VI2_0 0x398
-#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0BB 0x69c
-#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0CB 0x6a4
-#define MC_LATENCY_ALLOWANCE_SATA_0 0x350
-#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0A 0x690
-#define MC_LATENCY_ALLOWANCE_HC_0 0x310
-#define MC_LATENCY_ALLOWANCE_DC_3 0x3c8
-#define MC_LATENCY_ALLOWANCE_GPU_0 0x3ac
-#define MC_LATENCY_ALLOWANCE_SDMMCAB_0 0x3c4
-#define MC_LATENCY_ALLOWANCE_ISP2B_1 0x388
-#define MC_LATENCY_ALLOWANCE_NVENC_0 0x328
-#define MC_LATENCY_ALLOWANCE_HDA_0 0x318
-#define MC_MIN_LENGTH_APE_0 0xb34
-#define MC_MIN_LENGTH_DCB_2 0x8a8
-#define MC_MIN_LENGTH_A9AVP_0 0x950
-#define MC_MIN_LENGTH_TSEC_0 0x93c
-#define MC_MIN_LENGTH_DC_1 0x898
-#define MC_MIN_LENGTH_AXIAP_0 0x94c
-#define MC_MIN_LENGTH_ISP2B_0 0x930
-#define MC_MIN_LENGTH_VI2_0 0x944
-#define MC_MIN_LENGTH_DCB_0 0x8a0
-#define MC_MIN_LENGTH_DCB_1 0x8a4
-#define MC_MIN_LENGTH_PPCS_1 0x8f4
-#define MC_MIN_LENGTH_NVJPG_0 0xb3c
-#define MC_MIN_LENGTH_HDA_0 0x8c4
-#define MC_MIN_LENGTH_NVENC_0 0x8d4
-#define MC_MIN_LENGTH_SDMMC_0 0xb18
-#define MC_MIN_LENGTH_ISP2B_1 0x934
-#define MC_MIN_LENGTH_HC_1 0x8c0
-#define MC_MIN_LENGTH_DC_3 0xb20
-#define MC_MIN_LENGTH_AVPC_0 0x890
-#define MC_MIN_LENGTH_VIC_0 0x940
-#define MC_MIN_LENGTH_ISP2_0 0x91c
-#define MC_MIN_LENGTH_HC_0 0x8bc
-#define MC_MIN_LENGTH_SE_0 0xb38
-#define MC_MIN_LENGTH_NVDEC_0 0xb30
-#define MC_MIN_LENGTH_SATA_0 0x8fc
-#define MC_MIN_LENGTH_DC_0 0x894
-#define MC_MIN_LENGTH_XUSB_1 0x92c
-#define MC_MIN_LENGTH_DC_2 0x89c
-#define MC_MIN_LENGTH_SDMMCAA_0 0xb14
-#define MC_MIN_LENGTH_GPU_0 0xb04
-#define MC_MIN_LENGTH_ETR_0 0xb44
-#define MC_MIN_LENGTH_AFI_0 0x88c
-#define MC_MIN_LENGTH_PPCS_0 0x8f0
-#define MC_MIN_LENGTH_ISP2_1 0x920
-#define MC_MIN_LENGTH_XUSB_0 0x928
-#define MC_MIN_LENGTH_MPCORE_0 0x8cc
-#define MC_MIN_LENGTH_TSECB_0 0xb48
-#define MC_MIN_LENGTH_SDMMCA_0 0xb10
-#define MC_MIN_LENGTH_GPU2_0 0xb40
-#define MC_MIN_LENGTH_SDMMCAB_0 0xb1c
-#define MC_MIN_LENGTH_PTC_0 0x8f8
-#define MC_EMEM_ARB_OVERRIDE_1 0x968
-#define MC_VIDEO_PROTECT_GPU_OVERRIDE_0 0x984
-#define MC_VIDEO_PROTECT_GPU_OVERRIDE_1 0x988
-#define MC_EMEM_ARB_STATS_0 0x990
-#define MC_EMEM_ARB_STATS_1 0x994
-#define MC_MTS_CARVEOUT_BOM 0x9a0
-#define MC_MTS_CARVEOUT_SIZE_MB 0x9a4
-#define MC_MTS_CARVEOUT_ADR_HI 0x9a8
-#define MC_MTS_CARVEOUT_REG_CTRL 0x9ac
-#define MC_ERR_MTS_STATUS 0x9b0
-#define MC_ERR_MTS_ADR 0x9b4
-#define MC_ERR_GENERALIZED_CARVEOUT_STATUS 0xc00
-#define MC_ERR_GENERALIZED_CARVEOUT_ADR 0xc04
-#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS2 0xd74
-#define MC_SECURITY_CARVEOUT4_CFG0 0xcf8
-#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2 0xd10
-#define MC_SECURITY_CARVEOUT4_SIZE_128KB 0xd04
-#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4 0xc28
-#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS1 0xc30
-#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4 0xc8c
-#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS0 0xd1c
-#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS1 0xd70
-#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS0 0xc2c
-#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS4 0xd7c
-#define MC_SECURITY_CARVEOUT3_SIZE_128KB 0xcb4
-#define MC_SECURITY_CARVEOUT2_CFG0 0xc58
-#define MC_SECURITY_CARVEOUT1_CFG0 0xc08
-#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2 0xc84
-#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0 0xc68
-#define MC_SECURITY_CARVEOUT3_BOM 0xcac
-#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2 0xc70
-#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS3 0xd78
-#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0 0xc7c
-#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4 0xd18
-#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1 0xcbc
-#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3 0xc38
-#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2 0xc34
-#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2 0xcc0
-#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2 0xd60
-#define MC_SECURITY_CARVEOUT3_CFG0 0xca8
-#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0 0xcb8
-#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3 0xc88
-#define MC_SECURITY_CARVEOUT2_SIZE_128KB 0xc64
-#define MC_SECURITY_CARVEOUT5_BOM_HI 0xd50
-#define MC_SECURITY_CARVEOUT1_SIZE_128KB 0xc14
-#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS3 0xd14
-#define MC_SECURITY_CARVEOUT1_BOM 0xc0c
-#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4 0xd2c
-#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS4 0xd68
-#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4 0xcc8
-#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS0 0xd58
-#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS2 0xd24
-#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3 0xcc4
-#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4 0xc78
-#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1 0xc1c
-#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0 0xc18
-#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3 0xd28
-#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS1 0xd5c
-#define MC_SECURITY_CARVEOUT3_BOM_HI 0xcb0
-#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3 0xcd8
-#define MC_SECURITY_CARVEOUT2_BOM_HI 0xc60
-#define MC_SECURITY_CARVEOUT4_BOM_HI 0xd00
-#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS3 0xd64
-#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4 0xcdc
-#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1 0xc80
-#define MC_SECURITY_CARVEOUT5_SIZE_128KB 0xd54
-#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS1 0xd20
-#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2 0xcd4
-#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS1 0xd0c
-#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3 0xc74
-#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0 0xccc
-#define MC_SECURITY_CARVEOUT4_BOM 0xcfc
-#define MC_SECURITY_CARVEOUT5_CFG0 0xd48
-#define MC_SECURITY_CARVEOUT2_BOM 0xc5c
-#define MC_SECURITY_CARVEOUT5_BOM 0xd4c
-#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3 0xc24
-#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS0 0xd6c
-#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1 0xcd0
-#define MC_SECURITY_CARVEOUT1_BOM_HI 0xc10
-#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2 0xc20
-#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4 0xc3c
-#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1 0xc6c
-#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0 0xd08
-#define MC_ERR_APB_ASID_UPDATE_STATUS 0x9d0
-#define MC_DA_CONFIG0 0x9dc
diff --git a/libraries/libmesosphere/source/kern_debug_log.cpp b/libraries/libmesosphere/source/kern_debug_log.cpp
index 861859b8f..9a14405bd 100644
--- a/libraries/libmesosphere/source/kern_debug_log.cpp
+++ b/libraries/libmesosphere/source/kern_debug_log.cpp
@@ -17,386 +17,9 @@
#include "kern_debug_log_impl.hpp"
namespace ams::kern {
- #pragma GCC push_options
- #pragma GCC optimize ("-Os")
namespace {
- /* Useful definitions for our VSNPrintf implementation. */
- enum FormatSpecifierFlag : u32 {
- FormatSpecifierFlag_None = 0,
- FormatSpecifierFlag_EmptySign = (1 << 0),
- FormatSpecifierFlag_ForceSign = (1 << 1),
- FormatSpecifierFlag_Hash = (1 << 2),
- FormatSpecifierFlag_LeftJustify = (1 << 3),
- FormatSpecifierFlag_ZeroPad = (1 << 4),
- FormatSpecifierFlag_Char = (1 << 5),
- FormatSpecifierFlag_Short = (1 << 6),
- FormatSpecifierFlag_Long = (1 << 7),
- FormatSpecifierFlag_LongLong = (1 << 8),
- FormatSpecifierFlag_Uppercase = (1 << 9),
- FormatSpecifierFlag_HasPrecision = (1 << 10),
- };
-
- using FormatSpecifierFlagStorage = std::underlying_type::type;
-
- constexpr ALWAYS_INLINE bool IsDigit(char c) {
- return '0' <= c && c <= '9';
- }
-
- constexpr ALWAYS_INLINE u32 ParseU32(const char *&str) {
- u32 value = 0;
- do {
- value = (value * 10) + static_cast(*(str++) - '0');
- } while (IsDigit(*str));
- return value;
- }
-
- constexpr ALWAYS_INLINE size_t Strnlen(const char *str, size_t max) {
- const char *cur = str;
- while (*cur && max--) {
- cur++;
- }
- return static_cast(cur - str);
- }
-
- ALWAYS_INLINE void VSNPrintfImpl(char * const dst, const size_t dst_size, const char *format, ::std::va_list vl) {
- size_t dst_index = 0;
-
- auto WriteCharacter = [dst, dst_size, &dst_index](char c) ALWAYS_INLINE_LAMBDA {
- if (dst_index < dst_size) {
- dst[dst_index++] = c;
- }
- };
-
- /* Loop over every character in the string, looking for format specifiers. */
- while (*format) {
- if (const char c = *(format++); c != '%') {
- WriteCharacter(c);
- continue;
- }
-
- /* We have to parse a format specifier. */
- /* Start by parsing flags. */
- FormatSpecifierFlagStorage flags = FormatSpecifierFlag_None;
- auto SetFlag = [&flags](FormatSpecifierFlag f) ALWAYS_INLINE_LAMBDA { flags |= f; };
- auto ClearFlag = [&flags](FormatSpecifierFlag f) ALWAYS_INLINE_LAMBDA { flags &= ~f; };
- auto HasFlag = [&flags](FormatSpecifierFlag f) ALWAYS_INLINE_LAMBDA { return (flags & f) != 0; };
- {
- bool parsed_flags = false;
- while (!parsed_flags) {
- switch (*format) {
- case ' ': SetFlag(FormatSpecifierFlag_EmptySign); format++; break;
- case '+': SetFlag(FormatSpecifierFlag_ForceSign); format++; break;
- case '#': SetFlag(FormatSpecifierFlag_Hash); format++; break;
- case '-': SetFlag(FormatSpecifierFlag_LeftJustify); format++; break;
- case '0': SetFlag(FormatSpecifierFlag_ZeroPad); format++; break;
- default:
- parsed_flags = true;
- break;
- }
- }
- }
-
- /* Next, parse width. */
- u32 width = 0;
- if (IsDigit(*format)) {
- /* Integer width. */
- width = ParseU32(format);
- } else if (*format == '*') {
- /* Dynamic width. */
- const int _width = va_arg(vl, int);
- if (_width >= 0) {
- width = static_cast(_width);
- } else {
- SetFlag(FormatSpecifierFlag_LeftJustify);
- width = static_cast(-_width);
- }
- format++;
- }
-
- /* Next, parse precision if present. */
- u32 precision = 0;
- if (*format == '.') {
- SetFlag(FormatSpecifierFlag_HasPrecision);
- format++;
-
- if (IsDigit(*format)) {
- /* Integer precision. */
- precision = ParseU32(format);
- } else if (*format == '*') {
- /* Dynamic precision. */
- const int _precision = va_arg(vl, int);
- if (_precision > 0) {
- precision = static_cast(_precision);
- }
- format++;
- }
- }
-
- /* Parse length. */
- constexpr bool SizeIsLong = sizeof(size_t) == sizeof(long);
- constexpr bool IntMaxIsLong = sizeof(intmax_t) == sizeof(long);
- constexpr bool PtrDiffIsLong = sizeof(ptrdiff_t) == sizeof(long);
- switch (*format) {
- case 'z':
- SetFlag(SizeIsLong ? FormatSpecifierFlag_Long : FormatSpecifierFlag_LongLong);
- format++;
- break;
- case 'j':
- SetFlag(IntMaxIsLong ? FormatSpecifierFlag_Long : FormatSpecifierFlag_LongLong);
- format++;
- break;
- case 't':
- SetFlag(PtrDiffIsLong ? FormatSpecifierFlag_Long : FormatSpecifierFlag_LongLong);
- format++;
- break;
- case 'h':
- SetFlag(FormatSpecifierFlag_Short);
- format++;
- if (*format == 'h') {
- SetFlag(FormatSpecifierFlag_Char);
- format++;
- }
- break;
- case 'l':
- SetFlag(FormatSpecifierFlag_Long);
- format++;
- if (*format == 'l') {
- SetFlag(FormatSpecifierFlag_LongLong);
- format++;
- }
- break;
- default:
- break;
- }
-
- const char specifier = *(format++);
- switch (specifier) {
- case 'p':
- if constexpr (sizeof(uintptr_t) == sizeof(long long)) {
- SetFlag(FormatSpecifierFlag_LongLong);
- } else {
- SetFlag(FormatSpecifierFlag_Long);
- }
- SetFlag(FormatSpecifierFlag_Hash);
- [[fallthrough]];
- case 'd':
- case 'i':
- case 'u':
- case 'b':
- case 'o':
- case 'x':
- case 'X':
- {
- /* Determine the base to print with. */
- u32 base;
- switch (specifier) {
- case 'b':
- base = 2;
- break;
- case 'o':
- base = 8;
- break;
- case 'X':
- SetFlag(FormatSpecifierFlag_Uppercase);
- [[fallthrough]];
- case 'p':
- case 'x':
- base = 16;
- break;
- default:
- base = 10;
- ClearFlag(FormatSpecifierFlag_Hash);
- break;
- }
-
- /* Precision implies no zero-padding. */
- if (HasFlag(FormatSpecifierFlag_HasPrecision)) {
- ClearFlag(FormatSpecifierFlag_ZeroPad);
- }
-
- /* Unsigned types don't get signs. */
- const bool is_unsigned = base != 10 || specifier == 'u';
- if (is_unsigned) {
- ClearFlag(FormatSpecifierFlag_EmptySign);
- ClearFlag(FormatSpecifierFlag_ForceSign);
- }
-
- auto PrintInteger = [&](bool negative, uintmax_t value) {
- constexpr size_t BufferSize = 64; /* Binary digits for 64-bit numbers may use 64 digits. */
- char buf[BufferSize];
- size_t len = 0;
-
- /* No hash flag for zero. */
- if (value == 0) {
- ClearFlag(FormatSpecifierFlag_Hash);
- }
-
- if (!HasFlag(FormatSpecifierFlag_HasPrecision) || value != 0) {
- do {
- const char digit = static_cast(value % base);
- buf[len++] = (digit < 10) ? ('0' + digit) : ((HasFlag(FormatSpecifierFlag_Uppercase) ? 'A' : 'a') + digit - 10);
- value /= base;
- } while (value);
- }
-
- /* Determine our prefix length. */
- size_t prefix_len = 0;
- const bool has_sign = negative || HasFlag(FormatSpecifierFlag_ForceSign) || HasFlag(FormatSpecifierFlag_EmptySign);
- if (has_sign) {
- prefix_len++;
- }
- if (HasFlag(FormatSpecifierFlag_Hash)) {
- prefix_len += (base != 8) ? 2 : 1;
- }
-
- /* Determine zero-padding count. */
- size_t num_zeroes = (len < precision) ? precision - len : 0;
- if (!HasFlag(FormatSpecifierFlag_LeftJustify) && HasFlag(FormatSpecifierFlag_ZeroPad)) {
- num_zeroes = (len + prefix_len < width) ? width - len - prefix_len : 0;
- }
-
- /* Print out left padding. */
- if (!HasFlag(FormatSpecifierFlag_LeftJustify)) {
- for (size_t i = len + prefix_len + num_zeroes; i < static_cast(width); i++) {
- WriteCharacter(' ');
- }
- }
-
- /* Print out sign. */
- if (negative) {
- WriteCharacter('-');
- } else if (HasFlag(FormatSpecifierFlag_ForceSign)) {
- WriteCharacter('+');
- } else if (HasFlag(FormatSpecifierFlag_EmptySign)) {
- WriteCharacter(' ');
- }
-
- /* Print out base prefix. */
- if (HasFlag(FormatSpecifierFlag_Hash)) {
- WriteCharacter('0');
- if (base == 2) {
- WriteCharacter('b');
- } else if (base == 16) {
- WriteCharacter('x');
- }
- }
-
- /* Print out zeroes. */
- for (size_t i = 0; i < num_zeroes; i++) {
- WriteCharacter('0');
- }
-
- /* Print out digits. */
- for (size_t i = 0; i < len; i++) {
- WriteCharacter(buf[len - 1 - i]);
- }
-
- /* Print out right padding. */
- if (HasFlag(FormatSpecifierFlag_LeftJustify)) {
- for (size_t i = len + prefix_len + num_zeroes; i < static_cast(width); i++) {
- WriteCharacter(' ');
- }
- }
- };
-
- /* Output the integer. */
- if (is_unsigned) {
- uintmax_t n = 0;
- if (HasFlag(FormatSpecifierFlag_LongLong)) {
- n = static_cast(va_arg(vl, unsigned long long));
- } else if (HasFlag(FormatSpecifierFlag_Long)) {
- n = static_cast(va_arg(vl, unsigned long));
- } else if (HasFlag(FormatSpecifierFlag_Char)) {
- n = static_cast(va_arg(vl, unsigned int));
- } else if (HasFlag(FormatSpecifierFlag_Short)) {
- n = static_cast(va_arg(vl, unsigned int));
- } else {
- n = static_cast(va_arg(vl, unsigned int));
- }
- if (specifier == 'p' && n == 0) {
- WriteCharacter('(');
- WriteCharacter('n');
- WriteCharacter('i');
- WriteCharacter('l');
- WriteCharacter(')');
- } else {
- PrintInteger(false, n);
- }
- } else {
- intmax_t n = 0;
- if (HasFlag(FormatSpecifierFlag_LongLong)) {
- n = static_cast(va_arg(vl, signed long long));
- } else if (HasFlag(FormatSpecifierFlag_Long)) {
- n = static_cast(va_arg(vl, signed long));
- } else if (HasFlag(FormatSpecifierFlag_Char)) {
- n = static_cast(va_arg(vl, signed int));
- } else if (HasFlag(FormatSpecifierFlag_Short)) {
- n = static_cast(va_arg(vl, signed int));
- } else {
- n = static_cast(va_arg(vl, signed int));
- }
- const bool negative = n < 0;
- const uintmax_t u = (negative) ? static_cast(-n) : static_cast(n);
- PrintInteger(negative, u);
- }
- }
- break;
- case 'c':
- {
- size_t len = 1;
- if (!HasFlag(FormatSpecifierFlag_LeftJustify)) {
- while (len++ < width) {
- WriteCharacter(' ');
- }
- }
- WriteCharacter(static_cast(va_arg(vl, int)));
- if (HasFlag(FormatSpecifierFlag_LeftJustify)) {
- while (len++ < width) {
- WriteCharacter(' ');
- }
- }
- }
- break;
- case 's':
- {
- const char *str = va_arg(vl, char *);
- if (str == nullptr) {
- str = "(null)";
- }
-
- size_t len = Strnlen(str, precision > 0 ? precision : std::numeric_limits::max());
- if (HasFlag(FormatSpecifierFlag_HasPrecision)) {
- len = (len < precision) ? len : precision;
- }
- if (!HasFlag(FormatSpecifierFlag_LeftJustify)) {
- while (len++ < width) {
- WriteCharacter(' ');
- }
- }
- while (*str && (!HasFlag(FormatSpecifierFlag_HasPrecision) || (precision--) != 0)) {
- WriteCharacter(*(str++));
- }
- if (HasFlag(FormatSpecifierFlag_LeftJustify)) {
- while (len++ < width) {
- WriteCharacter(' ');
- }
- }
- }
- break;
- case '%':
- default:
- WriteCharacter(specifier);
- break;
- }
- }
-
- /* Ensure null termination. */
- WriteCharacter('\0');
- dst[dst_size - 1] = '\0';
- }
-
KSpinLock g_debug_log_lock;
bool g_initialized_impl;
@@ -452,9 +75,6 @@ namespace ams::kern {
}
-
- #pragma GCC pop_options
-
void KDebugLog::Initialize() {
if (KTargetSystem::IsDebugLoggingEnabled()) {
KScopedInterruptDisable di;
@@ -486,7 +106,7 @@ namespace ams::kern {
}
void KDebugLog::VSNPrintf(char *dst, const size_t dst_size, const char *format, ::std::va_list vl) {
- VSNPrintfImpl(dst, dst_size, format, vl);
+ ::ams::util::TVSNPrintf(dst, dst_size, format, vl);
}
Result KDebugLog::PrintUserString(ams::kern::svc::KUserPointer user_str, size_t len) {
diff --git a/libraries/libstratosphere/include/stratosphere.hpp b/libraries/libstratosphere/include/stratosphere.hpp
index 9fffefa9f..6096ca240 100644
--- a/libraries/libstratosphere/include/stratosphere.hpp
+++ b/libraries/libstratosphere/include/stratosphere.hpp
@@ -47,6 +47,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -60,7 +61,6 @@
#include
#include
#include
-#include
#include
#include
#include
diff --git a/libraries/libstratosphere/include/stratosphere/ams/impl/ams_system_thread_definitions.hpp b/libraries/libstratosphere/include/stratosphere/ams/impl/ams_system_thread_definitions.hpp
index 7d60ab72d..837598518 100644
--- a/libraries/libstratosphere/include/stratosphere/ams/impl/ams_system_thread_definitions.hpp
+++ b/libraries/libstratosphere/include/stratosphere/ams/impl/ams_system_thread_definitions.hpp
@@ -39,19 +39,21 @@ namespace ams::impl {
AMS_DEFINE_SYSTEM_THREAD(21, pm, Main);
AMS_DEFINE_SYSTEM_THREAD(21, pm, ProcessTrack);
+
/* NCM. */
AMS_DEFINE_SYSTEM_THREAD(21, ncm, MainWaitThreads);
AMS_DEFINE_SYSTEM_THREAD(21, ncm, ContentManagerServerIpcSession);
AMS_DEFINE_SYSTEM_THREAD(21, ncm, LocationResolverServerIpcSession);
/* FS. */
- AMS_DEFINE_SYSTEM_THREAD(16, fs, WorkerThreadPool);
- AMS_DEFINE_SYSTEM_THREAD(17, fs, Main);
- AMS_DEFINE_SYSTEM_THREAD(17, fs, WorkerRealTimeAccess);
- AMS_DEFINE_SYSTEM_THREAD(18, fs, WorkerNormalPriorityAccess);
- AMS_DEFINE_SYSTEM_THREAD(19, fs, WorkerLowPriorityAccess);
- AMS_DEFINE_SYSTEM_THREAD(30, fs, WorkerBackgroundAccess);
- AMS_DEFINE_SYSTEM_THREAD(30, fs, PatrolReader);
+ AMS_DEFINE_SYSTEM_THREAD(11, sdmmc, DeviceDetector);
+ AMS_DEFINE_SYSTEM_THREAD(16, fs, WorkerThreadPool);
+ AMS_DEFINE_SYSTEM_THREAD(17, fs, Main);
+ AMS_DEFINE_SYSTEM_THREAD(17, fs, WorkerRealTimeAccess);
+ AMS_DEFINE_SYSTEM_THREAD(18, fs, WorkerNormalPriorityAccess);
+ AMS_DEFINE_SYSTEM_THREAD(19, fs, WorkerLowPriorityAccess);
+ AMS_DEFINE_SYSTEM_THREAD(30, fs, WorkerBackgroundAccess);
+ AMS_DEFINE_SYSTEM_THREAD(30, fs, PatrolReader);
/* Boot. */
AMS_DEFINE_SYSTEM_THREAD(-1, boot, Main);
diff --git a/libraries/libstratosphere/include/stratosphere/dd/dd_io_mappings.hpp b/libraries/libstratosphere/include/stratosphere/dd/dd_io_mappings.hpp
index 4cd493b28..c0f3ac992 100644
--- a/libraries/libstratosphere/include/stratosphere/dd/dd_io_mappings.hpp
+++ b/libraries/libstratosphere/include/stratosphere/dd/dd_io_mappings.hpp
@@ -19,16 +19,13 @@
namespace ams::dd {
- uintptr_t QueryIoMapping(uintptr_t phys_addr, size_t size);
-
- u32 ReadRegister(uintptr_t phys_addr);
- void WriteRegister(uintptr_t phys_addr, u32 value);
- u32 ReadWriteRegister(uintptr_t phys_addr, u32 value, u32 mask);
+ u32 ReadRegister(dd::PhysicalAddress phys_addr);
+ void WriteRegister(dd::PhysicalAddress phys_addr, u32 value);
+ u32 ReadWriteRegister(dd::PhysicalAddress phys_addr, u32 value, u32 mask);
/* Convenience Helper. */
-
- inline uintptr_t GetIoMapping(uintptr_t phys_addr, size_t size) {
- const uintptr_t io_mapping = QueryIoMapping(phys_addr, size);
+ inline uintptr_t GetIoMapping(dd::PhysicalAddress phys_addr, size_t size) {
+ const uintptr_t io_mapping = dd::QueryIoMapping(phys_addr, size);
AMS_ABORT_UNLESS(io_mapping);
return io_mapping;
}
diff --git a/libraries/libmesosphere/source/board/nintendo/nx/kern_evp_registers.hpp b/libraries/libstratosphere/include/stratosphere/ddsf.hpp
similarity index 92%
rename from libraries/libmesosphere/source/board/nintendo/nx/kern_evp_registers.hpp
rename to libraries/libstratosphere/include/stratosphere/ddsf.hpp
index 5f7bdf084..000a4aedd 100644
--- a/libraries/libmesosphere/source/board/nintendo/nx/kern_evp_registers.hpp
+++ b/libraries/libstratosphere/include/stratosphere/ddsf.hpp
@@ -2,7 +2,7 @@
* 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
+ * 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
@@ -13,6 +13,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
+
#pragma once
-#define EVP_COP_RESET_VECTOR 0x200
+#include
diff --git a/libraries/libstratosphere/include/stratosphere/ddsf/ddsf_types.hpp b/libraries/libstratosphere/include/stratosphere/ddsf/ddsf_types.hpp
new file mode 100644
index 000000000..467c48dbe
--- /dev/null
+++ b/libraries/libstratosphere/include/stratosphere/ddsf/ddsf_types.hpp
@@ -0,0 +1,30 @@
+/*
+ * 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 .
+ */
+
+#pragma once
+#include
+
+namespace ams::ddsf {
+
+ enum AccessMode {
+ AccessMode_None = (0u << 0),
+ AccessMode_Read = (1u << 0),
+ AccessMode_Write = (1u << 1),
+
+ AccessMode_ReadWrite = AccessMode_Read | AccessMode_Write,
+ };
+
+}
diff --git a/libraries/libstratosphere/include/stratosphere/gpio.hpp b/libraries/libstratosphere/include/stratosphere/gpio.hpp
new file mode 100644
index 000000000..02175345f
--- /dev/null
+++ b/libraries/libstratosphere/include/stratosphere/gpio.hpp
@@ -0,0 +1,22 @@
+/*
+ * 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 .
+ */
+
+#pragma once
+#include
+#include
+#include
+#include
+#include
diff --git a/libraries/libmesosphere/source/board/nintendo/nx/kern_pmc_registers.hpp b/libraries/libstratosphere/include/stratosphere/gpio/gpio_api.hpp
similarity index 81%
rename from libraries/libmesosphere/source/board/nintendo/nx/kern_pmc_registers.hpp
rename to libraries/libstratosphere/include/stratosphere/gpio/gpio_api.hpp
index 2ed4d670f..a58c8b21c 100644
--- a/libraries/libmesosphere/source/board/nintendo/nx/kern_pmc_registers.hpp
+++ b/libraries/libstratosphere/include/stratosphere/gpio/gpio_api.hpp
@@ -2,7 +2,7 @@
* 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
+ * 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
@@ -14,8 +14,12 @@
* along with this program. If not, see .
*/
#pragma once
+#include
+#include
-#define APBDEV_PMC_DPD_ENABLE 0x024
-#define APBDEV_PMC_SCRATCH0 0x050
-#define APBDEV_PMC_SCRATCH4 0x060
-#define APBDEV_PMC_SCRATCH39 0x138
+namespace ams::gpio {
+
+ void Initialize();
+ void Finalize();
+
+}
diff --git a/libraries/libstratosphere/include/stratosphere/gpio/gpio_pad_api.hpp b/libraries/libstratosphere/include/stratosphere/gpio/gpio_pad_api.hpp
new file mode 100644
index 000000000..a02d34884
--- /dev/null
+++ b/libraries/libstratosphere/include/stratosphere/gpio/gpio_pad_api.hpp
@@ -0,0 +1,58 @@
+/*
+ * 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 .
+ */
+#pragma once
+#include
+#include
+#include
+#include
+
+namespace ams::gpio {
+
+ struct GpioPadSession {
+ void *_session;
+ os::SystemEventType *_event;
+ };
+
+ Result OpenSession(GpioPadSession *out_session, ams::DeviceCode device_code);
+ void CloseSession(GpioPadSession *session);
+
+ Direction GetDirection(GpioPadSession *session);
+ void SetDirection(GpioPadSession *session, Direction direction);
+
+ GpioValue GetValue(GpioPadSession *session);
+ void SetValue(GpioPadSession *session, GpioValue value);
+
+ InterruptMode GetInterruptMode(GpioPadSession *session);
+ void SetInterruptMode(GpioPadSession *session, InterruptMode mode);
+
+ bool GetInterruptEnable(GpioPadSession *session);
+ void SetInterruptEnable(GpioPadSession *session, bool en);
+
+ InterruptStatus GetInterruptStatus(GpioPadSession *session);
+ void ClearInterruptStatus(GpioPadSession *session);
+
+ int GetDebounceTime(GpioPadSession *session);
+ void SetDebounceTime(GpioPadSession *session, int ms);
+
+ bool GetDebounceEnabled(GpioPadSession *session);
+ void SetDebounceEnabled(GpioPadSession *session, bool en);
+
+ Result BindInterrupt(os::SystemEventType *event, GpioPadSession *session);
+ void UnbindInterrupt(GpioPadSession *session);
+
+ Result IsWakeEventActive(bool *out_is_active, ams::DeviceCode device_code);
+
+}
diff --git a/libraries/libstratosphere/include/stratosphere/gpio/gpio_pad_name.board.nintendo_nx.hpp b/libraries/libstratosphere/include/stratosphere/gpio/gpio_pad_name.board.nintendo_nx.hpp
new file mode 100644
index 000000000..c1c816c95
--- /dev/null
+++ b/libraries/libstratosphere/include/stratosphere/gpio/gpio_pad_name.board.nintendo_nx.hpp
@@ -0,0 +1,55 @@
+/*
+ * 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 .
+ */
+#pragma once
+#include
+#include
+
+namespace ams::gpio {
+
+ enum GpioPadName : u32 {
+ GpioPadName_CodecLdoEnTemp = 1,
+ GpioPadName_ButtonVolUp = 25,
+ GpioPadName_ButtonVolDn = 26,
+ GpioPadName_SdCd = 56,
+ };
+
+ /* TODO: Better place for this? */
+ constexpr inline const DeviceCode DeviceCode_CodecLdoEnTemp = 0x33000002;
+ constexpr inline const DeviceCode DeviceCode_ButtonVolUp = 0x35000002;
+ constexpr inline const DeviceCode DeviceCode_ButtonVolDn = 0x35000003;
+ constexpr inline const DeviceCode DeviceCode_SdCd = 0x3C000002;
+
+ constexpr inline GpioPadName ConvertToGpioPadName(DeviceCode dc) {
+ switch (dc.GetInternalValue()) {
+ case DeviceCode_CodecLdoEnTemp.GetInternalValue(): return GpioPadName_CodecLdoEnTemp;
+ case DeviceCode_ButtonVolUp .GetInternalValue(): return GpioPadName_ButtonVolUp;
+ case DeviceCode_ButtonVolDn .GetInternalValue(): return GpioPadName_ButtonVolDn;
+ case DeviceCode_SdCd .GetInternalValue(): return GpioPadName_SdCd;
+ AMS_UNREACHABLE_DEFAULT_CASE();
+ }
+ }
+
+ constexpr inline DeviceCode ConvertToDeviceCode(GpioPadName gpn) {
+ switch (gpn) {
+ case GpioPadName_CodecLdoEnTemp: return DeviceCode_CodecLdoEnTemp;
+ case GpioPadName_ButtonVolUp: return DeviceCode_ButtonVolUp;
+ case GpioPadName_ButtonVolDn: return DeviceCode_ButtonVolDn;
+ case GpioPadName_SdCd: return DeviceCode_SdCd;
+ AMS_UNREACHABLE_DEFAULT_CASE();
+ }
+ }
+
+}
diff --git a/libraries/libstratosphere/include/stratosphere/gpio/gpio_select_pad_name.hpp b/libraries/libstratosphere/include/stratosphere/gpio/gpio_select_pad_name.hpp
new file mode 100644
index 000000000..25e665375
--- /dev/null
+++ b/libraries/libstratosphere/include/stratosphere/gpio/gpio_select_pad_name.hpp
@@ -0,0 +1,24 @@
+/*
+ * 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 .
+ */
+#pragma once
+#include
+#include
+
+#if defined(ATMOSPHERE_BOARD_NINTENDO_NX)
+ #include
+#else
+ /* Error? */
+#endif
diff --git a/libraries/libstratosphere/include/stratosphere/gpio/gpio_types.hpp b/libraries/libstratosphere/include/stratosphere/gpio/gpio_types.hpp
new file mode 100644
index 000000000..8d456c547
--- /dev/null
+++ b/libraries/libstratosphere/include/stratosphere/gpio/gpio_types.hpp
@@ -0,0 +1,46 @@
+/*
+ * 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 .
+ */
+#pragma once
+#include
+
+namespace ams::gpio {
+
+ enum InterruptMode : u32 {
+ InterruptMode_LowLevel = 0,
+ InterruptMode_HighLevel = 1,
+ InterruptMode_RisingEdge = 2,
+ InterruptMode_FallingEdge = 3,
+ InterruptMode_AnyEdge = 4,
+ };
+
+ enum Direction : u32 {
+ Direction_Input = 0,
+ Direction_Output = 1,
+ };
+
+ enum GpioValue : u32 {
+ GpioValue_Low = 0,
+ GpioValue_High = 1,
+ };
+
+ enum InterruptStatus : u32 {
+ InterruptStatus_Inactive = 0,
+ InterruptStatus_Active = 1,
+ };
+
+ using WakeBitFlag = util::BitFlagSet<128>;
+
+}
diff --git a/libraries/libstratosphere/include/stratosphere/gpio/sf/gpio_sf_i_manager.hpp b/libraries/libstratosphere/include/stratosphere/gpio/sf/gpio_sf_i_manager.hpp
new file mode 100644
index 000000000..e54dc7b1b
--- /dev/null
+++ b/libraries/libstratosphere/include/stratosphere/gpio/sf/gpio_sf_i_manager.hpp
@@ -0,0 +1,41 @@
+/*
+ * 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 .
+ */
+
+#pragma once
+#include
+#include
+#include
+#include
+#include
+
+namespace ams::gpio::sf {
+
+ #define AMS_GPIO_I_MANAGER_INTERFACE_INFO(C, H) \
+ AMS_SF_METHOD_INFO(C, H, 0, Result, OpenSessionForDev, (ams::sf::Out> out, s32 pad_descriptor) ) \
+ AMS_SF_METHOD_INFO(C, H, 1, Result, OpenSession, (ams::sf::Out> out, gpio::GpioPadName pad_name) ) \
+ AMS_SF_METHOD_INFO(C, H, 2, Result, OpenSessionForTest, (ams::sf::Out> out, gpio::GpioPadName pad_name) ) \
+ AMS_SF_METHOD_INFO(C, H, 3, Result, IsWakeEventActive, (ams::sf::Out out, gpio::GpioPadName pad_name), hos::Version_Min, hos::Version_6_2_0) \
+ AMS_SF_METHOD_INFO(C, H, 4, Result, GetWakeEventActiveFlagSet, (ams::sf::Out out), hos::Version_Min, hos::Version_6_2_0) \
+ AMS_SF_METHOD_INFO(C, H, 5, Result, SetWakeEventActiveFlagSetForDebug, (gpio::GpioPadName pad_name, bool is_enabled), hos::Version_Min, hos::Version_6_2_0) \
+ AMS_SF_METHOD_INFO(C, H, 6, Result, SetWakePinDebugMode, (s32 mode) ) \
+ AMS_SF_METHOD_INFO(C, H, 7, Result, OpenSession2, (ams::sf::Out> out, DeviceCode device_code, ddsf::AccessMode access_mode), hos::Version_5_0_0 ) \
+ AMS_SF_METHOD_INFO(C, H, 8, Result, IsWakeEventActive2, (ams::sf::Out out, DeviceCode device_code), hos::Version_5_0_0 ) \
+ AMS_SF_METHOD_INFO(C, H, 9, Result, SetWakeEventActiveFlagSetForDebug2, (DeviceCode device_code, bool is_enabled), hos::Version_5_0_0 ) \
+ AMS_SF_METHOD_INFO(C, H, 10, Result, SetRetryValues, (u32 arg0, u32 arg1), hos::Version_6_0_0 )
+
+ AMS_SF_DEFINE_INTERFACE(IManager, AMS_GPIO_I_MANAGER_INTERFACE_INFO)
+
+}
diff --git a/libraries/libstratosphere/include/stratosphere/gpio/sf/gpio_sf_i_pad_session.hpp b/libraries/libstratosphere/include/stratosphere/gpio/sf/gpio_sf_i_pad_session.hpp
new file mode 100644
index 000000000..ec4791b1b
--- /dev/null
+++ b/libraries/libstratosphere/include/stratosphere/gpio/sf/gpio_sf_i_pad_session.hpp
@@ -0,0 +1,45 @@
+/*
+ * 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 .
+ */
+
+#pragma once
+#include
+#include
+
+namespace ams::gpio::sf {
+
+ #define AMS_GPIO_I_PAD_SESSION_INTERFACE_INFO(C, H) \
+ AMS_SF_METHOD_INFO(C, H, 0, Result, SetDirection, (gpio::Direction direction) ) \
+ AMS_SF_METHOD_INFO(C, H, 1, Result, GetDirection, (ams::sf::Out out) ) \
+ AMS_SF_METHOD_INFO(C, H, 2, Result, SetInterruptMode, (gpio::InterruptMode mode) ) \
+ AMS_SF_METHOD_INFO(C, H, 3, Result, GetInterruptMode, (ams::sf::Out out) ) \
+ AMS_SF_METHOD_INFO(C, H, 4, Result, SetInterruptEnable, (bool enable) ) \
+ AMS_SF_METHOD_INFO(C, H, 5, Result, GetInterruptEnable, (ams::sf::Out out) ) \
+ AMS_SF_METHOD_INFO(C, H, 6, Result, GetInterruptStatus, (ams::sf::Out out) ) \
+ AMS_SF_METHOD_INFO(C, H, 7, Result, ClearInterruptStatus, () ) \
+ AMS_SF_METHOD_INFO(C, H, 8, Result, SetValue, (gpio::GpioValue value) ) \
+ AMS_SF_METHOD_INFO(C, H, 9, Result, GetValue, (ams::sf::Out out) ) \
+ AMS_SF_METHOD_INFO(C, H, 10, Result, BindInterrupt, (ams::sf::OutCopyHandle out) ) \
+ AMS_SF_METHOD_INFO(C, H, 11, Result, UnbindInterrupt, () ) \
+ AMS_SF_METHOD_INFO(C, H, 12, Result, SetDebounceEnabled, (bool enable) ) \
+ AMS_SF_METHOD_INFO(C, H, 13, Result, GetDebounceEnabled, (ams::sf::Out out) ) \
+ AMS_SF_METHOD_INFO(C, H, 14, Result, SetDebounceTime, (s32 ms) ) \
+ AMS_SF_METHOD_INFO(C, H, 15, Result, GetDebounceTime, (ams::sf::Out out) ) \
+ AMS_SF_METHOD_INFO(C, H, 16, Result, SetValueForSleepState, (gpio::GpioValue value), hos::Version_4_0_0) \
+ AMS_SF_METHOD_INFO(C, H, 16, Result, GetValueForSleepState, (ams::sf::Out out), hos::Version_6_0_0)
+
+ AMS_SF_DEFINE_INTERFACE(IPadSession, AMS_GPIO_I_PAD_SESSION_INTERFACE_INFO)
+
+}
diff --git a/libraries/libstratosphere/include/stratosphere/reg.hpp b/libraries/libstratosphere/include/stratosphere/reg.hpp
deleted file mode 100644
index 6b5076f93..000000000
--- a/libraries/libstratosphere/include/stratosphere/reg.hpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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 .
- */
-
-#pragma once
-#include
-
-namespace ams::reg {
-
- inline void Write(volatile u32 *reg, u32 val) {
- *reg = val;
- }
-
- inline void Write(uintptr_t reg, u32 val) {
- Write(reinterpret_cast(reg), val);
- }
-
- inline u32 Read(volatile u32 *reg) {
- return *reg;
- }
-
- inline u32 Read(uintptr_t reg) {
- return Read(reinterpret_cast(reg));
- }
-
- inline void SetBits(volatile u32 *reg, u32 mask) {
- *reg = *reg | mask;
- }
-
- inline void SetBits(uintptr_t reg, u32 mask) {
- SetBits(reinterpret_cast(reg), mask);
- }
-
- inline void ClearBits(volatile u32 *reg, u32 mask) {
- *reg = *reg & ~mask;
- }
-
- inline void ClearBits(uintptr_t reg, u32 mask) {
- ClearBits(reinterpret_cast(reg), mask);
- }
-
- inline void MaskBits(volatile u32 *reg, u32 mask) {
- *reg = *reg & mask;
- }
-
- inline void MaskBits(uintptr_t reg, u32 mask) {
- MaskBits(reinterpret_cast(reg), mask);
- }
-
- inline void ReadWrite(volatile u32 *reg, u32 val, u32 mask) {
- *reg = (*reg & (~mask)) | (val & mask);
- }
-
- inline void ReadWrite(uintptr_t reg, u32 val, u32 mask) {
- ReadWrite(reinterpret_cast(reg), val, mask);
- }
-
-}
\ No newline at end of file
diff --git a/libraries/libstratosphere/source/boot2/boot2_api.cpp b/libraries/libstratosphere/source/boot2/boot2_api.cpp
index c2c050f39..4f4cda01a 100644
--- a/libraries/libstratosphere/source/boot2/boot2_api.cpp
+++ b/libraries/libstratosphere/source/boot2/boot2_api.cpp
@@ -167,20 +167,19 @@ namespace ams::boot2 {
}
}
- bool GetGpioPadLow(GpioPadName pad) {
- GpioPadSession button;
- if (R_FAILED(gpioOpenSession(&button, pad))) {
+ bool GetGpioPadLow(DeviceCode device_code) {
+ gpio::GpioPadSession button;
+ if (R_FAILED(gpio::OpenSession(std::addressof(button), device_code))) {
return false;
}
/* Ensure we close even on early return. */
- ON_SCOPE_EXIT { gpioPadClose(&button); };
+ ON_SCOPE_EXIT { gpio::CloseSession(std::addressof(button)); };
/* Set direction input. */
- gpioPadSetDirection(&button, GpioDirection_Input);
+ gpio::SetDirection(std::addressof(button), gpio::Direction_Input);
- GpioValue val;
- return R_SUCCEEDED(gpioPadGetValue(&button, &val)) && val == GpioValue_Low;
+ return gpio::GetValue(std::addressof(button)) == gpio::GpioValue_Low;
}
bool IsForceMaintenance() {
@@ -197,7 +196,7 @@ namespace ams::boot2 {
/* Contact GPIO, read plus/minus buttons. */
{
- return GetGpioPadLow(GpioPadName_ButtonVolUp) && GetGpioPadLow(GpioPadName_ButtonVolDown);
+ return GetGpioPadLow(gpio::DeviceCode_ButtonVolUp) && GetGpioPadLow(gpio::DeviceCode_ButtonVolDn);
}
}
diff --git a/libraries/libstratosphere/source/dd/dd_io_mappings.cpp b/libraries/libstratosphere/source/dd/dd_io_mappings.cpp
deleted file mode 100644
index 8bc84442c..000000000
--- a/libraries/libstratosphere/source/dd/dd_io_mappings.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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 .
- */
-#include
-
-namespace ams::dd {
-
- uintptr_t QueryIoMapping(uintptr_t phys_addr, size_t size) {
- u64 virtual_addr;
- const u64 aligned_addr = util::AlignDown(phys_addr, os::MemoryPageSize);
- const size_t offset = phys_addr - aligned_addr;
- const u64 aligned_size = size + offset;
- if (hos::GetVersion() >= hos::Version_10_0_0) {
- u64 region_size;
- R_TRY_CATCH(svcQueryIoMapping(&virtual_addr, ®ion_size, aligned_addr, aligned_size)) {
- /* Official software handles this by returning 0. */
- R_CATCH(svc::ResultNotFound) { return 0; }
- } R_END_TRY_CATCH_WITH_ABORT_UNLESS;
- AMS_ASSERT(region_size >= aligned_size);
- } else {
- R_TRY_CATCH(svcLegacyQueryIoMapping(&virtual_addr, aligned_addr, aligned_size)) {
- /* Official software handles this by returning 0. */
- R_CATCH(svc::ResultNotFound) { return 0; }
- } R_END_TRY_CATCH_WITH_ABORT_UNLESS;
- }
-
- return static_cast(virtual_addr + offset);
- }
-
- namespace {
-
- inline u32 ReadWriteRegisterImpl(uintptr_t phys_addr, u32 value, u32 mask) {
- u32 out_value;
- R_ABORT_UNLESS(svcReadWriteRegister(&out_value, phys_addr, mask, value));
- return out_value;
- }
-
- }
-
- u32 ReadRegister(uintptr_t phys_addr) {
- return ReadWriteRegisterImpl(phys_addr, 0, 0);
- }
-
- void WriteRegister(uintptr_t phys_addr, u32 value) {
- ReadWriteRegisterImpl(phys_addr, value, ~u32());
- }
-
- u32 ReadWriteRegister(uintptr_t phys_addr, u32 value, u32 mask) {
- return ReadWriteRegisterImpl(phys_addr, value, mask);
- }
-
-}
diff --git a/libraries/libstratosphere/source/gpio/gpio_client_api.cpp b/libraries/libstratosphere/source/gpio/gpio_client_api.cpp
new file mode 100644
index 000000000..c5d88023b
--- /dev/null
+++ b/libraries/libstratosphere/source/gpio/gpio_client_api.cpp
@@ -0,0 +1,197 @@
+/*
+ * 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 .
+ */
+#include
+#include "gpio_remote_manager_impl.hpp"
+
+namespace ams::gpio {
+
+ namespace {
+
+ /* TODO: Manager object. */
+ constinit os::SdkMutex g_init_mutex;
+ constinit int g_initialize_count = 0;
+ std::shared_ptr g_manager;
+
+ using InternalSession = std::shared_ptr;
+
+ InternalSession &GetInterface(GpioPadSession *session) {
+ AMS_ASSERT(session->_session != nullptr);
+ return *static_cast(session->_session);
+ }
+
+ }
+
+ void Initialize() {
+ std::scoped_lock lk(g_init_mutex);
+
+ if ((g_initialize_count++) == 0) {
+ R_ABORT_UNLESS(::gpioInitialize());
+ g_manager = ams::sf::MakeShared();
+ }
+ }
+
+ void Finalize() {
+ std::scoped_lock lk(g_init_mutex);
+
+ AMS_ASSERT(g_initialize_count > 0);
+
+ if ((--g_initialize_count) == 0) {
+ g_manager.reset();
+ ::gpioExit();
+ }
+ }
+
+ Result OpenSession(GpioPadSession *out_session, ams::DeviceCode device_code) {
+ /* Allocate the session. */
+ InternalSession *internal_session = new (std::nothrow) InternalSession;
+ AMS_ABORT_UNLESS(internal_session != nullptr);
+ auto session_guard = SCOPE_GUARD { delete internal_session; };
+
+ /* Get the session. */
+ {
+ ams::sf::cmif::ServiceObjectHolder object_holder;
+ if (hos::GetVersion() >= hos::Version_7_0_0) {
+ R_TRY(g_manager->OpenSession2(std::addressof(object_holder), device_code, ddsf::AccessMode_ReadWrite));
+ } else {
+ R_TRY(g_manager->OpenSession(std::addressof(object_holder), ConvertToGpioPadName(device_code)));
+ }
+ *internal_session = object_holder.GetServiceObject();
+ }
+
+ /* Set output. */
+ out_session->_session = internal_session;
+ out_session->_event = nullptr;
+
+ /* We succeeded. */
+ session_guard.Cancel();
+ return ResultSuccess();
+ }
+
+ void CloseSession(GpioPadSession *session) {
+ AMS_ASSERT(session != nullptr);
+
+ /* Unbind the interrupt, if it's still bound. */
+ if (session->_event != nullptr) {
+ gpio::UnbindInterrupt(session);
+ }
+
+ /* Close the session. */
+ delete std::addressof(GetInterface(session));
+ session->_session = nullptr;
+ }
+
+ Result IsWakeEventActive(bool *out_is_active, ams::DeviceCode device_code) {
+ if (hos::GetVersion() >= hos::Version_7_0_0) {
+ R_TRY(g_manager->IsWakeEventActive2(out_is_active, device_code));
+ } else {
+ R_TRY(g_manager->IsWakeEventActive(out_is_active, ConvertToGpioPadName(device_code)));
+ }
+
+ return ResultSuccess();
+ }
+
+ Direction GetDirection(GpioPadSession *session) {
+ Direction out;
+ R_ABORT_UNLESS(GetInterface(session)->GetDirection(std::addressof(out)));
+ return out;
+ }
+
+ void SetDirection(GpioPadSession *session, Direction direction) {
+ R_ABORT_UNLESS(GetInterface(session)->SetDirection(direction));
+ }
+
+ GpioValue GetValue(GpioPadSession *session) {
+ GpioValue out;
+ R_ABORT_UNLESS(GetInterface(session)->GetValue(std::addressof(out)));
+ return out;
+ }
+
+ void SetValue(GpioPadSession *session, GpioValue value) {
+ R_ABORT_UNLESS(GetInterface(session)->SetValue(value));
+ }
+
+ InterruptMode GetInterruptMode(GpioPadSession *session) {
+ InterruptMode out;
+ R_ABORT_UNLESS(GetInterface(session)->GetInterruptMode(std::addressof(out)));
+ return out;
+ }
+
+ void SetInterruptMode(GpioPadSession *session, InterruptMode mode) {
+ R_ABORT_UNLESS(GetInterface(session)->SetInterruptMode(mode));
+ }
+
+ bool GetInterruptEnable(GpioPadSession *session) {
+ bool out;
+ R_ABORT_UNLESS(GetInterface(session)->GetInterruptEnable(std::addressof(out)));
+ return out;
+ }
+
+ void SetInterruptEnable(GpioPadSession *session, bool en) {
+ R_ABORT_UNLESS(GetInterface(session)->SetInterruptEnable(en));
+ }
+
+ InterruptStatus GetInterruptStatus(GpioPadSession *session) {
+ InterruptStatus out;
+ R_ABORT_UNLESS(GetInterface(session)->GetInterruptStatus(std::addressof(out)));
+ return out;
+ }
+
+ void ClearInterruptStatus(GpioPadSession *session) {
+ R_ABORT_UNLESS(GetInterface(session)->ClearInterruptStatus());
+ }
+
+ int GetDebounceTime(GpioPadSession *session) {
+ int out;
+ R_ABORT_UNLESS(GetInterface(session)->GetDebounceTime(std::addressof(out)));
+ return out;
+ }
+
+ void SetDebounceTime(GpioPadSession *session, int ms) {
+ R_ABORT_UNLESS(GetInterface(session)->SetDebounceTime(ms));
+ }
+
+ bool GetDebounceEnabled(GpioPadSession *session) {
+ bool out;
+ R_ABORT_UNLESS(GetInterface(session)->GetDebounceEnabled(std::addressof(out)));
+ return out;
+ }
+
+ void SetDebounceEnabled(GpioPadSession *session, bool en) {
+ R_ABORT_UNLESS(GetInterface(session)->SetDebounceEnabled(en));
+ }
+
+ Result BindInterrupt(os::SystemEventType *event, GpioPadSession *session) {
+ AMS_ASSERT(session->_event == nullptr);
+
+ ams::sf::CopyHandle handle;
+ R_TRY(GetInterface(session)->BindInterrupt(std::addressof(handle)));
+
+ os::AttachReadableHandleToSystemEvent(event, handle.GetValue(), true, os::EventClearMode_ManualClear);
+
+ session->_event = event;
+ return ResultSuccess();
+ }
+
+ void UnbindInterrupt(GpioPadSession *session) {
+ AMS_ASSERT(session->_event != nullptr);
+
+ R_ABORT_UNLESS(GetInterface(session)->UnbindInterrupt());
+
+ os::DestroySystemEvent(session->_event);
+ session->_event = nullptr;
+ }
+
+}
diff --git a/libraries/libstratosphere/source/gpio/gpio_remote_manager_impl.hpp b/libraries/libstratosphere/source/gpio/gpio_remote_manager_impl.hpp
new file mode 100644
index 000000000..bb439b79f
--- /dev/null
+++ b/libraries/libstratosphere/source/gpio/gpio_remote_manager_impl.hpp
@@ -0,0 +1,91 @@
+/*
+ * 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 .
+ */
+#pragma once
+#include
+#include "gpio_remote_pad_session_impl.hpp"
+
+namespace ams::gpio {
+
+ class RemoteManagerImpl {
+ public:
+ RemoteManagerImpl() { /* ... */ }
+
+ ~RemoteManagerImpl() { /* ... */ }
+ public:
+ /* Actual commands. */
+ Result OpenSessionForDev(ams::sf::Out> out, s32 pad_descriptor) {
+ /* TODO: libnx bindings */
+ AMS_ABORT();
+ }
+
+ Result OpenSession(ams::sf::Out> out, gpio::GpioPadName pad_name) {
+ ::GpioPadSession p;
+ R_TRY(::gpioOpenSession(std::addressof(p), static_cast<::GpioPadName>(static_cast(pad_name))));
+
+ out.SetValue(ams::sf::MakeShared(p));
+ return ResultSuccess();
+ }
+
+ Result OpenSessionForTest(ams::sf::Out> out, gpio::GpioPadName pad_name) {
+ /* TODO: libnx bindings */
+ AMS_ABORT();
+ }
+
+ Result IsWakeEventActive(ams::sf::Out out, gpio::GpioPadName pad_name) {
+ return ::gpioIsWakeEventActive2(out.GetPointer(), static_cast<::GpioPadName>(static_cast(pad_name)));
+ }
+
+ Result GetWakeEventActiveFlagSet(ams::sf::Out out) {
+ /* TODO: libnx bindings */
+ AMS_ABORT();
+ }
+
+ Result SetWakeEventActiveFlagSetForDebug(gpio::GpioPadName pad_name, bool is_enabled) {
+ /* TODO: libnx bindings */
+ AMS_ABORT();
+ }
+
+ Result SetWakePinDebugMode(s32 mode) {
+ /* TODO: libnx bindings */
+ AMS_ABORT();
+ }
+
+ Result OpenSession2(ams::sf::Out> out, DeviceCode device_code, ddsf::AccessMode access_mode) {
+ ::GpioPadSession p;
+ R_TRY(::gpioOpenSession2(std::addressof(p), device_code.GetInternalValue(), access_mode));
+
+ out.SetValue(ams::sf::MakeShared(p));
+ return ResultSuccess();
+ }
+
+ Result IsWakeEventActive2(ams::sf::Out out, DeviceCode device_code) {
+ return ::gpioIsWakeEventActive2(out.GetPointer(), device_code.GetInternalValue());
+ }
+
+ Result SetWakeEventActiveFlagSetForDebug2(DeviceCode device_code, bool is_enabled) {
+ /* TODO: libnx bindings */
+ AMS_ABORT();
+ }
+
+ Result SetRetryValues(u32 arg0, u32 arg1) {
+ /* TODO: libnx bindings */
+ AMS_ABORT();
+ }
+
+ };
+ static_assert(gpio::sf::IsIManager);
+
+}
diff --git a/libraries/libstratosphere/source/gpio/gpio_remote_pad_session_impl.hpp b/libraries/libstratosphere/source/gpio/gpio_remote_pad_session_impl.hpp
new file mode 100644
index 000000000..297132f08
--- /dev/null
+++ b/libraries/libstratosphere/source/gpio/gpio_remote_pad_session_impl.hpp
@@ -0,0 +1,113 @@
+/*
+ * 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 .
+ */
+#pragma once
+#include
+
+namespace ams::gpio {
+
+ class RemotePadSessionImpl {
+ private:
+ ::GpioPadSession srv;
+ public:
+ RemotePadSessionImpl(::GpioPadSession &p) : srv(p) { /* ... */ }
+
+ ~RemotePadSessionImpl() { ::gpioPadClose(std::addressof(this->srv)); }
+ public:
+ /* Actual commands. */
+ Result SetDirection(gpio::Direction direction) {
+ return ::gpioPadSetDirection(std::addressof(this->srv), static_cast<::GpioDirection>(static_cast(direction)));
+ }
+
+ Result GetDirection(ams::sf::Out out) {
+ static_assert(sizeof(gpio::Direction) == sizeof(::GpioDirection));
+ return ::gpioPadGetDirection(std::addressof(this->srv), reinterpret_cast<::GpioDirection *>(out.GetPointer()));
+ }
+
+ Result SetInterruptMode(gpio::InterruptMode mode) {
+ return ::gpioPadSetInterruptMode(std::addressof(this->srv), static_cast<::GpioInterruptMode>(static_cast(mode)));
+ }
+
+ Result GetInterruptMode(ams::sf::Out out) {
+ static_assert(sizeof(gpio::InterruptMode) == sizeof(::GpioInterruptMode));
+ return ::gpioPadGetInterruptMode(std::addressof(this->srv), reinterpret_cast<::GpioInterruptMode *>(out.GetPointer()));
+ }
+
+ Result SetInterruptEnable(bool enable) {
+ return ::gpioPadSetInterruptEnable(std::addressof(this->srv), enable);
+ }
+
+ Result GetInterruptEnable(ams::sf::Out out) {
+ return ::gpioPadGetInterruptEnable(std::addressof(this->srv), out.GetPointer());
+ }
+
+ Result GetInterruptStatus(ams::sf::Out out) {
+ static_assert(sizeof(gpio::InterruptStatus) == sizeof(::GpioInterruptStatus));
+ return ::gpioPadGetInterruptStatus(std::addressof(this->srv), reinterpret_cast<::GpioInterruptStatus *>(out.GetPointer()));
+ }
+
+ Result ClearInterruptStatus() {
+ return ::gpioPadClearInterruptStatus(std::addressof(this->srv));
+ }
+
+ Result SetValue(gpio::GpioValue value) {
+ return ::gpioPadSetValue(std::addressof(this->srv), static_cast<::GpioValue>(static_cast(value)));
+ }
+
+ Result GetValue(ams::sf::Out out) {
+ static_assert(sizeof(gpio::GpioValue) == sizeof(::GpioValue));
+ return ::gpioPadGetValue(std::addressof(this->srv), reinterpret_cast<::GpioValue *>(out.GetPointer()));
+ }
+
+ Result BindInterrupt(ams::sf::OutCopyHandle out) {
+ ::Event ev;
+ R_TRY(::gpioPadBindInterrupt(std::addressof(this->srv), std::addressof(ev)));
+ out.SetValue(ev.revent);
+ return ResultSuccess();
+ }
+
+ Result UnbindInterrupt() {
+ return ::gpioPadUnbindInterrupt(std::addressof(this->srv));
+ }
+
+ Result SetDebounceEnabled(bool enable) {
+ return ::gpioPadSetDebounceEnabled(std::addressof(this->srv), enable);
+ }
+
+ Result GetDebounceEnabled(ams::sf::Out out) {
+ return ::gpioPadGetDebounceEnabled(std::addressof(this->srv), out.GetPointer());
+ }
+
+ Result SetDebounceTime(s32 ms) {
+ return ::gpioPadSetDebounceTime(std::addressof(this->srv), ms);
+ }
+
+ Result GetDebounceTime(ams::sf::Out out) {
+ return ::gpioPadGetDebounceTime(std::addressof(this->srv), out.GetPointer());
+ }
+
+ Result SetValueForSleepState(gpio::GpioValue value) {
+ /* TODO: libnx bindings. */
+ AMS_ABORT();
+ }
+
+ Result GetValueForSleepState(ams::sf::Out out) {
+ /* TODO: libnx bindings. */
+ AMS_ABORT();
+ }
+ };
+ static_assert(gpio::sf::IsIPadSession);
+
+}
diff --git a/libraries/libvapours/include/vapours.hpp b/libraries/libvapours/include/vapours.hpp
index 84820cb2b..a47ec53bc 100644
--- a/libraries/libvapours/include/vapours.hpp
+++ b/libraries/libvapours/include/vapours.hpp
@@ -20,12 +20,22 @@
#include
#include
+#include
#include
#include
#include
#include
+#include
+
+#if defined(ATMOSPHERE_BOARD_NINTENDO_NX)
+#include
+#endif
+
#include
#include
#include
+
+#include
+#include
\ No newline at end of file
diff --git a/libraries/libvapours/include/vapours/dd.hpp b/libraries/libvapours/include/vapours/dd.hpp
new file mode 100644
index 000000000..52d3e9cd0
--- /dev/null
+++ b/libraries/libvapours/include/vapours/dd.hpp
@@ -0,0 +1,24 @@
+/*
+ * 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 .
+ */
+
+#pragma once
+#include
+#include
+#include
+
+#include
+#include
+#include
diff --git a/libraries/libvapours/include/vapours/dd/dd_cache.hpp b/libraries/libvapours/include/vapours/dd/dd_cache.hpp
new file mode 100644
index 000000000..8ea0e200a
--- /dev/null
+++ b/libraries/libvapours/include/vapours/dd/dd_cache.hpp
@@ -0,0 +1,25 @@
+/*
+ * 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 .
+ */
+#pragma once
+#include
+
+namespace ams::dd {
+
+ void InvalidateDataCache(void *addr, size_t size);
+ void StoreDataCache(void *addr, size_t size);
+ void FlushDataCache(void *addr, size_t size);
+
+}
diff --git a/libraries/libvapours/include/vapours/dd/dd_common_types.hpp b/libraries/libvapours/include/vapours/dd/dd_common_types.hpp
new file mode 100644
index 000000000..25a533b0f
--- /dev/null
+++ b/libraries/libvapours/include/vapours/dd/dd_common_types.hpp
@@ -0,0 +1,29 @@
+/*
+ * 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 .
+ */
+
+#pragma once
+#include
+#include
+#include
+
+namespace ams::dd {
+
+ using PhysicalAddress = u64;
+ using DeviceVirtualAddress = u64;
+
+ static_assert(std::same_as);
+
+}
diff --git a/libraries/libvapours/include/vapours/dd/dd_io_mapping.hpp b/libraries/libvapours/include/vapours/dd/dd_io_mapping.hpp
new file mode 100644
index 000000000..f82552bb0
--- /dev/null
+++ b/libraries/libvapours/include/vapours/dd/dd_io_mapping.hpp
@@ -0,0 +1,26 @@
+/*
+ * 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 .
+ */
+#pragma once
+#include
+
+namespace ams::dd {
+
+ uintptr_t QueryIoMapping(dd::PhysicalAddress phys_addr, size_t size);
+
+ u32 ReadIoRegister(dd::PhysicalAddress phys_addr);
+ void WriteIoRegister(dd::PhysicalAddress phys_addr, u32 value);
+
+}
diff --git a/libraries/libvapours/include/vapours/device_code.hpp b/libraries/libvapours/include/vapours/device_code.hpp
new file mode 100644
index 000000000..c39abcaf2
--- /dev/null
+++ b/libraries/libvapours/include/vapours/device_code.hpp
@@ -0,0 +1,49 @@
+/*
+ * 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 .
+ */
+
+#pragma once
+#include
+#include
+
+namespace ams {
+
+ namespace impl {
+
+ using DeviceCodeType = u32;
+
+ }
+
+ /* TODO: Better understand device code components. */
+ class DeviceCode {
+ private:
+ impl::DeviceCodeType inner_value;
+ public:
+ constexpr DeviceCode(impl::DeviceCodeType v) : inner_value(v) { /* ... */ }
+
+ constexpr impl::DeviceCodeType GetInternalValue() const { return this->inner_value; }
+
+ constexpr bool operator==(const DeviceCode &rhs) const {
+ return this->GetInternalValue() == rhs.GetInternalValue();
+ }
+
+ constexpr bool operator!=(const DeviceCode &rhs) const {
+ return !(*this == rhs);
+ }
+ };
+
+ constexpr inline const DeviceCode InvalidDeviceCode(0);
+
+}
diff --git a/libraries/libexosphere/include/exosphere/reg.hpp b/libraries/libvapours/include/vapours/reg.hpp
similarity index 58%
rename from libraries/libexosphere/include/exosphere/reg.hpp
rename to libraries/libvapours/include/vapours/reg.hpp
index 1ac314110..7cf770312 100644
--- a/libraries/libexosphere/include/exosphere/reg.hpp
+++ b/libraries/libvapours/include/vapours/reg.hpp
@@ -18,6 +18,9 @@
namespace ams::reg {
+ template
+ concept UnsignedNonConstIntegral = std::unsigned_integral && !std::is_const::value;
+
using BitsValue = std::tuple;
using BitsMask = std::tuple;
@@ -48,100 +51,137 @@ namespace ams::reg {
return (EncodeValue(values) | ...);
}
- ALWAYS_INLINE void Write(volatile u32 *reg, u32 val) { *reg = val; }
- ALWAYS_INLINE void Write(volatile u32 ®, u32 val) { reg = val; }
+ template requires ((sizeof...(Masks) > 0) && (std::is_same::value && ...))
+ constexpr ALWAYS_INLINE u32 EncodeMask(const Masks... masks) {
+ return (EncodeMask(masks) | ...);
+ }
+
+ template requires UnsignedNonConstIntegral
+ ALWAYS_INLINE void Write(volatile IntType *reg, std::type_identity_t val) { *reg = val; }
+
+ template requires UnsignedNonConstIntegral
+ ALWAYS_INLINE void Write(volatile IntType ®, std::type_identity_t val) { reg = val; }
+
ALWAYS_INLINE void Write(uintptr_t reg, u32 val) { Write(reinterpret_cast(reg), val); }
- template requires ((sizeof...(Values) > 0) && (std::is_same::value && ...))
- ALWAYS_INLINE void Write(volatile u32 *reg, const Values... values) { return Write(reg, (EncodeValue(values) | ...)); }
+ template requires UnsignedNonConstIntegral && ((sizeof...(Values) > 0) && (std::is_same::value && ...))
+ ALWAYS_INLINE void Write(volatile IntType *reg, const Values... values) { return Write(reg, static_cast((EncodeValue(values) | ...))); }
- template requires ((sizeof...(Values) > 0) && (std::is_same::value && ...))
- ALWAYS_INLINE void Write(volatile u32 ®, const Values... values) { return Write(reg, (EncodeValue(values) | ...)); }
+ template requires UnsignedNonConstIntegral && ((sizeof...(Values) > 0) && (std::is_same::value && ...))
+ ALWAYS_INLINE void Write(volatile IntType ®, const Values... values) { return Write(reg, static_cast((EncodeValue(values) | ...))); }
template requires ((sizeof...(Values) > 0) && (std::is_same::value && ...))
ALWAYS_INLINE void Write(uintptr_t reg, const Values... values) { return Write(reg, (EncodeValue(values) | ...)); }
- ALWAYS_INLINE u32 Read(volatile u32 *reg) { return *reg; }
- ALWAYS_INLINE u32 Read(volatile u32 ®) { return reg; }
+ template requires UnsignedNonConstIntegral
+ ALWAYS_INLINE IntType Read(volatile IntType *reg) { return *reg; }
+
+ template requires UnsignedNonConstIntegral
+ ALWAYS_INLINE IntType Read(volatile IntType ®) { return reg; }
+
ALWAYS_INLINE u32 Read(uintptr_t reg) { return Read(reinterpret_cast(reg)); }
- ALWAYS_INLINE u32 Read(volatile u32 *reg, u32 mask) { return *reg & mask; }
- ALWAYS_INLINE u32 Read(volatile u32 ®, u32 mask) { return reg & mask; }
+ template requires UnsignedNonConstIntegral
+ ALWAYS_INLINE IntType Read(volatile IntType *reg, std::type_identity_t mask) { return *reg & mask; }
+
+ template requires UnsignedNonConstIntegral
+ ALWAYS_INLINE IntType Read(volatile IntType ®, std::type_identity_t mask) { return reg & mask; }
+
ALWAYS_INLINE u32 Read(uintptr_t reg, u32 mask) { return Read(reinterpret_cast(reg), mask); }
- template requires ((sizeof...(Masks) > 0) && (std::is_same::value && ...))
- ALWAYS_INLINE u32 Read(volatile u32 *reg, const Masks... masks) { return Read(reg, (EncodeMask(masks) | ...)); }
+ template requires UnsignedNonConstIntegral && ((sizeof...(Masks) > 0) && (std::is_same::value && ...))
+ ALWAYS_INLINE IntType Read(volatile IntType *reg, const Masks... masks) { return Read(reg, static_cast((EncodeMask(masks) | ...))); }
+
+ template requires UnsignedNonConstIntegral && ((sizeof...(Masks) > 0) && (std::is_same::value && ...))
+ ALWAYS_INLINE IntType Read(volatile IntType ®, const Masks... masks) { return Read(reg, static_cast((EncodeMask(masks) | ...))); }
template requires ((sizeof...(Masks) > 0) && (std::is_same::value && ...))
- ALWAYS_INLINE u32 Read(volatile u32 ®, const Masks... masks) { return Read(reg, (EncodeMask(masks) | ...)); }
+ ALWAYS_INLINE u32 Read(uintptr_t reg, const Masks... masks) { return Read(reg, (EncodeMask(masks) | ...)); }
- template requires ((sizeof...(Masks) > 0) && (std::is_same::value && ...))
- ALWAYS_INLINE u32 Read(uintptr_t reg, const Masks... masks) { return Read(reg, (EncodeMask(masks) | ...)); }
+ template requires UnsignedNonConstIntegral && ((sizeof...(Values) > 0) && (std::is_same::value && ...))
+ ALWAYS_INLINE bool HasValue(volatile IntType *reg, const Values... values) { return Read(reg, static_cast((EncodeMask(values) | ...))) == static_cast(Encode(values...)); }
- template requires ((sizeof...(Values) > 0) && (std::is_same::value && ...))
- ALWAYS_INLINE bool HasValue(volatile u32 *reg, const Values... values) { return Read(reg, (EncodeMask(values) | ...)) == Encode(values...); }
-
- template requires ((sizeof...(Values) > 0) && (std::is_same::value && ...))
- ALWAYS_INLINE bool HasValue(volatile u32 ®, const Values... values) { return Read(reg, (EncodeMask(values) | ...)) == Encode(values...); }
+ template requires UnsignedNonConstIntegral && ((sizeof...(Values) > 0) && (std::is_same::value && ...))
+ ALWAYS_INLINE bool HasValue(volatile IntType ®, const Values... values) { return Read(reg, static_cast((EncodeMask(values) | ...))) == static_cast(Encode(values...)); }
template