From 78da29719922381bfed16e642509023e791237c3 Mon Sep 17 00:00:00 2001 From: a92126 <182859762@qq.com> Date: Mon, 5 Aug 2024 10:42:11 +0800 Subject: [PATCH] =?UTF-8?q?pxi.h:=20=E6=B7=BB=E5=8A=A0=E4=BA=86=E6=B8=85?= =?UTF-8?q?=E7=90=86=E5=A4=84=E7=90=86=E5=9B=9E=E8=B0=83=20gfx:=20?= =?UTF-8?q?=E5=B8=B8=E9=87=8F=E5=A4=A7=E6=94=B9=E5=90=8D=E3=80=81=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E5=A4=A7=E6=94=B9=E5=90=8D=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E4=BA=86=E5=8F=8C=E7=BC=93=E5=86=B2=E7=9A=84=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E9=A9=B1=E5=8A=A8=E5=87=BD=E6=95=B0=20=E5=85=B6=E4=BB=96?= =?UTF-8?q?=EF=BC=9A=E5=9F=BA=E6=9C=AC=E6=98=AFARM9/ARM11=E5=AE=8F?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=92=8CBIT=E5=8F=96=E5=80=BC=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=EF=BC=8Cbool=E4=BB=8Ec=E9=A3=8E=E6=A0=BC=E8=BD=AC?= =?UTF-8?q?=E6=88=90c++=E5=BC=BA=E7=B1=BB=E5=9E=8B=E9=A3=8E=E6=A0=BC?= =?UTF-8?q?=E7=AD=89=E3=80=82sha.c=E4=BD=BF=E7=94=A8=E4=BA=86memory.h?= =?UTF-8?q?=E8=BF=9B=E8=A1=8C=E7=9A=84=E6=94=B9=E5=8A=A8(copy32)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libn3ds/include/drivers/cache.h | 73 +++++- libn3ds/include/drivers/corelink_dma-330.h | 92 +++---- libn3ds/include/drivers/gfx.h | 259 +++++++++++++++----- libn3ds/include/drivers/lgy_common.h | 15 +- libn3ds/include/drivers/pxi.h | 77 +++--- libn3ds/include/drivers/sha.h | 42 ++-- libn3ds/include/drivers/tmio.h | 270 +++++++++++---------- libn3ds/include/drivers/tmio_config.h | 27 ++- libn3ds/source/drivers/corelink_dma-330.c | 22 +- libn3ds/source/drivers/mmc/sdmmc.c | 32 +-- libn3ds/source/drivers/pxi.c | 48 ++-- libn3ds/source/drivers/sha.c | 14 +- libn3ds/source/drivers/tmio.c | 43 ++-- 13 files changed, 638 insertions(+), 376 deletions(-) diff --git a/libn3ds/include/drivers/cache.h b/libn3ds/include/drivers/cache.h index f06c345..87b0b7e 100644 --- a/libn3ds/include/drivers/cache.h +++ b/libn3ds/include/drivers/cache.h @@ -1,8 +1,8 @@ #pragma once /* - * This file is part of open_agb_firm - * Copyright (C) 2021 derrek, profi200 + * This file is part of libn3ds + * Copyright (C) 2024 derrek, profi200 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,11 +22,68 @@ +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @brief Invalidates all instruction cache lines. + */ void invalidateICache(void); -void invalidateICacheRange(const void *base, u32 size); -void cleanDCache(void); -void flushDCache(void); -void cleanDCacheRange(const void *base, u32 size); -void flushDCacheRange(const void *base, u32 size); + +/** + * @brief Invalidates instruction cache lines in an address range. + * + * @param[in] base The base address. + * @param[in] size The range size in bytes. + */ +void invalidateICacheRange(const void *base, size_t size); + +/** + * @brief Invalidates all data cache lines. + */ void invalidateDCache(void); -void invalidateDCacheRange(const void *base, u32 size); + +/** + * @brief Invalidates data cache lines in an address range. + * + * @param[in] base The base address. + * @param[in] size The range size in bytes. + */ +void invalidateDCacheRange(const void *base, size_t size); + +/** + * @brief Invalidates all instruction and data caches lines. + */ +void invalidateBothCaches(void); + +/** + * @brief Cleans (writes back to memory) all data cache lines. + */ +void cleanDCache(void); + +/** + * @brief Cleans (writes back to memory) data cache lines in an address range. + * + * @param[in] base The base address. + * @param[in] size The range size in bytes. + */ +void cleanDCacheRange(const void *base, size_t size); + +/** + * @brief Flushes (clean + invalidate) all data cache lines. + */ +void flushDCache(void); + +/** + * @brief Flushes (clean + invalidate) data cache lines in an address range. + * + * @param[in] base The base address. + * @param[in] size The range size in bytes. + */ +void flushDCacheRange(const void *base, size_t size); + +#ifdef __cplusplus +} // extern "C" +#endif \ No newline at end of file diff --git a/libn3ds/include/drivers/corelink_dma-330.h b/libn3ds/include/drivers/corelink_dma-330.h index 0fbf7be..69cdaad 100644 --- a/libn3ds/include/drivers/corelink_dma-330.h +++ b/libn3ds/include/drivers/corelink_dma-330.h @@ -1,8 +1,8 @@ #pragma once /* - * This file is part of open_agb_firm - * Copyright (C) 2021 derrek, profi200 + * This file is part of libn3ds + * Copyright (C) 2024 derrek, profi200 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,22 +18,26 @@ * along with this program. If not, see . */ -#include #include "types.h" #include "mem_map.h" +#ifdef __cplusplus +extern "C" +{ +#endif + //#define USE_NEW_CDMA (1) -#ifdef ARM11 +#ifdef __ARM11__ #ifdef USE_NEW_CDMA #define DMA330_REGS_BASE (IO_AXI_BASE + 0x6000) #else #define DMA330_REGS_BASE (IO_AXI_BASE + 0x0000) #endif // ifdef USE_NEW_CDMA -#elif ARM9 +#elif __ARM9__ #define DMA330_REGS_BASE (IO_AHB_BASE + 0xC000) -#endif // ifdef ARM11 +#endif // ifdef __ARM11__ typedef struct { @@ -100,7 +104,7 @@ ALWAYS_INLINE Dma330* getDma330Regs(void) // REG_DMA330_DSR #define DSR_WAKE_EVNT_SHIFT (4u) #define DSR_WAKE_EVNT_MASK (0x1Fu<. */ -#include "mem_map.h" #include "types.h" +#include "rgb_conv.h" -#define SCREEN_TOP (0u) -#define SCREEN_BOT (1u) +#ifdef __cplusplus +extern "C" +{ +#endif -#define SCREEN_WIDTH_TOP (400u) -#define SCREEN_HEIGHT_TOP (240u) -#define SCREEN_SIZE_TOP (SCREEN_WIDTH_TOP * SCREEN_HEIGHT_TOP * 2) -#define SCREEN_WIDTH_BOT (320u) -#define SCREEN_HEIGHT_BOT (240u) -#define SCREEN_SIZE_BOT (SCREEN_WIDTH_BOT * SCREEN_HEIGHT_BOT * 2) +// Note: The LCDs are physically rotated 90° CCW. +#define LCD_WIDTH_TOP (240u) +#define LCD_HEIGHT_TOP (400u) +#define LCD_WIDE_HEIGHT_TOP (800u) // In wide mode. +#define LCD_WIDTH_BOT (240u) +#define LCD_HEIGHT_BOT (320u) -// TODO: -// Because we are using a VRAM allocator this may break any time. -#define FRAMEBUF_TOP_A_1 ((void*)VRAM_BASE) -#define FRAMEBUF_BOT_A_1 (FRAMEBUF_TOP_A_1 + SCREEN_SIZE_TOP) -#define FRAMEBUF_TOP_A_2 (FRAMEBUF_BOT_A_1 + SCREEN_SIZE_BOT + SCREEN_SIZE_TOP) // Skip B1 -#define FRAMEBUF_BOT_A_2 (FRAMEBUF_TOP_A_2 + SCREEN_SIZE_TOP) - -#define DEFAULT_BRIGHTNESS (0x30) - -/// Converts packed RGB8 to packed RGB565. -#define RGB8_to_565(r,g,b) (((((r)>>3) & 0x1f)<<11) | ((((g)>>2) & 0x3f)<<5) | (((b)>>3) & 0x1f)) +#define BGR8_2_565(r, g, b) ((((249u * (r) + 1024)>>11)<<11) | (((253u * (g) + 512)>>10)<<5) | ((249u * (b) + 1024)>>11)) -/// Framebuffer format. +// Pixel formats. typedef enum { - GFX_RGBA8 = 0, ///< RGBA8. (4 bytes) - GFX_BGR8 = 1, ///< BGR8. (3 bytes) - GFX_RGB565 = 2, ///< RGB565. (2 bytes) - GFX_RGB5A1 = 3, ///< RGB5A1. (2 bytes) - GFX_RGBA4 = 4 ///< RGBA4. (2 bytes) -} GfxFbFmt; + GFX_ABGR8 = 0u, // {0xAA, 0xBB, 0xGG, 0xRR} in memory from lowest to highest address. + GFX_BGR8 = 1u, // {0xBB, 0xGG, 0xRR} in memory from lowest to highest address. + GFX_BGR565 = 2u, // {0bGGGBBBBB, 0bRRRRRGGG} in memory from lowest to highest address. + GFX_A1BGR5 = 3u, // {0bGGBBBBBA, 0bRRRRRGGG} in memory from lowest to highest address. + GFX_ABGR4 = 4u // {0bBBBBAAAA, 0bRRRRGGGG} in memory from lowest to highest address. +} GfxFmt; + +typedef enum +{ + GFX_LCD_TOP = 0u, + GFX_LCD_BOT = 1u +} GfxLcd; + +typedef enum +{ + GFX_SIDE_LEFT = 0u, + GFX_SIDE_RIGHT = 1u +} GfxSide; + +static inline u8 GFX_getPixelSize(const GfxFmt fmt) +{ + if(fmt == GFX_ABGR8) + { + return 4; + } + else if(fmt == GFX_BGR8) + { + return 3; + } + + return 2; // BGR565, A1BGR5, ABGR4. +} -#ifdef ARM11 + +#ifdef __ARM11__ +typedef enum +{ + GFX_TOP_2D = 0u, // 240x400. + GFX_TOP_WIDE = 1u, // 240x800. + GFX_TOP_3D = 2u // Stereo 240x400 (left + right eye). +} GfxTopMode; + typedef enum { GFX_EVENT_PSC0 = 0u, @@ -67,60 +93,179 @@ typedef enum GFX_EVENT_P3D = 5u } GfxEvent; +// Note: Keep this synchronized with MCU backlight bits. typedef enum { - GFX_BLIGHT_BOT = 1u<<2, - GFX_BLIGHT_TOP = 1u<<4, - GFX_BLIGHT_BOTH = GFX_BLIGHT_TOP | GFX_BLIGHT_BOT -} GfxBlight; + GFX_BL_BOT = BIT(2), + GFX_BL_TOP = BIT(4), + GFX_BL_BOTH = GFX_BL_TOP | GFX_BL_BOT +} GfxBl; -void GFX_init(GfxFbFmt fmtTop, GfxFbFmt fmtBot); +/** + * @brief Turns on the LCDs and initializes graphics. + * + * @param[in] fmtTop Top LCD pixel format. + * @param[in] fmtBot Bottom LCD pixel format. + * @param[in] topMode Top LCD mode. + */ +void GFX_init(const GfxFmt fmtTop, const GfxFmt fmtBot, const GfxTopMode mode); +/** + * @brief Equal to GFX_init(GFX_BGR8, GFX_BGR8, GFX_TOP_2D). + */ static inline void GFX_initDefault(void) { - GFX_init(GFX_BGR8, GFX_BGR8); + GFX_init(GFX_BGR8, GFX_BGR8, GFX_TOP_2D); } +/** + * @brief Turns LCDs off and deinitializes graphics. + */ void GFX_deinit(void); -void GFX_setFramebufFmt(GfxFbFmt fmtTop, GfxFbFmt fmtBot); +/** + * @brief Sets the frame buffer format. + * + * @param[in] fmtTop The top frame buffer format. + * @param[in] fmtBot The bottom frame buffer format. + * @param[in] mode Top LCD mode. + */ +void GFX_setFormat(const GfxFmt fmtTop, const GfxFmt fmtBot, const GfxTopMode mode); -void GFX_powerOnBacklights(GfxBlight mask); +/** + * @brief Powers on LCD backlights. + * + * @param[in] mask The backlights to power on. + */ +void GFX_powerOnBacklight(const GfxBl mask); -void GFX_powerOffBacklights(GfxBlight mask); +/** + * @brief Powers off LCD backlights. + * + * @param[in] mask The backlights to power off. + */ +void GFX_powerOffBacklight(const GfxBl mask); -void GFX_setBrightness(u16 top, u16 bot); +/** + * @brief Sets the LCD luminance for both LCDs. + * + * @param[in] lum The luminance. + */ +void GFX_setLcdLuminance(const u32 lum); -void GFX_setForceBlack(bool top, bool bot); +/** + * @brief Forces black output to the LCDs. + * + * @param[in] top Set to true for black top LCD. + * @param[in] bot Set to true for black bottom LCD. + */ +void GFX_setForceBlack(const bool top, const bool bot); -void GFX_setDoubleBuffering(u8 screen, bool dBuf); +/** + * @brief Enables or disables double buffering for a LCD. + * + * @param[in] lcd The lcd. + * @param[in] dBuf Set to true to enable double buffering. + */ +void GFX_setDoubleBuffering(const GfxLcd lcd, const bool dBuf); -void* GFX_getFramebuffer(u8 screen); +/** + * @brief Returns the currently inactive frame buffer for drawing. + * Always the same buffer in single buffer mode. + * + * @param[in] lcd The lcd to return the buffer pointer for. + * @param[in] side The side in 3D mode. Otherwise always use GFX_SIDE_LEFT. + * + * @return Returns the frame buffer pointer. + */ +void* GFX_getBuffer(const GfxLcd lcd, const GfxSide side); -void GFX_swapFramebufs(void); +/** + * @brief Flushes the CPU data cache for all current frame buffers. + */ +void GFX_flushBuffers(void); -void GFX_waitForEvent(GfxEvent event, bool discard); +/** + * @brief Swaps the buffers for all LCDs with double buffering enabled. + */ +void GFX_swapBuffers(void); + +/** + * @brief Waits for a GPU hardware event. + * + * @param[in] event The event to wait for. + * @param[in] discard Set to true to clear the event before waiting. + */ +void GFX_waitForEvent(const GfxEvent event); // Helpers -#define GFX_waitForPSC0() GFX_waitForEvent(GFX_EVENT_PSC0, false) -#define GFX_waitForPSC1() GFX_waitForEvent(GFX_EVENT_PSC1, false) -#define GFX_waitForVBlank0() GFX_waitForEvent(GFX_EVENT_PDC0, true) -//#define GFX_waitForVBlank1() GFX_waitForEvent(GFX_EVENT_PDC1, true) // Disabled -#define GFX_waitForPPF() GFX_waitForEvent(GFX_EVENT_PPF, false) -#define GFX_waitForP3D() GFX_waitForEvent(GFX_EVENT_P3D, false) +#define GFX_waitForPSC0() GFX_waitForEvent(GFX_EVENT_PSC0) +#define GFX_waitForPSC1() GFX_waitForEvent(GFX_EVENT_PSC1) +#define GFX_waitForVBlank0() GFX_waitForEvent(GFX_EVENT_PDC0) +#define GFX_waitForVBlank1() GFX_waitForEvent(GFX_EVENT_PDC1) +#define GFX_waitForPPF() GFX_waitForEvent(GFX_EVENT_PPF) +#define GFX_waitForP3D() GFX_waitForEvent(GFX_EVENT_P3D) +/** + * @brief Fill memory with a pattern via DMA. 2 fill engines. + * + * @param buf0a Buffer 0 pointer. Must be 8 bytes aligned. Set to NULL disable. + * @param[in] buf0v Fill 0 pattern size flags. + * @param[in] buf0Sz Fill 0 buffer size in bytes. Must be 8 bytes aligned. + * @param[in] val0 Fill 0 value. + * @param buf1a Buffer 1 pointer. Must be 8 bytes aligned. Set to NULL disable. + * @param[in] buf1v Fill 1 pattern size flags. + * @param[in] buf1Sz Fill 1 buffer size in bytes. Must be 8 bytes aligned. + * @param[in] val1 Fill 1 value. + */ void GX_memoryFill(u32 *buf0a, u32 buf0v, u32 buf0Sz, u32 val0, u32 *buf1a, u32 buf1v, u32 buf1Sz, u32 val1); -void GX_displayTransfer(const u32 *const in, u32 indim, u32 *out, u32 outdim, u32 flags); +/** + * @brief Transfers a pixel buffer from A to B with optional (de)swizzling. + * + * @param[in] src Source pointer. Must be 8 bytes aligned. + * @param[in] inDim Input dimensions. + * @param dst Destination pointer. Must be 8 bytes aligned. + * @param[in] outDim Output dimensions. + * @param[in] flags Transfer control flags. Swizzling, flip, anti-aliasing ect. + */ +void GX_displayTransfer(const u32 *const src, const u32 inDim, u32 *const dst, const u32 outDim, const u32 flags); -void GX_textureCopy(const u32 *const in, u32 indim, u32 *out, u32 outdim, u32 size); +/** + * @brief Raw DMA copy without conversion. + * + * @param[in] src Source pointer. Must be 8 bytes aligned. + * @param[in] inDim Input dimensions. + * @param dst Destination pointer. Must be 8 bytes aligned. + * @param[in] outDim Output dimensions. + * @param[in] size Total transfer size in bytes. + */ +void GX_textureCopy(const u32 *const src, const u32 inDim, u32 *const dst, const u32 outDim, const u32 size); -void GX_processCommandList(u32 size, const u32 *const cmdList); +/** + * @brief Starts GPU command buffer execution. + * + * @param[in] size Buffer size in bytes. Must be 8 bytes aligned. + * @param[in] cmdList Command list buffer pointer. Must be 8 bytes aligned. + */ +void GX_processCommandList(const u32 size, const u32 *const cmdList); -//void GFX_enterLowPowerState(void); +/** + * @brief Power down and prepare graphics hardware for sleep mode. + */ +void GFX_sleep(void); -//void GFX_returnFromLowPowerState(void); +/** + * @brief Wake up/initialize graphics hardware after sleep mode. + */ +void GFX_sleepAwake(void); -#endif +bool GFX_setupExceptionFrameBuffer(void); + +#endif // #ifdef __ARM11__ + +#ifdef __cplusplus +} // extern "C" +#endif \ No newline at end of file diff --git a/libn3ds/include/drivers/lgy_common.h b/libn3ds/include/drivers/lgy_common.h index 11e6490..6a495a4 100644 --- a/libn3ds/include/drivers/lgy_common.h +++ b/libn3ds/include/drivers/lgy_common.h @@ -1,8 +1,8 @@ #pragma once /* - * This file is part of open_agb_firm - * Copyright (C) 2021 derrek, profi200 + * This file is part of libn3ds + * Copyright (C) 2024 derrek, profi200 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,6 +23,11 @@ #include "error_codes.h" +#ifdef __cplusplus +extern "C" +{ +#endif + #define LGY_MAX_ROM_SIZE (1024u * 1024 * 32) #define LGY_MAX_SAVE_SIZE (1024u * 128) #define LGY_ROM_LOC (FCRAM_BASE) @@ -30,7 +35,7 @@ #define LGY_MODE_TWL (1u) #define LGY_MODE_AGB (2u) -#define LGY_MODE_START (1u<<15) +#define LGY_MODE_START BIT(15) enum { @@ -87,3 +92,7 @@ Result LGY_prepareGbaMode(bool directBoot, u16 saveType, const char *const saveP Result LGY_setGbaRtc(const GbaRtc rtc); Result LGY_getGbaRtc(GbaRtc *const out); Result LGY_backupGbaSave(void); + +#ifdef __cplusplus +} // extern "C" +#endif \ No newline at end of file diff --git a/libn3ds/include/drivers/pxi.h b/libn3ds/include/drivers/pxi.h index 621fd1d..684c790 100644 --- a/libn3ds/include/drivers/pxi.h +++ b/libn3ds/include/drivers/pxi.h @@ -1,8 +1,8 @@ #pragma once /* - * This file is part of open_agb_firm - * Copyright (C) 2021 derrek, profi200 + * This file is part of libn3ds + * Copyright (C) 2024 derrek, profi200 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,16 +18,20 @@ * along with this program. If not, see . */ -#include #include "types.h" #include "mem_map.h" -#ifdef ARM9 -#define PXI_REGS_BASE (IO_AHB_BASE + 0x8000) -#elif ARM11 -#define PXI_REGS_BASE (IO_COMMON_BASE + 0x63000) -#endif // #ifdef ARM9 +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifdef __ARM9__ +#define PXI_REGS_BASE (IO_AHB_BASE + 0x8000) +#elif __ARM11__ +#define PXI_REGS_BASE (IO_COMMON_BASE + 0x63000) +#endif // #ifdef __ARM9__ typedef struct { @@ -58,41 +62,46 @@ ALWAYS_INLINE Pxi* getPxiRegs(void) // Note: SENT and RECV in REG_PXI_SYNC do not count // the amount of bytes sent or received through the FIFOs! // They are simply CPU read-/writable fields. -#define PXI_SYNC_RECVD (REG_PXI_SYNC & 0xFFu) -#define PXI_SYNC_SENT(sent) ((REG_PXI_SYNC & ~(0xFFu<<8)) | (sent)<<8) -#ifdef ARM9 -#define PXI_SYNC_IRQ (1u<<29) // Trigger interrupt on ARM11. -#define PXI_SYNC_IRQ2 (1u<<30) // Another, separate interrupt trigger for ARM11. -#elif ARM11 +#define PXI_SYNC_RECVD (REG_PXI_SYNC & 0xFFu) +#define PXI_SYNC_SENT(sent) ((REG_PXI_SYNC & ~(0xFFu<<8)) | (sent)<<8) +#ifdef __ARM9__ +#define PXI_SYNC_IRQ BIT(29) // Trigger interrupt on ARM11. +#define PXI_SYNC_IRQ2 BIT(30) // Another, separate interrupt trigger for ARM11. +#elif __ARM11__ // 29 unused unlike ARM9 side. -#define PXI_SYNC_IRQ (1u<<30) // Trigger interrupt on ARM9. -#endif // #ifdef ARM9 -#define PXI_SYNC_IRQ_EN (1u<<31) // Enable interrupt(s) from remote CPU. +#define PXI_SYNC_IRQ BIT(30) // Trigger interrupt on ARM9. +#endif // #ifdef __ARM9__ +#define PXI_SYNC_IRQ_EN BIT(31) // Enable interrupt(s) from remote CPU. // REG_PXI_SYNC_IRQ (byte 3 of REG_PXI_SYNC) -#ifdef ARM9 -#define PXI_SYNC_IRQ_IRQ (1u<<5) // Trigger interrupt on ARM11. -#define PXI_SYNC_IRQ_IRQ2 (1u<<6) // Another, separate interrupt trigger for ARM11. -#elif ARM11 +#ifdef __ARM9__ +#define PXI_SYNC_IRQ_IRQ BIT(5) // Trigger interrupt on ARM11. +#define PXI_SYNC_IRQ_IRQ2 BIT(6) // Another, separate interrupt trigger for ARM11. +#elif __ARM11__ // 29 unused unlike ARM9 side. -#define PXI_SYNC_IRQ_IRQ (1u<<6) // Trigger interrupt on ARM9. -#endif // #ifdef ARM9 -#define PXI_SYNC_IRQ_IRQ_EN (1u<<7) // Enable interrupt(s) from remote CPU. +#define PXI_SYNC_IRQ_IRQ BIT(6) // Trigger interrupt on ARM9. +#endif // #ifdef __ARM9__ +#define PXI_SYNC_IRQ_IRQ_EN BIT(7) // Enable interrupt(s) from remote CPU. // REG_PXI_CNT // Status bits: 0 = no, 1 = yes. -#define PXI_CNT_SEND_EMPTY (1u<<0) // Send FIFO empty status. -#define PXI_CNT_SEND_FULL (1u<<1) // Send FIFO full status. -#define PXI_CNT_SEND_NOT_FULL_IRQ_EN (1u<<2) // Send FIFO not full interrupt enable. TODO: Test the behavior. -#define PXI_CNT_FLUSH_SEND (1u<<3) // Flush send FIFO. -#define PXI_CNT_RECV_EMPTY (1u<<8) // Receive FIFO empty status. -#define PXI_CNT_RECV_FULL (1u<<9) // Receive FIFO full status. -#define PXI_CNT_RECV_NOT_EMPTY_IRQ_EN (1u<<10) // Receive FIFO not empty interrupt enable. TODO: Test the behavior. -#define PXI_CNT_FIFO_ERROR (1u<<14) // Receive FIFO underrun or send FIFO overrun error flag. Acknowledge by writing 1. -#define PXI_CNT_EN_FIFOS (1u<<15) // Enables REG_PXI_SEND and REG_PXI_RECV FIFOs. +#define PXI_CNT_SEND_EMPTY BIT(0) // Send FIFO empty status. +#define PXI_CNT_SEND_FULL BIT(1) // Send FIFO full status. +#define PXI_CNT_SEND_NOT_FULL_IRQ_EN BIT(2) // Send FIFO not full interrupt enable. TODO: Test the behavior. +#define PXI_CNT_FLUSH_SEND BIT(3) // Flush send FIFO. +#define PXI_CNT_RECV_EMPTY BIT(8) // Receive FIFO empty status. +#define PXI_CNT_RECV_FULL BIT(9) // Receive FIFO full status. +#define PXI_CNT_RECV_NOT_EMPTY_IRQ_EN BIT(10) // Receive FIFO not empty interrupt enable. TODO: Test the behavior. +#define PXI_CNT_FIFO_ERROR BIT(14) // Receive FIFO underrun or send FIFO overrun error flag. Acknowledge by writing 1. +#define PXI_CNT_EN_FIFOS BIT(15) // Enables REG_PXI_SEND and REG_PXI_RECV FIFOs. +// All of the below functions for libn3ds internal usage only. void PXI_init(void); +void PXI_deinit(void); u32 PXI_sendCmd(u32 cmd, const u32 *buf, u32 words); -void PXI_sendPanicCmd(u32 cmd); // Not intended for normal use! + +#ifdef __cplusplus +} // extern "C" +#endif \ No newline at end of file diff --git a/libn3ds/include/drivers/sha.h b/libn3ds/include/drivers/sha.h index 445e6ea..ef9ea26 100644 --- a/libn3ds/include/drivers/sha.h +++ b/libn3ds/include/drivers/sha.h @@ -1,8 +1,8 @@ #pragma once /* - * This file is part of open_agb_firm - * Copyright (C) 2021 derrek, profi200 + * This file is part of libn3ds + * Copyright (C) 2024 derrek, profi200 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,16 +18,20 @@ * along with this program. If not, see . */ -#include #include "types.h" #include "mem_map.h" -#ifdef ARM11 +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifdef __ARM11__ #define SHA_REGS_BASE (IO_COMMON_BASE + 0x1000) -#elif ARM9 +#elif __ARM9__ #define SHA_REGS_BASE (IO_AHB_BASE + 0xA000) -#endif // #ifdef ARM11 +#endif // #ifdef __ARM11__ // Vectorizing the FIFO improves code generation at the cost of being slightly slower for small data. typedef u32 ShaFifo __attribute__((vector_size(64))); @@ -50,19 +54,19 @@ ALWAYS_INLINE Sha* getShaRegs(void) ALWAYS_INLINE volatile ShaFifo* getShaFifo(Sha *const regs) { -#ifdef ARM11 +#ifdef __ARM11__ return (volatile ShaFifo*)((uintptr_t)regs + 0x200000); #else return ®s->fifo; -#endif // #ifdef ARM11 +#endif // #ifdef __ARM11__ } // REG_SHA_CNT -#define SHA_EN (1u) // Also used as busy flag. -#define SHA_FINAL_ROUND (1u<<1) // Final round/add input padding. -#define SHA_I_DMA_EN (1u<<2) // Input DMA enable. -#define SHA_IN_BIG (1u<<3) +#define SHA_EN BIT(0) // Also used as busy flag. +#define SHA_FINAL_ROUND BIT(1) // Final round/add input padding. +#define SHA_I_DMA_EN BIT(2) // Input DMA enable. +#define SHA_IN_BIG BIT(3) #define SHA_IN_LITTLE (0u) #define SHA_OUT_BIG (SHA_IN_BIG) #define SHA_OUT_LITTLE (SHA_IN_LITTLE) @@ -70,9 +74,9 @@ ALWAYS_INLINE volatile ShaFifo* getShaFifo(Sha *const regs) #define SHA_224_MODE (1u<<4) #define SHA_1_MODE (2u<<4) #define SHA_MODE_MASK (SHA_1_MODE | SHA_224_MODE | SHA_256_MODE) -#define SHA_RB_MODE (1u<<8) // Readback mode. -#define SHA_RB_FIFO_NE (1u<<9) // Readback mode FIFO not empty status. -#define SHA_O_DMA_EN (1u<<10) // Output DMA enable (readback mode). +#define SHA_RB_MODE BIT(8) // Readback mode. +#define SHA_RB_FIFO_NE BIT(9) // Readback mode FIFO not empty status. +#define SHA_O_DMA_EN BIT(10) // Output DMA enable (readback mode). @@ -126,6 +130,10 @@ void sha(const u32 *data, u32 size, u32 *const hash, u16 params, u16 hashEndiane * @param[in] params Extra parameters like endianess. See REG_SHA_CNT defines above. * @param[in] hashEndianess Endianess bitmask for the hash. */ -#ifdef ARM9 +#ifdef __ARM9__ void sha_dma(const u32 *data, u32 size, u32 *const hash, u16 params, u16 hashEndianess); -#endif +#endif // #ifdef __ARM9__ + +#ifdef __cplusplus +} // extern "C" +#endif \ No newline at end of file diff --git a/libn3ds/include/drivers/tmio.h b/libn3ds/include/drivers/tmio.h index 5c4cfa0..ba3550b 100644 --- a/libn3ds/include/drivers/tmio.h +++ b/libn3ds/include/drivers/tmio.h @@ -1,19 +1,41 @@ #pragma once -#include +/* + * This file is part of libn3ds + * Copyright (C) 2024 profi200 + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include "types.h" #include "mem_map.h" +#ifdef __cplusplus +extern "C" +{ +#endif + // For simplicity we will name the accessible 2 controllers 1 and 2. // The real controller number is in the comment. -#ifdef ARM9 +#ifdef __ARM9__ #define TMIO1_REGS_BASE (IO_AHB_BASE + 0x6000) // Controller 1. #define TMIO2_REGS_BASE (IO_AHB_BASE + 0x7000) // Controller 3. Remappable. -#elif ARM11 +#elif __ARM11__ #define TMIO1_REGS_BASE (IO_COMMON_BASE + 0x22000) // Controller 2. #define TMIO2_REGS_BASE (IO_COMMON_BASE) // Controller 3. Remappable. -#endif // #ifdef ARM9 +#endif // #ifdef __ARM9__ #define TMIO_HCLK (67027964u) // In Hz. @@ -67,11 +89,11 @@ ALWAYS_INLINE Tmio* getTmioRegs(const u8 controller) ALWAYS_INLINE vu32* getTmioFifo(Tmio *const regs) { -#ifdef ARM11 +#ifdef __ARM11__ return (vu32*)((uintptr_t)regs + 0x200000); // FIFO is in the DMA region. #else return ®s->sd_fifo32; -#endif // #ifdef ARM11 +#endif // #ifdef __ARM11__ } @@ -83,7 +105,7 @@ ALWAYS_INLINE vu32* getTmioFifo(Tmio *const regs) // When using auto response leave bits 11-13 unset (zero). // Bit 0-5 command index. -#define CMD_ACMD (1u<<6) // Application command. +#define CMD_ACMD BIT(6) // Application command. #define CMD_RESP_AUTO (0u) // Response type auto. Only works with certain commands. #define CMD_RESP_NONE (3u<<8) // Response type none. #define CMD_RESP_R1 (4u<<8) // Response type R1 48 bit. @@ -96,11 +118,11 @@ ALWAYS_INLINE vu32* getTmioFifo(Tmio *const regs) #define CMD_RESP_R3 (7u<<8) // Response type R3 48 bit OCR without CRC. #define CMD_RESP_R4 (CMD_RESP_R3) // Response type R4 48 bit OCR without CRC. #define CMD_RESP_MASK (CMD_RESP_R3) -#define CMD_DATA_EN (1u<<11) // Data transfer enable. -#define CMD_DATA_R (1u<<12) // Data transfer direction read. +#define CMD_DATA_EN BIT(11) // Data transfer enable. +#define CMD_DATA_R BIT(12) // Data transfer direction read. #define CMD_DATA_W (0u) // Data transfer direction write. -#define CMD_MULTI_DATA (1u<<13) // Multi block transfer (auto STOP_TRANSMISSION). -#define CMD_SEC_SDIO (1u<<14) // Security/SDIO command. +#define CMD_MULTI_DATA BIT(13) // Multi block transfer (auto STOP_TRANSMISSION). +#define CMD_SEC_SDIO BIT(14) // Security/SDIO command. // REG_SD_PORTSEL #define PORTSEL_P0 (0u) // Controller port 0. @@ -109,72 +131,72 @@ ALWAYS_INLINE vu32* getTmioFifo(Tmio *const regs) #define PORTSEL_P3 (3u) // Controller port 3. #define PORTSEL_MASK (PORTSEL_P3) // Bit 8-9 number of supported ports? -#define PORTSEL_UNK10 (1u<<10) // Unknown writable bit 10? +#define PORTSEL_UNK10 BIT(10) // Unknown writable bit 10? // REG_SD_STOP -#define STOP_STOP (1u) // Abort data transfer and send STOP_TRANSMISSION CMD. -#define STOP_AUTO_STOP (1u<<8) // Automatically send STOP_TRANSMISSION on multi-block transfer end. +#define STOP_STOP BIT(0) // Abort data transfer and send STOP_TRANSMISSION CMD. +#define STOP_AUTO_STOP BIT(8) // Automatically send STOP_TRANSMISSION on multi-block transfer end. // REG_SD_STATUS1/2 Write 0 to acknowledge a bit. // REG_SD_STATUS1/2_MASK (M) = Maskable bit. 1 = disabled. // Unmaskable bits act as status only, don't trigger IRQs and can't be acknowledged. -#define STATUS_RESP_END (1u) // (M) Response end. -#define STATUS_DATA_END (1u<<2) // (M) Data transfer end (triggers after last block). -#define STATUS_REMOVE (1u<<3) // (M) Card got removed. -#define STATUS_INSERT (1u<<4) // (M) Card got inserted. Set at the same time as DETECT. -#define STATUS_DETECT (1u<<5) // Card detect status (SD_OPTION detection timer). 1 = inserted. -#define STATUS_NO_WRPROT (1u<<7) // Write protection slider unlocked (low). -#define STATUS_DAT3_REMOVE (1u<<8) // (M) Card DAT3 got removed (low). -#define STATUS_DAT3_INSERT (1u<<9) // (M) Card DAT3 got inserted (high). -#define STATUS_DAT3_DETECT (1u<<10) // Card DAT3 status. 1 = inserted. -#define STATUS_ERR_CMD_IDX (1u<<16) // (M) Bad CMD index in response. -#define STATUS_ERR_CRC (1u<<17) // (M) Bad CRC in response. -#define STATUS_ERR_STOP_BIT (1u<<18) // (M) Stop bit error. Failed to recognize response frame end? -#define STATUS_ERR_DATA_TIMEOUT (1u<<19) // (M) Response data timeout. -#define STATUS_ERR_RX_OVERF (1u<<20) // (M) Receive FIFO overflow. -#define STATUS_ERR_TX_UNDERF (1u<<21) // (M) Send FIFO underflow. -#define STATUS_ERR_CMD_TIMEOUT (1u<<22) // (M) Response start bit timeout. -#define STATUS_SD_BUSY (1u<<23) // SD card signals busy if this bit is 0 (DAT0 held low). -#define STATUS_RX_RDY (1u<<24) // (M) FIFO ready for read. -#define STATUS_TX_REQ (1u<<25) // (M) FIFO write request. +#define STATUS_RESP_END BIT(0) // (M) Response end. +#define STATUS_DATA_END BIT(2) // (M) Data transfer end (triggers after last block). +#define STATUS_REMOVE BIT(3) // (M) Card got removed. +#define STATUS_INSERT BIT(4) // (M) Card got inserted. Set at the same time as DETECT. +#define STATUS_DETECT BIT(5) // Card detect status (SD_OPTION detection timer). 1 = inserted. +#define STATUS_NO_WRPROT BIT(7) // Write protection slider unlocked (low). +#define STATUS_DAT3_REMOVE BIT(8) // (M) Card DAT3 got removed (low). +#define STATUS_DAT3_INSERT BIT(9) // (M) Card DAT3 got inserted (high). +#define STATUS_DAT3_DETECT BIT(10) // Card DAT3 status. 1 = inserted. +#define STATUS_ERR_CMD_IDX BIT(16) // (M) Bad CMD index in response. +#define STATUS_ERR_CRC BIT(17) // (M) Bad CRC in response. +#define STATUS_ERR_STOP_BIT BIT(18) // (M) Stop bit error. Failed to recognize response frame end? +#define STATUS_ERR_DATA_TIMEOUT BIT(19) // (M) Response data timeout. +#define STATUS_ERR_RX_OVERF BIT(20) // (M) Receive FIFO overflow. +#define STATUS_ERR_TX_UNDERF BIT(21) // (M) Send FIFO underflow. +#define STATUS_ERR_CMD_TIMEOUT BIT(22) // (M) Response start bit timeout. +#define STATUS_SD_BUSY BIT(23) // SD card signals busy if this bit is 0 (DAT0 held low). +#define STATUS_RX_RDY BIT(24) // (M) FIFO ready for read. +#define STATUS_TX_REQ BIT(25) // (M) FIFO write request. // Bit 27 is maskable. Purpose unknown. // Bit 29 exists (not maskable). Signals when clock divider changes are allowed? -#define STATUS_CMD_BUSY (1u<<30) // Command register busy. -#define STATUS_ERR_ILL_ACC (1u<<31) // (M) Illegal access error. TODO: What does that mean? +#define STATUS_CMD_BUSY BIT(30) // Command register busy. +#define STATUS_ERR_ILL_ACC BIT(31) // (M) Illegal access error. TODO: What does that mean? #define STATUS_MASK_ALL (0xFFFFFFFFu) -#define STATUS_MASK_DEFAULT ((1u<<27) | STATUS_TX_REQ | STATUS_RX_RDY | \ +#define STATUS_MASK_DEFAULT (BIT(27) | STATUS_TX_REQ | STATUS_RX_RDY | \ STATUS_DAT3_INSERT | STATUS_DAT3_REMOVE) #define STATUS_MASK_ERR (STATUS_ERR_ILL_ACC | STATUS_ERR_CMD_TIMEOUT | STATUS_ERR_TX_UNDERF | \ STATUS_ERR_RX_OVERF | STATUS_ERR_DATA_TIMEOUT | STATUS_ERR_STOP_BIT | \ STATUS_ERR_CRC | STATUS_ERR_CMD_IDX) // REG_SD_CLK_CTRL -#define SD_CLK_DIV_2 (0u) // Clock divider 2. -#define SD_CLK_DIV_4 (1u) // Clock divider 4. -#define SD_CLK_DIV_8 (1u<<1) // Clock divider 8. -#define SD_CLK_DIV_16 (1u<<2) // Clock divider 16. -#define SD_CLK_DIV_32 (1u<<3) // Clock divider 32. -#define SD_CLK_DIV_64 (1u<<4) // Clock divider 64. -#define SD_CLK_DIV_128 (1u<<5) // Clock divider 128. -#define SD_CLK_DIV_256 (1u<<6) // Clock divider 256. -#define SD_CLK_DIV_512 (1u<<7) // Clock divider 512. -#define SD_CLK_EN (1u<<8) // Clock enable. -#define SD_CLK_PWR_SAVE (1u<<9) // Disables clock on idle. +#define SD_CLK_DIV_2 (0u) // Clock divider 2. +#define SD_CLK_DIV_4 BIT(0) // Clock divider 4. +#define SD_CLK_DIV_8 BIT(1) // Clock divider 8. +#define SD_CLK_DIV_16 BIT(2) // Clock divider 16. +#define SD_CLK_DIV_32 BIT(3) // Clock divider 32. +#define SD_CLK_DIV_64 BIT(4) // Clock divider 64. +#define SD_CLK_DIV_128 BIT(5) // Clock divider 128. +#define SD_CLK_DIV_256 BIT(6) // Clock divider 256. +#define SD_CLK_DIV_512 BIT(7) // Clock divider 512. +#define SD_CLK_EN BIT(8) // Clock enable. +#define SD_CLK_PWR_SAVE BIT(9) // Disables clock on idle. // Bit 10 is writable... at least according to gbatek (can't confirm). Purpose unknown. // Outputs the matching divider for clk. // Shift the output right by 2 to get the value for REG_SD_CLK_CTRL. -#define TMIO_CLK2DIV(clk) \ -({ \ - u32 __shift = 1; \ - while((clk) < TMIO_HCLK>>__shift) ++__shift; \ - 1u<<__shift; \ -}) +ALWAYS_INLINE u32 TMIO_clk2div(const u32 clk) +{ + u32 shift = 1; + while(clk < TMIO_HCLK>>shift) ++shift; + return BIT(shift); +} // Clock off by default. // Nearest possible for 400 kHz is 261.827984375 kHz. -#define SD_CLK_DEFAULT (TMIO_CLK2DIV(400000)>>2) +#define SD_CLK_DEFAULT (TMIO_clk2div(400000)>>2) // REG_SD_OPTION // Note on card detection time: @@ -183,9 +205,9 @@ ALWAYS_INLINE vu32* getTmioFifo(Tmio *const regs) // // Bit 0-3 card detect timer 0x400<sd_clk_ctrl = SD_CLK_PWR_SAVE | SD_CLK_EN | TMIO_CLK2DIV(clk)>>2; + port->sd_clk_ctrl = SD_CLK_PWR_SAVE | SD_CLK_EN | TMIO_clk2div(clk)>>2; } /** @@ -401,3 +423,7 @@ ALWAYS_INLINE void TMIO_setBuffer(TmioPort *const port, void *buf, const u16 blo port->buf = buf; port->blocks = blocks; } + +#ifdef __cplusplus +} // extern "C" +#endif \ No newline at end of file diff --git a/libn3ds/include/drivers/tmio_config.h b/libn3ds/include/drivers/tmio_config.h index 011c7d9..3b6bcaf 100644 --- a/libn3ds/include/drivers/tmio_config.h +++ b/libn3ds/include/drivers/tmio_config.h @@ -18,14 +18,19 @@ * along with this program. If not, see . */ -#ifdef ARM9 +#ifdef __ARM9__ #include "arm9/drivers/interrupt.h" #include "arm9/drivers/cfg9.h" -#elif ARM11 +#elif __ARM11__ #include "arm11/drivers/interrupt.h" -#endif // #ifdef ARM9 +#endif // #ifdef __ARM9__ +#ifdef __cplusplus +extern "C" +{ +#endif + // Note on port numbers: // To make things easier 2 ports are assigned to each controller. // There are a maximum of 2 controllers mapped at the same time @@ -39,18 +44,18 @@ // ARM9 or ARM11 when TMIO_CARD_PORT for ARM9 is set to 2. #define TMIO_C2_MAP (0u) // Controller 2 (physical 3) memory mapping. 0=ARM9 0x10007000 or 1=ARM11 0x10100000. -#ifdef ARM9 +#ifdef __ARM9__ #define TMIO_CARD_PORT (2u) // Can be on port 0 or 2. 0 always on ARM9. #define TMIO_eMMC_PORT (1u) // Port 1 only. Do not change. -#elif ARM11 +#elif __ARM11__ #define TMIO_CARD_PORT (2u) // Port 2 only. Do not change. #define TMIO_eMMC_PORT (3u) // Placeholder. Do not change. Not connected/accessible. -#endif // #ifdef ARM9 +#endif // #ifdef __ARM9__ // Don't modify anything below! -#ifdef ARM9 +#ifdef __ARM9__ #define TMIO_MAP_CONTROLLERS() \ { \ getCfg9Regs()->sdmmcctl = (TMIO_CARD_PORT == 2u ? SDMMCCTL_CARD_TMIO3_SEL : SDMMCCTL_CARD_TMIO1_SEL) | \ @@ -67,7 +72,7 @@ if(TMIO_NUM_CONTROLLERS == 2u) \ IRQ_registerIsr(IRQ_TMIO3, (isr)); \ } -#elif ARM11 +#elif __ARM11__ #define TMIO_MAP_CONTROLLERS() #define TMIO_UNMAP_CONTROLLERS() #define TMIO_NUM_CONTROLLERS (TMIO_C2_MAP == 1u ? 2u : 1u) @@ -78,7 +83,7 @@ if(TMIO_NUM_CONTROLLERS == 2u) \ IRQ_registerIsr(IRQ_TMIO3, 14, 0, (isr)); \ } -#endif // #ifdef ARM9 +#endif // #ifdef __ARM9__ #define TMIO_UNREGISTER_ISR() \ { \ @@ -86,3 +91,7 @@ if(TMIO_NUM_CONTROLLERS == 2u) \ IRQ_unregisterIsr(IRQ_TMIO3); \ } + +#ifdef __cplusplus +} // extern "C" +#endif \ No newline at end of file diff --git a/libn3ds/source/drivers/corelink_dma-330.c b/libn3ds/source/drivers/corelink_dma-330.c index 064c7bd..af068e8 100644 --- a/libn3ds/source/drivers/corelink_dma-330.c +++ b/libn3ds/source/drivers/corelink_dma-330.c @@ -1,6 +1,6 @@ /* - * This file is part of open_agb_firm - * Copyright (C) 2021 derrek, profi200 + * This file is part of libn3ds + * Copyright (C) 2024 derrek, profi200 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,7 +21,7 @@ #include "drivers/cache.h" -#ifdef ARM11 +#ifdef __ARM11__ #ifdef USE_NEW_CDMA #error "TODO: New3DS CDMA" #else @@ -29,13 +29,13 @@ #define PERIPHALS (18u) #define IRQ_LINES (9u) // The controller reports 16 but we only have 9 physical lines. #endif // ifdef USE_NEW_CDMA -#elif ARM9 +#elif __ARM9__ #define CHANNELS (4u) #define PERIPHALS (8u) #define IRQ_LINES (12u) -#endif // ifdef ARM11 +#endif // ifdef __ARM11__ -#define INTEN_VAL ((1u< 0) { -#ifdef ARM11 +#ifdef __ARM11__ u16 progBuf[33]; // Max 32 periphals + 1 for DMAEND. -#elif ARM9 +#elif __ARM9__ u16 *progBuf = (u16*)(AHB_RAM_BASE + AHB_RAM_SIZE - 33 * 2); // ARM9 DTCM stack workaround. -#endif // ifdef ARM11 +#endif // ifdef __ARM11__ for(u32 i = 0; i < PERIPHALS; i++) { // DMAFLUSHP i. @@ -141,7 +141,7 @@ void DMA330_kill(u8 ch) } } -/*#ifdef ARM11 +/*#ifdef __ARM11__ #include "arm11/fmt.h" void DMA330_dbgPrint(void) { @@ -153,4 +153,4 @@ void DMA330_dbgPrint(void) ee_printf(" CSR/FTR%lu: %08lX %08lX\n", i, dma330->chStat[i].csr, dma330->ftr[i]); } } -#endif*/ // ifdef ARM11 +#endif*/ // ifdef __ARM11__ \ No newline at end of file diff --git a/libn3ds/source/drivers/mmc/sdmmc.c b/libn3ds/source/drivers/mmc/sdmmc.c index 43446d5..40119c1 100644 --- a/libn3ds/source/drivers/mmc/sdmmc.c +++ b/libn3ds/source/drivers/mmc/sdmmc.c @@ -1,6 +1,6 @@ /* - * This file is part of open_agb_firm - * Copyright (C) 2021 derrek, profi200 + * This file is part of libn3ds + * Copyright (C) 2024 derrek, profi200 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,11 +20,11 @@ #include "drivers/mmc/sdmmc.h" // Includes types.h. #include "drivers/tmio.h" #include "drivers/tmio_config.h" -#ifdef ARM9 +#ifdef __ARM9__ #include "arm9/drivers/timer.h" -#elif ARM11 +#elif __ARM11__ #include "arm11/drivers/timer.h" -#endif // #ifdef ARM9 +#endif // #ifdef __ARM9__ #include "drivers/mmc/mmc_spec.h" #include "drivers/mmc/sd_spec.h" @@ -237,7 +237,7 @@ static u32 initIdentState(SdmmcDev *const dev, const u8 devType, u32 *const rcaO // Extracts up to 32 bits from a u32[4] array. static inline u32 extractBits(const u32 resp[4], const u32 start, const u32 size) { - const u32 mask = (size < 32 ? 1u<ccc & 1u<<10) // Class 10 command support. + if(dev->ccc & BIT(10)) // Class 10 command support. { // Set 64 bytes block length for SWITCH_FUNC status. TMIO_setBlockLen(port, 64); @@ -383,7 +383,7 @@ static u32 initTranState(SdmmcDev *const dev, const u8 devType, const u32 rca, c TMIO_setBlockLen(port, 512); // [415:400] Support Bits of Functions in Function Group 1. - if(switchStat[63u - 400 / 8] & 1u<<1) // Is group 1, function 1 "High-Speed" supported? + if(switchStat[63u - 400 / 8] & BIT(1)) // Is group 1, function 1 "High-Speed" supported? { // High-Speed (max. 50 MHz at 3.3V) supported. Switch to highest supported clock. TMIO_setClock(port, HS_CLOCK); @@ -483,7 +483,7 @@ u32 SDMMC_setSleepMode(const u8 devNum, const bool enabled) if(IS_DEV_MMC(devType)) { // Switch (e)MMC into sleep mode. - res = TMIO_sendCommand(port, MMC_SLEEP_AWAKE, rca | 1u<<15); + res = TMIO_sendCommand(port, MMC_SLEEP_AWAKE, rca | BIT(15)); if(res != 0) return SDMMC_ERR_SLEEP_AWAKE; // TODO: Power down eMMC. This is confirmed working on 3DS. } @@ -574,8 +574,8 @@ u32 SDMMC_lockUnlock(const u8 devNum, const u8 mode, const u8 *const pwd, const res = SDMMC_ERR_LOCK_UNLOCK_FAIL; // Update lock status. - const u8 prot = dev->prot & ~(1u<<3); - dev->prot = prot | (status>>22 & 1u<<3); + const u8 prot = dev->prot & ~BIT(3); + dev->prot = prot | (status>>22 & BIT(3)); } while(0); return res; @@ -616,7 +616,7 @@ u32 SDMMC_importDevState(const u8 devNum, const u8 devIn[64]) return SDMMC_ERR_NONE; } -#ifdef ARM9 +#ifdef __ARM9__ typedef struct { bool initialized; @@ -710,7 +710,7 @@ u32 SDMMC_importHosEmmcState(void) return SDMMC_ERR_NONE; } -#endif +#endif // #ifdef __ARM9__ // TODO: Less controller dependent code. u32 SDMMC_getDevInfo(const u8 devNum, SdmmcInfo *const infoOut) @@ -744,8 +744,8 @@ u32 SDMMC_getCid(const u8 devNum, u32 cidOut[4]) return SDMMC_ERR_NONE; } -#include "fatfs/ff.h" // Needed for the "byte" type used in diskio.h. -#include "fatfs/diskio.h" +#include "fatfs/source/ff.h" // Needed for the "byte" type used in diskio.h. +#include "fatfs/source/diskio.h" u8 SDMMC_getDiskStatus(const u8 devNum) { if(devNum > SDMMC_MAX_DEV_NUM) return STA_NODISK | STA_NOINIT; @@ -891,4 +891,4 @@ u32 SDMMC_getLastR1error(const u8 devNum) dev->status = 0; return status; -} +} \ No newline at end of file diff --git a/libn3ds/source/drivers/pxi.c b/libn3ds/source/drivers/pxi.c index 6c8de73..af9a3f5 100644 --- a/libn3ds/source/drivers/pxi.c +++ b/libn3ds/source/drivers/pxi.c @@ -1,6 +1,6 @@ /* * This file is part of open_agb_firm - * Copyright (C) 2021 derrek, profi200 + * Copyright (C) 2023 derrek, profi200 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,13 +18,12 @@ #include "types.h" #include "drivers/pxi.h" -#ifdef ARM9 - #include "arm9/drivers/interrupt.h" - #include "arm9/debug.h" -#elif ARM11 - #include "arm11/drivers/interrupt.h" - #include "arm11/debug.h" -#endif // #ifdef ARM9 +#ifdef __ARM9__ +#include "arm9/drivers/interrupt.h" +#elif __ARM11__ +#include "arm11/drivers/interrupt.h" +#endif // #ifdef __ARM9__ +#include "debug.h" #include "ipc_handler.h" #include "fb_assert.h" #include "drivers/cache.h" @@ -50,7 +49,7 @@ static inline u32 recvWord(const Pxi *const pxi) static inline bool getFifoError(const Pxi *const pxi) { - return (pxi->cnt & PXI_CNT_FIFO_ERROR) != 0u; + return !!(pxi->cnt & PXI_CNT_FIFO_ERROR); } static inline void sendSyncRequest(Pxi *const pxi) @@ -61,28 +60,33 @@ static inline void sendSyncRequest(Pxi *const pxi) void PXI_init(void) { Pxi *const pxi = getPxiRegs(); - pxi->sync = PXI_SYNC_IRQ_EN; pxi->cnt = PXI_CNT_EN_FIFOS | PXI_CNT_FIFO_ERROR | PXI_CNT_FLUSH_SEND; // TODO: Make this handshake IRQ driven. -#ifdef ARM9 +#ifdef __ARM9__ sendWord(pxi, 0x99); while(recvWord(pxi) != 0x11); IRQ_registerIsr(IRQ_PXI_SYNC, pxiIrqHandler); -#elif ARM11 +#elif __ARM11__ while(recvWord(pxi) != 0x99); sendWord(pxi, 0x11); IRQ_registerIsr(IRQ_PXI_SYNC, 13, 0, pxiIrqHandler); -#endif +#endif // #ifdef __ARM9__ +} + +void PXI_deinit(void) +{ + Pxi *const pxi = getPxiRegs(); + pxi->cnt = PXI_CNT_FIFO_ERROR | PXI_CNT_FLUSH_SEND; + pxi->sync = 0; } static void pxiIrqHandler(UNUSED u32 id) { Pxi *const pxi = getPxiRegs(); - const u32 cmdCode = recvWord(pxi); if(cmdCode & IPC_CMD_RESP_FLAG) { @@ -139,7 +143,7 @@ u32 PXI_sendCmd(u32 cmd, const u32 *buf, u32 words) g_lastResp[0] = 0; const u32 res = g_lastResp[1]; -#ifdef ARM11 +#ifdef __ARM11__ // The CPU may do speculative prefetches of data after the first invalidation // so we need to do it again. for(u32 i = sendBufs; i < sendBufs + recvBufs; i++) @@ -147,17 +151,7 @@ u32 PXI_sendCmd(u32 cmd, const u32 *buf, u32 words) const IpcBuffer *const recvBuf = (IpcBuffer*)&buf[i * sizeof(IpcBuffer) / 4]; if(recvBuf->ptr && recvBuf->size) invalidateDCacheRange(recvBuf->ptr, recvBuf->size); } -#endif +#endif // #ifdef __ARM11__ return res; -} - -void PXI_sendPanicCmd(u32 cmd) -{ - Pxi *const pxi = getPxiRegs(); - - sendWord(pxi, cmd); - sendSyncRequest(pxi); - while(recvWord(pxi) != (IPC_CMD_RESP_FLAG | cmd)); - // We don't care about the result. -} +} \ No newline at end of file diff --git a/libn3ds/source/drivers/sha.c b/libn3ds/source/drivers/sha.c index 83efea9..99d284f 100644 --- a/libn3ds/source/drivers/sha.c +++ b/libn3ds/source/drivers/sha.c @@ -1,6 +1,6 @@ /* * This file is part of open_agb_firm - * Copyright (C) 2021 derrek, profi200 + * Copyright (C) 2024 derrek, profi200 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ */ #include "drivers/sha.h" -#include "mmio.h" +#include "memory.h" @@ -50,7 +50,7 @@ void SHA_update(const u32 *data, u32 size) if(size != 0u) { waitBusy(sha); - iomemcpy((vu32*)fifo, data, size); + copy32((u32*)fifo, data, size); } } @@ -80,7 +80,7 @@ void SHA_getState(u32 *const out) size = 20; } - iomemcpy(out, sha->hash, size); + copy32(out, (u32*)sha->hash, size); } void sha(const u32 *data, u32 size, u32 *const hash, u16 params, u16 hashEndianess) @@ -90,7 +90,7 @@ void sha(const u32 *data, u32 size, u32 *const hash, u16 params, u16 hashEndiane SHA_finish(hash, hashEndianess); } -#ifdef ARM11 +#ifdef __ARM11__ // Note: The FIFO is 64 bit capable but 64 bit is slower than 32 bit. /*SHA CDMA test prog: # 4 bytes burst with 16 transfers. Total 64 bytes per burst. @@ -129,7 +129,7 @@ void sha_dma(const u32 *data, u32 size, u32 *const hash, u16 params, u16 hashEnd SHA_finish(hash, hashEndianess); }*/ -#elif ARM9 +#elif __ARM9__ #include "arm9/drivers/ndma.h" #include "arm9/drivers/interrupt.h" @@ -156,4 +156,4 @@ void sha_dma(const u32 *data, u32 size, u32 *const hash, u16 params, u16 hashEnd SHA_finish(hash, hashEndianess); } -#endif // #ifdef ARM11 +#endif // #ifdef __ARM11__ diff --git a/libn3ds/source/drivers/tmio.c b/libn3ds/source/drivers/tmio.c index 1646845..9feb4b0 100644 --- a/libn3ds/source/drivers/tmio.c +++ b/libn3ds/source/drivers/tmio.c @@ -16,15 +16,14 @@ * along with this program. If not, see . */ -#include #include "types.h" #include "drivers/tmio.h" #include "drivers/tmio_config.h" -#ifdef ARM9 +#ifdef __ARM9__ #include "util.h" // wait_cycles() -#elif ARM11 +#elif __ARM11__ #include "arm11/drivers/timer.h" -#endif // #ifdef ARM9 +#endif // #ifdef __ARM9__ // Using atomic load/store produces better code than volatile @@ -32,17 +31,16 @@ #define GET_STATUS(ptr) atomic_load_explicit((ptr), memory_order_relaxed) #define SET_STATUS(ptr, val) atomic_store_explicit((ptr), (val), memory_order_relaxed) -#ifdef ARM9 -// TODO: Use a timer instead? The delay is only ~283 µs at ~261 kHz though. +#ifdef __ARM9__ +// TODO: Use a timer instead? The delay is only ~282.628 µs at ~261.827 kHz. // ARM9 timer clock = controller clock. CPU is x2 timer clock. -#define INIT_DELAY_FUNC() wait_cycles(2 * TMIO_CLK2DIV(400000u) * 74) -#elif ARM11 -// ARM11 timer is x2 controller clock. -#define INIT_DELAY_FUNC() TIMER_sleepTicks(2 * TMIO_CLK2DIV(400000u) * 74) -#endif // #ifdef ARM9 +#define INIT_DELAY_FUNC() wait_cycles(2 * TMIO_clk2div(400000u) * 74) +#elif __ARM11__ +#define INIT_DELAY_FUNC() TIMER_sleepNs((1000000000ull * TMIO_clk2div(400000u) * 74) / TMIO_HCLK) +#endif // #ifdef __ARM9__ -static u32 g_status[2] = {0}; +static au32 g_status[2] = {0}; @@ -56,7 +54,7 @@ static void tmioIsr(const u32 id) const u8 controller = (id == TMIO_IRQ_ID_CONTROLLER1 ? 0 : 1); Tmio *const regs = getTmioRegs(controller); - g_status[controller] |= regs->sd_status; + SET_STATUS(&g_status[controller], GET_STATUS(&g_status[controller]) | regs->sd_status); regs->sd_status = STATUS_CMD_BUSY; // Never acknowledge STATUS_CMD_BUSY. // TODO: Some kind of event to notify the main loop for remove/insert. @@ -151,12 +149,12 @@ static void setPort(Tmio *const regs, const TmioPort *const port) bool TMIO_cardDetected(void) { - return getTmioRegs(port2Controller(TMIO_CARD_PORT))->sd_status & STATUS_DETECT; + return !!(getTmioRegs(port2Controller(TMIO_CARD_PORT))->sd_status & STATUS_DETECT); } bool TMIO_cardWritable(void) { - return getTmioRegs(port2Controller(TMIO_CARD_PORT))->sd_status & STATUS_NO_WRPROT; + return !!(getTmioRegs(port2Controller(TMIO_CARD_PORT))->sd_status & STATUS_NO_WRPROT); } void TMIO_powerupSequence(TmioPort *const port) @@ -188,7 +186,7 @@ static void getResponse(const Tmio *const regs, TmioPort *const port, const u16 // Note: Using STATUS_DATA_END to detect transfer end doesn't work reliably // because STATUS_DATA_END fires before we even read anything from FIFO // on single block read transfer. -static void doCpuTransfer(Tmio *const regs, const u16 cmd, u8 *buf, const u32 *const statusPtr) +static void doCpuTransfer(Tmio *const regs, const u16 cmd, u8 *buf, const au32 *const statusPtr) { const u32 blockLen = regs->sd_blocklen; u32 blockCount = regs->sd_blockcount; @@ -202,9 +200,8 @@ static void doCpuTransfer(Tmio *const regs, const u16 cmd, u8 *buf, const u32 *c const u8 *const blockEnd = buf + blockLen; do { -#ifdef ARM11 +#ifdef __ARM11__ // ARM11 supports unaligned access. - // TODO: Adjust diskio to allow unaligned transfers. *((u32*)buf) = *fifo; #else if((uintptr_t)buf % 4 == 0) @@ -219,7 +216,7 @@ static void doCpuTransfer(Tmio *const regs, const u16 cmd, u8 *buf, const u32 *c buf[2] = tmp>>16; buf[3] = tmp>>24; } -#endif +#endif // #ifdef __ARM11__ buf += 4; } while(buf < blockEnd); @@ -239,7 +236,7 @@ static void doCpuTransfer(Tmio *const regs, const u16 cmd, u8 *buf, const u32 *c const u8 *const blockEnd = buf + blockLen; do { -#ifdef ARM11 +#ifdef __ARM11__ // ARM11 supports unaligned access. *fifo = *((u32*)buf); #else @@ -255,7 +252,7 @@ static void doCpuTransfer(Tmio *const regs, const u16 cmd, u8 *buf, const u32 *c tmp |= (u32)buf[3]<<24; *fifo = tmp; } -#endif +#endif // #ifdef __ARM11__ buf += 4; } while(buf < blockEnd); @@ -272,7 +269,7 @@ u32 TMIO_sendCommand(TmioPort *const port, const u16 cmd, const u32 arg) Tmio *const regs = getTmioRegs(controller); // Clear status before sending another command. - u32 *const statusPtr = &g_status[controller]; + au32 *const statusPtr = &g_status[controller]; SET_STATUS(statusPtr, 0); setPort(regs, port); @@ -308,4 +305,4 @@ u32 TMIO_sendCommand(TmioPort *const port, const u16 cmd, const u32 arg) // STATUS_CMD_BUSY is no longer set at this point. return GET_STATUS(statusPtr) & STATUS_MASK_ERR; -} +} \ No newline at end of file