2018-04-19 13:24:26 +02:00
|
|
|
//---
|
|
|
|
// gint:drivers - General tools for drivers
|
|
|
|
//---
|
|
|
|
|
|
|
|
#ifndef GINT_DRIVERS
|
|
|
|
#define GINT_DRIVERS
|
|
|
|
|
2019-02-21 20:58:38 +01:00
|
|
|
#include <gint/defs/attributes.h>
|
|
|
|
#include <gint/defs/types.h>
|
2018-04-19 13:24:26 +02:00
|
|
|
|
2018-08-01 20:41:36 +02:00
|
|
|
//---
|
2019-03-06 14:32:51 +01:00
|
|
|
// Driver procedure flow
|
2018-08-01 20:41:36 +02:00
|
|
|
//
|
2019-03-06 14:32:51 +01:00
|
|
|
// Drivers are initialized in priority order, and in linking order within
|
2019-05-04 12:07:14 +02:00
|
|
|
// the same priority level (pretty much undefined). Make sure every
|
2020-05-10 16:36:21 +02:00
|
|
|
// driver's priority level is higher than those of its dependencies. In
|
|
|
|
// the description below, every function can be NULL.
|
2018-08-01 20:41:36 +02:00
|
|
|
//
|
2019-03-06 14:32:51 +01:00
|
|
|
// At initialization, the following functions are called:
|
2020-05-10 16:36:21 +02:00
|
|
|
// 1. driver_sh3() [on SH3-based fx9860g only]
|
|
|
|
// 2. ctx_save(sys_ctx)
|
|
|
|
// 3. init()
|
2019-03-06 14:32:51 +01:00
|
|
|
//
|
|
|
|
// 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.
|
2020-06-20 09:46:39 +02:00
|
|
|
// 4. wait()
|
|
|
|
// 5. ctx_save(gint_ctx)
|
|
|
|
// 6. ctx_restore(sys_ctx)
|
2020-05-10 16:36:21 +02:00
|
|
|
// (stuff happening outside of gint)
|
2020-06-20 09:46:39 +02:00
|
|
|
// 7. ctx_save(sys_ctx)
|
|
|
|
// 8. ctx_restore(gint_ctx)
|
2019-03-06 14:32:51 +01:00
|
|
|
//
|
|
|
|
// When finally the driver is unloaded, the system context is restored.
|
2020-06-20 09:46:39 +02:00
|
|
|
// 9. wait()
|
|
|
|
// 10. ctx_restore(sys_ctx)
|
2018-08-01 20:41:36 +02:00
|
|
|
//---
|
|
|
|
|
2018-04-19 13:24:26 +02:00
|
|
|
/* gint_driver_t - driver meta-information used by gint */
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
/* Driver name */
|
2020-02-23 15:49:55 +01:00
|
|
|
char const *name;
|
2018-04-19 13:24:26 +02:00
|
|
|
|
2020-05-10 16:36:21 +02:00
|
|
|
/* SH3-specific preinitializaton; called before init() when running on
|
|
|
|
SH3. May be NULL. */
|
2018-08-01 20:41:36 +02:00
|
|
|
void (*driver_sh3)(void);
|
|
|
|
|
2020-05-10 16:36:21 +02:00
|
|
|
/* 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. */
|
2018-08-01 20:41:36 +02:00
|
|
|
void (*init)(void);
|
|
|
|
|
2020-05-10 16:36:21 +02:00
|
|
|
/* 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. */
|
|
|
|
void (*wait)(void);
|
2018-08-19 17:11:37 +02:00
|
|
|
|
2020-05-10 14:03:41 +02:00
|
|
|
/* 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
|
2020-05-10 16:36:21 +02:00
|
|
|
section using the GBSS macro of <gint/defs/attributes.h>. May be
|
|
|
|
NULL only if both ctx_save() and ctx_restore() are NULL. */
|
2018-04-19 13:24:26 +02:00
|
|
|
void *sys_ctx;
|
2020-05-10 14:03:41 +02:00
|
|
|
void *gint_ctx;
|
2020-02-23 15:49:55 +01:00
|
|
|
|
2020-05-10 16:36:21 +02:00
|
|
|
/* Must save the state of as much driver-controlled hardware as
|
|
|
|
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]. */
|
2018-04-19 13:24:26 +02:00
|
|
|
void (*ctx_save)(void *ctx);
|
|
|
|
|
2020-05-10 16:36:21 +02:00
|
|
|
/* Must restore the state of the driver as saved by ctx_save(). */
|
2018-04-19 13:24:26 +02:00
|
|
|
void (*ctx_restore)(void *ctx);
|
|
|
|
|
2019-02-21 20:58:38 +01:00
|
|
|
} GPACKED(4) gint_driver_t;
|
2018-04-19 13:24:26 +02:00
|
|
|
|
|
|
|
/* GINT_DECLARE_DRIVER() - make a driver visible to gint
|
2018-08-19 17:11:37 +02:00
|
|
|
|
2018-04-19 13:24:26 +02:00
|
|
|
Use this macro to expose a driver by passing it the name of a gint_driver_t
|
2018-08-19 17:11:37 +02:00
|
|
|
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
|
|
|
|
drivers will be loaded sooner. This numbering allows a primitive form of
|
2019-02-21 20:58:38 +01:00
|
|
|
dependency for drivers. You need to specify a level which is strictly
|
2018-08-19 17:11:37 +02:00
|
|
|
higher than the level of all the drivers you depend on. */
|
|
|
|
#define GINT_DECLARE_DRIVER(level, name) \
|
2019-02-21 20:58:38 +01:00
|
|
|
GSECTION(".gint.drivers." #level) extern gint_driver_t name;
|
2018-04-19 13:24:26 +02:00
|
|
|
|
2020-05-10 16:36:21 +02:00
|
|
|
/* GINT_DRIVER_SH3() - declare a function for SH3 preinitialization
|
2019-03-06 14:32:51 +01:00
|
|
|
This macro makes its argument NULL on fxcg50, this way the named function
|
|
|
|
can be defined under #ifdef FX9860G while keeping the structure clean. */
|
|
|
|
|
|
|
|
#ifdef FXCG50
|
|
|
|
#define GINT_DRIVER_SH3(name) NULL
|
2019-09-04 14:44:48 +02:00
|
|
|
#else
|
|
|
|
#define GINT_DRIVER_SH3(name) name
|
2019-03-06 14:32:51 +01:00
|
|
|
#endif
|
|
|
|
|
2018-04-19 13:24:26 +02:00
|
|
|
#endif /* GINT_DRIVERS */
|