usb hubs, hotplug support, unplug support, saving log files to disk, smt
This commit is contained in:
1 parent
b838f8d83d
commit
27b31f62b6
39 files changed
+6294
-735
No files matched your search
@@ -382,6 +382,28 @@ static KSTATUS do_write(AHCI_DRIVE *drv, uint64_t lba,
|
||||
// Async IRP dispatch
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
static KSTATUS AhciGetIrpReadWrite(IRP* irp, bool* outWrite, uint64_t* outLba,
|
||||
uint32_t* outSectors, void** outBuffer) {
|
||||
if (!irp || !outWrite || !outLba || !outSectors || !outBuffer)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
IO_STACK_LOCATION* ios = IoGetCurrentIrpStackLocation(irp);
|
||||
if (!ios) return STATUS_INVALID_PARAMETER;
|
||||
if (ios->MajorFunction != IRP_MJ_READ && ios->MajorFunction != IRP_MJ_WRITE)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
if ((ios->Parameters.ReadWrite.ByteOffset & 511ull) ||
|
||||
(ios->Parameters.ReadWrite.Length & 511u))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
if (!irp->UserBuffer || ios->Parameters.ReadWrite.Length == 0)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
*outWrite = (ios->MajorFunction == IRP_MJ_WRITE);
|
||||
*outLba = ios->Parameters.ReadWrite.ByteOffset >> 9;
|
||||
*outSectors = ios->Parameters.ReadWrite.Length >> 9;
|
||||
*outBuffer = irp->UserBuffer;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// AhciDispatchReadWrite - DEVICE_OBJECT dispatch entry for disk IRPs.
|
||||
// Accepted IRPs are queued to the per-drive worker and completed later with
|
||||
// IoCompleteRequest(). Rejected IRPs are returned synchronously and are not
|
||||
@@ -390,8 +412,22 @@ static KSTATUS AhciDispatchReadWrite(DEVICE_OBJECT *device, IRP *irp) {
|
||||
if (!device || !irp) return STATUS_INVALID_PARAMETER;
|
||||
AHCI_DRIVE *drv = (AHCI_DRIVE *)device->DeviceExtension;
|
||||
if (!drv) return STATUS_INVALID_PARAMETER;
|
||||
if (irp->SectorCount == 0 || !irp->Buffer) return STATUS_INVALID_PARAMETER;
|
||||
if (irp->Lba + irp->SectorCount > drv->sectorCount) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
KSTATUS st = IoAcquireRemoveLock(&drv->removeLock, irp);
|
||||
if (!KSUCCESS(st))
|
||||
return st;
|
||||
|
||||
bool write = false;
|
||||
uint64_t lba = 0;
|
||||
uint32_t sectors = 0;
|
||||
void* buffer = (void*)0;
|
||||
st = AhciGetIrpReadWrite(irp, &write, &lba, §ors, &buffer);
|
||||
(void)write;
|
||||
(void)buffer;
|
||||
if (!KSUCCESS(st) || lba + sectors > drv->sectorCount) {
|
||||
IoReleaseRemoveLock(&drv->removeLock, irp);
|
||||
return KSUCCESS(st) ? STATUS_INVALID_PARAMETER : st;
|
||||
}
|
||||
|
||||
irp->Status = STATUS_FAILURE;
|
||||
irp->Information = 0;
|
||||
@@ -399,6 +435,49 @@ static KSTATUS AhciDispatchReadWrite(DEVICE_OBJECT *device, IRP *irp) {
|
||||
return STATUS_PENDING;
|
||||
}
|
||||
|
||||
static void AhciCancelReleaseRemoveLock(IRP* irp, void* context) {
|
||||
AHCI_DRIVE* drv = (AHCI_DRIVE*)context;
|
||||
if (drv)
|
||||
IoReleaseRemoveLock(&drv->removeLock, irp);
|
||||
}
|
||||
|
||||
static KSTATUS AhciDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
||||
if (!device || !irp) return STATUS_INVALID_PARAMETER;
|
||||
AHCI_DRIVE* drv = (AHCI_DRIVE*)device->DeviceExtension;
|
||||
if (!drv) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
IO_STACK_LOCATION* ios = IoGetCurrentIrpStackLocation(irp);
|
||||
if (!ios || ios->MajorFunction != IRP_MJ_PNP)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
switch ((IO_PNP_MINOR_FUNCTION)ios->MinorFunction) {
|
||||
case IRP_MN_START_DEVICE:
|
||||
device->PnpState = DevicePnpStarted;
|
||||
return STATUS_SUCCESS;
|
||||
case IRP_MN_QUERY_REMOVE_DEVICE:
|
||||
device->PnpState = DevicePnpRemovePending;
|
||||
return STATUS_SUCCESS;
|
||||
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
||||
device->PnpState = DevicePnpStarted;
|
||||
return STATUS_SUCCESS;
|
||||
case IRP_MN_SURPRISE_REMOVAL:
|
||||
drv->surpriseRemoved = true;
|
||||
device->PnpState = DevicePnpSurpriseRemoved;
|
||||
IrpQueueCancelAllEx(&drv->irpQueue, STATUS_OBJECT_DEAD, AhciCancelReleaseRemoveLock, drv);
|
||||
return STATUS_SUCCESS;
|
||||
case IRP_MN_REMOVE_DEVICE:
|
||||
drv->removed = true;
|
||||
device->PnpState = DevicePnpDeleted;
|
||||
IrpQueueCancelAllEx(&drv->irpQueue, STATUS_OBJECT_DEAD, AhciCancelReleaseRemoveLock, drv);
|
||||
IoReleaseRemoveLockAndWait(&drv->removeLock, irp);
|
||||
IoDeleteDevice(device);
|
||||
drv->deviceObject = (DEVICE_OBJECT*)0;
|
||||
return STATUS_SUCCESS;
|
||||
default:
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
@@ -420,17 +499,24 @@ static void AhciWorker(uintptr_t arg) {
|
||||
KeWaitSemaphore(drv->irpQueue.Semaphore);
|
||||
|
||||
IRP *irp = IrpQueueDequeue(&drv->irpQueue);
|
||||
if (!irp) KePanic(KE_PANIC_CODE_DRIVER, "AhciWorker: semaphore fired but queue is empty - IRP accounting bug\n");
|
||||
if (!irp)
|
||||
continue;
|
||||
|
||||
bool write = !!(irp->Flags & IRP_FLAG_WRITE);
|
||||
KSTATUS st;
|
||||
if (write)
|
||||
st = do_write(drv, irp->Lba, irp->SectorCount, irp->Buffer);
|
||||
else
|
||||
st = do_read (drv, irp->Lba, irp->SectorCount, irp->Buffer);
|
||||
bool write = false;
|
||||
uint64_t lba = 0;
|
||||
uint32_t sectors = 0;
|
||||
void* buffer = (void*)0;
|
||||
KSTATUS st = AhciGetIrpReadWrite(irp, &write, &lba, §ors, &buffer);
|
||||
if (KSUCCESS(st)) {
|
||||
if (write)
|
||||
st = do_write(drv, lba, sectors, buffer);
|
||||
else
|
||||
st = do_read (drv, lba, sectors, buffer);
|
||||
}
|
||||
|
||||
// Publish result then fire completion hooks through the common I/O path.
|
||||
IoCompleteRequest(irp, st, KSUCCESS(st) ? ((size_t)irp->SectorCount * 512u) : 0);
|
||||
IoReleaseRemoveLock(&drv->removeLock, irp);
|
||||
IoCompleteRequest(irp, st, KSUCCESS(st) ? ((size_t)sectors * 512u) : 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -467,9 +553,10 @@ KSTATUS AhciInitialize(const HAL_API *hal) {
|
||||
g_driveCount = 0;
|
||||
|
||||
memset(&g_driver, 0, sizeof(g_driver));
|
||||
g_driver.Name = "ahci";
|
||||
IoInitializeDriverObject(&g_driver, SYS_SV_LITERAL("ahci"));
|
||||
g_driver.MajorFunction[IRP_MJ_READ] = AhciDispatchReadWrite;
|
||||
g_driver.MajorFunction[IRP_MJ_WRITE] = AhciDispatchReadWrite;
|
||||
g_driver.MajorFunction[IRP_MJ_PNP] = AhciDispatchPnp;
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Locate AHCI controller via PCI class scan
|
||||
@@ -588,6 +675,11 @@ KSTATUS AhciInitialize(const HAL_API *hal) {
|
||||
continue;
|
||||
}
|
||||
IrpQueueInit(&drv->irpQueue, irpSem);
|
||||
st = IoInitializeRemoveLock(&drv->removeLock);
|
||||
if (!KSUCCESS(st)) {
|
||||
DbgPrint("AHCI: port %u: remove-lock init failed (0x%x)\n", portno, st);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Phase 6: IDENTIFY (polled - scheduler not yet running)
|
||||
st = port_identify(drv);
|
||||
@@ -613,7 +705,8 @@ KSTATUS AhciInitialize(const HAL_API *hal) {
|
||||
continue;
|
||||
}
|
||||
drv->deviceObject->DeviceExtension = drv;
|
||||
drv->deviceObject->SectorCount = drv->sectorCount;
|
||||
drv->deviceObject->u.Disk.SectorCount = drv->sectorCount;
|
||||
drv->deviceObject->u.Disk.SectorSize = 512;
|
||||
drv->deviceObject->AlignmentRequirement = 512;
|
||||
|
||||
st = IoRegisterDiskDevice((uint8_t)driveIdx, drv->deviceObject);
|
||||
|
||||
Reference in new issue
Block a user