replace ad hoc driver loading with a proper driver manager, new DDK, new PnP manager with device matching, asynchronous startup, resource ownership and removal, add shared PCI capability helpers, replace typed, rigid services with a proper service manager, implement proper system shutdown and restart, shutting down unloads drivers and shuts down services, add simple power button, remove heavyweight boot self-tests and SMP stress runs, add monotonic timestamps to kernel debug output, fruitless USB and PS/2 fixes, make test builds opt in.

This commit is contained in:
maksw committed 2026-10-26 10:08:03 +01:00
1 parent c0ad63c27f
commit d36f19509c
160 files changed
+6563 -7366

No files matched your search

+10 -16
View File
@@ -1,10 +1,10 @@
#include <ntlite/ddk/module.h>
// Intel High Definition Audio PCI attachment and controller lifetime management.
#include "hda.h"
#include <string.h>
const NTL_DDK* gHdaDdk;
static DRIVER_OBJECT gHdaDriver;
static HDA_CONTROLLER* gHdaControllers[HDA_MAX_CONTROLLERS];
static uint32_t gHdaControllerCount;
@@ -157,7 +157,7 @@ static KSTATUS HdaConfigureInterrupt(HDA_CONTROLLER* controller) {
return NTLSTATUS_SUCCESS;
}
gHdaDdk->Debug->Print(
DbgPrint(
"HDA: MSI setup failed status=0x%x; attempting explicit INTx fallback\n",
status);
controller->UsingMsi = false;
@@ -182,7 +182,7 @@ static KSTATUS HdaWaitForControllerInterruptWorkIdle(HDA_CONTROLLER* controller)
if (controller->IsrActive == 0 &&
controller->Dpc.Inserted == 0 && controller->DpcActive == 0)
return NTLSTATUS_SUCCESS;
gHdaDdk->Timer->Stall(10);
KeStallExecution(10);
}
return NTLSTATUS_TIMEOUT;
}
@@ -268,7 +268,7 @@ static KSTATUS HdaStartDevice(HDA_CONTROLLER* controller) {
return status;
}
if (!KSUCCESS(status)) {
gHdaDdk->Debug->Print(
DbgPrint(
"HDA: no analog endpoint registered status=0x%x\n",
status);
}
@@ -379,14 +379,9 @@ static KSTATUS HdaAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDevice
}
// Registers the Intel HDA transport driver with the I/O manager.
KSTATUS DriverEntry(const NTL_DDK* ddk, NTL_DRIVER_INIT* init) {
(void)init;
if (!ddk || !ddk->Debug || !ddk->Debug->Print || !ddk->Dma || !ddk->Timer ||
!ddk->Timer->QueryTicks || !ddk->Timer->Stall || !ddk->Audio ||
!ddk->Scheduler || !ddk->Scheduler->DelayThread)
return NTLSTATUS_INVALID_PARAMETER;
static KSTATUS DriverInitialize(NTL_MODULE* module) {
(void)module;
gHdaDdk = ddk;
gHdaControllerCount = 0;
memset(gHdaControllers, 0, sizeof(gHdaControllers));
@@ -395,9 +390,8 @@ KSTATUS DriverEntry(const NTL_DDK* ddk, NTL_DRIVER_INIT* init) {
gHdaDriver.IdTable = &gHdaIdTable;
gHdaDriver.DriverAddDevice = HdaAddDevice;
gHdaDriver.MajorFunction[IRP_MJ_PNP] = HdaDispatchPnp;
KSTATUS status = IoRegisterDriverObject(&gHdaDriver);
if (!KSUCCESS(status))
gHdaDdk->Debug->Print("HDA: IoRegisterDriverObject failed status=0x%x\n", status);
return status;
return NTLSTATUS_SUCCESS;
}
static DRIVER_OBJECT* const gModuleIoDrivers[] = { &gHdaDriver };
NTL_DECLARE_IO_MODULE(DriverInitialize, gModuleIoDrivers);
-2
View File
@@ -300,8 +300,6 @@ struct HDA_CONTROLLER {
uint64_t ControllerInterruptCount;
};
extern const NTL_DDK* gHdaDdk;
// Returns one byte from the controller register aperture.
uint8_t HdaRead8(const HDA_CONTROLLER* controller, uint32_t offset);
+12 -12
View File
@@ -281,7 +281,7 @@ static KSTATUS HdaCodecPowerD0(HDA_CODEC_STATE* state,
if ((powerState & HDA_POWER_ACTUAL_MASK) ==
(HDA_POWER_STATE_D0 << HDA_POWER_ACTUAL_SHIFT))
return NTLSTATUS_SUCCESS;
gHdaDdk->Timer->Stall(10);
KeStallExecution(10);
}
return NTLSTATUS_TIMEOUT;
}
@@ -583,7 +583,7 @@ static KSTATUS HdaCodecEnumerateAll(HDA_CODEC_STATE* state) {
continue;
}
lastStatus = status;
gHdaDdk->Debug->Print(
DbgPrint(
"HDA: codec %u topology discovery failed status=0x%x\n",
codecAddress,
status);
@@ -1176,7 +1176,7 @@ static void HdaCodecRefreshEndpointsLocked(HDA_CODEC_STATE* state) {
if (endpoint->Available != available) {
endpoint->Available = available;
if (endpoint->KernelEndpoint)
gHdaDdk->Audio->SetEndpointAvailable(endpoint->KernelEndpoint,
IoAudioSetEndpointAvailable(endpoint->KernelEndpoint,
available ? 1u : 0u);
}
if (!endpoint->Running || endpoint->Starting ||
@@ -1210,13 +1210,13 @@ static void HdaCodecRefreshEndpointsLocked(HDA_CODEC_STATE* state) {
uintptr_t flags = KeAcquireSpinlock(&state->CallbackLock);
endpoint->Running = false;
KeReleaseSpinlock(&state->CallbackLock, flags);
gHdaDdk->Debug->Print(
DbgPrint(
"HDA: jack reroute failed kind=%u route=%u status=0x%x\n",
endpoint->Kind,
selectedRoute,
status);
if (endpoint->KernelEndpoint) {
gHdaDdk->Audio->ReportEndpointFailure(endpoint->KernelEndpoint,
IoAudioReportEndpointFailure(endpoint->KernelEndpoint,
status,
0);
}
@@ -1306,7 +1306,7 @@ static void HdaCodecWorkThread(uintptr_t argument) {
static void HdaCodecPollThread(uintptr_t argument) {
HDA_CODEC_STATE* state = (HDA_CODEC_STATE*)argument;
while (state->PollRunning) {
(void)gHdaDdk->Scheduler->DelayThread(HDA_JACK_POLL_INTERVAL_MS);
(void)KeDelayThread(HDA_JACK_POLL_INTERVAL_MS);
if (!state->PollRunning)
break;
uintptr_t flags = KeAcquireSpinlock(&state->CallbackLock);
@@ -1355,7 +1355,7 @@ static void HdaCodecPeriodComplete(void* context,
endpoint = state->ActiveEndpoint->KernelEndpoint;
KeReleaseSpinlock(&state->CallbackLock, flags);
if (endpoint) {
gHdaDdk->Audio->NotifyPeriod(endpoint,
IoAudioNotifyPeriod(endpoint,
completedPeriodIndex,
presentedFrames,
finePositionFrames,
@@ -1453,7 +1453,7 @@ static void HdaCodecTransportFailure(void* context, KSTATUS failureStatus) {
KeReleaseSpinlock(&state->CallbackLock, flags);
for (uint8_t index = 0; index < state->EndpointCount; index++) {
if (state->Endpoints[index].KernelEndpoint) {
gHdaDdk->Audio->ReportEndpointFailure(
IoAudioReportEndpointFailure(
state->Endpoints[index].KernelEndpoint,
failureStatus,
0);
@@ -1747,7 +1747,7 @@ static KSTATUS HdaCodecRegisterEndpoints(HDA_CODEC_STATE* state) {
}
}
status = gHdaDdk->Audio->RegisterEndpoint(&registration,
status = IoAudioRegisterEndpoint(&registration,
&endpoint->KernelEndpoint);
if (!KSUCCESS(status))
return status;
@@ -1779,7 +1779,7 @@ static void HdaCodecStopWorkers(HDA_CODEC_STATE* state) {
// Discovers codec topology and registers usable analog render endpoints.
KSTATUS HdaCodecInitialize(HDA_CONTROLLER* controller) {
if (!controller || !gHdaDdk || !gHdaDdk->Audio || !gHdaDdk->Scheduler)
if (!controller)
return NTLSTATUS_INVALID_PARAMETER;
HDA_CODEC_STATE* state = (HDA_CODEC_STATE*)MmAllocatePoolTag(
sizeof(HDA_CODEC_STATE),
@@ -1801,7 +1801,7 @@ KSTATUS HdaCodecInitialize(HDA_CONTROLLER* controller) {
goto failed;
status = HdaCodecBuildRoutes(state);
if (!KSUCCESS(status)) {
gHdaDdk->Debug->Print(
DbgPrint(
"HDA: no usable 48000 Hz, stereo, 16-bit analog converter-to-pin route\n");
goto failed;
}
@@ -1873,7 +1873,7 @@ void HdaCodecStop(HDA_CONTROLLER* controller, IO_AUDIO_REMOVAL_MODE mode) {
HDA_LOGICAL_ENDPOINT* endpoint = &state->Endpoints[index - 1u];
if (!endpoint->KernelEndpoint)
continue;
gHdaDdk->Audio->UnregisterEndpoint(endpoint->KernelEndpoint, mode);
IoAudioUnregisterEndpoint(endpoint->KernelEndpoint, mode);
endpoint->KernelEndpoint = (IO_AUDIO_ENDPOINT*)0;
}
+28 -31
View File
@@ -16,15 +16,12 @@ static __forceinline void HdaMemoryBarrier(void) {
// Returns the controller's monotonic microsecond counter.
static uint64_t HdaQueryTicks(void) {
if (!gHdaDdk || !gHdaDdk->Timer || !gHdaDdk->Timer->QueryTicks)
return 0;
return gHdaDdk->Timer->QueryTicks();
return KeQueryTicks();
}
// Delays for a bounded controller settling interval.
static void HdaStall(uint32_t microseconds) {
if (gHdaDdk && gHdaDdk->Timer && gHdaDdk->Timer->Stall)
gHdaDdk->Timer->Stall(microseconds);
KeStallExecution(microseconds);
}
// Returns one byte from the controller register aperture.
@@ -170,7 +167,7 @@ static uint8_t HdaRingSizeSelector(uint16_t count) {
// Releases all DMA and synchronization resources owned by one controller.
void HdaReleaseDma(HDA_CONTROLLER* controller) {
if (!controller || !gHdaDdk || !gHdaDdk->Dma)
if (!controller)
return;
if (controller->StreamMutex) {
@@ -190,12 +187,12 @@ void HdaReleaseDma(HDA_CONTROLLER* controller) {
controller->RecoveryFinished = (EVENT*)0;
}
gHdaDdk->Dma->FreeCommonBuffer(controller->Output.BdlDma);
IoDmaFreeCommonBuffer(controller->Output.BdlDma);
for (uint32_t ringIndex = 0; ringIndex < HDA_MAX_LOGICAL_ENDPOINTS; ringIndex++)
gHdaDdk->Dma->FreeCommonBuffer(controller->Output.Rings[ringIndex].Dma);
gHdaDdk->Dma->FreeCommonBuffer(controller->PositionDma);
gHdaDdk->Dma->FreeCommonBuffer(controller->RirbDma);
gHdaDdk->Dma->FreeCommonBuffer(controller->CorbDma);
IoDmaFreeCommonBuffer(controller->Output.Rings[ringIndex].Dma);
IoDmaFreeCommonBuffer(controller->PositionDma);
IoDmaFreeCommonBuffer(controller->RirbDma);
IoDmaFreeCommonBuffer(controller->CorbDma);
controller->Output.BdlDma = (IO_DMA_BUFFER*)0;
for (uint32_t ringIndex = 0; ringIndex < HDA_MAX_LOGICAL_ENDPOINTS; ringIndex++) {
controller->Output.Rings[ringIndex].Dma = (IO_DMA_BUFFER*)0;
@@ -211,14 +208,14 @@ void HdaReleaseDma(HDA_CONTROLLER* controller) {
controller->Corb = (uint32_t*)0;
if (controller->DmaAdapter) {
gHdaDdk->Dma->PutAdapter(controller->DmaAdapter);
IoDmaPutAdapter(controller->DmaAdapter);
controller->DmaAdapter = (IO_DMA_ADAPTER*)0;
}
}
// Allocates the transport and output DMA resources for one controller.
KSTATUS HdaAllocateDma(HDA_CONTROLLER* controller) {
if (!controller || !controller->Fdo || !gHdaDdk || !gHdaDdk->Dma)
if (!controller || !controller->Fdo)
return NTLSTATUS_INVALID_PARAMETER;
IO_DMA_REQUIREMENTS requirements;
@@ -229,7 +226,7 @@ KSTATUS HdaAllocateDma(HDA_CONTROLLER* controller) {
requirements.Alignment = 128u;
requirements.MaximumSegments = 1u;
KSTATUS status = gHdaDdk->Dma->GetAdapter(controller->Fdo,
KSTATUS status = IoDmaGetAdapter(controller->Fdo,
&requirements,
&controller->DmaAdapter);
if (!KSUCCESS(status))
@@ -248,7 +245,7 @@ KSTATUS HdaAllocateDma(HDA_CONTROLLER* controller) {
return status;
}
status = gHdaDdk->Dma->AllocateCommonBuffer(controller->DmaAdapter,
status = IoDmaAllocateCommonBuffer(controller->DmaAdapter,
(size_t)controller->CorbEntryCount * sizeof(uint32_t),
128u,
&controller->CorbDma);
@@ -256,7 +253,7 @@ KSTATUS HdaAllocateDma(HDA_CONTROLLER* controller) {
HdaReleaseDma(controller);
return status;
}
status = gHdaDdk->Dma->AllocateCommonBuffer(controller->DmaAdapter,
status = IoDmaAllocateCommonBuffer(controller->DmaAdapter,
(size_t)controller->RirbEntryCount * sizeof(HDA_RIRB_ENTRY),
128u,
&controller->RirbDma);
@@ -266,7 +263,7 @@ KSTATUS HdaAllocateDma(HDA_CONTROLLER* controller) {
}
// The position buffer is optional because LPIB is the supported fallback.
status = gHdaDdk->Dma->AllocateCommonBuffer(controller->DmaAdapter,
status = IoDmaAllocateCommonBuffer(controller->DmaAdapter,
(size_t)controller->TotalStreamCount * sizeof(uint64_t),
128u,
&controller->PositionDma);
@@ -274,7 +271,7 @@ KSTATUS HdaAllocateDma(HDA_CONTROLLER* controller) {
controller->PositionDma = (IO_DMA_BUFFER*)0;
for (uint32_t ringIndex = 0; ringIndex < HDA_MAX_LOGICAL_ENDPOINTS; ringIndex++) {
status = gHdaDdk->Dma->AllocateCommonBuffer(
status = IoDmaAllocateCommonBuffer(
controller->DmaAdapter,
HDA_OUTPUT_BUFFER_BYTES,
128u,
@@ -284,7 +281,7 @@ KSTATUS HdaAllocateDma(HDA_CONTROLLER* controller) {
return status;
}
}
status = gHdaDdk->Dma->AllocateCommonBuffer(controller->DmaAdapter,
status = IoDmaAllocateCommonBuffer(controller->DmaAdapter,
HDA_OUTPUT_PERIOD_COUNT * sizeof(HDA_BDL_ENTRY),
128u,
&controller->Output.BdlDma);
@@ -293,27 +290,27 @@ KSTATUS HdaAllocateDma(HDA_CONTROLLER* controller) {
return status;
}
controller->Corb = (uint32_t*)gHdaDdk->Dma->GetCommonBufferAddress(controller->CorbDma);
controller->Rirb = (HDA_RIRB_ENTRY*)gHdaDdk->Dma->GetCommonBufferAddress(controller->RirbDma);
controller->CorbDeviceAddress = gHdaDdk->Dma->GetCommonBufferDeviceAddress(controller->CorbDma);
controller->RirbDeviceAddress = gHdaDdk->Dma->GetCommonBufferDeviceAddress(controller->RirbDma);
controller->Corb = (uint32_t*)IoDmaGetCommonBufferAddress(controller->CorbDma);
controller->Rirb = (HDA_RIRB_ENTRY*)IoDmaGetCommonBufferAddress(controller->RirbDma);
controller->CorbDeviceAddress = IoDmaGetCommonBufferDeviceAddress(controller->CorbDma);
controller->RirbDeviceAddress = IoDmaGetCommonBufferDeviceAddress(controller->RirbDma);
if (controller->PositionDma) {
controller->PositionBuffer = (volatile uint64_t*)
gHdaDdk->Dma->GetCommonBufferAddress(controller->PositionDma);
IoDmaGetCommonBufferAddress(controller->PositionDma);
controller->PositionDeviceAddress =
gHdaDdk->Dma->GetCommonBufferDeviceAddress(controller->PositionDma);
IoDmaGetCommonBufferDeviceAddress(controller->PositionDma);
}
for (uint32_t ringIndex = 0; ringIndex < HDA_MAX_LOGICAL_ENDPOINTS; ringIndex++) {
controller->Output.Rings[ringIndex].Buffer = (uint8_t*)
gHdaDdk->Dma->GetCommonBufferAddress(controller->Output.Rings[ringIndex].Dma);
IoDmaGetCommonBufferAddress(controller->Output.Rings[ringIndex].Dma);
controller->Output.Rings[ringIndex].DeviceAddress =
gHdaDdk->Dma->GetCommonBufferDeviceAddress(
IoDmaGetCommonBufferDeviceAddress(
controller->Output.Rings[ringIndex].Dma);
}
controller->Output.Bdl = (HDA_BDL_ENTRY*)
gHdaDdk->Dma->GetCommonBufferAddress(controller->Output.BdlDma);
IoDmaGetCommonBufferAddress(controller->Output.BdlDma);
controller->Output.BdlDeviceAddress =
gHdaDdk->Dma->GetCommonBufferDeviceAddress(controller->Output.BdlDma);
IoDmaGetCommonBufferDeviceAddress(controller->Output.BdlDma);
memset(controller->Corb, 0, (size_t)controller->CorbEntryCount * sizeof(uint32_t));
memset(controller->Rirb, 0, (size_t)controller->RirbEntryCount * sizeof(HDA_RIRB_ENTRY));
@@ -502,7 +499,7 @@ static KSTATUS HdaResetCorbReadPointer(HDA_CONTROLLER* controller) {
static KSTATUS HdaReportInitializationFailure(HDA_CONTROLLER* controller,
const char* stage,
KSTATUS status) {
gHdaDdk->Debug->Print(
DbgPrint(
"HDA: init stage=%s failed status=0x%x GCTL=0x%08x STATESTS=0x%04x "
"CORB=%02x/%02x/%04x/%04x RIRB=%02x/%02x/%04x SDCTL=0x%06x\n",
stage,
@@ -1381,7 +1378,7 @@ static void HdaRecoveryWorker(uintptr_t argument) {
if (!KSUCCESS(status) && status != NTLSTATUS_DEVICE_REMOVED) {
if (callbacks.TransportFailure)
callbacks.TransportFailure(callbackContext, status);
gHdaDdk->Debug->Print("HDA: recovery failed status=0x%x\n", status);
DbgPrint("HDA: recovery failed status=0x%x\n", status);
}
if (queueDpc)
(void)KeInsertQueueDpc(&controller->Dpc, (void*)0, (void*)0);