replace nob with ms' build, move disk creation to build.bat, major comment cleanup, remove old and stupid tests, overhaul interrupt management with per-CPU vector allocation, affinity migration and safe teardown, add proper IOAPIC routing and PCI MSI/MSI-X/INTx support, migrate drivers to the new interrupt API, integrate ACPICA with a proper OS services layer, move ACPI firmware events, power button handling and S5 shutdown into acpi.sys, add parallel driver startup and atomic publication, replace PnP arrays with dynamic lists, redesign service startup again to be asynchronous, add delayed startup mode for services, allow omitting keys in services.ini, fix acpi ec deferred work handling, fix kernel threads having garbage exit code.

This commit is contained in:
maksw committed 2026-10-28 15:18:43 +01:00
1 parent d36f19509c
commit 36eef8f58d
696 files changed
+147281 -7530

No files matched your search

+19 -114
View File
@@ -6,10 +6,6 @@
#include <string.h>
static DRIVER_OBJECT gHdaDriver;
static HDA_CONTROLLER* gHdaControllers[HDA_MAX_CONTROLLERS];
static uint32_t gHdaControllerCount;
static SPINLOCK gHdaRegistryLock = SPINLOCK_INIT;
static const IO_DEVICE_ID gHdaIds[] = {
{ IoBusPci, { "PCI\\VEN_8086&DEV_2668", sizeof("PCI\\VEN_8086&DEV_2668") - 1u } },
{ IoBusPci, { "PCI\\VEN_15AD&DEV_1977", sizeof("PCI\\VEN_15AD&DEV_1977") - 1u } },
@@ -21,79 +17,14 @@ static const IO_DRIVER_ID_TABLE gHdaIdTable = {
sizeof(gHdaIds) / sizeof(gHdaIds[0]),
};
// Registers a controller in the shared interrupt scan set.
static KSTATUS HdaRegisterController(HDA_CONTROLLER* controller) {
if (!controller)
return NTLSTATUS_INVALID_PARAMETER;
uintptr_t flags = KeAcquireSpinlock(&gHdaRegistryLock);
for (uint32_t index = 0; index < gHdaControllerCount; index++) {
if (gHdaControllers[index] == controller) {
KeReleaseSpinlock(&gHdaRegistryLock, flags);
return NTLSTATUS_SUCCESS;
}
}
if (gHdaControllerCount == HDA_MAX_CONTROLLERS) {
KeReleaseSpinlock(&gHdaRegistryLock, flags);
return NTLSTATUS_NO_MEMORY;
}
gHdaControllers[gHdaControllerCount++] = controller;
KeReleaseSpinlock(&gHdaRegistryLock, flags);
return NTLSTATUS_SUCCESS;
// Handles the interrupt for its owning HDA controller.
static void HdaIsr(void* context) {
HDA_CONTROLLER* controller = (HDA_CONTROLLER*)context;
if (controller && controller->Magic == HDA_CONTROLLER_MAGIC)
HdaHandleInterrupt(controller);
}
// Removes a controller from the shared interrupt scan set.
static void HdaUnregisterController(HDA_CONTROLLER* controller) {
if (!controller)
return;
uintptr_t flags = KeAcquireSpinlock(&gHdaRegistryLock);
for (uint32_t index = 0; index < gHdaControllerCount; index++) {
if (gHdaControllers[index] != controller)
continue;
gHdaControllers[index] = gHdaControllers[gHdaControllerCount - 1u];
gHdaControllers[gHdaControllerCount - 1u] = (HDA_CONTROLLER*)0;
gHdaControllerCount--;
break;
}
KeReleaseSpinlock(&gHdaRegistryLock, flags);
}
// Dispatches a hardware interrupt to every live HDA controller.
static void HdaIsr(void) {
DEVICE_OBJECT* devices[HDA_MAX_CONTROLLERS];
uint32_t count = 0;
uintptr_t flags = KeAcquireSpinlock(&gHdaRegistryLock);
count = gHdaControllerCount;
if (count > HDA_MAX_CONTROLLERS)
count = HDA_MAX_CONTROLLERS;
for (uint32_t index = 0; index < count; index++) {
HDA_CONTROLLER* controller = gHdaControllers[index];
devices[index] = controller ? controller->Fdo : (DEVICE_OBJECT*)0;
if (devices[index])
IoReferenceDeviceObject(devices[index]);
}
KeReleaseSpinlock(&gHdaRegistryLock, flags);
for (uint32_t index = 0; index < count; index++) {
DEVICE_OBJECT* device = devices[index];
if (!device)
continue;
HDA_CONTROLLER* controller = (HDA_CONTROLLER*)device->DeviceExtension;
if (controller && controller->Magic == HDA_CONTROLLER_MAGIC)
HdaHandleInterrupt(controller);
IoDereferenceDeviceObject(device);
}
}
// Registers the global ISR once for each kernel IRQ slot used by HDA.
static KSTATUS HdaRegisterIrq(uint8_t irq) {
if (irq >= 24u)
return NTLSTATUS_NOT_SUPPORTED;
KeIrqRegister(irq, HdaIsr);
return NTLSTATUS_SUCCESS;
}
// Maps BAR0 and validates the stream-descriptor aperture described by GCAP.
static KSTATUS HdaMapRegisters(HDA_CONTROLLER* controller) {
@@ -149,29 +80,14 @@ static KSTATUS HdaMapRegisters(HDA_CONTROLLER* controller) {
return NTLSTATUS_SUCCESS;
}
// Configures MSI first and enables INTx only after MSI setup reports failure.
// Connects the controller interrupt using the PCI bus routing policy.
static KSTATUS HdaConfigureInterrupt(HDA_CONTROLLER* controller) {
KSTATUS status = PciEnableMsiAuto(controller->Pdo, &controller->Irq);
if (KSUCCESS(status)) {
controller->UsingMsi = true;
return NTLSTATUS_SUCCESS;
}
DbgPrint(
"HDA: MSI setup failed status=0x%x; attempting explicit INTx fallback\n",
status);
controller->UsingMsi = false;
status = PciGetInterrupt(controller->Pdo, &controller->Irq);
if (!KSUCCESS(status))
return status;
if (controller->Irq == 0xFFu || controller->Irq >= 24u)
return NTLSTATUS_NOT_SUPPORTED;
status = PciEnableDevice(controller->Pdo,
PCI_ENABLE_MEMORY |
PCI_ENABLE_BUSMASTER |
PCI_ENABLE_INTX);
return status;
controller->InterruptRequest.Routine = HdaIsr;
controller->InterruptRequest.Context = controller;
controller->InterruptRequest.Affinity = 0;
controller->InterruptRequest.Interrupt = (KE_INTERRUPT*)0;
return PciConnectInterrupts(controller->Pdo, &controller->InterruptRequest,
1u, &controller->UsingMsi);
}
// Waits until queued or active interrupt work no longer references the controller.
@@ -214,9 +130,6 @@ static KSTATUS HdaStartDevice(HDA_CONTROLLER* controller) {
if (!KSUCCESS(status))
return status;
status = HdaConfigureInterrupt(controller);
if (!KSUCCESS(status))
return status;
status = HdaAllocateDma(controller);
if (!KSUCCESS(status))
@@ -237,21 +150,13 @@ static KSTATUS HdaStartDevice(HDA_CONTROLLER* controller) {
return status;
}
status = HdaRegisterController(controller);
status = HdaConfigureInterrupt(controller);
if (!KSUCCESS(status)) {
HdaStopRecoveryWorker(controller);
HdaQuiesceController(controller);
HdaReleaseDma(controller);
return status;
}
status = HdaRegisterIrq(controller->Irq);
if (!KSUCCESS(status)) {
HdaUnregisterController(controller);
HdaStopRecoveryWorker(controller);
HdaQuiesceController(controller);
HdaReleaseDma(controller);
return status;
}
controller->Started = true;
controller->Fdo->PnpState = DevicePnpStarted;
@@ -261,7 +166,8 @@ static KSTATUS HdaStartDevice(HDA_CONTROLLER* controller) {
status != NTLSTATUS_NOT_FOUND) {
controller->Started = false;
controller->Fdo->PnpState = DevicePnpNotStarted;
HdaUnregisterController(controller);
if (controller->InterruptRequest.Interrupt)
PciDisconnectInterrupts(controller->Pdo, &controller->InterruptRequest, 1u);
HdaStopRecoveryWorker(controller);
HdaQuiesceController(controller);
HdaReleaseDma(controller);
@@ -302,7 +208,8 @@ static KSTATUS HdaDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
case IRP_MN_SURPRISE_REMOVAL:
controller->Started = false;
controller->SurpriseRemoved = true;
HdaUnregisterController(controller);
if (controller->InterruptRequest.Interrupt)
PciDisconnectInterrupts(controller->Pdo, &controller->InterruptRequest, 1u);
HdaStopRecoveryWorker(controller);
KSTATUS surpriseDpcStatus =
HdaWaitForControllerInterruptWorkIdle(controller);
@@ -320,7 +227,8 @@ static KSTATUS HdaDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
if (!controller->SurpriseRemoved && controller->Registers)
HdaWrite32(controller, HDA_REG_INTCTL, 0);
controller->Started = false;
HdaUnregisterController(controller);
if (controller->InterruptRequest.Interrupt)
PciDisconnectInterrupts(controller->Pdo, &controller->InterruptRequest, 1u);
HdaStopRecoveryWorker(controller);
KSTATUS dpcStatus = HdaWaitForControllerInterruptWorkIdle(controller);
if (!KSUCCESS(dpcStatus)) {
@@ -366,7 +274,6 @@ static KSTATUS HdaAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDevice
controller->Magic = HDA_CONTROLLER_MAGIC;
controller->Fdo = fdo;
controller->Pdo = physicalDeviceObject;
controller->Irq = 0xFFu;
controller->StateLock = (SPINLOCK)SPINLOCK_INIT;
controller->Output.StreamTag = HDA_OUTPUT_STREAM_TAG;
@@ -382,8 +289,6 @@ static KSTATUS HdaAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDevice
static KSTATUS DriverInitialize(NTL_MODULE* module) {
(void)module;
gHdaControllerCount = 0;
memset(gHdaControllers, 0, sizeof(gHdaControllers));
memset(&gHdaDriver, 0, sizeof(gHdaDriver));
IoInitializeDriverObject(&gHdaDriver, SYS_SV_LITERAL("hda"));