I am trying to register an MSI interrupt handling routine with wdm.
However, calling the IoConnectInterruptEx() function causes a BSOD (PNP_DETECTED_FATAL_ERROR).
May I know what am I doing wrong?
I wrote the code like this:
StartDevice(
PDEVICE_OBJECT fdo,
PCM_PARTIAL_RESOURCE_LIST ResourceListRaw,
PCM_PARTIAL_RESOURCE_LIST ResourceList
)
{
U32 vector;
KIRQL IrqL;
KAFFINITY affinity;
KINTERRUPT_MODE mode;
DEVICE_EXTENSION* pdx;
PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceRaw;
PCM_PARTIAL_RESOURCE_DESCRIPTOR Resource;
....
pdx = fdo->DeviceExtension;
for (i = 0; i < ResourceListRaw->Count; ++i, ++Resource, ++ResourceRaw)
{
KdPrint((" Resource %02d\n", i));
switch (ResourceRaw->Type)
{
case CmResourceTypeInterrupt:
if (ResourceRaw->Flags & CM_RESOURCE_INTERRUPT_MESSAGE)
{
MSIIntPresent = TRUE;
IrqL = (KIRQL)Resource->u.MessageInterrupt.Translated.Level;
vector = Resource->u.MessageInterrupt.Translated.Vector;
affinity = Resource->u.MessageInterrupt.Translated.Affinity;
ShareVector = (BOOLEAN)(Resource->ShareDisposition == CmResourceShareShared);
KdPrint((" Type : Message Interrupt\n"
" Vector : (Translated = 0x%02x)\n"
" IRQL : (Translated = 0x%02x)\n",
" ShareVector : (Translated = 0x%02x)\n",
vector, IrqL, ShareVector));
}
...
}
}
if (MSIIntPresent)
{
IO_CONNECT_INTERRUPT_PARAMETERS params;
RtlZeroMemory(¶ms, sizeof(IO_CONNECT_INTERRUPT_PARAMETERS));
KdPrint(("MSIIntPresent\n"));
KdPrint(("Vector=%d IrqL=%d affinity=%d ShareVector=%d,\n", vector, IrqL, affinity, ShareVector));
params.Version = CONNECT_FULLY_SPECIFIED;
params.FullySpecified.PhysicalDeviceObject = pdx->pPhysicalDeviceObject;
params.FullySpecified.InterruptObject = &pdx->pInterruptObject;
params.FullySpecified.ServiceRoutine = OnInterrupt;
params.FullySpecified.ServiceContext = fdo;
params.FullySpecified.SpinLock = NULL;
params.FullySpecified.Vector = vector;
params.FullySpecified.Irql = IrqL;
params.FullySpecified.SynchronizeIrql = IrqL;
params.FullySpecified.InterruptMode = mode;
params.FullySpecified.ShareVector = ShareVector;
params.FullySpecified.ProcessorEnableMask = affinity;
params.FullySpecified.FloatingSave = FALSE;
status = IoConnectInterruptEx(¶ms);
if (!NT_SUCCESS(status))
{
KdPrint((DBG_NAME "ERROR - IoConnectInterrupt() failed, status = 0x%08x\n", status));
if (status == STATUS_NOT_SUPPORTED)
{
KdPrint(("STATUS_NOT_SUPPORTED\n"));
}
pdx->pInterruptObject = NULL;
}
else
{
KdPrint((DBG_NAME "Connected to interrupt vector\n"));
}
}
}
Is there something wrong with specifying PhysicalDeviceObject or ServiceContext?
I’ve read the documentation provided by microsoft, but I don’t quite understand.
( https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/using-the-connect-fully-specified-version-of-ioconnectinterruptex )
Any advice would be appreciated.