Passing hardware events to client

All,

My custom PCI hardware asserts an interrupt when any of about sixteen events occur (ie: timer rolls over, data received on port, user presses ‘reset’, etc.). I need my kernel mode driver to somehow tell my client software that the interrupt occurred so that the software can do some IOCTLS to find out what the state of the hardware is and then do a ReadFile() or WriteFile() to transfer the event data.

My driver development knowledge is quite limited (newbie), so I’m familiar with IOCTLs, DMA Reads & Writes (and therefore IRQs and DPCs), but only in a synchronous context (more accurately, I know just enough to be very dangerous). My only ideas for solving this problem are:

  1. Having the client software wait for an event (call to WaitForSingleObject()) that the driver can set once it detects and services an interrupt. This would be most simple and clean from a client stand point, but I have NO IDEA if a kernal mode driver can set an event for a user mode app, I would think it can’t.

  2. Having the client software call an IOCTL where the IRP doesn’t get completed until the driver detects and serves an interrupt. That way the DeviceIoControl() call basically blocks similarly to calling WaitForSingleObject(), and returns once the IRP is completed. This would also require setting up the IRPs as asynchronous so that I can do other things while that IRP is hanging, which just doesn’t seem ideal for me and my lack of understanding.

I don’t want to poll the driver for data - I need more responsiveness than polling would provide. I’d think this is a common situation (ie hardware asynchronous events) that pretty much any hardware device would have, just wondering what the best industry-standard (but simple) solution is. I hope this post makes sense.

Thanks!
Ryan

You want the second solution this is the better approach for Windows.
The approach is known as the inverted call, and you can typically hold a
bunch of requests. There is a good article
http://www.osronline.com/article.cfm?id=94 describing this.

Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

xxxxx@lmco.com” wrote in message
news:xxxxx@ntdev:

> All,
>
> My custom PCI hardware asserts an interrupt when any of about sixteen events occur (ie: timer rolls over, data received on port, user presses ‘reset’, etc.). I need my kernel mode driver to somehow tell my client software that the interrupt occurred so that the software can do some IOCTLS to find out what the state of the hardware is and then do a ReadFile() or WriteFile() to transfer the event data.
>
> My driver development knowledge is quite limited (newbie), so I’m familiar with IOCTLs, DMA Reads & Writes (and therefore IRQs and DPCs), but only in a synchronous context (more accurately, I know just enough to be very dangerous). My only ideas for solving this problem are:
>
> 1) Having the client software wait for an event (call to WaitForSingleObject()) that the driver can set once it detects and services an interrupt. This would be most simple and clean from a client stand point, but I have NO IDEA if a kernal mode driver can set an event for a user mode app, I would think it can’t.
>
> 2) Having the client software call an IOCTL where the IRP doesn’t get completed until the driver detects and serves an interrupt. That way the DeviceIoControl() call basically blocks similarly to calling WaitForSingleObject(), and returns once the IRP is completed. This would also require setting up the IRPs as asynchronous so that I can do other things while that IRP is hanging, which just doesn’t seem ideal for me and my lack of understanding.
>
> I don’t want to poll the driver for data - I need more responsiveness than polling would provide. I’d think this is a common situation (ie hardware asynchronous events) that pretty much any hardware device would have, just wondering what the best industry-standard (but simple) solution is. I hope this post makes sense.
>
> Thanks!
> Ryan

Furthermore, the output buffer of this IOCTL can contain data, so if the driver knows how to extract the data generically after the interrupt, it can do that and then complete the irp with that data. Then the app is notified the interrupt has occurred and there might no longer be a need to send a different data retrieval ioctl down the stack.

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Don Burn
Sent: Tuesday, February 22, 2011 12:25 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] Passing hardware events to client

You want the second solution this is the better approach for Windows.
The approach is known as the inverted call, and you can typically hold a bunch of requests. There is a good article
http://www.osronline.com/article.cfm?id=94 describing this.

Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

