Message signaled interrupt with IoConnectInterruptEx

Dear Anton

Thank you for your help.
Our “Ethernet” is not a “conventional” network. The latency of communication is another topic. And it is not a problem in our project.
We are searching for just an interrupt which would call our ISR stably and periodically.

Best regard.

tatuo wrote:

Our “Ethernet” is not a “conventional” network. The latency of communication is another topic. And it is not a problem in our project.

How can you possibly argue that?  It HAS to be a consideration.
Remember, your goal is not to get periodic interrupts.  That’s just a
step.  Your goal (apparently) is to get regular packets to your
network.  In order to achieve that, you HAVE to look at the entire
infrastructure: not only the timer accuracy, but the network software
latency, the NIC latency, the network latency, collisions, delays on the
other end, etc.  It is a waste of time an energy to try to build a timer
with picosecond precision if your network transmission time varies
within a couple of milliseconds, as it probably does.  It’s a
statistical process.

We are searching for just an interrupt which would call our ISR stably and periodically.

There are many, many PCIExpress general purpose I/O boards with
countdown timers that can issue an interrupt.  Here’s one.

https://logical-co.com/product/dual-programmable-timer-pci-express/

Dear Tim
Thank you very much for your help.

It is a waste of time an energy to try to build a timer
with picosecond precision if your network transmission time varies
within a couple of milliseconds,

The period we need is 250~1000microseconds, and jitter is 50 microseconds or so. It is not so hard in some sense. It is not in picosecond.
It is true that the latency is composed of many and many factors. First we have to have a precise timer. It is the base of all. We will leave other problems to the hardware of network. It is doing its best. It is said to have a precision in nanosecond. Thing can become well only after all is perfect. We should do our best ourselves first.
I would appreciate it very much if you could give me some advice about registering an interrupt to ACPI with ASL.

There are many, many PCIExpress general purpose I/O boards with
countdown timers that can issue an interrupt. Here’s one.

After I have failed to all test of possibility, I shall change my design. I think it is not so long.

Thanks again.

On May 16, 2019, at 4:22 PM, tatuo wrote:
>
> The period we need is 250~1000microseconds, and jitter is 50 microseconds or so. It is not so hard in some sense. It is not in picosecond.

I know, I was exaggerating to make a point.

> I would appreciate it very much if you could give me some advice about registering an interrupt to ACPI with ASL.

Do you have the ability to modify the BIOS in your machine? If you have the source code, then you might be able to modify the DSDT in the BIOS to add a device for the HPET that you can provide an INF for. Such a driver would be assigned the appropriate interrupt by the system. No hackery.

However, that requires the BIOS source. Linux has the ability to add DSDT overrides during boot, but Windows (to my knowledge) does not.

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

Dear Tim

I love you.

Dear Tim

I love you

We all love Mr. Roberts, Mr. Tatuo. We all do.

This is precisely why Mr. Roberts was canonized some years back. You probably missed the announcement. We have yet to establish a particular day in his honor… but we’re open to you suggesting one (sadly, today is already taken by William Hobart Hare, who was not so active on NTDEV but worthy of remembrance nonetheless).

Peter

I would appreciate it very much if you could give me some advice about registering an interrupt to ACPI with ASL.

Please note that setting an interrupt that fires with high precision is not going to solve your problems concerning the precise timing the egress packets leave your machine. You are unable to do send packets in context of ISR, right - you best possible bet is DPC_LEVEL code. At this point the issue of possible jitter arises, because the precise timing of DPC depends on the external factors like the length of DPC queue at the moment. Therefore, your problem is not yet solved…

Anton Bassov

In short… this is yet another case of A/B problem. What can be actually be done, depends on the custom network adapter of the OP - can they hack it to do the scheduling itself? Replace it by a cheap microcontroller with ethernet? Move the whole project to the other OS?

– pa

Dear Mr. viscarola

Thank you very much.
I am sorry replying to you so late due to the weekend days.
Thank you for giving us such a platform to discuss our problem. Thank you for giving me such a chance.
I feel honored to suggest a particular day to give our respect to Mr. Roberts.
I think he is worthy.
Because I am new to this forum, please tell me how to take the procedure.
How about today?

Yours sincerely.

Tatuo

Dear Anton

Thank you for your advice.
I think I had better open another thread to discuss problems that occur when data are sent to network.

Thanks again.

Dear Mr. Pavel_A

Thank you very much for your advice.
You are right.
But I must send data which are produced from a program running on windows.

Thanks again.

Dear Mr. Roberts

Do you have the ability to modify the BIOS in your machine? If you have the source code, then you might be able to modify the DSDT in the BIOS to add >a device for the HPET that you can provide an INF for. Such a driver would be assigned the appropriate interrupt by the system. No hackery.

