implement proper IRQL, DPCs, kernel and user APCs, alertable waits, async file I/O with cancellation, trap frames, selftests, a real driver/device model, native async FAT32, VFAT dotfile fixes, syscall ABI cleanup, async_apc and async_cancel tests, POSIX multi-volume paths, and pimp the readme.

This commit is contained in:
maksw committed 2026-05-19 20:56:15 +02:00
1 parent f5fd7bdd75
commit 529f816166
75 files changed
+9969 -5675

No files matched your search

+59 -35
View File
@@ -13,15 +13,15 @@
// Byte 2: delta-Y unsigned magnitude (sign in byte-0 bit 5); PS/2 Y+ = up
//
// The ISR accumulates the 3-byte packet, converts it to a screen-space delta
// (Y-axis flipped), clamps the absolute position to [0, bounds), enqueues a
// MOUSE_EVENT, and then calls EraseOldCursor / DrawNewCursor via the two
// screen helpers that hal_screen.c exports.
// (Y-axis flipped), and queues the completed packet to the HAL's kernel-queued
// bottom half. Cursor drawing, public event enqueue, and optional callbacks
// run from that bottom half instead of hard IRQ context.
//
// Threading model
// ---------------
// Single-producer (ISR on IRQ 12) / single-consumer ring buffer.
// All ISR-written fields are volatile; on a uniprocessor this is sufficient.
// On SMP, add acquire/release barriers around gHead / gTail.
// Public events are produced by the mouse DPC and consumed by callers.
// Raw completed packets are produced by the ISR and consumed by the same DPC.
// On SMP, add acquire/release barriers around the ring head/tail pairs.
#include <stdint.h>
#include <stdbool.h>
@@ -44,8 +44,13 @@ typedef struct {
} MOUSE_EVENT;
static MOUSE_EVENT gBuf[MOUSE_BUF_SIZE];
static volatile int gHead = 0; // consumer read pointer
static volatile int gTail = 0; // producer write pointer (updated by ISR)
static volatile int gHead = 0; // public consumer read pointer
static volatile int gTail = 0; // public producer write pointer (updated by DPC)
// Completed hardware packets waiting for the DPC bottom half.
static MOUSE_EVENT gDpcBuf[MOUSE_BUF_SIZE];
static volatile int gDpcHead = 0;
static volatile int gDpcTail = 0;
// -- Absolute cursor position & screen bounds ----------------------------------
static volatile int gMouseX = 0;
@@ -57,7 +62,7 @@ static volatile int gBoundsH = 1080;
static volatile uint8_t gPacket[3];
static volatile int gPacketIdx = 0; // 0, 1, or 2
// -- Optional callback (called from ISR) ---------------------------------------
// -- Optional callback (called from mouse DPC) ---------------------------------
static void (* volatile gCallback)(int dx, int dy, uint8_t buttons) = NULL;
// -- Cursor helpers provided by hal_screen.c -----------------------------------
@@ -101,9 +106,45 @@ static uint8_t MouseRecvByte(void) {
return __inbyte(PS2_DATA);
}
// -- Deferred mouse bottom half -------------------------------------------------
static void MouseDpc(void) {
for (;;) {
if (gDpcHead == gDpcTail)
break;
MOUSE_EVENT ev = gDpcBuf[gDpcHead];
gDpcHead = (gDpcHead + 1) & (int)MOUSE_BUF_MASK;
// Update absolute position and redraw the cursor outside DIRQL.
HalScreenEraseCursor();
int nx = gMouseX + ev.dx;
int ny = gMouseY + ev.dy;
if (nx < 0) nx = 0;
if (nx >= gBoundsW) nx = gBoundsW - 1;
if (ny < 0) ny = 0;
if (ny >= gBoundsH) ny = gBoundsH - 1;
gMouseX = nx;
gMouseY = ny;
HalScreenDrawCursor(nx, ny);
// Publish event to the normal consumer ring.
int next = (gTail + 1) & (int)MOUSE_BUF_MASK;
if (next != gHead) {
gBuf[gTail] = ev;
gTail = next;
}
void (*cb)(int, int, uint8_t) = (void (*)(int, int, uint8_t))gCallback;
if (cb)
cb(ev.dx, ev.dy, ev.buttons);
}
}
// -- Interrupt service routine --------------------------------------------------
// Called with interrupts disabled by KeIrqDispatch (IRQ 12).
// The dispatcher sends the APIC EOI before this function is invoked.
// The dispatcher sends the APIC EOI after this function returns.
static void MouseIsr(void) {
uint8_t data = __inbyte(PS2_DATA);
@@ -130,32 +171,14 @@ static void MouseIsr(void) {
int dy = (int)gPacket[2] - ((flags & 0x20u) ? 256 : 0);
dy = -dy; // PS/2 Y+ = up; screen Y+ = down, so invert.
// -- Update absolute position (clamped to screen bounds) ------------------
HalScreenEraseCursor();
int nx = gMouseX + dx;
int ny = gMouseY + dy;
if (nx < 0) nx = 0;
if (nx >= gBoundsW) nx = gBoundsW - 1;
if (ny < 0) ny = 0;
if (ny >= gBoundsH) ny = gBoundsH - 1;
gMouseX = nx;
gMouseY = ny;
HalScreenDrawCursor(nx, ny);
// -- Enqueue event; silently drop if buffer is full -----------------------
int next = (gTail + 1) & (int)MOUSE_BUF_MASK;
if (next != gHead) {
gBuf[gTail].dx = dx;
gBuf[gTail].dy = dy;
gBuf[gTail].buttons = buttons;
gTail = next;
// -- Queue completed packet to the DPC bottom half -------------------------
int next = (gDpcTail + 1) & (int)MOUSE_BUF_MASK;
if (next != gDpcHead) {
gDpcBuf[gDpcTail].dx = dx;
gDpcBuf[gDpcTail].dy = dy;
gDpcBuf[gDpcTail].buttons = buttons;
gDpcTail = next;
}
// -- Optional callback (raw ISR context) -----------------------------------
void (*cb)(int, int, uint8_t) = (void (*)(int, int, uint8_t))gCallback;
if (cb) cb(dx, dy, buttons);
}
// -- Consumer API --------------------------------------------------------------
@@ -278,5 +301,6 @@ void HalMouseInitialize(HAL_MOUSE* out, int screenW, int screenH) {
out->SetPosition = MouseSetPosition;
out->SetBounds = MouseSetBounds;
out->Isr = MouseIsr;
out->Dpc = MouseDpc;
out->IrqNumber = 12;
}