Dispatching interrupts to child device drivers

Hi all,

Thanks mostly to Doron I have a KMDF bus driver which, among other
things, creates multiple child PDOs (for UARTs) to which then attaches a
customised version of serial.sys from the WDK.

My one last step is to dispatch the interrupts to serial.sys. The bus
driver controls a PCI card with a single hardware interrupt. This single
hardware interrupt comprises multiple interrupt sources including each
of the UARTs. I therefore need the bus driver to examine the interrupt
status register and dispatch the interrupt to the appropriate child
device driver.

I was wondering the best way to go about this. My initial research
suggests to me that a DPC, or rather multiple DPC queues, would be the
way to go?!?

Only thing is, the ISR for serial.sys is rather complex and there’s a
lot happening that I’m assuming expects to be running within the context
of an ISR. I’m wondering if I’ll have synchronisation issues if that
code is running within a DPC rather than an ISR…

In any case, am I on the right track? And how best to call a DPC in my
serial driver from the ISR of the bus driver?

TIA
Regards,


Mark McDougall, Engineer
Virtual Logic Pty Ltd, http:
21-25 King St, Rockdale, 2216
Ph: +612-9599-3255 Fax: +612-9599-3266</http:>

I also notice calls to WdfInterruptSynchronize() in the serial.sys code

  • without an interrupt object in serial.sys I guess I’ll have to use
    some other form of synchronisation in these cases?!?

Regards,


Mark McDougall, Engineer
Virtual Logic Pty Ltd, http:
21-25 King St, Rockdale, 2216
Ph: +612-9599-3255 Fax: +612-9599-3266</http:>

Well, what I would do is have the PDO stack provide a function callback
to the FDO that the FDO can call in its ISR once the FDO determines
which UART generated the interrupt. Furthermore, the PDO exposes a
function, SynchronizeInterrupt with its own context (e.g. another field
in the interface and the context would be a WDFINTERRUPT behind the
covers). The parameters would be the context along with the remaining
arguments to WdfInterruptSynchronize after the WDFINTERRUPT argument.
the PDO’s stack calls SynchronizeInterrupt in place of
WdfInterruptSynchronize

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Mark McDougall
Sent: Sunday, March 04, 2007 8:03 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Dispatching interrupts to child device drivers

I also notice calls to WdfInterruptSynchronize() in the serial.sys code

  • without an interrupt object in serial.sys I guess I’ll have to use
    some other form of synchronisation in these cases?!?

Regards,


Mark McDougall, Engineer
Virtual Logic Pty Ltd, http:
21-25 King St, Rockdale, 2216
Ph: +612-9599-3255 Fax: +612-9599-3266


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer</http:>

Doron Holan wrote:

Well, what I would do is have the PDO stack provide a function callback
to the FDO that the FDO can call in its ISR once the FDO determines
which UART generated the interrupt.

Are you saying that my serial.sys should provide a callback to my bus
driver? Then my bus driver would need to provide the callback with the
appropriate PDO so it would execute in the correct context - yes? And
how do I expose the callback to the bus driver - via an interface? I
guess I can make my existing interface 2-way and provide it that way?

Furthermore, the PDO exposes a

function, SynchronizeInterrupt with its own context (e.g. another field
in the interface and the context would be a WDFINTERRUPT behind the
covers). The parameters would be the context along with the remaining
arguments to WdfInterruptSynchronize after the WDFINTERRUPT argument.
the PDO’s stack calls SynchronizeInterrupt in place of
WdfInterruptSynchronize

Currently my PDO has no interrupt object. Are you saying I should create
an interrupt object in each PDO (that won’t be hooked to a hardware
interrupt) and export the SynchronizeInterrupt function simply to
provide synchronisation for serial.sys?

Regards,


Mark McDougall, Engineer
Virtual Logic Pty Ltd, http:
21-25 King St, Rockdale, 2216
Ph: +612-9599-3255 Fax: +612-9599-3266</http:>

Mark McDougall wrote:

Currently my PDO has no interrupt object. Are you saying I should create
an interrupt object in each PDO (that won’t be hooked to a hardware
interrupt) and export the SynchronizeInterrupt function simply to
provide synchronisation for serial.sys?

Or should I be using the interrupt in the bus driver (PDO parent?)

Regards,


Mark McDougall, Engineer
Virtual Logic Pty Ltd, http:
21-25 King St, Rockdale, 2216
Ph: +612-9599-3255 Fax: +612-9599-3266</http:>

I’ve got an operational serial port now with interrupts “working”!!!