xxxxx@lmco.com” wrote in message
news:xxxxx@ntdev:

> All,
>
> My custom PCI hardware asserts an interrupt when any of about sixteen events occur (ie: timer rolls over, data received on port, user presses ‘reset’, etc.). I need my kernel mode driver to somehow tell my client software that the interrupt occurred so that the software can do some IOCTLS to find out what the state of the hardware is and then do a ReadFile() or WriteFile() to transfer the event data.
>
> My driver development knowledge is quite limited (newbie), so I’m familiar with IOCTLs, DMA Reads & Writes (and therefore IRQs and DPCs), but only in a synchronous context (more accurately, I know just enough to be very dangerous). My only ideas for solving this problem are:
>
> 1) Having the client software wait for an event (call to WaitForSingleObject()) that the driver can set once it detects and services an interrupt. This would be most simple and clean from a client stand point, but I have NO IDEA if a kernal mode driver can set an event for a user mode app, I would think it can’t.
>
> 2) Having the client software call an IOCTL where the IRP doesn’t get completed until the driver detects and serves an interrupt. That way the DeviceIoControl() call basically blocks similarly to calling WaitForSingleObject(), and returns once the IRP is completed. This would also require setting up the IRPs as asynchronous so that I can do other things while that IRP is hanging, which just doesn’t seem ideal for me and my lack of understanding.
>
> I don’t want to poll the driver for data - I need more responsiveness than polling would provide. I’d think this is a common situation (ie hardware asynchronous events) that pretty much any hardware device would have, just wondering what the best industry-standard (but simple) solution is. I hope this post makes sense.
>
> Thanks!
> Ryan


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

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

And even further, assuming that the actions of the UM app are ‘stateless’,
you should look at an IOCP design with a number of pended requests. That
way, when the HW interrupts, and your driver sees an interrupt, it can
satisfy a request and maybe avoid a buffer copy & UM-KM transition. IMHO
‘stateless’ requests need not be truly stateless, but merely orthogonal
enough to allow multi-thread / processor / NUMA efficiently.

If none of this makes sense to you, than please ignore it as coming from
someone focused on the last few percent of efficiency.

“Doron Holan” wrote in message news:xxxxx@ntdev…

Furthermore, the output buffer of this IOCTL can contain data, so if the
driver knows how to extract the data generically after the interrupt, it can
do that and then complete the irp with that data. Then the app is notified
the interrupt has occurred and there might no longer be a need to send a
different data retrieval ioctl down the stack.

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Don Burn
Sent: Tuesday, February 22, 2011 12:25 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] Passing hardware events to client

You want the second solution this is the better approach for Windows.
The approach is known as the inverted call, and you can typically hold a
bunch of requests. There is a good article
http://www.osronline.com/article.cfm?id=94 describing this.

Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

xxxxx@lmco.com” wrote in message
news:xxxxx@ntdev:

> All,
>
> My custom PCI hardware asserts an interrupt when any of about sixteen
> events occur (ie: timer rolls over, data received on port, user presses
> ‘reset’, etc.). I need my kernel mode driver to somehow tell my client
> software that the interrupt occurred so that the software can do some
> IOCTLS to find out what the state of the hardware is and then do a
> ReadFile() or WriteFile() to transfer the event data.
>
> My driver development knowledge is quite limited (newbie), so I’m familiar
> with IOCTLs, DMA Reads & Writes (and therefore IRQs and DPCs), but only in
> a synchronous context (more accurately, I know just enough to be very
> dangerous). My only ideas for solving this problem are:
>
> 1) Having the client software wait for an event (call to
> WaitForSingleObject()) that the driver can set once it detects and
> services an interrupt. This would be most simple and clean from a client
> stand point, but I have NO IDEA if a kernal mode driver can set an event
> for a user mode app, I would think it can’t.
>
> 2) Having the client software call an IOCTL where the IRP doesn’t get
> completed until the driver detects and serves an interrupt. That way the
> DeviceIoControl() call basically blocks similarly to calling
> WaitForSingleObject(), and returns once the IRP is completed. This would
> also require setting up the IRPs as asynchronous so that I can do other
> things while that IRP is hanging, which just doesn’t seem ideal for me and
> my lack of understanding.
>
> I don’t want to poll the driver for data - I need more responsiveness than
> polling would provide. I’d think this is a common situation (ie hardware
> asynchronous events) that pretty much any hardware device would have, just
> wondering what the best industry-standard (but simple) solution is. I
> hope this post makes sense.
>
> Thanks!
> Ryan


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

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

