From 2b629b4c43c1155d6c6d90c6a8ba4cae0ae0f683 Mon Sep 17 00:00:00 2001 From: Mateusz Faderewski Date: Sun, 25 Aug 2024 03:15:26 +0200 Subject: [PATCH] debug: added support for SummerCart64 AUX register --- include/debug.h | 11 +++++- include/n64sys.h | 5 +++ include/regsinternal.h | 2 + src/debug.c | 84 ++++++++++++++++++++++++++++++++++++++++++ src/entrypoint.S | 14 ++++--- src/n64sys.c | 70 ++++++++++++++++++++++++++++++----- 6 files changed, 170 insertions(+), 16 deletions(-) diff --git a/include/debug.h b/include/debug.h index 54323fefa2..aa8a6bfc56 100644 --- a/include/debug.h +++ b/include/debug.h @@ -116,6 +116,9 @@ extern "C" { #define DEBUG_FEATURE_FILE_SD (1 << 3) +#define DEBUG_FEATURE_CART_INTERRUPT (1 << 4) + + /** * @brief Flag to activate all supported debugging features. * @@ -142,6 +145,10 @@ extern "C" { /** @brief Shutdown SD filesystem. */ void debug_close_sdfs(void); + + bool debug_init_cart_interrupt(void); + void debug_close_cart_interrupt(void); + /** * @brief Initialize debugging features of libdragon. * @@ -163,7 +170,9 @@ extern "C" { if (features & DEBUG_FEATURE_FILE_SD) ok = debug_init_sdfs("sd:/", -1) || ok; if (features & DEBUG_FEATURE_LOG_SD) - ok = debug_init_sdlog("sd:/libdragon.log", "a"); + ok = debug_init_sdlog("sd:/libdragon.log", "a") || ok; + if (features & DEBUG_FEATURE_CART_INTERRUPT) + ok = debug_init_cart_interrupt() || ok; return ok; } diff --git a/include/n64sys.h b/include/n64sys.h index 910636c989..42be8d05e1 100644 --- a/include/n64sys.h +++ b/include/n64sys.h @@ -279,6 +279,8 @@ void wait_ticks( unsigned long wait ); */ void wait_ms( unsigned long wait_ms ); +void halt(void); + /** * @brief Force a complete halt of all processors * @@ -292,6 +294,9 @@ void wait_ms( unsigned long wait_ms ); __attribute__((noreturn)) void die(void); +__attribute__((noreturn)) +void reboot(void); + /** * @brief Force a data cache invalidate over a memory region * diff --git a/include/regsinternal.h b/include/regsinternal.h index ca702a91b8..910c409a99 100644 --- a/include/regsinternal.h +++ b/include/regsinternal.h @@ -115,6 +115,8 @@ typedef struct PI_regs_s { uint32_t dom1_latency; /** @brief Cartridge domain 1 pulse width in RCP clock cycles. Requires DMA status bit guards to work reliably */ uint32_t dom1_pulse_width; + uint32_t dom1_page_size; + uint32_t dom1_release; // TODO: add remaining registers } PI_regs_t; diff --git a/src/debug.c b/src/debug.c index 050b02d7e4..4782599b53 100644 --- a/src/debug.c +++ b/src/debug.c @@ -669,6 +669,90 @@ void debug_close_sdfs(void) } } +#define SC64_SCR (0x1FFF0000) +#define SC64_IRQ (0x1FFF0014) +#define SC64_AUX (0x1FFF0018) + +#define SC64_SCR_AUX_IRQ_PENDING (1 << 23) +#define SC64_SCR_AUX_IRQ_MASK (1 << 22) + +#define SC64_IRQ_AUX_CLEAR (1 << 28) +#define SC64_IRQ_AUX_DISABLE (1 << 9) +#define SC64_IRQ_AUX_ENABLE (1 << 8) + +#define AUX_PING (0xFF000000) +#define AUX_HALT (0xFF000001) +#define AUX_REBOOT (0xFF000002) + +static void debug_cart_handler_sc64(void) +{ + bool halt_requested = false; + + do { + uint32_t scr = io_read(SC64_SCR); + + if ((scr & SC64_SCR_AUX_IRQ_MASK) && (scr & SC64_SCR_AUX_IRQ_PENDING)) { + io_write(SC64_IRQ, SC64_IRQ_AUX_CLEAR); + + switch (io_read(SC64_AUX)) { + case AUX_PING: + io_write(SC64_AUX, AUX_PING); + break; + + case AUX_HALT: + if (!halt_requested) { + halt(); + halt_requested = true; + } + io_write(SC64_AUX, AUX_HALT); + break; + + case AUX_REBOOT: + io_write(SC64_IRQ, SC64_IRQ_AUX_DISABLE); + io_write(SC64_AUX, AUX_REBOOT); + reboot(); + break; + + default: + break; + } + } + } while (halt_requested); +} + +bool debug_init_cart_interrupt(void) +{ + if (!sd_initialize_once()) + return false; + + if (cart_type == CART_SC) { + register_CART_handler(debug_cart_handler_sc64); + set_CART_interrupt(true); + + io_write(SC64_IRQ, SC64_IRQ_AUX_ENABLE); + + enabled_features |= DEBUG_FEATURE_CART_INTERRUPT; + + return true; + } + + return false; +} + +void debug_close_cart_interrupt(void) +{ + if (enabled_features & DEBUG_FEATURE_CART_INTERRUPT) { + enabled_features &= ~(DEBUG_FEATURE_CART_INTERRUPT); + + if (cart_type == CART_SC) { + io_write(SC64_IRQ, SC64_IRQ_AUX_DISABLE); + + set_CART_interrupt(false); + unregister_CART_handler(debug_cart_handler_sc64); + } + } +} + void debug_assert_func_f(const char *file, int line, const char *func, const char *failedexpr, const char *msg, ...) { disable_interrupts(); diff --git a/src/entrypoint.S b/src/entrypoint.S index 63bf35a349..a756669148 100644 --- a/src/entrypoint.S +++ b/src/entrypoint.S @@ -32,12 +32,14 @@ _start: sw t1, %gprel(__entropy_state+4)(gp) /* Copy other bootcode flags */ - lbu t0, 0x0009(v0) - lbu t1, 0x000A(v0) - lbu t2, 0x000B(v0) - sw t0, %gprel(__boot_tvtype)(gp) - sw t1, %gprel(__boot_resettype)(gp) - sw t2, %gprel(__boot_consoletype)(gp) + lbu t0, 0x0008(v0) + lbu t1, 0x0009(v0) + lbu t2, 0x000A(v0) + lbu t3, 0x000B(v0) + sw t0, %gprel(__boot_romtype)(gp) + sw t1, %gprel(__boot_tvtype)(gp) + sw t2, %gprel(__boot_resettype)(gp) + sw t3, %gprel(__boot_consoletype)(gp) la t0, debug_assert_func /* install assert function in system.c */ la t1, __assert_func_ptr diff --git a/src/n64sys.c b/src/n64sys.c index 0d72973f58..027ec56a44 100644 --- a/src/n64sys.c +++ b/src/n64sys.c @@ -10,6 +10,7 @@ #include #include "n64sys.h" #include "regsinternal.h" +#include "dma.h" #include "interrupt.h" #include "vi.h" #include "rsp.h" @@ -17,6 +18,7 @@ #include "utils.h" int __boot_memsize; ///< Memory size as detected by IPL3 +int __boot_romtype; ///< ROM type as detected by IPL3 int __boot_tvtype; ///< TV type as detected by IPL3 int __boot_resettype; ///< Reset type as detected by IPL3 int __boot_consoletype; ///< Console type as detected by IPL3 @@ -27,6 +29,9 @@ static uint32_t ticks64_base_tick; /** @brief Last value of the 64-bit counter */ static uint64_t ticks64_base; +/** @brief Structure used to interact with the PI registers */ +static volatile struct PI_regs_s * const PI_regs = (struct PI_regs_s *)0xa4600000; + /** * @brief Helper macro to perform cache refresh operations * @@ -175,6 +180,19 @@ void wait_ms( unsigned long wait_ms ) wait_ticks(TICKS_FROM_MS(wait_ms)); } +void halt(void) +{ + // Can't have any interrupts here + disable_interrupts(); + // Halt the RSP + *SP_STATUS = SP_WSTATUS_SET_HALT; + // Flush the RDP + *DP_STATUS = DP_WSTATUS_SET_FLUSH | DP_WSTATUS_SET_FREEZE; + *DP_STATUS = DP_WSTATUS_RESET_FLUSH | DP_WSTATUS_RESET_FREEZE; + // Shut the video off + *VI_CTRL = *VI_CTRL & (~VI_CTRL_TYPE); +} + /** * @brief Force a complete halt of all processors * @@ -187,19 +205,53 @@ void wait_ms( unsigned long wait_ms ) */ void die(void) { - // Can't have any interrupts here - disable_interrupts(); - // Halt the RSP - *SP_STATUS = SP_WSTATUS_SET_HALT; - // Flush the RDP - *DP_STATUS = DP_WSTATUS_SET_FLUSH | DP_WSTATUS_SET_FREEZE; - *DP_STATUS = DP_WSTATUS_RESET_FLUSH | DP_WSTATUS_RESET_FREEZE; - // Shut the video off - *VI_CTRL = *VI_CTRL & (~VI_CTRL_TYPE); + // Terminate the RCP execution + halt(); // Terminate the CPU execution abort(); } +void reboot(void) +{ + halt(); + + const uint32_t ROM_ADDRESS = 0x10000000; + + const int IPL3_SIZE = 0xFC0; + const uint32_t IPL3_OFFSET = 0x40; + + uint8_t ipl3_data[IPL3_SIZE] __attribute__((aligned(8))); + + C0_WRITE_STATUS(0x34000000); + + uint32_t pi_config = io_read(ROM_ADDRESS); + + PI_regs->dom1_latency = pi_config; + PI_regs->dom1_pulse_width = (pi_config >> 8); + PI_regs->dom1_page_size = (pi_config >> 16); + PI_regs->dom1_release = (pi_config >> 20); + + dma_read_raw_async(&ipl3_data, (ROM_ADDRESS + IPL3_OFFSET), sizeof(ipl3_data)); + dma_wait(); + rsp_load_data(ipl3_data, sizeof(ipl3_data), IPL3_OFFSET); + + void (*run_ipl3)(void) = (void (*)(void))((uint32_t)(SP_DMEM) + IPL3_OFFSET); + + register uint32_t rom_type asm ("s3") = __boot_romtype; + register uint32_t tv_type asm ("s4") = __boot_tvtype; + register uint32_t reset_type asm ("s5") = RESET_WARM; + + asm volatile ( + "jalr %[run_ipl3] \n" :: + [run_ipl3] "r" (run_ipl3), + [rom_type] "r" (rom_type), + [tv_type] "r" (tv_type), + [reset_type] "r" (reset_type) + ); + + abort(); +} + /** * @brief Initialize COP1 with default settings that prevent undesirable exceptions. *