Skip to content

Drivers

Allocate a new world buffer (single block), returns NULL on error

gint_world_t gint_world_alloc(void)

Free a world buffer

void gint_world_free(gint_world_t world)

Switch from the OS world to a gint-managed world

void gint_world_switch_in(gint_world_t world_os, gint_world_t world_addin)

Switch from a gint-managed world to the OS world

void gint_world_switch_out(gint_world_t world_addin, gint_world_t world_os)

GINT_DECLARE_DRIVER(): Declare a driver to the kernel

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 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.

The level number MUST HAVE EXACTLY 2 DIGITS, as it is used as a string in the section name and the linker then sorts by name. If your driver has a level lower than 10, you must add a leading 0.

#define GINT_DECLARE_DRIVER ((level, name)) \
GSECTION(".gint.drivers." #level) GVISIBLE extern gint_driver_t name;

Number of drivers in the (gint_drivers) array

#define gint_driver_count (()) \
((gint_driver_t *)&gint_drivers_end - (gint_driver_t *)&gint_drivers)
typedef struct
{
/* Driver name */ char const *name;
/* General constructor, is called before any interaction with the driver. This can be used to adjust settings based on detected hardware. */ void (*constructor)(void);
// Foreign calls /* Foreign unbind: separate the hardware from the OS driver. If NULL, the OS driver is always considered idle. */ void (*funbind)(void);
// "Hypervisor" calls /* Determine whether the device is powered. If NULL, the device is assumed to be permanently powered. */ bool (*hpowered)(void);
/* Power on the device;
this should allow register access to save the peripheral state, with minimal state changes. Cannot be NULL if hpowered() can return false. */ void (*hpoweron)(void);
/* Power off the device;
cannot be NULL if hpowered() can return false. */ void (*hpoweroff)(void);
/* Save the hardware state;
the (state) pointer points to a 4-aligned region of (state_size) bytes. */ void (*hsave)(void *state);
/* Restore a hardware state previously saved by hsave(). */ void (*hrestore)(void const *state);
// Standard calls /* Bind the driver to acquire control of the device. May be NULL. */ void (*bind)(void);
/* Unbind the driver from the hardware. Usually sleeps until processes that block world switches terminate, like bind(). May be NULL. */ void (*unbind)(void);
/* Initialize the hardware for the driver to work in gint. Usually installs interrupt handlers and configures registers. May be NULL. */ void (*configure)(void);
/* Size of the peripheral's hardware state (assumed 4-aligned) */ uint16_t state_size;
/* Initial flags */ uint8_t flags;
}
gint_driver_t

gint_world_t: World state capture

The world state is a copy of the (almost) complete hardware state, which can be used to switch between several kernels running in parallel on the same machine. gint runs in a different world than the OS, allowing it to control peripheral modules in ways incompatible with the OS without compromising the stability of either program.

The world state is a sequence of 4-aligned buffers each holding a copy of a module’s state, as saved (and restored) by a driver. It is prefixed with an array of pointers, one for each driver, specifying the driver’s spot within the sequence.

The layout is as follows: An array of (void *), with one entry per driver, in priority order. Each pointer is to a buffer in the sequence. A sequence of buffers of size (state_size), rounded up to a multiple of 4 bytes, for each driver in priority order.

The world is returned as a (void *) array but allocated in one block.

typedef void **gint_world_t
enum
{
/* Driver is clean (needs to be configured before running) */ GINT_DRV_CLEAN = 0x01, /* Device was powered during the last foreign unbind */ GINT_DRV_FOREIGN_POWERED = 0x02, /* Driver does not require hardware state saves during world switches */ GINT_DRV_SHARED = 0x10, /* Flags that can be set in the (flags) attribute of the driver struct */ GINT_DRV_INIT_ = 0x10,
}