Message signaled interrupt with IoConnectInterruptEx

The problem is your whole concept is whacked out. You have a driver here, but a driver for what? The fact that this is in DispatchCreate suggests to me that you have created a software/virtual device. If so, why did you think the HPET interrupt would be assigned to you? In order to access the HPET interrupt, you have to have been assigned the HPET resources by PnP. VIrtual devices are not assigned resources.

In addition, the HPET is not a PCI device, and therefore does not use message-based interrupts. It is a traditional IRQ device, but you don’t know which IRQ, because you aren’t the owner.

Dear Tim

Thank you very much for your help.
You are right.
No HPET resource is assigned to me.
When I used IoConnectInterrupt, it told me “object was not found”, although I have routed the output of HPET to ioAPIC.
And when I tried WdfInterruptCreate, EVT_WDF_DEVICE_PREPARE_HARDWARE did not work.
But I think HPET supports message-based interrupts. Because it has FSB Interrupt Route Registers. I do not know how to set Tn_FSB_INT_ADDR and Tn_FSB_INT_VAL. IoConnectInterruptEx outputs ConnectionContext(InterruptMessageTable). I think I can use MessageData and MessageAddress in MessageInfo of InterruptMessageTable after I register a message-based interrupt with IoConnectInterruptEx.
I agree with you that I would manage to make the interrupt resource of HPET related to IRQ, IRQL and IRQ vector. But I do not know how I can make it. It annoyed me.
Maybe I am wrong basically.
I just want an interrupt that happened at every about 0.25ms. Can you give me any help more?

Best regard.

On May 8, 2019, at 5:23 PM, tatuo wrote:
>
> You are right.
> No HPET resource is assigned to me.
> When I used IoConnectInterrupt, it told me “object was not found”, although I have routed the output of HPET to ioAPIC.

How do you know the operating system (or some other entity) isn’t already using the HPET?

> But I think HPET supports message-based interrupts.

You are correct; HPET supports a mode similar to PCIe message-based interrupts. I didn’t know that until 10 minutes ago.

However, the kernel does not allow a driver to claim an arbitrary message-based interrupt. It will only configure MBIs that have been assigned to the driver by PnP. Unless you are the device’s driver, you cannot handle its interrupt. If you can find the ACPI identifier assigned to the 2nd HPET by the ACPI BIOS tables, you might be able to write an INF to claim it.

> Maybe I am wrong basically.
> I just want an interrupt that happened at every about 0.25ms.

Not in Windows. If you need a reliable sub-millisecond timer, you’ll need to get a piece of hardware to do it. For example, you could get a $15 USB experimenter’s board, and give it a fake interrupt endpoint with a period of 2 microframes. Such a device would provide your desired interrupt frequency.

Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

Dear Tim

Thank you very much for your help.

How do you know the operating system (or some other entity) isn’t already using the HPET?

HPET has more than 3 timers. It is acceptable that some times are used by system. And we can limit our application to some special hardware.

you might be able to write an INF to claim it.

That is great. I shall try to learn writing a INF file to do it. And I shall report to you if I have succeeded or not.

you could get a $15 USB experimenter’s board, and give it a fake interrupt endpoint with a period of 2 microframes.

I learned USB interrupt Endpoint can not really interrupt. It works in a polling mechanism, therefore the interval between interrupts is not procise. Anyway, it sounds good. I would buy such a board to have a test if I failed with the message-based interrupt.

Thanks a lot.

A 16550 compatible UART should also work fine. Just disable any hardware handshake and keep sending a contiguous data stream into the void. By configuring the baudrate and FIFO thresholds you can control the interrupt frequency quite well. Current industry PC mainboards often still have onboard 16550 compatible UARTs and there are also PCIe expansion cards. And IIRC the DDK contains a driver sample for 16550.

tatuo wrote:

I learned USB interrupt Endpoint can not really interrupt. It works in a polling mechanism, therefore the interval between interrupts is not procise.

That’s because you don’t understand the architecture.  It’s true that
the “interrupt endpoint” has nothing to do with bus interrupts. 
“Interrupt endpoint” was a terrible name choice; it should have been
called a “periodic endpoint”.

However, a USB host controller is a piece of hardware that has very
precise timing.  It fires an interrupt every 125 microseconds so the
driver can complete any requests that completed during the microframe. 
You don’t need to care exactly when during the microframe your interrupt
request happened.  You just know that your request will complete every
other microframe, which is every 250us.

That’s because you don’t understand the architecture. It’s true that the “interrupt endpoint” has nothing to do with bus interrupts.

