Sample driver code using StorPortInitializeWorker() and StorPortQueueWorkItem()

I’m hoping this would be an easy question to answer.

can anyone point me to some real sample driver code that uses:

ULONG StorPortQueueWorkItem(
In PVOID HwDeviceExtension,
In PHW_WORKITEM WorkItemCallback,
In PVOID WorkItem,
In_opt PVOID Context)

and

ULONG StorPortInitializeWorker(
In PVOID HwDeviceExtension,
Out PVOID *Worker
);

From reading msdn, I really do not understand what I actually have to provide to PVOID WorkItem and PVOID *Worker. I’m assuming PHW_WORKITEM WorkItemCallback is just a function pointer to function of the work it will execute, but again, example code would be great (one thing msdn is lacking).

Basically, I have a routine that needs to be executed on an MSI-X interrupt, which is too long to be executed in the ISR and probably too long to be executed in a DPC. So I thought these WorkItem calls is what I need to use.

Thanks!

From MSDN:

“The work item context returned in the Worker parameter by StorPortInitializeWorker is used in future calls to StorPortQueueWorkItem or StorPortFreeWorker.”

It could have been explained better, but still it’s clear that Worker is a returned PVOID.

You pass that PVOID as WorkItem.

Thanks for the reply, but it’s not clear.

If I look at PVOID HwDeviceExtension, this is a type PVOID too. But it is really not- it’s a user-defined extension of the driver. I’ve done enough device driver development to understand just by looking at the naming convention what that is. And MSDN’s description is clear enough to me what that is:

HwDeviceExtension [in]
A pointer to the hardware device extension for the host bus adapter (HBA).

Looking at:

Worker [out]
A pointer to an opaque buffer that holds context information for the work item.

Questions arise, like “Am I really defining a PVOID, or can I use an int or even a user-defined extension/type?” “What does a ‘work item’ for storport look like?” “Since this will initialize the variable, what is it initializing?”

That is why example code would help.

xxxxx@intel.com wrote:

Looking at:

Worker [out]
A pointer to an opaque buffer that holds context information for the work item.

Questions arise, like “Am I really defining a PVOID, or can I use an int or even a user-defined extension/type?”

Well, StorPortInitializeWorker is returning to you the address of an
internal structure. You don’t get to know what’s inside of that
structure. You just hand that address back to him in
StorPortQueueWorkItem. Think if it as a handle, if you want. An int is
not large enough to hold a pointer, so you can’t use an int. I’m not
sure why you’d want to, since PVOID is not that hard to type.

“What does a ‘work item’ for storport look like?” “Since this will initialize the variable, what is it initializing?”

You don’t get to know this. That’s the meaning of “opaque”. What it’s
doing is allocating some memory, filling in its own information, and
returning to you the address of that memory. It’s just like handles in
user mode. It’s a number that means something to someone, just not to you.


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

> Thanks for the reply, but it’s not clear.

If I look at PVOID HwDeviceExtension, this is a type PVOID too. But it is
really not- it’s a user-defined extension of the driver. I’ve done enough
device driver development to understand just by looking at the naming
convention what that is. And MSDN’s description is clear enough to me
what that is:

HwDeviceExtension [in]
A pointer to the hardware device extension for the host bus adapter
(HBA).

Looking at:

Worker [out]
A pointer to an opaque buffer that holds context information for the
work item.

Questions arise, like “Am I really defining a PVOID, or can I use an int
or even a user-defined extension/type?” “What does a ‘work item’ for
storport look like?” “Since this will initialize the variable, what is it
initializing?”

****
Pointer-to-void means “a pointer to anything”. Any pointer type, such as
a pointer to a device extension, can be passed via a PVOID.

This pattern is very common in user space as well, and sometimes it’s a
PVOID, sometimes it’s an LPARAM, or DWORD_PTR, or something else. My
explanation to my students was "What you are going to do is have a
component that has no idea what your data is or means accept a value from
you, and push it through a PVOID-shaped (or LPARAM-shaped, or …) hole in
the wall to the other side. The other side can take things from the
PVOID-shaped (etc.) hole, open them up, and find a useful value inside.
Sometimes, and most often, it is a pointer, but sometimes it’s an integer.
The important thing is this: the call specifies a generic PVOID (or
LPARAM or …), and if your value isn’t shaped like one of those, the
compiler complains. Therefore, except for the PVOID case, you must cast
the data type you have to the shape of the hole, and after it passes
through (animated slide of box passing through wall here), you cast it
back to the type you think you passed. Note that there is no need to
explicitly cast to PVOID because the compiler does that implicitly for all
pointer types. In essence, PVOID is the abstract superclass of all
pointers (yes, these are mostly C++ programmers)

So, on the “other side of the wall”, you are given a PVOID, and you must
cast it to a pointer to a real type if you want to access its fields (or
methods, if you are using C++):

Prototype
void SendAcrossWall(PVOID p)
Sender:
MyDevExt * ext;
ext = …

DoSomething(other parameter(s), ext); // implicit cast to PVOID

Receiver:
result_type OnOtherSide(other parameter(s), PVOID p)
{
MyDevExt * ext = (MyDevExt *)p;

Note the cast is optional in C, which doesn’t check for what is called
“downcasting”, but mandatory in C++.

I think that every interface in the kernel that calls a function passed as
a pointer uses a PVOID as one of the arguments that will be passed to that
function. It is a lot stranger in user space, where historically every
programmer chose a different type to use, and it is complete chaos.
joe
****8

That is why example code would help.


NTDEV is sponsored by OSR

OSR is HIRING!! See http://www.osr.com/careers

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