/* StarForth — Steady-State Virtual Machine Runtime Copyright (c) 2023–2025 Robert A. James All rights reserved. This file is part of the StarForth project. Licensed under the StarForth License, Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: https://github.com/star.4th@proton.me/StarForth/LICENSE.txt This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and noninfringement. See the License for the specific language governing permissions and limitations under the License. */ /** * i8042.h - PS/2 keyboard controller interface (amd64 only) * * Item 4.3.5 (FABRIC.md §27.5). Interrupt-driven only — no polling of the * status port (0x64) anywhere in this path. Groundwork only: this captures * and prints raw scancodes. Scancode-to-keycode translation and a consumer * API belong to the REPL keyboard-input work noted in FABRIC.md, not here. */ #ifndef STARKERNEL_I8042_H #define STARKERNEL_I8042_H #include /* IDT vector the I/O APIC delivers legacy IRQ1 to. */ #define I8042_KEYBOARD_VECTOR 0x21 /** * Enable IRQ1 delivery in the i8042 controller's command byte. Assumes the * controller was already brought up by firmware (OVMF) — does not run the * 0xAA self-test or the full two-port init sequence, since that is more * than this item's scope requires. */ void i8042_init(void); /** * Drain any byte sitting in the output buffer right before unmasking IRQ1. * Edge-triggered lines only assert on a rising edge; if OBF is already set * (from real wall-clock time elapsing between i8042_init() and unmask * while OBF was already high), there is no edge left to fire on, ever. */ void i8042_drain_stale(void); /* Count of real keyboard IRQs serviced since boot (diagnostic). */ extern volatile uint32_t g_i8042_isr_count; /** * Called from the keyboard IRQ dispatch path (interrupts.c) on every * I8042_KEYBOARD_VECTOR interrupt. Trivial by design: reads the scancode * from port 0x60 (must always be read, or the controller never clears * OBF and stops delivering further interrupts) and pushes it onto a small * ring buffer. No printing, no translation, no other work — that all * happens outside interrupt context via i8042_pop_scancode(). Does not * issue apic_eoi() — the caller does. */ void i8042_handle_irq(void); /** * Pop one raw scancode off the ring buffer, from non-interrupt context. * Single producer (the ISR), single reader (this function) — same shape * already established safe on one hart elsewhere in this tree (§21.1). * * @param out Written with the popped scancode on success. * @return 1 if a scancode was popped, 0 if the buffer was empty. */ int i8042_pop_scancode(uint8_t *out); #endif /* STARKERNEL_I8042_H */