However, I still haven’t solved the synchronisation issues.

My SynchronizeInterrupt() routine exposed by the PDO simply calls the
callback routine atm without any synchronisation functionality. That’s
because I’m not sure whether I should be using the WdfInterrupt object
in the bus driver or creating another WdfInterrupt object in each PDO
and using that???

Thanks again Doron and good job on the WDF - certainly is less painful
than WDM!!!

Regards,


Mark McDougall, Engineer
Virtual Logic Pty Ltd, http:
21-25 King St, Rockdale, 2216
Ph: +612-9599-3255 Fax: +612-9599-3266</http:>

There is one and only one WDFINTERRRUPT, the one created by the FDO.
The PDO provides a function based on this type

typedef
BOOLEAN
(*PFN_PDO_INTERRUPT_SYNCHRONIZE) (
IN WDFCONTEXT Context
);

And then you call it like this in FDO

Typedef struct _DATA {
PFN_PDO_INTERRUPT_SYNCHRONIZE PdoSynchronize;
WDFCONTEXT Context;
} DATA, *PDATAl

{
DATA data = { fdoExt->PdoSyncRoutine, fdoExt->PdoContext };
BOOLEAN ret;

ret = WdfInterruptSynchronize(fdoExt->Interupt, CallPdoSync, &data);


}

BOOLEAN CallPdoSync(WDFINTERRUPT Interrupt, WDFCONTEXT Context)
{
Return ((PDATA) Context)->PdoSynchronize(((PDATA)
Context)->Context);
}

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Mark McDougall
Sent: Monday, March 05, 2007 11:30 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Dispatching interrupts to child device drivers

I’ve got an operational serial port now with interrupts “working”!!!

However, I still haven’t solved the synchronisation issues.

My SynchronizeInterrupt() routine exposed by the PDO simply calls the
callback routine atm without any synchronisation functionality. That’s
because I’m not sure whether I should be using the WdfInterrupt object
in the bus driver or creating another WdfInterrupt object in each PDO
and using that???

Thanks again Doron and good job on the WDF - certainly is less painful
than WDM!!!

Regards,


Mark McDougall, Engineer
Virtual Logic Pty Ltd, http:
21-25 King St, Rockdale, 2216
Ph: +612-9599-3255 Fax: +612-9599-3266


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer</http:>

Doron Holan wrote:

Sorry Doron, you’ve really lost me one this one. I’m not really sure
what the point of the CallPdoSync routine is, other than provide a
second level of indirection on the callback. And I don’t see how it
helps me. :frowning:

My bus driver FDO has a WdfInterrupt for the hardware PCI interrupt. The
ISR determines which (if any) UART has pending interrupts and calls what
was the ISR in serial.sys with a pointer to the serial device
extension for that UART.

As you know, serial.sys also has a WdfInterrupt, which was used
originally for UART interrupts. I’ve maintained this interrupt only
because the code calls WdfInterruptGetDevice() in several
WdfInterruptSynchronize callbacks - if this was missing or was the bus
driver FDO interrupt it would break the code.

What I’m wondering now is if I can simply leave serial.sys as-is, except
the “ISR” routine, now called from the bus driver FDO ISR, simply calls
WdfInterruptAcquireLock/ReleaseLock using the local WdfInterrupt?!?
Existing calls to WdfInterruptSynchronize would remain unchanged. Surely
this is preferable than locking the interrupt at the bus driver level
whenever serial.sys needs to call WdfInterruptSynchronize???

Regards,


Mark McDougall, Engineer
Virtual Logic Pty Ltd, http:
21-25 King St, Rockdale, 2216
Ph: +612-9599-3255 Fax: +612-9599-3266</http:>

I will give a better/more details answer later, but what it boils down
to is this

  1. only the FDO as a WDFINTERRUPT, no PDO has one
  2. you will have to change the interrupt related code (ISR and sync
    routines) in your custom serial.sys
  3. you can choose to continue to use WdfInterruptSynchronize (or more
    succinctly, the FDO’s exported functional equivalent), but if you are
    taking the time to rewrite these parts of serial.sys, just have the FDO
    export a function equivalent of WdfInterruptAcquire/ReleaseLock and
    forget about the sync callback. The only reason the sync callback exists
    is b/c on win2k, there was no way to directly acquire the interrupt’s
    lock (this was added on XP, but serial was not updated to use this new
    functionality)

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Mark McDougall
Sent: Tuesday, March 06, 2007 5:29 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Dispatching interrupts to child device drivers

Doron Holan wrote:

Sorry Doron, you’ve really lost me one this one. I’m not really sure
what the point of the CallPdoSync routine is, other than provide a
second level of indirection on the callback. And I don’t see how it
helps me. :frowning:

My bus driver FDO has a WdfInterrupt for the hardware PCI interrupt. The
ISR determines which (if any) UART has pending interrupts and calls what
was the ISR in serial.sys with a pointer to the serial device
extension for that UART.

As you know, serial.sys also has a WdfInterrupt, which was used
originally for UART interrupts. I’ve maintained this interrupt only
because the code calls WdfInterruptGetDevice() in several
WdfInterruptSynchronize callbacks - if this was missing or was the bus
driver FDO interrupt it would break the code.

What I’m wondering now is if I can simply leave serial.sys as-is, except
the “ISR” routine, now called from the bus driver FDO ISR, simply calls
WdfInterruptAcquireLock/ReleaseLock using the local WdfInterrupt?!?
Existing calls to WdfInterruptSynchronize would remain unchanged. Surely
this is preferable than locking the interrupt at the bus driver level
whenever serial.sys needs to call WdfInterruptSynchronize???

Regards,


Mark McDougall, Engineer
Virtual Logic Pty Ltd, http:
21-25 King St, Rockdale, 2216
Ph: +612-9599-3255 Fax: +612-9599-3266


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer</http:>

Doron Holan wrote:

  1. only the FDO as a WDFINTERRUPT, no PDO has one

OK.

  1. you will have to change the interrupt related code (ISR and sync
    routines) in your custom serial.sys
  2. you can choose to continue to use WdfInterruptSynchronize (or more
    succinctly, the FDO’s exported functional equivalent), but if you are
    taking the time to rewrite these parts of serial.sys, just have the FDO
    export a function equivalent of WdfInterruptAcquire/ReleaseLock and
    forget about the sync callback.

I’ve exported InterruptAcquire/ReleaseLock from my FDO - although I also
had to export the device object so serial.sys could pass it back into
the routines so ultimately they could get a handle to the interrupt
object… which leaves me wondering if these routines could’ve just been
part of serial.sys…

Anyway, every call in serial.sys that was using WftInterruptSynchronize
is now surrounded by the Acquire/Lock calls. I also had to modify 2 of
these routines to accept a WDFDEVICE…

So far it appears to work - thanks again! I’m yet to test much on the
concurrency side of things - I’m setting up the hardware as I email this
reply so hopefully all is good…

Regards,


Mark McDougall, Engineer
Virtual Logic Pty Ltd, http:
21-25 King St, Rockdale, 2216
Ph: +612-9599-3255 Fax: +612-9599-3266</http:>

I wouldn’t make the PDEVICE_OBJECT for the FDO a formal type in the
callback. Just declare it as a PVOID and then recast it in the FDO’s
function call. You don’t want to tie an implementation detail like what
the type of the context is to the client of the interface

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Mark McDougall
Sent: Tuesday, March 06, 2007 9:01 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Dispatching interrupts to child device drivers

Doron Holan wrote:

  1. only the FDO as a WDFINTERRUPT, no PDO has one

OK.

  1. you will have to change the interrupt related code (ISR and sync
    routines) in your custom serial.sys
  2. you can choose to continue to use WdfInterruptSynchronize (or more
    succinctly, the FDO’s exported functional equivalent), but if you are
    taking the time to rewrite these parts of serial.sys, just have the
    FDO
    export a function equivalent of WdfInterruptAcquire/ReleaseLock and
    forget about the sync callback.

I’ve exported InterruptAcquire/ReleaseLock from my FDO - although I also
had to export the device object so serial.sys could pass it back into
the routines so ultimately they could get a handle to the interrupt
object… which leaves me wondering if these routines could’ve just been
part of serial.sys…

Anyway, every call in serial.sys that was using WftInterruptSynchronize
is now surrounded by the Acquire/Lock calls. I also had to modify 2 of
these routines to accept a WDFDEVICE…

So far it appears to work - thanks again! I’m yet to test much on the
concurrency side of things - I’m setting up the hardware as I email this
reply so hopefully all is good…

Regards,


Mark McDougall, Engineer
Virtual Logic Pty Ltd, http:
21-25 King St, Rockdale, 2216
Ph: +612-9599-3255 Fax: +612-9599-3266


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer</http:>

Just for you …

http://blogs.msdn.com/doronh/archive/2007/03/06/interfaces-can-contain-both-input-and-output-parameters-and-not-just-function-pointers.aspx

… I was planning on writing this topic later on, but it seems appropriate to finish it now …

d