asl.exe can be used to retrieve the DSDT.
ASL file can even been generated using ACPIGenFx.
The modified DSDT can be stored in registry to test.

But I failed with the test.
First, I set the system to test mode.
bcdedit /set TESTSIGNING ON
I retrieved the current DSDT with below command.
asl.exe /tab=DSDT
It gave me a dsdt.asl.
When I compiled it, so many errors were made that were beyond my ability to fix.

Then I decided to test with the sample asl file GpioSampleKMDF.asl under simdevice.
It succeeded to be loaded to registry.


But it did not appeare in the device manager of windows.

Last, I generated an asl file myself with below code.
static void Main(string args)
{

        x86Platform Platform = Platforms.Createx86Platform(
            OEMID: "MSFT",
            OEMTableID: "EDK2",
            CreatorID: "MSFT",
            Revision: 1, FileName: "DSDT"
            );

        GenericDevice Gen3 = Platform.AddGenericDevice("Tim1", "APIC23", "PNP0003", 1);
        Gen3.AddInterrupt(InterruptType.Edge, InterruptActiveLevel.ActiveHigh, SharingLevel.Exclusive, 23);

        Platform.WriteAsl();
    }

It can be loaded but it did not appear in the device manager of windows too.
Who can give me some hints?
Help me!

Thanks in advance.

tatuo wrote:

When I compiled it, so many errors were made that were beyond my ability to fix.

Yes, this happens.  The Intel and Microsoft ASL compilers use different
rules, and that allows invalid things to slip in.  Most of the errors
are probably the same; you’ll need to do some web searching to find
them.  There are lots of people hacking their DSDTs in the Linux world,
and those posts may provide some tops for you.

Then I decided to test with the sample asl file GpioSampleKMDF.asl under simdevice.
It succeeded to be loaded to registry.

This is a bit dangerous.  When you put a DSDT in the registry you are
REPLACING the DSDT provided by the BIOS.  If you don’t have all of the
entries in the original DSDT, that is an excellent way to turn your
computer into a brick.  You may need to use “last known good” or “safe
mode” to get rid of it.

Better to add you unique devices to the SSDT using this method. Any existing SSDT will be shorter, for sure, than the DSDT. See https://docs.microsoft.com/en-us/windows-hardware/drivers/bringup/generate-acpi-tables-by-using-acpigenfx

Peter

Dear Mr. Viscarola

Thank you very much.
I am using the way you told me today.
But the device cannot appear in the device manager if just this produced file is used without the contend retrieved from windows with iasl or asl command. If the produced file is attached to the file retrieved from system, it workes fine except for strange view of some device.
Anyway, I can communicate to the new device now.
I can verify the resoure information sent to EVT_WDF_DEVICE_PREPARE_HARDWARE.
u.Interrupt.Vector is 0xa0
u.Interrupt.Level is 0x0a
u.Interrupt.Affinity is 0x0f

But when I install the driver, computer crushes.
The source code is as following.

NTSTATUS InterruptPrepareHardware(
In WDFDEVICE Device,
In WDFCMRESLIST ResourcesRaw,
In WDFCMRESLIST ResourcesTranslated
)
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor;
PDEVICE_CONTEXT deviceContext;

PAGED_CODE();
deviceContext = WdfObjectGet_DEVICE_CONTEXT(Device);

      status = IoConnectInterrupt(
			&deviceContext->InterruptObject,
			InterruptServiceRoutine,
			deviceContext,
			NULL,
			descriptor->u.Interrupt.Vector,
			(KIRQL)descriptor->u.Interrupt.Level,
			(KIRQL)descriptor->u.Interrupt.Level,
			LevelSensitive,
			FALSE,
			descriptor->u.Interrupt.Affinity,
			FALSE
		);
     return STATUS_SUCCESS;

...................

}
InterruptServiceRoutine does nothing now.
I am searching for the cause…

Best regard.

Tatuo

Hi

When I use below code to connect interrupt in EVT_WDF_DEVICE_PREPARE_HARDWARE, error code 0xc000000d is returned, meaning “An invalid parameter was passed to a service or function”.

        RtlZeroMemory(&InterruptParams, sizeof(IO_CONNECT_INTERRUPT_PARAMETERS));
		InterruptParams.Version = CONNECT_LINE_BASED;
		InterruptParams.LineBased.PhysicalDeviceObject = WdfDeviceWdmGetDeviceObject(Device);
		InterruptParams.LineBased.InterruptObject = &deviceContext->InterruptObject;
		InterruptParams.LineBased.ServiceRoutine = InterruptServiceRoutine;
		InterruptParams.LineBased.ServiceContext = deviceContext;
		InterruptParams.LineBased.SpinLock = NULL;
		InterruptParams.LineBased.SynchronizeIrql = 0;
		InterruptParams.LineBased.FloatingSave = FALSE;

		status = IoConnectInterruptEx(&InterruptParams);