Actually, the whole nonsense reminds me of a thread where the OP from some “outsourcing location” was just desperate to handle interrupts in his USB driver, and fiercely resisted all our futile attempts to explain to him that USB drivers just don’t handle interrupts…

IIRC, it was that thread when Mr. Aseltine had reached the point of explicitly telling him “Look - you just cannot be THAT obtuse, can you”. OTOH, I am not sure whether we had heard a mantra about “everyone having had been inexperienced once” on that particular occasion…

Anton Bassov

Hi, dear friends
Thank you for your help.
I am testing message-based interrupt on a software_only driver. Test of USB is going to be made afterwards.
I would report the progress to you.
The test is based on echo project of Windows-driver-samples-master.
I added below code to the inf file and create an interrupt with WdfInterruptCreate in EchoDeviceCreate subroutine. I can verify that MSI is supported after the driver is installed. The screen shot is attached.


[ECHO_Device.NT.HW]
[MSI_Interrupts]
HKR,Interrupt Management,0x00000010
HKR,Interrupt Management\MessageSignaledInterruptProperties,0x00000010
HKR,Interrupt Management\MessageSignaledInterruptProperties,MSISupported,0x00010001,1


WDF_INTERRUPT_CONFIG_INIT(&InterruptConfiguration,
InterruptServiceRoutine,
DrvInterruptDpc);

InterruptConfiguration.EvtInterruptEnable = TimerInterruptEnable;
InterruptConfiguration.EvtInterruptDisable = TimerInterruptDisable;
InterruptConfiguration.AutomaticSerialization = TRUE;

status = WdfInterruptCreate(device,
	&InterruptConfiguration,
	WDF_NO_OBJECT_ATTRIBUTES,
	&deviceContext->WdfInterrupt);

I can be sure that EVT_WDF_DEVICE_PREPARE_HARDWARE is called.
But WDFCMRESLIST ResourcesRaw and ResourcesTranslated are empty. Both WdfCmResourceListGetCount(ResourcesTranslated) and WdfCmResourceListGetCount(ResourcesRaw) return 0.

I do not know what is the problem.
I think I should test with a WDM project of software_only driver.
Could anyone tell me where I can get an example WDM project of software_only driver with an inf file?

Thanks.

I am testing message-based interrupt on a software_only driver.

…and this part is reminiscent of Alberto’s attempts to “raise MSI” by the CPU by means of writing to the local APIC’s ICR…

Anton Bassov

The problem is you don’t have a device with the hardware capability necessary to generate the MSI.

You need MSI-capable hardware to generate MSIs. Not every device is MSI capable.

Peter

tatuo wrote:

I am testing message-based interrupt on a software_only driver. Test of USB is going to be made afterwards.

Peter and Anton have already correctly pointed out that hardware is
required for interrupts, but before you waste any more time on this, I
want to address your second sentence.  YOU do not get to handle USB
interrupts.  It’s true that the USB host controller generates interrupts
for certain events, but those interrupts are all handled at the lowest
level by the host controller driver. Higher level drivers just submit
URBs and wait for them to be completed.  When an interrupt does occur,
the host controller driver will figure out what work has been completed,
and will send the completed requests back to the drivers that made them.

But WDFCMRESLIST ResourcesRaw and ResourcesTranslated are empty. Both WdfCmResourceListGetCount(ResourcesTranslated) and WdfCmResourceListGetCount(ResourcesRaw) return 0.

Of course they are empty.  Resources come from hardware.  You have no
hardware, so PnP has no resources for you to handle.  What did you
expect here?  Those MSI registry entries just tell the system “I am
prepared to handle MSIs if my hardware is prepared to generate them.”

I do not know what is the problem.
I think I should test with a WDM project of software_only driver.

No, you should not.  What you need is a better understanding of the
low-level system architecture.  Unless you are the lowest level driver
for a PCI or PCIExpress device, you will not handle interrupts of any kind.

YOU do not get to handle USB interrupts.

OMG…

I was holding my breath in anticipation, waiting for the OP’s next “inquiry” - I bet he would be asking why he does not get an interrupt for his USB device despite having had called IoConnectInterruptEx(). However, now it looks like it may not happen.

What a frustration (unless the OP ignores all your explanations and decides that he has to handle interrupts for his USB device no matter what and no matter how, of course).

Anton Bassov

Dear Tim

Thank you very much for your help.
The reason that I test MSI first is very simple. If interrupt can be done with MSI of HPET, we would not need any hardware. And I can test it shortly.
Now, I nearly give up with MSI.