All,

Thanks for the feedback, this is very helpful. After reading the page on the inverted call and lots of online research I think I’m on my way to implementation. I had a hard time understanding the sample code since it wasn’t written using WDF, but I think I got the jest of what I should be doing.

As a test to make sure I’m understanding this stuff, I created a simple driver. Its IOCTL queue is setup for parallel dispatch. I’ve set up a few IOCTLs - one that completes the request immediately, and another that saves the request, starts a timer that expires after a few seconds, and then completes the request at that time. So I would expect that while waiting for the delayed IOCTL to complete (from one thread in the user app), I should be able to call the immediate one a bunch of times (in another thread in the user app). However, my second call to DeviceIoControl() blocks until the the timer expires and the first IOCTL is completed. Why is this? It appears that the queue is still being blocked by that first message. My only guess is that maybe I should be calling WdfRequestForardToIoQueue() to save the first request rather than just putting it into the device context? Below is my related bare bone code:

:

// Create a new IO Queue for IRP_MJ_DEVICE_CONTROL requests in PARALLAL mode, so we can continue to serve IOCTL IRPs while others are pending.
WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchParallel);

queueConfig.EvtIoDeviceControl = HIBEvtDeviceControl;

status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &devContext->DevCtrlQueue);

// Set the device control Queue forwarding for IRP_MJ_DEVICE_CONTROL requests.
status = WdfDeviceConfigureRequestDispatching(device, devContext->DevCtrlQueue, WdfRequestTypeDeviceControl);

:

Essentially all I do when it’s my delayed control code is to save the request to my device context, start a timer that will fire in a few seconds, then return.

:

devContext->TestInProgress = 0;
status = WdfRequestRetrieveOutputBuffer(devContext->TestRequest, sizeof(ULONG), (PVOID *)&PRetData, NULL);
*PRetData = devContext->Test;
len = sizeof(ULONG);

//Complete the request with the status and number of bytes read/written.
WdfRequestCompleteWithInformation(devContext->TestRequest, status, len);

Any ideas? Once I get this figure out I think I can implement the proper synchronization and get the inverse call working. Thanks!

xxxxx@lmco.com wrote:

As a test to make sure I’m understanding this stuff, I created a simple driver. Its IOCTL queue is setup for parallel dispatch. I’ve set up a few IOCTLs - one that completes the request immediately, and another that saves the request, starts a timer that expires after a few seconds, and then completes the request at that time. So I would expect that while waiting for the delayed IOCTL to complete (from one thread in the user app), I should be able to call the immediate one a bunch of times (in another thread in the user app). However, my second call to DeviceIoControl() blocks until the the timer expires and the first IOCTL is completed. Why is this?

My guess is that you have not opened the file with
FILE_FLAG_OVERLAPPED. In order to have multiple requests outstanding on
a single file handle, you must use overlapped I/O.


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

You probably don’t want to just stuff the wdfrequest into your context without setting a cancel routine. Consider creating a 2ndary manual WDFQUEUE that you fwd the request to from your EvtDeviceControl callback. That will make it cancelable. When you want to complete the request, pop the request out of the manual queue (making it uncancelable) and complete it

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@lmco.com
Sent: Wednesday, February 23, 2011 4:39 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Passing hardware events to client

All,

