Punch list §25 item 4.3.5c complete. Amended from a nonexistent MMIO transport to PCI (matching the board's actual virtio-blk-pci precedent). New virtio-input driver: eventq with pre-posted buffers, PLIC source computed at runtime from PCI slot/pin (derived live from this host's QEMU riscv64 DTB), mandatory ISR-status read, PCI interrupt-disable-bit check. New VKBD-EVENT/VKBD-DEBUG FORTH words. Verified with a real QEMU sendkey keypress: exact KEY_A/press match, two real interrupts serviced, zero exceptions. Three-arch acceptance boot clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
100 lines
2.8 KiB
C
100 lines
2.8 KiB
C
/*
|
||
StarForth — Steady-State Virtual Machine Runtime
|
||
|
||
Copyright (c) 2023–2025 Robert A. James
|
||
All rights reserved.
|
||
|
||
Licensed under the StarForth License, Version 1.0
|
||
*/
|
||
|
||
/* keyboard_words.c — raw scancode-ring diagnostic word (FABRIC.md item
|
||
* 4.3.5). Kernel-only, amd64-only; no-op elsewhere. */
|
||
|
||
#include "include/keyboard_words.h"
|
||
#include "../../include/word_registry.h"
|
||
|
||
#if defined(__STARKERNEL__) && defined(ARCH_AMD64)
|
||
#include "starkernel/i8042.h"
|
||
#endif
|
||
|
||
#if defined(__STARKERNEL__) && defined(ARCH_RISCV64)
|
||
#include "starkernel/virtio_input.h"
|
||
#endif
|
||
|
||
/* KBD-SCAN ( -- c -1 | 0 ) */
|
||
static void kbw_scan(VM *vm)
|
||
{
|
||
#if defined(__STARKERNEL__) && defined(ARCH_AMD64)
|
||
uint8_t sc;
|
||
if (i8042_pop_scancode(&sc)) {
|
||
vm_push(vm, (cell_t)sc);
|
||
vm_push(vm, -1);
|
||
} else {
|
||
vm_push(vm, 0);
|
||
}
|
||
#else
|
||
vm_push(vm, 0);
|
||
#endif
|
||
}
|
||
|
||
/* KBD-DEBUG ( -- isr_count spurious_count ): cheap standing diagnostic,
|
||
* not scaffolding -- confirms the interrupt path is alive (isr_count) and
|
||
* flags the failure mode item 4.3.5 found (a real IRQ misreported as
|
||
* spurious) without needing a live debugger. */
|
||
extern volatile uint32_t g_i8042_isr_count;
|
||
extern volatile uint32_t g_spurious_count;
|
||
static void kbw_debug(VM *vm)
|
||
{
|
||
#if defined(__STARKERNEL__) && defined(ARCH_AMD64)
|
||
vm_push(vm, (cell_t)g_i8042_isr_count);
|
||
vm_push(vm, (cell_t)g_spurious_count);
|
||
#else
|
||
vm_push(vm, 0);
|
||
vm_push(vm, 0);
|
||
#endif
|
||
}
|
||
|
||
/* VKBD-EVENT ( -- code value -1 | 0 ): item 4.3.5c, riscv64 virtio-input.
|
||
* Pop one decoded EV_KEY event off the interrupt-fed ring buffer. Pushes
|
||
* code and value and -1 (true) if one was available, or just 0 (false) if
|
||
* the buffer was empty. Distinct word from KBD-SCAN rather than a shared
|
||
* one: different device, different event shape (Linux-style code/value
|
||
* pair vs. a raw XT scancode byte) -- convergence onto one interface is
|
||
* item 4.3.5f's explicit job, not this one's. */
|
||
static void kbw_vevent(VM *vm)
|
||
{
|
||
#if defined(__STARKERNEL__) && defined(ARCH_RISCV64)
|
||
uint16_t code;
|
||
uint32_t value;
|
||
if (virtio_input_pop_event(&code, &value)) {
|
||
vm_push(vm, (cell_t)code);
|
||
vm_push(vm, (cell_t)value);
|
||
vm_push(vm, -1);
|
||
} else {
|
||
vm_push(vm, 0);
|
||
}
|
||
#else
|
||
vm_push(vm, 0);
|
||
#endif
|
||
}
|
||
|
||
/* VKBD-DEBUG ( -- isr_count ): standing diagnostic, same shape as
|
||
* KBD-DEBUG -- confirms the virtio-input interrupt path is alive. */
|
||
extern volatile uint32_t g_virtio_input_isr_count;
|
||
static void kbw_vdebug(VM *vm)
|
||
{
|
||
#if defined(__STARKERNEL__) && defined(ARCH_RISCV64)
|
||
vm_push(vm, (cell_t)g_virtio_input_isr_count);
|
||
#else
|
||
vm_push(vm, 0);
|
||
#endif
|
||
}
|
||
|
||
void register_keyboard_words(VM *vm)
|
||
{
|
||
register_word(vm, "KBD-SCAN", kbw_scan);
|
||
register_word(vm, "KBD-DEBUG", kbw_debug);
|
||
register_word(vm, "VKBD-EVENT", kbw_vevent);
|
||
register_word(vm, "VKBD-DEBUG", kbw_vdebug);
|
||
}
|