* Change gint_inth_callback()
* Add intc_handler_function() to use C functions as handlers instead of
writing assembler, and use it in the RTC and USB
* Revisit the TMU handlers, which after moving out the callbacks, now
fit into 3 gates (great!), and adapt the ETMU handler
* Improve the timer driver (less code = better code, removed magic
constants assuming the VBR layout on SH3/SH4, etc.)
* Remove 2 gates and a gap from the compact scheme on SH3
* Define timer_configure() to replace timer_setup(), which could not be
cleanly updated to support GINT_CALL()
* Replace rtc_start/stop_timer with rtc_periodic_enable/disable, which
is less confusing because of ETMU being "RTC timers"
Changes in the driver and world system:
* Rewrite driver logic to include more advanced concepts. The notion of
binding a driver to a device is introduced to formalize wait(); power
management is now built-in instead of being handled by the drivers
(for instance DMA). The new driver model is described in great detail
in <gint/drivers.h>
* Formalized the concept of "world switch" where the hardware state is
saved and later restored. As a tool, the world switch turns out to be
very stable, and allows a lot of hardware manipulation that would be
edgy at best when running in the OS world.
* Added a GINT_DRV_SHARED flag for drivers to specify that their state
is shared between worlds and not saved/restored. This has a couple of
uses.
* Exposed a lot more of the internal driver/world system as their is no
particular downside to it. This includes stuff in <gint/drivers.h>
and the driver's state structures in <gint/drivers/states.h>. This is
useful for debugging and for cracked concepts, but there is no
API stability guarantee.
* Added a more flexible driver level system that allows any 2-digit
level to be used.
Feature changes:
* Added a CPU driver that provides the VBR change as its state save.
Because the whole context switch relied on interrupts being disabled
anyway, there is no longer an inversion of control when setting the
VBR; this is just part of the CPU driver's configuration. The CPU
driver may also support other features such as XYRAM block transfer
in the future.
* Moved gint_inthandler() to the INTC driver under the name
intc_handler(), pairing up again with intc_priority().
* Added a reentrant atomic lock based on the test-and-set primitive.
Interrupts are disabled with IMASK=15 for the duration of atomic
operations.
* Enabled the DMA driver on SH7305-based fx-9860G. The DMA provides
little benefit on this platform because the RAM is generally faster
and buffers are ultimately small. The DMA is still not available on
SH3-based fx-9860G models.
* Solved an extremely obnoxious bug in timer_spin_wait() where the
timer is not freed, causing the callback to be called when interrupts
are re-enabled. This increments a random value on the stack. As a
consequence of the change, removed the long delays in the USB driver
since they are not actually needed.
Minor changes:
* Deprecated some of the elements in <gint/hardware.h>. There really is
no good way to "enumerate" devices yet.
* Deprecated gint_switch() in favor of a new function
gint_world_switch() which uses the GINT_CALL abstraction.
* Made the fx-9860G VRAM 32-aligned so that it can be used for tests
with the DMA.
Some features of the driver and world systems have not been implemented
yet, but may be in the future:
* Some driver flags should be per-world in order to create multiple
gint worlds. This would be useful in Yatis' hypervisor.
* A GINT_DRV_LAZY flag would be useful for drivers that don't want to
be started up automatically during a world switch. This is relevant
for drivers that have a slow start/stop sequence. However, this is
tricky to do correctly as it requires dynamic start/stop and also
tracking which world the current hardware state belongs to.
* Add the power management functions (mostly stable even under
overclock; requires some testing, but no known issue)
* Add a dynamic configuration system where interfaces can declare
descriptors with arbitrary endpoint numbers and additional
parameters, and the driver allocates USB resources (endpoints, pipes
and FIFO memory) between interfaces at startup. This allows
implementations of different classes to be independent from each
other.
* Add responses to common SETUP requests.
* Add pipe logic that allows programs to write data synchronously or
asynchronously to pipes, in a single or several fragments, regardless
of the buffer size (still WIP with a few details to polish and the
API is not public yet).
* Add a WIP bulk IN interface that allows sending data to the host.
This will eventually support the fxlink protocol.
Since both platforms now have their VBR and gint-specific data loaded
along the add-in's data, the .gint.data section is entirely unused.
The .gint.bss section is still used for uninitialized objects (it has
different semantics than .bss which is initially cleared) and the
.gint.data.sh3 and .gint.bss.sh3 sections that are dropped on the
SH4-only fx-CG 50 are also still used.
I have recenty discovered that the so-called "rram" section used by gint
to store its VBR space and a couple memory structures gets overwritten
when returning to the main menu. It is thus necessary to get rid of it
and store that data somewhere else.
My current lead is to have it at the start of the static RAM by querying
its address in the TLB. However, the static RAM is very small on SH3
(8k) so the VBR must be made more compact.
This change elaborates the event code translation scheme used on SH3 to
emulate SH4 event codes. It is now used to translate the event codes to
a gint-specific VBR layout that leaves no gaps and thus reduces the size
of the VBR space. The gint_inthandler() method has to be modified for
every new SH3 interrupt to maintain this scheme.
* Removed .pretext sections since the TLB is now entirely dynamic; left
only .text.entry for the start symbol.
* Reworked the main files of src/core to move the INTC to its own driver
and let the kernel handle only VBR space and CPU (now: VBR & CPUOPM).
* Moved src/core/gint.c to src/core/kernel.c and centralized all driver
loops that save or restore context for more robustness. This leaves
the callbacks of cpu_setVBR() (formerly gint_setvbr()) pretty short.
* Coalesced gint_switch_out() and gint_switch_in() into a single
function callback for cpu_setVBR().
* Added an abstraction of interrupt signals as an enumerated value so
that drivers no longer hardcode the IPR and IMR numbers and bits,
sometimes even with isSH3() due to differences in the SH7705.
* Changed the interrupt blocking method in cpu_setVBR() from SR.BL=1 to
SR.IMASK=15 so that TLB misses are still handled. This removes the
need for callback functions to be GMAPPED.
* Moved gint_osmenu() and its utilities to a new file src/core/osmenu.c.