What is the problem?

Tatuo

Hi

When I use below code to connect interrupt to my ISR in EVT_WDF_DEVICE_PREPARE_HARDWARE, no error occurs.
But I do not know if interrupt can be triggered yet, because I have not connected it to HPET…

   WDF_INTERRUPT_CONFIG_INIT(&InterruptConfiguration,
			InterruptServiceRoutine,
			DrvInterruptDpc);

		InterruptConfiguration.EvtInterruptEnable = TimerInterruptEnable;
		InterruptConfiguration.EvtInterruptDisable = TimerInterruptDisable;
		InterruptConfiguration.InterruptTranslated = descriptor;
		InterruptConfiguration.InterruptRaw = WdfCmResourceListGetDescriptor(ResourcesRaw, i);

		InterruptConfiguration.AutomaticSerialization = TRUE;

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

Thanks.

Tatuo

Well, that’s the next step.

Hello, dear friends

From that, I got both HPET and ioAPIC worked well individually.
But I failed in getting them talked to each other. The ISR could not be called.

First, the HPET side:
I use timer0 and set it to work in Periodic Mode.
The General Configuration Register is set as 0x01. ( Allow to run and interrupt, diable legacyreplacement route).
I can read the value of Configuration and Capabilities Register. It is 0x00f000000000ad3c,
which means
Interrupt Type: edge triggered
Interrupt Enable: Yes
Timer Type: periodic interrupt
Periodic Interrupt Capable: YES
Timer Size: 64bit
32-bit Mode: YES
Interrupt Route: 22pin
FSB Interrupt Enable: NO
FSB Interrupt Delivery: available.

I can see the Comparator Value Register steps up by the value last written.
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Then, the ioAPIC side:
Because I used 22nd pin in my asl file,

   Device (TMR1)
    {
        Name (_HID, "HPET0016")
        Name (_CID, "ACPI\SofTimer")
        Name (_UID, 0x1)
        Method (_STA)
        {
            Return(0xf)
        }
        Method (_CRS, 0x0, NotSerialized) {
            Name (RBUF, ResourceTemplate () {
                Interrupt(ResourceConsumer, Edge, ActiveHigh, Exclusive) { 0x16 }
            })
            Return(RBUF)
        }
    }

I noticed that the 22nd I/O Redirection Table entry register is changed to 0xf000000000009a0 by OS.
which means
Interrupt Vector: a0
Delivery Mode:001(Lowest priority)
Destination Mode: Logical Mode
Delivery Status: IDLE
Interrupt Input Pin Polarity: High active
Trigger Mode: Edge sensitive
Interrupt Mask: Not masked
These parameters can also be confirmed in EVT_WDF_DEVICE_PREPARE_HARDWARE by PCM_PARTIAL_RESOURCE_DESCRIPTOR.

I also noticed that the Delivery Status bit of I/O Redirection Table entry register stayed IDLE.
And the ISR is not called.

I can see IRQ22 has been allocated to my device from device manager.

Is the 22nd pin of HPET not connected(mapped) to the IRQ22 of ioAPIC? or is there something I have not set?

I have searched for the cause for three days and found no way out.
Help me!

On May 27, 2019, at 5:34 PM, tatuo wrote:
>
> From that, I got both HPET and ioAPIC worked well individually.
> But I failed in getting them talked to each other. The ISR could not be called.

Are you absolutely sure that HPET timer 1 is not already in use by the operating system?

> Interrupt Route: 22pin
> FSB Interrupt Enable: NO
> FSB Interrupt Delivery: available.

What does “22pin” mean? Does that mean pin 22 of the HPET chip? Do you actually know what IRQ that’s tied to? And don’t you need the interrupt to be enable?

> Because I used 22nd pin in my asl file,
>
> Device (TMR1) { Name (_HID, “HPET0016”) Name (_CID, “ACPI\SofTimer”) Name (_UID, 0x1) Method (_STA) { Return(0xf) } Method (_CRS, 0x0, NotSerialized) { Name (RBUF, ResourceTemplate () { Interrupt(ResourceConsumer, Edge, ActiveHigh, Exclusive) { 0x16 } }) Return(RBUF) } }

OK, but how did you pick IRQ 0x16?

> Is the 22nd pin of HPET not connected(mapped) to the IRQ22 of ioAPIC? or is there something I have not set?

Well, right, you have to know this. You can’t assume that a pin number has anything to do with IRQ number. Do you have schematics for the board?

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