Technical Document #40

Technical Document #40
How do I call WD_Transfer() in the Kernel PlugIn interrupt handler?

You can call WD_Transfer() from within the KP_IntAtIrql or KP_IntAtDpc functions (replace "KP" in the function names with your Kernel PlugIn driver name — e.g., "KP_PCI") in order to access the hardware (see below).

Please note that you can also access the memory or I/O directly from within the Kernel PlugIn interrupt functions. (For direct memory access, use the kernel mapping of the memory, returned from WD_CardRegister() in cardReg.Card.Item[i].I.Mem.pTransAddr / dwTransAddr before v11.8.0.)

When calling WD_Transfer() you will need to pass as the first argument a handle to WinDriver (hWD). You can refer to Technical Document #38 to find out how to obtain a handle to WinDriver from within the Kernel PlugIn.

As specified in the aforementioned Technical Document, you can store the handle to WinDriver in a global Kernel PlugIn variable (recommended), or pass it from one function to another. Below is an example of passing a handle to WinDriver from KP_Open() to KP_IntAtIrql:

Add the following line to KP_Open():

*ppDrvContext = (PVOID) hWD;
Add the following line to KP_IntEnable():
*ppIntContext = pDrvContext;
You can now use WD_Transfer() to access memory/IO from within KP_IntAtIrql. For example (IO access):
HANDLE hWD = (HANDLE) pIntContext;
trans.cmdTrans = WP_BYTE;
trans.pPort = 0x378;
trans.Data.Byte = 0x65;
WD_Transfer(hWD, &trans);
This will write 0x65 to port 0x378 upon interrupt. The hWD handle is passed from KP_Open() to KP_IntEnable() to KP_IntAtIrql via the context. (Note: The pPort field was renamed from dwPort in v11.8.0 of WinDriver.)

Beginning with version 5.2.0 of WinDriver you can also view the generated DriverWizard Kernel PlugIn code for an example of calling WD_MultiTransfer() from KP_IntAtIrql, provided you have used the DriverWizard to define and assign the register/s for the interrupt acknowledgment before generating the code.