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:
1 parent
f5fd7bdd75
commit
529f816166
75 files changed
+9969
-5675
No files matched your search
+59
-35
@@ -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;
|
||||
}
|
||||
Reference in new issue
Block a user