temp
This commit is contained in:
1 parent
d36f19509c
commit
30d20457f0
309 files changed
+121746
-1963
No files matched your search
+19
-114
@@ -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"));
|
||||
|
||||
@@ -242,7 +242,7 @@ struct HDA_CONTROLLER {
|
||||
uint8_t BidirectionalStreamCount;
|
||||
uint8_t TotalStreamCount;
|
||||
uint16_t CodecMask;
|
||||
uint8_t Irq;
|
||||
PCI_INTERRUPT_REQUEST InterruptRequest;
|
||||
bool UsingMsi;
|
||||
bool Started;
|
||||
bool Removed;
|
||||
|
||||
Reference in new issue
Block a user