Files
nt-lite/code/hal/hal_disk.c
T

94 lines
3.8 KiB
C

// hal_disk.c - drive registry; drivers register themselves via IoRegisterDisk.
//
// This file lives in the HAL layer and must NOT reference any kernel sync
// objects (KeEventCreate, KeSignalEvent, KeWaitForEvent, ObDereferenceObject).
// All IRP event signalling is done in kernel/ke_irp.c, which sits above us
// in the dependency graph.
//
// HalDiskDispatch is the one bridge: it calls the driver's SubmitIrp (async)
// or runs the sync callbacks inline and writes irp->Status. It does not
// touch irp->CompletionEvent — that is ke_irp.c's responsibility.
#include <stdint.h>
#include <stdbool.h>
#include <hal_api.h>
#include <io_driver.h>
#include <ke_irp.h>
#define MAX_DRIVES 8
static DISK_DRIVER gDrives[MAX_DRIVES];
static bool gPresent[MAX_DRIVES];
__declspec(dllexport) KSTATUS IoRegisterDisk(uint8_t index, const DISK_DRIVER *driver) {
if (index >= MAX_DRIVES || !driver) return STATUS_INVALID_PARAMETER;
if (gPresent[index]) return STATUS_ALREADY_EXISTS;
gDrives[index] = *driver;
gPresent[index] = true;
return STATUS_SUCCESS;
}
// -------------------------------------------------------------------------
// HalDiskDispatch — called exclusively by ke_irp.c::IoSubmitIrp()
// -------------------------------------------------------------------------
// Separating dispatch here keeps hal_disk.c free of event primitives while
// still allowing ke_irp.c (kernel layer) to fire completion hooks after we
// return.
//
// Returns STATUS_PENDING — driver accepted the IRP asynchronously.
// ke_irp.c must NOT touch irp->CompletionEvent
// yet; the driver will fire it.
// Returns STATUS_SUCCESS — sync fallback ran; irp->Status is already
// written. ke_irp.c should fire completion hooks.
// Returns STATUS_NOT_FOUND — drive not registered.
__declspec(dllexport) KSTATUS HalDiskDispatch(uint8_t drive, IRP *irp) {
if (drive >= MAX_DRIVES || !gPresent[drive]) return STATUS_NOT_FOUND;
DISK_DRIVER *drv = &gDrives[drive];
if (drv->SubmitIrp)
return drv->SubmitIrp(drv->Ctx, irp); // STATUS_PENDING
// Sync fallback: execute inline, write result, let caller fire hooks.
bool write = !!(irp->Flags & IRP_FLAG_WRITE);
if (write)
irp->Status = drv->WriteSectors(drv->Ctx, irp->Lba, irp->SectorCount, irp->Buffer);
else
irp->Status = drv->ReadSectors (drv->Ctx, irp->Lba, irp->SectorCount, irp->Buffer);
return STATUS_SUCCESS; // ran synchronously
}
// -------------------------------------------------------------------------
// Legacy HAL_DISK vtable — direct sync calls, no IRP involvement.
// Existing callers (FAT32, shell) use this path unchanged.
// -------------------------------------------------------------------------
static KSTATUS DiskRead(uint8_t drive, uint64_t lba,
uint32_t count, void *buf) {
if (drive >= MAX_DRIVES || !gPresent[drive]) return STATUS_NOT_FOUND;
return gDrives[drive].ReadSectors(gDrives[drive].Ctx, lba, count, buf);
}
static KSTATUS DiskWrite(uint8_t drive, uint64_t lba,
uint32_t count, const void *buf) {
if (drive >= MAX_DRIVES || !gPresent[drive]) return STATUS_NOT_FOUND;
return gDrives[drive].WriteSectors(gDrives[drive].Ctx, lba, count, buf);
}
static bool DiskPresent(uint8_t drive) {
return drive < MAX_DRIVES && gPresent[drive];
}
static uint64_t DiskSectorCount(uint8_t drive) {
if (drive >= MAX_DRIVES || !gPresent[drive]) return 0;
return gDrives[drive].SectorCount;
}
void HalDiskInitialize(HAL_DISK *out) {
out->ReadSectors = DiskRead;
out->WriteSectors = DiskWrite;
out->DrivePresent = DiskPresent;
out->DriveSectorCount = DiskSectorCount;
}