Can you give me some more deteal information about USB interrupt?
Is it a host controller driver using xHCI?
Where can I download a sample project to start with?

Thanks again.

On May 13, 2019, at 12:28 AM, tatuo wrote:
>
> Can you give me some more deteal information about USB interrupt?
> Is it a host controller driver using xHCI?
> Where can I download a sample project to start with?

There are many, many little USB experimenter’s kits that you could play with. You’ll want to get one that does high speed (USB 2.0) to get sub-millisecond resolution.

But, again, you need to remember that you aren’t literally handling interrupts. That’s all done by the host controller driver. The term “interrupt pipe” is just a way of saying “periodic pipe”. You’d set up your descriptors so your interrupt endpoint has an interval of 2 microframes, which is 250 microseconds. You would need to write a little application using WinUSB that submits a couple of read requests on the interrupt endpoint. When the request is completed, you’ll know another 250us have elapsed.

Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

Dear Tim

Thank you very much for your help.
I can conceive, that using “interrupt pipe” , my program would run in DPC, not in ISR.
It is something different to my expectation.
I think if MessageData and MessageAddress are returned successfully from IoConnectInterruptEx I can use them to configurate HPET.
Then HPET would trigger the interrupt.
The problem is that IoConnectInterruptEx failed.
I modified my source code so that I can use IoConnectInterruptEx after I install my driver with an inf file which enable MSISupported.

InterruptParams.MessageBased.PhysicalDeviceObject = WdfDeviceWdmGetPhysicalDevice(device);

Then IoConnectInterruptEx returns 0xC0000034L, which means “Object Name not found”.
(Before modification, it returned 0xC0000225L, “The object was not found”.)

What is the “Object Name”? What is lack of condition?

Thanks again.

On May 13, 2019, at 10:43 PM, tatuo wrote:
>
> I can conceive, that using “interrupt pipe” , my program would run in DPC, not in ISR.
> It is something different to my expectation.

You need to adjust your expectations, because Windows does not work the way you think it does.

By the way, WHY do you need 250us timer ticks? What is the use case?

> I think if MessageData and MessageAddress are returned successfully from IoConnectInterruptEx I can use them to configurate HPET.
> Then HPET would trigger the interrupt.

No, it doesn’t work that way. You seem to be thinking that IoConnectInterruptEx is going to allocate unattached MSI addresses which you can then assign. That’s not correct. You pass your PDO’s address to IoConnectInterruptEx, and that PDO already has to have MSIs. The system looks up the MSIs that were already assigned to you. In your case, with a virtual device, your PDO doesn’t have any resources, so the system is never going to hook up the MSIs.

> Then IoConnectInterruptEx returns 0xC0000034L, which means “Object Name not found”.
> (Before modification, it returned 0xC0000225L, “The object was not found”.)

Basically the same thing. You tried to connect to interrupts, but your driver had not been assigned any interrupts to connect to.

Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

Dear Tim
Thank you very much for your help.
I got it.
The key point is that system does not assign MSI resource to virtual device.
I was misled by the output direction of IoConnectInterruptEx’s InterruptMessageTable.



I want to send some data at constant time interval using ethernet network. (All work in kernel mode).
250us is expected. 1ms is acceptable too.
The severest request is that the jitter should be less than 50us.
I worked with ExSetTimer and WdfTimerStart. I was disappointed.
I think a program run in DPC cannot meet the request.

Yours sincerely.

The key point is that system does not assign MSI resource to virtual device.

“The key point” is that drivers for the virtual devices just don’t handle interrupts, in the first place. Certainly, interrupts may be virtualised as well, as as it happens,for example, when the target paravirtualised OS runs as an unprivileged guest under XEN or Hyper-V. In such case a
driver for the target device is aware that both device and interrupt are virtual, but this is not the scenario we are speaking about here.

I was misled by the output direction of IoConnectInterruptEx’s InterruptMessageTable.

Actually, I would rather say that you are “mislead” by the lack of profound understanding of the architectural concepts…

I think a program run in DPC cannot meet the request.

True, because the precise timing of DPC execution may depend on the “external” factors like the size of DPC queue at the moment. Therefore, 250us precision cannot be guaranteed here…

Anton Bassov

Dear Anton

Actually, I would rather say that you are “mislead” by the lack of profound understanding of the architectural concepts…

Yes, I do not understand the architectural yet.
Can you be so kind to teach the architectural to me with an instance?
Anything leading to the resolution is appreciated very much.

Best regard.