94 lines
3.8 KiB
C
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;
|
|
}
|