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:
1 parent
c0ad63c27f
commit
d36f19509c
160 files changed
+6563
-7366
No files matched your search
@@ -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);
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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(®istration,
|
||||
status = IoAudioRegisterEndpoint(®istration,
|
||||
&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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user