Thanks for the feedback, this is very helpful. After reading the page on the inverted call and lots of online research I think I’m on my way to implementation. I had a hard time understanding the sample code since it wasn’t written using WDF, but I think I got the jest of what I should be doing.

As a test to make sure I’m understanding this stuff, I created a simple driver. Its IOCTL queue is setup for parallel dispatch. I’ve set up a few IOCTLs - one that completes the request immediately, and another that saves the request, starts a timer that expires after a few seconds, and then completes the request at that time. So I would expect that while waiting for the delayed IOCTL to complete (from one thread in the user app), I should be able to call the immediate one a bunch of times (in another thread in the user app). However, my second call to DeviceIoControl() blocks until the the timer expires and the first IOCTL is completed. Why is this? It appears that the queue is still being blocked by that first message. My only guess is that maybe I should be calling WdfRequestForardToIoQueue() to save the first request rather than just putting it into the device context? Below is my related bare bone code:

:

// Create a new IO Queue for IRP_MJ_DEVICE_CONTROL requests in PARALLAL mode, so we can continue to serve IOCTL IRPs while others are pending.
WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchParallel);

queueConfig.EvtIoDeviceControl = HIBEvtDeviceControl;

status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &devContext->DevCtrlQueue);

// Set the device control Queue forwarding for IRP_MJ_DEVICE_CONTROL requests.
status = WdfDeviceConfigureRequestDispatching(device, devContext->DevCtrlQueue, WdfRequestTypeDeviceControl);

:

Essentially all I do when it’s my delayed control code is to save the request to my device context, start a timer that will fire in a few seconds, then return.

:

devContext->TestInProgress = 0;
status = WdfRequestRetrieveOutputBuffer(devContext->TestRequest, sizeof(ULONG), (PVOID *)&PRetData, NULL);
*PRetData = devContext->Test;
len = sizeof(ULONG);

//Complete the request with the status and number of bytes read/written.
WdfRequestCompleteWithInformation(devContext->TestRequest, status, len);

Any ideas? Once I get this figure out I think I can implement the proper synchronization and get the inverse call working. Thanks!


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

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

That’s an awesome programming pattern, but BEWARE: If you’re receiving your requests from a sequential queue (or a parallel queue with a count of maximum I/Os) forwarding the active request to another queue is one of the events that will cause the sequential queue to present you with a new request.

It would sure be nice if there was an option in KMDF to facilitate this pattern that said either: (a) Do not present a new Request from this queue when an active request is forwarded to another queue, or alternatively and preferably (b) Do not present a new request from a queue as a result of forwarding a request to THIS queue (the former being set on the sequential queue, the latter being set on the manual queue). I’ve asked for this feature before. Maybe we should jointly campaign for it’s inclusion in the next version of KMDF?

Peter
OSR

“My guess is that you have not opened the file with FILE_FLAG_OVERLAPPED. In order to have multiple requests outstanding on a single file handle, you must use overlapped I/O.”

I did not realize that not opening a file handle as overlapped would force all the queues to sequential - is that what you’re saying? This is very interesting. I was really hoping that I could do synchronous I/O via a multi-threaded application with parallel queues so that the I/O could be finished concurrently. Darn, this will really mean re-thinking the architecture of my user mode app.

“You probably don’t want to just stuff the wdfrequest into your context without setting a cancel routine. Consider creating a 2ndary manual WDFQUEUE that you fwd the request to from your EvtDeviceControl callback. That will make it cancelable.”

You’re right - this is a better implementation, I plan to do it this way in the final driver. However, I’m confused because MSDN says this about the WdfRequestForwardToIoQueue() method: “The request must not be cancelable. If the driver has called WdfRequestMarkCancelable or WdfRequestMarkCancelableEx to make the request cancelable, it must call WdfRequestUnmarkCancelable before calling WdfRequestForwardToIoQueue.” I’m very interested in why a request can’t be marked as cancellable when stuffed into a manual queue, because I surely want it to be cancellable (it could set there fore a few dozen milliseconds before I manually pull it and complete it).

