add KePanic instead of splattering _disable __halt everywhere, implement a DMA + interrupts path to the IDE driver, move the dynamic arrays from kmain.c to ke_utils.h, remove weird unicode chars
This commit is contained in:
1 parent
83d48e09bb
commit
4b57738fe3
15 files changed
+673
-219
No files matched your search
+19
-19
@@ -20,7 +20,7 @@
|
||||
// returns STATUS_PENDING immediately. Multiple callers can have outstanding
|
||||
// requests against different drives concurrently without stalling each other.
|
||||
//
|
||||
// NCQ extension (future work — see "NCQ TODO" comments):
|
||||
// NCQ extension (future work - see "NCQ TODO" comments):
|
||||
// To saturate modern SSDs, replace the serialised single-slot model with
|
||||
// Native Command Queuing:
|
||||
// • Allocate per-slot bounce buffers (NUM_NCQ_SLOTS × SLOT_BOUNCE_BYTES).
|
||||
@@ -381,7 +381,7 @@ typedef struct {
|
||||
volatile uint32_t lastIs;
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// IRP queue — async dispatch
|
||||
// IRP queue - async dispatch
|
||||
// -----------------------------------------------------------------------
|
||||
// AhciWorker blocks here waiting for work. AhciSubmitIrp enqueues an IRP
|
||||
// and signals the semaphore to wake the worker.
|
||||
@@ -413,7 +413,7 @@ static KSTATUS ahci_map_mmio(uint64_t physBase) {
|
||||
uintptr_t virt = (uintptr_t)g_hal->PhysToVirt(phys);
|
||||
uint64_t flags = PAGE_PRESENT | PAGE_WRITE | PAGE_NOCACHE;
|
||||
KSTATUS st = MmMapPage(virt, phys, flags);
|
||||
// Ignore STATUS_ALREADY_EXISTS — a prior mapping with different flags
|
||||
// Ignore STATUS_ALREADY_EXISTS - a prior mapping with different flags
|
||||
// is possible for the first page if the bootloader was overly generous.
|
||||
// Use MmSetPageProtect to force NOCACHE in that case.
|
||||
if (st == STATUS_ALREADY_EXISTS) {
|
||||
@@ -535,7 +535,7 @@ static KSTATUS port_init_memory(AHCI_DRIVE *drv) {
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Issue a command — polling fallback (used during early init / IDENTIFY only,
|
||||
// Issue a command - polling fallback (used during early init / IDENTIFY only,
|
||||
// before the scheduler and interrupt handler are live).
|
||||
// Returns STATUS_SUCCESS, STATUS_DEVICE_ERROR, or STATUS_TIMEOUT.
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -580,7 +580,7 @@ static KSTATUS port_issue_cmd_poll(AHCI_DRIVE *drv) {
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// ISR — called from KeIrqDispatch on the AHCI PCI IRQ line.
|
||||
// ISR - called from KeIrqDispatch on the AHCI PCI IRQ line.
|
||||
// Walks all registered drives, checks if their port raised an interrupt,
|
||||
// captures IS, clears it, and signals the per-drive completion event.
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -597,10 +597,10 @@ static void AhciIsr(void) {
|
||||
uint32_t portBit = (1u << drv->portNo);
|
||||
if (!(pending & portBit)) continue;
|
||||
|
||||
// Capture and clear port IS before signalling — the waiter reads
|
||||
// Capture and clear port IS before signalling - the waiter reads
|
||||
// lastIs to check for errors without racing the next command.
|
||||
uint32_t portIs = drv->port->is;
|
||||
drv->port->is = portIs; // W1C — write back to clear
|
||||
drv->port->is = portIs; // W1C - write back to clear
|
||||
drv->lastIs = portIs;
|
||||
|
||||
// Clear the HBA-level bit.
|
||||
@@ -612,7 +612,7 @@ static void AhciIsr(void) {
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Issue a command — interrupt-driven (runtime path).
|
||||
// Issue a command - interrupt-driven (runtime path).
|
||||
// Caller has already built slot 0 via build_rw_cmd / port_identify.
|
||||
// Blocks the current thread until the ISR signals completionEvent.
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -638,7 +638,7 @@ static KSTATUS port_issue_cmd(AHCI_DRIVE *drv) {
|
||||
port->ci = (1u << 0);
|
||||
KeWaitForEvent(drv->completionEvent);
|
||||
|
||||
// The ISR has cleared IS — check for errors in the snapshot.
|
||||
// The ISR has cleared IS - check for errors in the snapshot.
|
||||
uint32_t is = drv->lastIs;
|
||||
if (is & (PORT_IS_TFES | PORT_IS_HBFS | PORT_IS_HBDS | PORT_IS_IFS)) {
|
||||
DbgPrint("AHCI: error IS=0x%x TFD=0x%x SERR=0x%x\n",
|
||||
@@ -808,7 +808,7 @@ static KSTATUS do_write(AHCI_DRIVE *drv, uint64_t lba,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// HAL_DISK callbacks — context pointer replaces trampolines.
|
||||
// HAL_DISK callbacks - context pointer replaces trampolines.
|
||||
// Ctx is the AHCI_DRIVE* stored in DISK_DRIVER.Ctx; the dispatch layer in
|
||||
// hal_disk.c passes it as the first argument to every call.
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -825,7 +825,7 @@ static KSTATUS AhciWrite(void *ctx, uint64_t lba, uint32_t count, const void *bu
|
||||
// Async IRP dispatch
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// AhciSubmitIrp — called by IoSubmitIrp().
|
||||
// AhciSubmitIrp - called by IoSubmitIrp().
|
||||
// Enqueues the IRP and wakes the per-drive worker thread.
|
||||
// Returns STATUS_PENDING immediately; the caller waits on irp->CompletionEvent
|
||||
// or irp->CompletionFn.
|
||||
@@ -836,7 +836,7 @@ static KSTATUS AhciSubmitIrp(void *ctx, IRP *irp) {
|
||||
return STATUS_PENDING;
|
||||
}
|
||||
|
||||
// AhciWorker — kernel thread, one per drive.
|
||||
// AhciWorker - kernel thread, one per drive.
|
||||
// Dequeues IRPs and executes them one at a time using the existing
|
||||
// single-slot interrupt-driven path. Completion fires the IRP's event
|
||||
// and/or callback so the original caller can observe the result without
|
||||
@@ -848,7 +848,7 @@ static KSTATUS AhciSubmitIrp(void *ctx, IRP *irp) {
|
||||
// 3. Grab a free bit in drv->slotMask (under the slot spinlock).
|
||||
// 4. Copy write data into slotBounce[slot], build the NCQ FIS (FPDMA),
|
||||
// record slotIrp[slot] = irp, and issue via port->sact + port->ci.
|
||||
// 5. Return immediately — the ISR drives all completions.
|
||||
// 5. Return immediately - the ISR drives all completions.
|
||||
static void AhciWorker(uintptr_t arg) {
|
||||
AHCI_DRIVE *drv = (AHCI_DRIVE *)arg;
|
||||
|
||||
@@ -857,7 +857,7 @@ static void AhciWorker(uintptr_t arg) {
|
||||
KeWaitSemaphore(drv->irpQueue.Semaphore);
|
||||
|
||||
IRP *irp = IrpQueueDequeue(&drv->irpQueue);
|
||||
if (!irp) continue; // spurious wakeup — should not happen
|
||||
if (!irp) KePanic("AhciWorker: semaphore fired but queue is empty - IRP accounting bug\n");
|
||||
|
||||
bool write = !!(irp->Flags & IRP_FLAG_WRITE);
|
||||
KSTATUS st;
|
||||
@@ -980,11 +980,11 @@ static KSTATUS port_comreset(AHCI_DRIVE *drv) {
|
||||
}
|
||||
|
||||
// PORT_IE bits we care about:
|
||||
// DHRS (bit 0) - D2H Register FIS received — normal completion
|
||||
// DHRS (bit 0) - D2H Register FIS received - normal completion
|
||||
// PSS (bit 1) - PIO Setup FIS received
|
||||
// DSS (bit 2) - DMA Setup FIS received
|
||||
// SDBS (bit 3) - Set Device Bits FIS received
|
||||
// TFES (bit 30) - Task File Error Status — error
|
||||
// TFES (bit 30) - Task File Error Status - error
|
||||
// HBFS (bit 29) - Host Bus Fatal error
|
||||
// HBDS (bit 28) - Host Bus Data error
|
||||
// IFS (bit 27) - Interface Fatal error
|
||||
@@ -1019,7 +1019,7 @@ KSTATUS AhciInitialize(const HAL_API *hal) {
|
||||
// -----------------------------------------------------------------------
|
||||
g_irq = hal->Pci.GetIrqLine(pciBus, pciDev, pciFn);
|
||||
if (g_irq == 0xFF) {
|
||||
DbgPrint("AHCI: no PCI IRQ wired — cannot use interrupt-driven mode\n");
|
||||
DbgPrint("AHCI: no PCI IRQ wired - cannot use interrupt-driven mode\n");
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
DbgPrint("AHCI: PCI IRQ line = %u\n", (unsigned)g_irq);
|
||||
@@ -1082,7 +1082,7 @@ KSTATUS AhciInitialize(const HAL_API *hal) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Phase 3: COMRESET — forces device to re-send D2H FIS for valid SIG
|
||||
// Phase 3: COMRESET - forces device to re-send D2H FIS for valid SIG
|
||||
st = port_comreset(drv);
|
||||
if (!KSUCCESS(st)) {
|
||||
DbgPrint("AHCI: port %u: COMRESET failed\n", portno);
|
||||
@@ -1113,7 +1113,7 @@ KSTATUS AhciInitialize(const HAL_API *hal) {
|
||||
}
|
||||
IrpQueueInit(&drv->irpQueue, irpSem);
|
||||
|
||||
// Phase 6: IDENTIFY (polled — scheduler not yet running)
|
||||
// Phase 6: IDENTIFY (polled - scheduler not yet running)
|
||||
st = port_identify(drv);
|
||||
if (!KSUCCESS(st)) {
|
||||
DbgPrint("AHCI: port %u: IDENTIFY failed (0x%x)\n", portno, st);
|
||||
|
||||
Reference in new issue
Block a user