From b7de559b78196a09453a9c328cadf50dbfc1f68e Mon Sep 17 00:00:00 2001 From: Lephe Date: Sat, 20 Jun 2020 11:41:13 +0200 Subject: [PATCH] some cleanup in src/core and in the repository --- TODO | 9 --- include/core/setup.h | 36 ------------ include/gint/drivers.h | 113 +++++++++++++++++++++----------------- make/Makefile | 1 + src/core/cpu.h | 34 ++++++++++++ src/core/{vbr.s => cpu.s} | 28 +++------- src/core/gint.c | 3 +- src/core/setup.c | 29 +++------- src/core/vbr.h | 32 +++++++++++ src/render-cg/dvram.c | 2 + 10 files changed, 151 insertions(+), 136 deletions(-) delete mode 100644 include/core/setup.h create mode 100644 src/core/cpu.h rename src/core/{vbr.s => cpu.s} (51%) create mode 100644 src/core/vbr.h diff --git a/TODO b/TODO index d46a7d7..fd0ad71 100644 --- a/TODO +++ b/TODO @@ -2,37 +2,28 @@ For the 2.1.0 release: * core: the four basic memory functions (with automated tests) * bopti: remove the deprecated image_t definition * project: remove the compat branch -* gray: remove g*() functions * core: remove the boot log Issues: -* #3 make drawing functions parameterized * #8 support fx-CG Manager * #10 support fx-CG 20 Extensions on existing code: * bopti: try to display fullscreen images with TLB access + DMA on fxcg50 -* gray: add gprint() * gray: double-buffer gray settings and unify d* with g* * topti: support unicode fonts * gray: find good values for more models than the Graph 35+E II * dma: fx9860g support (need to switch it on and update the Makefile) * core: try to leave add-in without reset in case of panic * hardware: fill in the HWMEM_FITTLB flag -* keyboard: think of extended functions * cpg: spread spectrum on fxcg50 -* display: use more of topti's assembler in drect() * core: use cmp/str for memchr() * r61524: brightness control and clean the file -* t6k11: check if dupdate() can be done by the DMA * core: review forgotten globals and MPU addresses not in * build: make the build system simpler (two targets are enough by default) * core: run destructors when a task-switch results in leaving the app * core: invoke main menu instead of returning after main() ends -* prizm: don't hardcode stack address in fxcg50.ld (if possible) -* prizm: detect P1 static RAM (stack) in TLB * core rtc: use qdiv10 to massively improve division performance -* core: document the SH7305 PFC in Future directions. * A complete file system abstraction diff --git a/include/core/setup.h b/include/core/setup.h deleted file mode 100644 index 803b1ea..0000000 --- a/include/core/setup.h +++ /dev/null @@ -1,36 +0,0 @@ -//--- -// core:setup - Installing and unloading the library -//--- - -#ifndef GINT_CORE_SETUP -#define GINT_CORE_SETUP - -#include - -/* Prototypes for the library management functions are in */ - -/* gint_setvbr() - Changes the VBR address and calls the configuration function while - interrupts are disabled. The configuration function must disable all - interrupts that the new handlers cannot handle, either by clearing the - priority registers or by setting the interrupt masks. - - @vbr New VBR address - @configure Configuration function - Returns the previous VBR address. */ -uint32_t gint_setvbr(uint32_t vbr, void (*configure)(void)); - -void gint_setcpuopm(uint32_t CPUOPM); -uint32_t gint_getcpuopm(void); - -/* gint_exch(): Exception handler */ -void gint_exch(void); -/* gint_tlbh(): TLB miss handler */ -void gint_tlbh(void); - -/* gint_inth_7705(): SH7705 exception handler */ -void gint_inth_7705(void); -/* gint_inth_7305(): SH7305 exception handler */ -void gint_inth_7305(void); - -#endif /* GINT_CORE_SETUP */ diff --git a/include/gint/drivers.h b/include/gint/drivers.h index 7ae9eb9..6a2d599 100644 --- a/include/gint/drivers.h +++ b/include/gint/drivers.h @@ -8,60 +8,74 @@ #include #include -//--- -// Driver procedure flow -// -// Drivers are initialized in priority order, and in linking order within -// the same priority level (pretty much undefined). Make sure every -// driver's priority level is higher than those of its dependencies. In -// the description below, every function can be NULL. -// -// At initialization, the following functions are called: -// 1. driver_sh3() [on SH3-based fx9860g only] -// 2. ctx_save(sys_ctx) -// 3. init() -// -// If the gint_switch() function is called to temporarily give back -// control to the operating system, the state of each driver is saved to -// the stack, then restored from there. -// 4. wait() -// 5. ctx_save(gint_ctx) -// 6. ctx_restore(sys_ctx) -// (stuff happening outside of gint) -// 7. ctx_save(sys_ctx) -// 8. ctx_restore(gint_ctx) -// -// When finally the driver is unloaded, the system context is restored. -// 9. wait() -// 10. ctx_restore(sys_ctx) -//--- +/* Driver procedure flow -/* gint_driver_t - driver meta-information used by gint */ + Drivers are initialized in priority order, and in linking order within the + the same priority level (which is pretty much undefined). Every driver's + priority level must be higher than those of its dependencies; the numbers + are fixed, see the documentation for level assignments. + + At initialization, drivers are first called to wait for the hardware to + become available before initialization. Then the system state is saved. We + still support SH3-based SH7705-like MPUs, so a function init_sh3() is called + for every driver that need to make adjustments to support them. Finally, the + driver is initialized. The calls are as follow; every function pointer can + be NULL in which case it is ignored. + + 1. wait() + 2. ctx_save(sys_ctx) + 3. driver_sh3() [SH3-based fx9860g] + 4. init() + + During the execution, gint_switch() can be called to temporarily give back + control to the OS. In this case, the state of each driver is saved to a + context from gint, then restored from there afterwards. + + 5. wait() + 6. ctx_save(gint_ctx) + 7. ctx_restore(sys_ctx) + (stuff happening outside of gint) + 8. wait() + 9. ctx_save(sys_ctx) + 10. ctx_restore(gint_ctx) + + When finally the driver is unloaded, the system context is restored. + + 11. wait() + 12. ctx_restore(sys_ctx) + + The wait() function is called both when gint has control and when the OS has + control; thus, it must not rely on any internal state other than the + hardware itself. + + The ctx_save() and ctx_restore() function are called with interrupts + disabled (IMASK=15) so you should not rely on interrupts. However, TLB + misses are still enabled so you can rely on TLB updates. */ + +/* gint_driver_t: Metadata and interface of kernel drivers */ typedef struct { /* Driver name */ char const *name; - /* SH3-specific preinitializaton; called before init() when running on - SH3. May be NULL. */ + /* SH3-specific initialization step. May be NULL. */ void (*driver_sh3)(void); - - /* Must initialize the hardware so that the driver can start working. - This is called only once when the add-in starts, and should not save - hardware state (ctx_save() is called before). May be NULL. */ + /* Should initialize the hardware so that the driver can start working. + Usually installs interrupt handlers and configures interrupts. Only + called once when the add-in starts. May be NULL. */ void (*init)(void); - /* This function can be used to enforce a waiting period before the - driver is unloaded. It is called before returning to the OS in - gint_switch() and if the add-in exits. May be NULL. */ + /* Should wait for the hardware to become available. Called both under + gint control and OS control every time control is passed around. It + is used for instance to wait for DMA transfers. May be NULL. */ void (*wait)(void); /* System's context and gint's context. These should point to enough - memory to store a full driver state each. These are used when - switching from the system to gint and back to the main menu. If they - don't need to be initialized, put them in gint's uninitialized BSS - section using the GBSS macro of . May be - NULL only if both ctx_save() and ctx_restore() are NULL. */ + memory to store a full driver state each. Used when switching from + the system to gint and back to the main menu. If they don't need to + be initialized, put them in gint's uninitialized BSS section using + the GBSS macro of . May be NULL only if both + ctx_save() and ctx_restore() are NULL. */ void *sys_ctx; void *gint_ctx; @@ -69,30 +83,29 @@ typedef struct possible (memory-mapped MPU registers, port state, etc). This function is called to save the system's hardware state and gint's hardware state when moving from one into the other. The parameter - [ctx] is always either [sys_ctx] or [gint_ctx]. */ + is always either sys_ctx or gint_ctx. */ void (*ctx_save)(void *ctx); - /* Must restore the state of the driver as saved by ctx_save(). */ void (*ctx_restore)(void *ctx); } GPACKED(4) gint_driver_t; -/* GINT_DECLARE_DRIVER() - make a driver visible to gint +/* GINT_DECLARE_DRIVER(): Declare a driver to the kernel - Use this macro to expose a driver by passing it the name of a gint_driver_t + Use this macro to declare a driver by passing it the name of a gint_driver_t structure. This macro moves the structure to the .gint.drivers.* sections, which are automatically traversed at startup. - The @level argument represents the priority level: lower numbers mean that + The level argument represents the priority level: lower numbers mean that drivers will be loaded sooner. This numbering allows a primitive form of dependency for drivers. You need to specify a level which is strictly higher than the level of all the drivers you depend on. */ #define GINT_DECLARE_DRIVER(level, name) \ GSECTION(".gint.drivers." #level) extern gint_driver_t name; -/* GINT_DRIVER_SH3() - declare a function for SH3 preinitialization - This macro makes its argument NULL on fxcg50, this way the named function - can be defined under #ifdef FX9860G while keeping the structure clean. */ +/* GINT_DRIVER_SH3(): Declare an init_sh3() function + This macro is NULL on fxcg50, so that the named function can be defined + under #ifdef FX9860G while keeping the structure clean. */ #ifdef FXCG50 #define GINT_DRIVER_SH3(name) NULL diff --git a/make/Makefile b/make/Makefile index e92843d..d293964 100755 --- a/make/Makefile +++ b/make/Makefile @@ -95,6 +95,7 @@ version_hash = 0x0$(shell git rev-parse --short HEAD) all: $(target) $(target): $(obj) + @ rm -f $@ $(call cmd_l,ar,$@) $(ar) rcs $(arflags) $@ $^ # Assembler sources diff --git a/src/core/cpu.h b/src/core/cpu.h new file mode 100644 index 0000000..adbf082 --- /dev/null +++ b/src/core/cpu.h @@ -0,0 +1,34 @@ +//--- +// core:cpu - CPU registers and operation management +//--- + +#ifndef GINT_CORE_CPU +#define GINT_CORE_CPU + +#include + +/* cpu_setVBR(): Change VBR address + + Blocks interrupts then changes the VBR address and calls the provided INTC + configuration function before restoring interrupts. This function must + configure the INTC in a way that is safe for the new VBR controller, + including disabling all interrupts that it cannot handle. + + @vbr New VBR address + @conf_intc Configuration function + Returns the previous VBR address. */ +uint32_t cpu_setVBR(uint32_t vbr, void (*conf_intc)(void)); + +/* cpu_setCPUOPM(): Change the CPU Operation Mode register + + Updates the CPU Operation Mode with the specified settings, then performs a + read and an ICBI to register the change. Only writable bits of CPUOPM should + be changed, other bits must be left at the value given by cpu_getcpuopm(). + + @CPUOPM New operation mode */ +void cpu_setCPUOPM(uint32_t CPUOPM); + +/* cpu_getCPUOPM(): Get the CPU OperatioN Mode register */ +uint32_t cpu_getCPUOPM(void); + +#endif /* GINT_CORE_CPU */ diff --git a/src/core/vbr.s b/src/core/cpu.s similarity index 51% rename from src/core/vbr.s rename to src/core/cpu.s index 69bbe41..4b1afdd 100644 --- a/src/core/vbr.s +++ b/src/core/cpu.s @@ -2,22 +2,14 @@ ** gint:core:vbr - Assembler-level VBR management */ -.global _gint_setvbr -.global _gint_setcpuopm -.global _gint_getcpuopm +.global _cpu_setVBR +.global _cpu_setCPUOPM +.global _cpu_getCPUOPM .section .gint.mapped -/* gint_setvbr() - Changes the VBR address and the calls the configuration function while - interrupts are disabled. The configuration function must change either the - priority registers or the interrupt masks, and make sure that all the - interrupts that it leaves enabled are handled by the new VBR handlers. - - @r4 vbr New VBR address (uint32_t) - @r5 configure Configuration function (void -> void) - Returns the previous VBR address. */ -_gint_setvbr: +/* cpu_setVBR(): Change VBR address */ +_cpu_setVBR: mov.l r9, @-r15 mov.l r8, @-r15 sts.l pr, @-r15 @@ -53,11 +45,8 @@ _gint_setvbr: .text -/* gint_setcpuopm() - Changes the CPUOPM value and executes an ICBI to register the change. - - @r4 New value of CPUOPM (uint32_t) */ -_gint_setcpuopm: +/* cpu_setCPUOPM(): Change the CPU Operation Mode register */ +_cpu_setCPUOPM: /* Set CPUOPM as requested */ mov.l 1f, r0 mov.l r4, @r0 @@ -74,7 +63,8 @@ _gint_setcpuopm: rts nop -_gint_getcpuopm: +/* cpu_getCPUOPM(): Get the CPU OperatioN Mode register */ +_cpu_getCPUOPM: mov.l 1f, r0 rts mov.l @r0, r0 diff --git a/src/core/gint.c b/src/core/gint.c index 86dc9a0..0bd8561 100644 --- a/src/core/gint.c +++ b/src/core/gint.c @@ -6,6 +6,7 @@ #include #include #include +#include "vbr.h" /* Interrupt controllers */ @@ -49,8 +50,6 @@ int gint_intlevel(int intid, int level) /* gint_inthandler() - configure interrupt handlers */ void *gint_inthandler(int event_code, const void *handler, size_t size) { - extern uint32_t gint_vbr; - /* Normalize the event code */ event_code -= 0x400; event_code &= ~0x1f; diff --git a/src/core/setup.c b/src/core/setup.c index a123dff..cf52928 100644 --- a/src/core/setup.c +++ b/src/core/setup.c @@ -5,27 +5,16 @@ #include #include #include -#include #include #include #include #include - -/* VBR address, from the linker script */ -#ifdef FX9860G -extern char gint_vbr_fx9860g[]; -#endif -#ifdef FXCG50 -extern char gint_vbr_fxcg50[]; -extern char gint_vbr_fxcg20[]; -#endif +#include "cpu.h" +#include "vbr.h" /* VBR addresses for gint and the system */ GBSS uint32_t gint_vbr; GBSS static uint32_t system_vbr; -/* Size of exception and TLB handler */ -extern char gint_exch_size; -extern char gint_tlbh_size; /* Driver table */ extern gint_driver_t bdrv, edrv; @@ -59,7 +48,7 @@ GMAPPED static void gint_ctx_save(gint_core_ctx *ctx) for(int i = 0; i < 13; i++, IMR += 4) ctx->masks[i] = *IMR; - ctx->CPUOPM = gint_getcpuopm(); + ctx->CPUOPM = cpu_getCPUOPM(); } } @@ -86,7 +75,7 @@ GMAPPED static void gint_ctx_restore(gint_core_ctx *ctx) *IMR = ctx->masks[i]; } - gint_setcpuopm(ctx->CPUOPM); + cpu_setCPUOPM(ctx->CPUOPM); } } @@ -106,7 +95,7 @@ GMAPPED static void lock(void) else for(int i = 0; i < 12; i++) SH7305_INTC.IPRS[2 * i] = 0x0000; - gint_setcpuopm(gint_getcpuopm() | 0x00000008); + cpu_setCPUOPM(cpu_getCPUOPM() | 0x00000008); } /* gint_install() - install and start gint */ @@ -141,7 +130,7 @@ void gint_install(void) memcpy(vbr + 0x600, inth_entry, 64); /* Time to switch VBR and roll! */ - system_vbr = gint_setvbr(gint_vbr, lock); + system_vbr = cpu_setVBR(gint_vbr, lock); } /* unlock() - unlock interrupts, restoring system settings */ @@ -166,7 +155,7 @@ void gint_unload(void) if(drv->wait) drv->wait(); } - gint_setvbr(system_vbr, unlock); + cpu_setVBR(system_vbr, unlock); } //--- @@ -223,7 +212,7 @@ void gint_switch(void (*function)(void)) if(drv->wait) drv->wait(); } - gint_setvbr(system_vbr, gint_switch_out); + cpu_setVBR(system_vbr, gint_switch_out); if(function) function(); /* Wait for the OS to finish working */ @@ -231,7 +220,7 @@ void gint_switch(void (*function)(void)) { if(drv->wait) drv->wait(); } - gint_setvbr(gint_vbr, gint_switch_in); + cpu_setVBR(gint_vbr, gint_switch_in); } int __Timer_Install(int id, void (*handler)(void), int delay); diff --git a/src/core/vbr.h b/src/core/vbr.h new file mode 100644 index 0000000..10e0475 --- /dev/null +++ b/src/core/vbr.h @@ -0,0 +1,32 @@ +//--- +// core:vbr - VBR-related functions and linker script symbols +//--- + +#ifndef GINT_CORE_VBR +#define GINT_CORE_VBR + +#include + +/* VBR addresses from the linker script */ +#ifdef FX9860G +extern char gint_vbr_fx9860g[]; +#endif +#ifdef FXCG50 +extern char gint_vbr_fxcg50[]; +extern char gint_vbr_fxcg20[]; +#endif + +/* gint's VBR address as determined at runtime; not valid before kinit() */ +extern uint32_t gint_vbr; + +/* The kernel's interrupt and exception handlers' entry points */ +void gint_exch(void); +void gint_tlbh(void); +void gint_inth_7705(void); +void gint_inth_7305(void); + +/* Size of exception and TLB handlers */ +extern char gint_exch_size; +extern char gint_tlbh_size; + +#endif /* GINT_CORE_VBR */ diff --git a/src/render-cg/dvram.c b/src/render-cg/dvram.c index ab874bd..392475f 100644 --- a/src/render-cg/dvram.c +++ b/src/render-cg/dvram.c @@ -4,6 +4,8 @@ static uint16_t *main = (void *)0xac0f0000; static uint16_t *scnd = (void *)0xac11b500; +/* On Prizm: should be: 0xa80f0000 and 0xa811b500 */ + /* Shared VRAM pointer, the one exposed by */ uint16_t *gint_vram = (void *)0xac0f0000;