Lastly, what you said Peter is very interesting. I didn’t realize when forwarding a packet to another queue I’d then get a new packet from a sequential queue. I thought that completing a request was the ONLY thing that would cause a new request to be presented from a sequential queue. This is actually a good thing for my application, but I could see how it would be a real pain in others!

Thanks everybody, I’m learning a ton here.
Ryan

Your app could open a non overlapped handle per thread of you want. This means your device cannot be marked as exclusive. As fir the docs youvare referring to , what it is saying istje request cannot be cancelable while you are trying to fwd it. Sitting in your Evtdevicecontrol routine as not cancelable is fine as ling as you are not blocking on anything and eventually fwd or complete the request in a timely manner.

d

dent from a phine with no keynoard

-----Original Message-----
From: xxxxx@lmco.com
Sent: Thursday, February 24, 2011 8:33 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Passing hardware events to client

“My guess is that you have not opened the file with FILE_FLAG_OVERLAPPED. In order to have multiple requests outstanding on a single file handle, you must use overlapped I/O.”

I did not realize that not opening a file handle as overlapped would force all the queues to sequential - is that what you’re saying? This is very interesting. I was really hoping that I could do synchronous I/O via a multi-threaded application with parallel queues so that the I/O could be finished concurrently. Darn, this will really mean re-thinking the architecture of my user mode app.

“You probably don’t want to just stuff the wdfrequest into your context without setting a cancel routine. Consider creating a 2ndary manual WDFQUEUE that you fwd the request to from your EvtDeviceControl callback. That will make it cancelable.”

You’re right - this is a better implementation, I plan to do it this way in the final driver. However, I’m confused because MSDN says this about the WdfRequestForwardToIoQueue() method: “The request must not be cancelable. If the driver has called WdfRequestMarkCancelable or WdfRequestMarkCancelableEx to make the request cancelable, it must call WdfRequestUnmarkCancelable before calling WdfRequestForwardToIoQueue.” I’m very interested in why a request can’t be marked as cancellable when stuffed into a manual queue, because I surely want it to be cancellable (it could set there fore a few dozen milliseconds before I manually pull it and complete it).

Lastly, what you said Peter is very interesting. I didn’t realize when forwarding a packet to another queue I’d then get a new packet from a sequential queue. I thought that completing a request was the ONLY thing that would cause a new request to be presented from a sequential queue. This is actually a good thing for my application, but I could see how it would be a real pain in others!

Thanks everybody, I’m learning a ton here.
Ryan


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

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

No, no… it doesn’t!

Open a single file handle for synchronous I/O (that is, NOT using an overlapped structure) simply means that I/O requests sent ON THAT HANDLE will be SENT one at a time. You could have multiple threads each open your device for sequential access (each getting its own handle) and these threads could each send one I/O Request at a time, and if your driver was configured with a parallel queue to receive these requests you could have them all in progress simultaneously on your device.

It’s confusing, I know… but I hope that’s a LITTLE more clear :wink:

For the archives, there are only 3 conditions that will trigger presentation of a new request from a sequential queue:

  1. Completing the Request (with WdfRequestComplete or friends)
  2. Forwarding the Request to a WDF Queue
  3. Sending the request to another device (an I/O Target in WDF speak) with the _SEND_AND_FORGET option.

Peter
OSR

xxxxx@lmco.com wrote:

“My guess is that you have not opened the file with FILE_FLAG_OVERLAPPED. In order to have multiple requests outstanding on a single file handle, you must use overlapped I/O.”

I did not realize that not opening a file handle as overlapped would force all the queues to sequential - is that what you’re saying? This is very interesting. I was really hoping that I could do synchronous I/O via a multi-threaded application with parallel queues so that the I/O could be finished concurrently. Darn, this will really mean re-thinking the architecture of my user mode app.

You don’t have to re-think the architecture at all. Overlapped I/O is
not that hard. You can make synchronous calls on an overlapped handle,
it just takes an extra API call:

