mirror of
https://gitee.com/anod/open_agb_firm.git
synced 2025-05-06 13:54:09 +08:00
pxi.h: 添加了清理处理回调
gfx: 常量大改名、函数大改名,增加了双缓冲的一些驱动函数 其他:基本是ARM9/ARM11宏修改和BIT取值修改,bool从c风格转成c++强类型风格等。sha.c使用了memory.h进行的改动(copy32)
This commit is contained in:
parent
c04e09a770
commit
78da297199
@ -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
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#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<<DSR_WAKEUP_EVNT_SHIFT)
|
||||
#define DSR_DNS (1u<<9) // DMA Manager is non-secure.
|
||||
#define DSR_DNS BIT(9) // DMA Manager is non-secure.
|
||||
|
||||
enum
|
||||
{
|
||||
@ -115,51 +119,51 @@ enum
|
||||
};
|
||||
|
||||
// REG_DMA330_INTEN
|
||||
#define INTEN_SEL_IRQ(n) (1u<<(n)) // Select IRQ instead of event.
|
||||
#define INTEN_SEL_IRQ(n) BIT(n) // Select IRQ instead of event.
|
||||
|
||||
// REG_DMA330_INT_EVENT_RIS
|
||||
#define INT_EVENT_RIS_ACTIVE(n) (1u<<(n)) // Interrupt or event N is active.
|
||||
#define INT_EVENT_RIS_ACTIVE(n) BIT(n) // Interrupt or event N is active.
|
||||
|
||||
// REG_DMA330_INTMIS
|
||||
#define INTMIS_IRQ_ACTIVE(n) (1u<<(n)) // Interrupt N is active.
|
||||
#define INTMIS_IRQ_ACTIVE(n) BIT(n) // Interrupt N is active.
|
||||
|
||||
// REG_DMA330_INTCLR
|
||||
#define INTCLR_IRQ_CLR(n) (1u<<(n)) // Clear interrupt N.
|
||||
#define INTCLR_IRQ_CLR(n) BIT(n) // Clear interrupt N.
|
||||
|
||||
// REG_DMA330_FSRD
|
||||
#define FSRD_FAULTING (1u) // DMA manager is in faulting state.
|
||||
#define FSRD_FAULTING BIT(0) // DMA manager is in faulting state.
|
||||
|
||||
// REG_DMA330_FSRC
|
||||
#define FSRC_FAULTING(n) (1u<<(n)) // DMA channel is in faulting or faulting completing state.
|
||||
#define FSRC_FAULTING(n) BIT(n) // DMA channel is in faulting or faulting completing state.
|
||||
|
||||
// REG_DMA330_FTRD
|
||||
#define FTRD_UNDEF_INSTR (1u)
|
||||
#define FTRD_OPERAND_INVALID (1u<<1)
|
||||
#define FTRD_DMAGO_ERR (1u<<4) // Starting a secure channel from a non-secure state.
|
||||
#define FTRD_MGR_EVNT_ERR (1u<<5) // Waiting for or creating secure events/interrupts in no-secure state.
|
||||
#define FTRD_INSTR_FETCH_ERR (1u<<16)
|
||||
#define FTRD_DBG_INSTR (1u<<30) // The erroneous instruction came from the debug interface.
|
||||
#define FTRD_UNDEF_INSTR BIT(0)
|
||||
#define FTRD_OPERAND_INVALID BIT(1)
|
||||
#define FTRD_DMAGO_ERR BIT(4) // Starting a secure channel from a non-secure state.
|
||||
#define FTRD_MGR_EVNT_ERR BIT(5) // Waiting for or creating secure events/interrupts in no-secure state.
|
||||
#define FTRD_INSTR_FETCH_ERR BIT(16)
|
||||
#define FTRD_DBG_INSTR BIT(30) // The erroneous instruction came from the debug interface.
|
||||
|
||||
// REG_DMA330_FTR0-7
|
||||
#define FTR_UNDEF_INSTR (1u)
|
||||
#define FTR_OPERAND_INVALID (1u<<1)
|
||||
#define FTR_CH_EVNT_ERR (1u<<5) // Waiting for or creating secure events/interrupts in no-secure state.
|
||||
#define FTR_CH_PERIPH_ERR (1u<<6) // Accessing secure periphals in non-secure state (DMAWFP, DMALDP, DMASTP, DMAFLUSHP).
|
||||
#define FTR_CH_RDWR_ERR (1u<<7) // Secure read or write in non-secure state.
|
||||
#define FTR_CH_MFIFO_ERR (1u<<12) // MFIFO too small to hold or store the data (DMALD, DMAST).
|
||||
#define FTR_CH_ST_DATA_UNAVAIL (1u<<13) // Not enough data in the MFIFO for DMAST to complete.
|
||||
#define FTR_INSTR_FETCH_ERR (1u<<16)
|
||||
#define FTR_DATA_WRITE_ERR (1u<<17)
|
||||
#define FTR_DATA_READ_ERR (1u<<18)
|
||||
#define FTR_DBG_INSTR (1u<<30) // The erroneous instruction came from the debug interface.
|
||||
#define FTR_LOCKUP_ERR (1u<<31) // Channel locked up because of resource starvation.
|
||||
#define FTR_UNDEF_INSTR BIT(0)
|
||||
#define FTR_OPERAND_INVALID BIT(1)
|
||||
#define FTR_CH_EVNT_ERR BIT(5) // Waiting for or creating secure events/interrupts in no-secure state.
|
||||
#define FTR_CH_PERIPH_ERR BIT(6) // Accessing secure periphals in non-secure state (DMAWFP, DMALDP, DMASTP, DMAFLUSHP).
|
||||
#define FTR_CH_RDWR_ERR BIT(7) // Secure read or write in non-secure state.
|
||||
#define FTR_CH_MFIFO_ERR BIT(12) // MFIFO too small to hold or store the data (DMALD, DMAST).
|
||||
#define FTR_CH_ST_DATA_UNAVAIL BIT(13) // Not enough data in the MFIFO for DMAST to complete.
|
||||
#define FTR_INSTR_FETCH_ERR BIT(16)
|
||||
#define FTR_DATA_WRITE_ERR BIT(17)
|
||||
#define FTR_DATA_READ_ERR BIT(18)
|
||||
#define FTR_DBG_INSTR BIT(30) // The erroneous instruction came from the debug interface.
|
||||
#define FTR_LOCKUP_ERR BIT(31) // Channel locked up because of resource starvation.
|
||||
|
||||
// REG_DMA330_CSR0-7
|
||||
#define CSR_WAKE_EVNT_SHIFT (4u)
|
||||
#define CSR_WAKE_EVNT_MASK (0x1Fu<<CSR_WAKEUP_EVNT_SHIFT)
|
||||
#define CSR_DMAWFP_B_NS (1u<<14) // DMAWFP executed with burst operand set.
|
||||
#define CSR_DMAWFP_PERIPH (1u<<15) // DMAWFP executed with periph operand set.
|
||||
#define CSR_CNS (1u<<21) // DMA channel is non-secure.
|
||||
#define CSR_DMAWFP_B_NS BIT(14) // DMAWFP executed with burst operand set.
|
||||
#define CSR_DMAWFP_PERIPH BIT(15) // DMAWFP executed with periph operand set.
|
||||
#define CSR_CNS BIT(21) // DMA channel is non-secure.
|
||||
|
||||
enum
|
||||
{
|
||||
@ -179,7 +183,7 @@ enum
|
||||
};
|
||||
|
||||
// REG_DMA330_CCR0-7
|
||||
#define CCR_SRC_INC (1u)
|
||||
#define CCR_SRC_INC BIT(0)
|
||||
#define CCR_SRC_BURST_SIZE_SHIFT (1u)
|
||||
#define CCR_SRC_BURST_SIZE_MASK (0x7u<<CCR_SRC_BURST_SIZE_SHIFT)
|
||||
#define CCR_SRC_BURST_LEN_SHIFT (4u)
|
||||
@ -189,7 +193,7 @@ enum
|
||||
#define CCR_SRC_CACHE_CTRL_SHIFT (11u)
|
||||
#define CCR_SRC_CACHE_CTRL_MASK (0x7u<<CCR_SRC_CACHE_CTRL_SHIFT)
|
||||
|
||||
#define CCR_DST_INC (1u<<14)
|
||||
#define CCR_DST_INC BIT(14)
|
||||
#define CCR_DST_BURST_SIZE_SHIFT (15u)
|
||||
#define CCR_DST_BURST_SIZE_MASK (0x7u<<CCR_DST_BURST_SIZE_SHIFT)
|
||||
#define CCR_DST_BURST_LEN_SHIFT (18u)
|
||||
@ -203,26 +207,30 @@ enum
|
||||
#define CCR_END_SWP_SIZE_MASK (0x7u<<CCR_END_SWP_SIZE_SHIFT)
|
||||
|
||||
// REG_DMA330_DBGSTATUS
|
||||
#define DBGSTATUS_BUSY (1u)
|
||||
#define DBGSTATUS_BUSY BIT(0)
|
||||
|
||||
// REG_DMA330_DBGCMD
|
||||
#define DBGCMD_EXECUTE (0u)
|
||||
|
||||
// REG_DMA330_DBGINST0
|
||||
#define DBGINST0_THR_MGR (0u) // Select DMA manager thread.
|
||||
#define DBGINST0_THR_CH (1u) // Select DMA channel thread (also needs a channel number).
|
||||
#define DBGINST0_THR_MGR (0u) // Select DMA manager thread.
|
||||
#define DBGINST0_THR_CH BIT(0) // Select DMA channel thread (also needs a channel number).
|
||||
#define DBGINST0(b10, ch, t) ((b10)<<16 | (ch)<<8 | (t)) // b10 = byte 1 and 0, ch = channel num, t = thread.
|
||||
// DBGINST1 stores the remaining 4 instruction bytes.
|
||||
|
||||
|
||||
|
||||
void DMA330_init(void);
|
||||
void DMA330_init(void); // For libn3ds internal usage only.
|
||||
u8 DMA330_run(u8 ch, const u8 *const prog);
|
||||
u8 DMA330_status(u8 ch);
|
||||
void DMA330_ackIrq(u8 eventIrq);
|
||||
void DMA330_sev(u8 event);
|
||||
void DMA330_kill(u8 ch);
|
||||
|
||||
#ifdef ARM11
|
||||
#ifdef __ARM11__
|
||||
//void DMA330_dbgPrint(void);
|
||||
#endif // ifdef ARM11
|
||||
#endif // ifdef __ARM11__
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
@ -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 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,45 +18,71 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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);
|
||||
|
||||
bool GFX_setupExceptionFrameBuffer(void);
|
||||
|
||||
#endif // #ifdef __ARM11__
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
@ -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
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#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
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#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 // #ifdef __ARM9__
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
@ -1,19 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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<<x HCLKs. 0xF timer test (0x100 HCLKs).
|
||||
// Bit 4-7 data timeout 0x2000<<x SDCLKs. 0xF timeout test (0x100 SDCLKs).
|
||||
#define OPTION_UNK14 (1u<<14) // "no C2 module" What the fuck is a C2 module?
|
||||
#define OPTION_BUS_WIDTH4 (0u) // 4 bit bus width.
|
||||
#define OPTION_BUS_WIDTH1 (1u<<15) // 1 bit bus width.
|
||||
#define OPTION_UNK14 BIT(14) // "no C2 module" What the fuck is a C2 module?
|
||||
#define OPTION_BUS_WIDTH4 (0u) // 4 bit bus width.
|
||||
#define OPTION_BUS_WIDTH1 BIT(15) // 1 bit bus width.
|
||||
|
||||
// Card detect time: 0x400<<9 / 67027964 = 0.007821929 seconds.
|
||||
// Data timeout: 0x2000<<12 / (67027964 / 2) = 1.001206959 seconds.
|
||||
@ -193,100 +215,100 @@ ALWAYS_INLINE vu32* getTmioFifo(Tmio *const regs)
|
||||
|
||||
// REG_SD_ERR_STATUS1/2 Write 0 to acknowledge a bit.
|
||||
// TODO: Are all of these actually supported on this controller?
|
||||
#define ERR_RESP_CMD_IDX (1u) // Manual command index error in response.
|
||||
#define ERR_RESP_CMD12_IDX (1u<<1) // Auto command index error in response.
|
||||
#define ERR_RESP_STOP_BIT (1u<<2) // Manual command response stop bit error.
|
||||
#define ERR_RESP_STOP_BIT_CMD12 (1u<<3) // Auto command response stop bit error.
|
||||
#define ERR_STOP_BIT_DATA_READ (1u<<4) // Stop bit error in read data.
|
||||
#define ERR_STOP_BIT_WR_CRC (1u<<5) // Stop bit error for write CRC status. What the hell does that mean?
|
||||
#define ERR_CMD_RESP_CRC (1u<<8) // Manual command response CRC error.
|
||||
#define ERR_CMD12_RESP_CRC (1u<<9) // Auto command response CRC error.
|
||||
#define ERR_DATA_READ_CRC (1u<<10) // CRC error for read data.
|
||||
#define ERR_WR_CRC_STAT (1u<<11) // "CRC error for Write CRC status for a write command". What the hell does that mean?
|
||||
#define ERR_RESP_CMD_IDX BIT(0) // Manual command index error in response.
|
||||
#define ERR_RESP_CMD12_IDX BIT(1) // Auto command index error in response.
|
||||
#define ERR_RESP_STOP_BIT BIT(2) // Manual command response stop bit error.
|
||||
#define ERR_RESP_STOP_BIT_CMD12 BIT(3) // Auto command response stop bit error.
|
||||
#define ERR_STOP_BIT_DATA_READ BIT(4) // Stop bit error in read data.
|
||||
#define ERR_STOP_BIT_WR_CRC BIT(5) // Stop bit error for write CRC status. What the hell does that mean?
|
||||
#define ERR_CMD_RESP_CRC BIT(8) // Manual command response CRC error.
|
||||
#define ERR_CMD12_RESP_CRC BIT(9) // Auto command response CRC error.
|
||||
#define ERR_DATA_READ_CRC BIT(10) // CRC error for read data.
|
||||
#define ERR_WR_CRC_STAT BIT(11) // "CRC error for Write CRC status for a write command". What the hell does that mean?
|
||||
// Bit 13 always 1.
|
||||
#define ERR_CMD_RESP_TMOUT (1u<<16) // Manual command response timeout.
|
||||
#define ERR_CMD12_RESP_TMOUT (1u<<17) // Auto command response timeout.
|
||||
#define ERR_CMD_RESP_TMOUT BIT(16) // Manual command response timeout.
|
||||
#define ERR_CMD12_RESP_TMOUT BIT(17) // Auto command response timeout.
|
||||
// TODO: Add the correct remaining ones.
|
||||
|
||||
// REG_SDIO_MODE
|
||||
#define SDIO_MODE_SDIO_IRQ_EN (1u) // SDIO IRQ enable (DAT1 low).
|
||||
#define SDIO_MODE_UNK2_EN (1u<<2) // IRQ on "read wait" requests?
|
||||
#define SDIO_MODE_UNK8 (1u<<8) // Aborts command and data transfer?
|
||||
#define SDIO_MODE_UNK9 (1u<<9) // Aborts command but not data transfer? CMD52 related.
|
||||
#define SDIO_MODE_SDIO_IRQ_EN BIT(0) // SDIO IRQ enable (DAT1 low).
|
||||
#define SDIO_MODE_UNK2_EN BIT(2) // IRQ on "read wait" requests?
|
||||
#define SDIO_MODE_UNK8 BIT(8) // Aborts command and data transfer?
|
||||
#define SDIO_MODE_UNK9 BIT(9) // Aborts command but not data transfer? CMD52 related.
|
||||
|
||||
// REG_SDIO_STATUS Write 0 to acknowledge a bit.
|
||||
// REG_SDIO_STATUS_MASK (M) = Maskable bit. 1 = disabled.
|
||||
#define SDIO_STATUS_SDIO_IRQ (1u) // (M) SDIO IRQ (DAT1 low).
|
||||
#define SDIO_STATUS_UNK1_IRQ (1u<<1) // (M) IRQ once CMD52 can be used after abort?
|
||||
#define SDIO_STATUS_UNK2_IRQ (1u<<2) // (M) Related to SDIO_MODE_UNK2_EN?
|
||||
#define SDIO_STATUS_UNK14_IRQ (1u<<14) // (M) Related to SDIO_MODE_UNK9?
|
||||
#define SDIO_STATUS_UNK15_IRQ (1u<<15) // (M) Related to SDIO_MODE_UNK2_EN?
|
||||
#define SDIO_STATUS_SDIO_IRQ BIT(0) // (M) SDIO IRQ (DAT1 low).
|
||||
#define SDIO_STATUS_UNK1_IRQ BIT(1) // (M) IRQ once CMD52 can be used after abort?
|
||||
#define SDIO_STATUS_UNK2_IRQ BIT(2) // (M) Related to SDIO_MODE_UNK2_EN?
|
||||
#define SDIO_STATUS_UNK14_IRQ BIT(14) // (M) Related to SDIO_MODE_UNK9?
|
||||
#define SDIO_STATUS_UNK15_IRQ BIT(15) // (M) Related to SDIO_MODE_UNK2_EN?
|
||||
|
||||
#define SDIO_STATUS_MASK_ALL (0xFFFFu)
|
||||
|
||||
// REG_DMA_EXT_MODE
|
||||
#define DMA_EXT_CPU_MODE (0u) // Disables DMA requests. Actually also turns off the 32 bit FIFO.
|
||||
#define DMA_EXT_DMA_MODE (1u<<1) // Enables DMA requests.
|
||||
#define DMA_EXT_UNK5 (1u<<5) // "Buffer status mode"?
|
||||
#define DMA_EXT_CPU_MODE (0u) // Disables DMA requests. Actually also turns off the 32 bit FIFO.
|
||||
#define DMA_EXT_DMA_MODE BIT(1) // Enables DMA requests.
|
||||
#define DMA_EXT_UNK5 BIT(5) // "Buffer status mode"?
|
||||
|
||||
// REG_SOFT_RST
|
||||
#define SOFT_RST_RST (0u) // Reset.
|
||||
#define SOFT_RST_NORST (1u) // No reset.
|
||||
#define SOFT_RST_RST (0u) // Reset.
|
||||
#define SOFT_RST_NORST BIT(0) // No reset.
|
||||
|
||||
// REG_EXT_SDIO_IRQ
|
||||
#define EXT_SDIO_IRQ_P1 (1u) // Port 1 SDIO IRQ (DAT1 low). Write 0 to acknowledge.
|
||||
#define EXT_SDIO_IRQ_P2 (1u<<1) // Port 2 SDIO IRQ (DAT1 low). Write 0 to acknowledge.
|
||||
#define EXT_SDIO_IRQ_P3 (1u<<2) // Port 3 SDIO IRQ (DAT1 low). Write 0 to acknowledge.
|
||||
#define EXT_SDIO_IRQ_P1_EN (1u<<4) // Port 1 SDIO IRQ enable (controller).
|
||||
#define EXT_SDIO_IRQ_P2_EN (1u<<5) // Port 2 SDIO IRQ enable (controller).
|
||||
#define EXT_SDIO_IRQ_P3_EN (1u<<6) // Port 3 SDIO IRQ enable (controller).
|
||||
#define EXT_SDIO_IRQ_P1_MASK (1u<<8) // Port 1 SDIO IRQ mask. 1 = disable IRQ (CPU).
|
||||
#define EXT_SDIO_IRQ_P2_MASK (1u<<9) // Port 2 SDIO IRQ mask. 1 = disable IRQ (CPU).
|
||||
#define EXT_SDIO_IRQ_P3_MASK (1u<<10) // Port 3 SDIO IRQ mask. 1 = disable IRQ (CPU).
|
||||
#define EXT_SDIO_IRQ_P1 BIT(0) // Port 1 SDIO IRQ (DAT1 low). Write 0 to acknowledge.
|
||||
#define EXT_SDIO_IRQ_P2 BIT(1) // Port 2 SDIO IRQ (DAT1 low). Write 0 to acknowledge.
|
||||
#define EXT_SDIO_IRQ_P3 BIT(2) // Port 3 SDIO IRQ (DAT1 low). Write 0 to acknowledge.
|
||||
#define EXT_SDIO_IRQ_P1_EN BIT(4) // Port 1 SDIO IRQ enable (controller).
|
||||
#define EXT_SDIO_IRQ_P2_EN BIT(5) // Port 2 SDIO IRQ enable (controller).
|
||||
#define EXT_SDIO_IRQ_P3_EN BIT(6) // Port 3 SDIO IRQ enable (controller).
|
||||
#define EXT_SDIO_IRQ_P1_MASK BIT(8) // Port 1 SDIO IRQ mask. 1 = disable IRQ (CPU).
|
||||
#define EXT_SDIO_IRQ_P2_MASK BIT(9) // Port 2 SDIO IRQ mask. 1 = disable IRQ (CPU).
|
||||
#define EXT_SDIO_IRQ_P3_MASK BIT(10) // Port 3 SDIO IRQ mask. 1 = disable IRQ (CPU).
|
||||
|
||||
#define EXT_SDIO_IRQ_MASK_ALL (EXT_SDIO_IRQ_P3_MASK | EXT_SDIO_IRQ_P2_MASK | EXT_SDIO_IRQ_P1_MASK)
|
||||
|
||||
// REG_EXT_WRPROT Each bit 1 = write protected unlike SD_STATUS.
|
||||
#define EXT_WRPROT_P1 (1u)
|
||||
#define EXT_WRPROT_P2 (1u<<1)
|
||||
#define EXT_WRPROT_P3 (1u<<2)
|
||||
#define EXT_WRPROT_P1 BIT(0)
|
||||
#define EXT_WRPROT_P2 BIT(1)
|
||||
#define EXT_WRPROT_P3 BIT(2)
|
||||
|
||||
// REG_EXT_CDET Acknowledgeable?
|
||||
// REG_EXT_CDET_MASK (M) = Maskable bit. 1 = disabled (no IRQ).
|
||||
#define EXT_CDET_P1_REMOVE (1u) // (M) Port 1 card got removed.
|
||||
#define EXT_CDET_P1_INSERT (1u<<1) // (M) Port 1 card got inserted. TODO: With detection timer?
|
||||
#define EXT_CDET_P1_DETECT (1u<<2) // Port 1 card detect status. 1 = inserted. TODO: With detection timer?
|
||||
#define EXT_CDET_P2_REMOVE (1u<<3) // (M) Port 2 card got removed.
|
||||
#define EXT_CDET_P2_INSERT (1u<<4) // (M) Port 2 card got inserted. TODO: With detection timer?
|
||||
#define EXT_CDET_P2_DETECT (1u<<5) // Port 2 card detect status. 1 = inserted. TODO: With detection timer?
|
||||
#define EXT_CDET_P3_REMOVE (1u<<6) // (M) Port 3 card got removed.
|
||||
#define EXT_CDET_P3_INSERT (1u<<7) // (M) Port 3 card got inserted. TODO: With detection timer?
|
||||
#define EXT_CDET_P3_DETECT (1u<<8) // Port 3 card detect status. 1 = inserted. TODO: With detection timer?
|
||||
#define EXT_CDET_P1_REMOVE BIT(0) // (M) Port 1 card got removed.
|
||||
#define EXT_CDET_P1_INSERT BIT(1) // (M) Port 1 card got inserted. TODO: With detection timer?
|
||||
#define EXT_CDET_P1_DETECT BIT(2) // Port 1 card detect status. 1 = inserted. TODO: With detection timer?
|
||||
#define EXT_CDET_P2_REMOVE BIT(3) // (M) Port 2 card got removed.
|
||||
#define EXT_CDET_P2_INSERT BIT(4) // (M) Port 2 card got inserted. TODO: With detection timer?
|
||||
#define EXT_CDET_P2_DETECT BIT(5) // Port 2 card detect status. 1 = inserted. TODO: With detection timer?
|
||||
#define EXT_CDET_P3_REMOVE BIT(6) // (M) Port 3 card got removed.
|
||||
#define EXT_CDET_P3_INSERT BIT(7) // (M) Port 3 card got inserted. TODO: With detection timer?
|
||||
#define EXT_CDET_P3_DETECT BIT(8) // Port 3 card detect status. 1 = inserted. TODO: With detection timer?
|
||||
|
||||
#define EXT_CDET_MASK_ALL (0xFFFFu)
|
||||
|
||||
// REG_EXT_CDET_DAT3 Acknowledgeable?
|
||||
// REG_EXT_CDET_DAT3_MASK (M) = Maskable bit. 1 = disabled (no IRQ).
|
||||
#define EXT_CDET_DAT3_P1_REMOVE (1u) // (M) Port 1 card DAT3 got removed (low).
|
||||
#define EXT_CDET_DAT3_P1_INSERT (1u<<1) // (M) Port 1 card DAT3 got inserted (high).
|
||||
#define EXT_CDET_DAT3_P1_DETECT (1u<<2) // Port 1 card DAT3 status. 1 = inserted.
|
||||
#define EXT_CDET_DAT3_P2_REMOVE (1u<<3) // (M) Port 2 card DAT3 got removed (low).
|
||||
#define EXT_CDET_DAT3_P2_INSERT (1u<<4) // (M) Port 2 card DAT3 got inserted (high).
|
||||
#define EXT_CDET_DAT3_P2_DETECT (1u<<5) // Port 2 card DAT3 status. 1 = inserted.
|
||||
#define EXT_CDET_DAT3_P3_REMOVE (1u<<6) // (M) Port 3 card DAT3 got removed (low).
|
||||
#define EXT_CDET_DAT3_P3_INSERT (1u<<7) // (M) Port 3 card DAT3 got inserted (high).
|
||||
#define EXT_CDET_DAT3_P3_DETECT (1u<<8) // Port 3 card DAT3 status. 1 = inserted.
|
||||
#define EXT_CDET_DAT3_P1_REMOVE BIT(0) // (M) Port 1 card DAT3 got removed (low).
|
||||
#define EXT_CDET_DAT3_P1_INSERT BIT(1) // (M) Port 1 card DAT3 got inserted (high).
|
||||
#define EXT_CDET_DAT3_P1_DETECT BIT(2) // Port 1 card DAT3 status. 1 = inserted.
|
||||
#define EXT_CDET_DAT3_P2_REMOVE BIT(3) // (M) Port 2 card DAT3 got removed (low).
|
||||
#define EXT_CDET_DAT3_P2_INSERT BIT(4) // (M) Port 2 card DAT3 got inserted (high).
|
||||
#define EXT_CDET_DAT3_P2_DETECT BIT(5) // Port 2 card DAT3 status. 1 = inserted.
|
||||
#define EXT_CDET_DAT3_P3_REMOVE BIT(6) // (M) Port 3 card DAT3 got removed (low).
|
||||
#define EXT_CDET_DAT3_P3_INSERT BIT(7) // (M) Port 3 card DAT3 got inserted (high).
|
||||
#define EXT_CDET_DAT3_P3_DETECT BIT(8) // Port 3 card DAT3 status. 1 = inserted.
|
||||
|
||||
#define EXT_CDET_DAT3_MASK_ALL (0xFFFFu)
|
||||
|
||||
// REG_SD_FIFO32_CNT
|
||||
// Bit 0 unknown, non-writable.
|
||||
#define FIFO32_EN (1u<<1) // Enables the 32 bit FIFO.
|
||||
#define FIFO32_FULL (1u<<8) // FIFO is full.
|
||||
#define FIFO32_NOT_EMPTY (1u<<9) // FIFO is not empty. Inverted bit. 0 means empty.
|
||||
#define FIFO32_CLEAR (1u<<10) // Clears the FIFO.
|
||||
#define FIFO32_FULL_IE (1u<<11) // FIFO full IRQ enable.
|
||||
#define FIFO32_NOT_EMPTY_IE (1u<<12) // FIFO not empty IRQ enable.
|
||||
#define FIFO32_EN BIT(1) // Enables the 32 bit FIFO.
|
||||
#define FIFO32_FULL BIT(8) // FIFO is full.
|
||||
#define FIFO32_NOT_EMPTY BIT(9) // FIFO is not empty. Inverted bit. 0 means empty.
|
||||
#define FIFO32_CLEAR BIT(10) // Clears the FIFO.
|
||||
#define FIFO32_FULL_IE BIT(11) // FIFO full IRQ enable.
|
||||
#define FIFO32_NOT_EMPTY_IE BIT(12) // FIFO not empty IRQ enable.
|
||||
|
||||
|
||||
|
||||
@ -304,12 +326,12 @@ typedef struct
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initializes the tmio driver.
|
||||
* @brief Initializes the tmio driver. For libn3ds internal usage only.
|
||||
*/
|
||||
void TMIO_init(void);
|
||||
|
||||
/**
|
||||
* @brief Deinitializes the tmio driver.
|
||||
* @brief Deinitializes the tmio driver. For libn3ds internal usage only.
|
||||
*/
|
||||
void TMIO_deinit(void);
|
||||
|
||||
@ -361,7 +383,7 @@ u32 TMIO_sendCommand(TmioPort *const port, const u16 cmd, const u32 arg);
|
||||
*/
|
||||
ALWAYS_INLINE void TMIO_setClock(TmioPort *const port, const u32 clk)
|
||||
{
|
||||
port->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
|
@ -18,14 +18,19 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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
|
@ -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<<IRQ_LINES) - 1) // Not 32 bit safe!
|
||||
#define INTEN_VAL (BIT(IRQ_LINES) - 1) // Not 32 bit safe!
|
||||
|
||||
|
||||
|
||||
@ -81,11 +81,11 @@ void DMA330_init(void)
|
||||
|
||||
if(PERIPHALS > 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__
|
@ -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<<size : 0u) - 1;
|
||||
const u32 mask = (size < 32 ? BIT(size) : 0u) - 1;
|
||||
const u32 off = 3 - (start / 32);
|
||||
const u32 shift = start & 31u;
|
||||
|
||||
@ -368,7 +368,7 @@ static u32 initTranState(SdmmcDev *const dev, const u8 devType, const u32 rca, c
|
||||
if(res != 0) return SDMMC_ERR_SET_BUS_WIDTH;
|
||||
TMIO_setBusWidth(port, 4);
|
||||
|
||||
if(dev->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;
|
||||
|
@ -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.
|
||||
}
|
||||
|
@ -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__
|
||||
|
@ -16,15 +16,14 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdatomic.h>
|
||||
#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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user