Hello,
I have a PCIe card which works in legacy mode.
Upon interrupt, I have to read 2 status registers. Each register contains that status of 4 channels. The card handled 8 channels.
Following is the code of the ISR:
BOOLEAN
PLxEvtInterruptIsr(
IN WDFINTERRUPT Interrupt,
IN ULONG MessageID
)
/*++
Routine Description:
Interrupt handler for this driver. Called at DIRQL level when the
device or another device sharing the same interrupt line asserts
the interrupt. The driver first checks the device to make sure whether
this interrupt is generated by its device and if so clear the interrupt
register to disable further generation of interrupts and queue a
DPC to do other I/O work related to interrupt - such as reading
the device memory, starting a DMA transaction, coping it to
the request buffer and completing the request, etc.
Arguments:
Interupt - Handle to WDFINTERRUPT Object for this device.
MessageID - MSI message ID (always 0 in this configuration)
Return Value:
TRUE -- This device generated the interrupt.
FALSE -- This device did not generated this interrupt.
--*/
{
PDEVICE_EXTENSION devExt;
BOOLEAN isRecognized = FALSE;
UINT32 Status14, Status58;
UNREFERENCED_PARAMETER(MessageID);
//KdPrint(("--> PLxEvtInterruptIsr"));
devExt = PLxGetDeviceContext(WdfInterruptGetDevice(Interrupt));
//Read interrupt status register of channels 1..4
Status14 = READ_REGISTER_ULONG((PVOID)((UINT64)devExt->Bar1Address + STATUS_14_OFFSET));
//Read interrupt status register of channels 5..8
Status58 = READ_REGISTER_ULONG((PVOID)((UINT64)devExt->Bar1Address + STATUS_58_OFFSET));
if ((Status14 & 0x03030303) || (Status58 & 0x03030303))
{
//Build 64bits word that contains 8 statuses. Each status is 8 bits
devExt->StatusAll = ((UINT64)Status58 << 32) | Status14;
//Write status register to clear interrupts
WRITE_REGISTER_ULONG((PVOID)((UINT64)devExt->Bar1Address + STATUS_14_OFFSET), Status14);
WRITE_REGISTER_ULONG((PVOID)((UINT64)devExt->Bar1Address + STATUS_58_OFFSET), Status58);
WdfInterruptQueueDpcForIsr(devExt->Interrupt);
isRecognized = TRUE;
}
return isRecognized;
}
In the ISR I save the 64bits status in "StatusAll"
Then in DPC, I have to handle "StatusAll" and call KeSetEvent (for example) to wake a thread that is blocked untill message received in its channel.
The IsrDPC contains the following section:
//
// Acquire this device's InterruptSpinLock.
//
WdfInterruptAcquireLock( Interrupt );
???????
// Release our interrupt spinlock
//
WdfInterruptReleaseLock(Interrupt);
As much as I know there is 1:1 releation between Isr and DPC.
What should I do inside the locked section ?
Thank you,
Zvika