#pragma once #include "core/types.h" // GMMOS -- Guru Meditation Micro OS. What runs after a panic. // // The PSOGM used to be the last thing the kernel did: a report, blinking // keyboard lights, and a machine that needed its power button. GMMOS keeps the // report and goes on living under it. The real kernel is dead and stays dead -- // every other processor is halted (see trap()), and nothing of it is called // again that takes a lock, sleeps, allocates or waits for an interrupt. What // GMMOS has instead is its own: the framebuffer, a clock read from the TSC, and // keyboards it polls itself through micro drivers. // // A micro driver is a cut-down copy of a real one that does only what a // keyboard needs. The real drivers run on interrupts, threads and locks, all of // which belong to the kernel that just died. // // See kernel/gmmos/gmmos.c. void gmmos_run(char *reason, addr_t *pcs, int npcs) __attribute__((noreturn)); // One keyboard GMMOS can read by polling. struct gmmos_kbd { const char *name; int (*probe)(void); // nonzero if it is there and usable // The next key, or 0 when there is none: a Unicode codepoint, or one of the // KBD_* codes from include/dev/kbd.h for keys that are not characters. int (*poll)(void); void (*leds)(int on); // optional: all three lights on or off }; extern const struct gmmos_kbd gmmos_ps2; extern const struct gmmos_kbd gmmos_i2c; // A USB or I2C keyboard report in the boot layout -- modifiers, a reserved // byte, six usages -- turned into keys. A report is a state, not an event, so // a key is a usage that was not in the previous one. kernel/gmmos/hidkeys.c. struct gmmos_hidkeys { uchar prev[8]; int q[16]; int qh, qt; }; void gmmos_hid_report(struct gmmos_hidkeys *k, const uchar *boot); int gmmos_hid_next(struct gmmos_hidkeys *k); // I2C keyboards, as kernel/acpi/i2c_hid.c found them at boot. GMMOS cannot run // ACPI to find them again, so the live driver hands over what it learnt: the // DesignWare controller, the device's address, its input report size, the // interrupt pin when there is one, and the parsed report descriptor. struct gmmos_i2c_kbd { volatile uint32 *regs; int txdepth, rxdepth; int addr; uint32 maxin; volatile uint32 *pin; // AMD GPIO pin register, or 0: poll blindly int active_low; void *hid; }; int i2c_hid_keyboards(struct gmmos_i2c_kbd *out, int max); // From kernel/core/panic.c: draw the report again, and where its closing // lines are, which GMMOS writes its status and its keys into. void psogm_repaint(void); void psogm_footer(int *x, int *y, int *step);