handle = CreateFile( … , 0 ); // non-overlapped
ReadFile( handle, x, x, x, NULL );

becomes this, modulo additional error checking:

handle = CreateFile( …, FILE_FLAG_OVERLAPPED );
OVERLAP olap = { 0 };
olap.hEvent = … some event handle … ;
ReadFile( handle, x, x, x, &olap );
if( GetLastError() == ERROR_IO_PENDING )
{
GetOverlappedResult( handle, &olap, x, TRUE );
}

GetOverlappedResult will block until the I/O is complete.


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

Unless something changed and I missed it, this will only work if there is
only one IO in flight, or the hardware always completes in order of
issuance.

If you have in order I/O completion, the manual WDFQUEUE works fine, but
once you have IOs completing in an arbitrary order, there doesn’t appear to
be a KMDF container of any sort that will simplify cancellation for you, and
you end up having to handle cancellation yourself. Kudos to the KMDF team
for ensuring that we could do it ourselves.

Is there an API that lets you remove an arbitrary WDFREQUEST from a manual
WDFQUEUE without that bizarre WdfQueueFindRequest /
WdfQueueRetrieveFoundRequest dance? When I was last working on such a
beast, we concluded that once you had put a WDFREQUEST in a manual WDFQUEUE,
it was an absolute pain to remove an arbitrary WDFREQUEST from it, because
there wasn’t any way to just complete it on the manual WDFQUEUE. Doron, you
said as much in this old
thread(http://www.osronline.com/showThread.cfm?link=141511)

Alternatively, is there another container I’ve missed that handles
cancellation for you, but allows arbitrary completion order without
gymnastics more significant than simple removal before completion? The
absence of a container supporting cancellation and arbitrary completion
order was personally the biggest disappointment in KMDF. And the source of
most of the races we ran into, because we were rolling our own cancellation
logic. Still, if that’s the biggest disappointment in KMDF, the KMDF team
hit an in-the-park homer.

Phil

Philip D. Barila (303) 776-1264

Alright… I don’t want to hijack the thread, but still… I just *have* to ask:

and given that the documentation explicitly says:

I’m not sure I understand, except for the stated restriction in the docs and the implication inherent in the DDI name, why WdfIoQueueRetrieveFoundRequest can’t be called with a Request handle that’s been stored away. What’s it protecting us against? And, is there some case when calling WdfIoQueueRetrieveFoundRequest succeeds, and returns a handle that’s DIFFERENT from the one that’s passed in as the FoundRequest parameter?

Sorry… I realize I’m venture out of the bounds of what’s documented. But I guess I’m asking “why” and “what am I missing” more than “isn’t it OK if I do this”…

Peter
OSR

The list chewed on some that question in

http://www.osronline.com/showthread.cfm?link=167013

I think it has to do with the ‘state’ of that request relative to cancelation. But I honestly do not recall it having been quite some time that I scratched my head over these very same questions.

My vague recollection is that a reference means you can access it but a ‘found reference’ means you can retrieve it (and thus remove it in the non-canceled state) from the queue.

Or something like that. Doron?

Cheers,
Dave Cattley

Date: Thu, 24 Feb 2011 14:36:24 -0500
From: xxxxx@osr.com
To: xxxxx@lists.osr.com
Subject: RE:[ntdev] Passing hardware events to client

Alright… I don’t want to hijack the thread, but still… I just *have* to ask:

and given that the documentation explicitly says:

I’m not sure I understand, except for the stated restriction in the docs and the implication inherent in the DDI name, why WdfIoQueueRetrieveFoundRequest can’t be called with a Request handle that’s been stored away. What’s it protecting us against? And, is there some case when calling WdfIoQueueRetrieveFoundRequest succeeds, and returns a handle that’s DIFFERENT from the one that’s passed in as the FoundRequest parameter?

Sorry… I realize I’m venture out of the bounds of what’s documented. But I guess I’m asking “why” and “what am I missing” more than “isn’t it OK if I do this”…

Peter
OSR


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

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

xxxxx@osr.com wrote:


I’m not sure I understand, except for the stated restriction in the docs and the implication inherent in the DDI name, why WdfIoQueueRetrieveFoundRequest can’t be called with a Request handle that’s been stored away. What’s it protecting us against? And, is there some case when calling WdfIoQueueRetrieveFoundRequest succeeds, and returns a handle that’s DIFFERENT from the one that’s passed in as the FoundRequest parameter?

The key, as I understand it, is ownership. When a request is in a
queue, the framework owns it. WdfIoQueueFindRequest returns a
WDFREQUEST, but it’s merely a shadow of request – more or less a
symbolic link. The driver does not own that request; ownership stays
with the framework. WdfIoQueueRetrieveFoundRequest, then, expects to
get that kind of “shadow” request, and translates it into a REAL
request, for which it has given up ownership. The driver now owns that
request.

When your driver stores a WDFREQUEST that is also in a manual queue,
there is an ownership clash. The driver doesn’t own the request that it
is storing. The framework might do anything it wants to that request.

I think that’s the issue.


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

Peter, thank you for post #11. Both things you said really cleared stuff up for me.
"Open a single file handle for synchronous I/O (that is, NOT using an overlapped structure) simply means that I/O requests sent ON THAT HANDLE will be SENT one at a time. You could have multiple threads each open your device for sequential access (each getting its own handle) and these threads could each send one I/O Request at a time, and if your driver was configured with a parallel queue to receive these requests you could have them all in progress simultaneously on your device. It’s confusing, I know… but I hope that’s a LITTLE more clear :wink: "

That’s not confusing to me - what you described is what I needed to hear and I REALLY wished I had read that in documentation somewhere a few hundred hours ago. I just compiled my driver and test application with a few different configs, and tested what you said to make sure I understand, and you’re 100% correct.

Therefore, I can either open multiple handles in a single application and block with threads, or open as overlapped, and use async I/O - glad to see I have both options.

For the second option, thank you Tim for the example. I didn’t know GetOverlappedResult() existed - that method makes things much easier.

Thank you for the education, I think I’ll be rolling forward with an implementation by the end of the day! :slight_smile:

> 2) Having the client software call an IOCTL where the IRP doesn’t get completed until the driver

I think this is the way.

Look at, for instance, IOCTL_SERIAL_WAIT_ON_MASK


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

I know what you’re getting at… but it doesn’t return the Request at all. It returns a HANDLE to a Request. Which, I quite understand, I do not own, and I can only use to remove that Request with the appropriate DDI or dereference it. OK… I’m perfectly good with that. But it’s still the HANDLE to the Request, no??

Yeah, I *totally* get that.

But if I have store-away the Request HANDLE, say in my Device Context, then – aside from the documentation, thank you very much – why can’t I reasonably expect to call WdfIoQueueRetrieveFoundRequest with that handle… and I either get back an error (which is already anticipated in the docs, saying the Request is no longer found) or I get back a success status. In any case, this allows me to “randomly” retrieve the request from the manual queue.

Inquiring minds want to know,

Please Doron or Peter or somebody?? I guess I’m asking what the design motivation is here and if the very stringent requirements stated in the existing docs couldn’t reasonably be lifted to facilitate the very handy design pattern to which Phil was referring.

And no, I’m not arguing that this isn’t possible with the existing DDIs. Just cumbersome and slow if you have a bunch of Requests in progress on your hardware.

Peter
OSR

Tim Roberts is correct. It is a matter of ownership.
If you own the request, there is no need to retrieve from the Queue. If you call the WdfIoqueueRetriveFoundRequest, that call will fail.
If you don’t own the request, you need to get a valid handle before calling WdfIoqueueRetriveFoundRequest. One way to do this is to call WdfIoQueueFindRequest.

Thx,
Egi.