DWORD InterruptEnable(
HANDLE *phThread,
HANDLE hWD,
WD_INTERRUPT *pInt,
INT_HANDLER func,
PVOID pData);
| Name | Type | Input/Output |
|---|---|---|
| phThread | HANDLE* | Output |
| hWD | HANDLE | Input |
| pInt | WD_INTERRUPT* | |
| • hInterrupt | DWORD | Input |
| • dwOptions | DWORD | Input |
| • Cmd | WD_TRANSFER* | Input |
| • dwCmds | DWORD | Input |
| • kpCall | WD_KERNEL_PLUGIN_CALL | |
| * hKernelPlugIn | DWORD | Input |
| * dwMessage | DWORD | N/A |
| * pData | PVOID | N/A |
| * dwResult | DWORD | N/A |
| • fEnableOk | DWORD | N/A |
| • dwCounter | DWORD | N/A |
| • dwLost | DWORD | N/A |
| • fStopped | DWORD | N/A |
| • dwLastMessage | DWORD | N/A |
| • dwEnabledIntType | DWORD | Output |
| func | typedef void (*INT_HANDLER)( PVOID pData); | Input |
| pData | PVOID | Input |
| Name | Description |
|---|---|
| phThread |
Pointer to the handle to the spawned interrupt thread, which should be
passed to InterruptDisable [2.19] when disabling the interrupt
|
| hWD | Handle to WinDriver's kernel-mode driver as
received from WD_Open [5.2] |
| pInt | Pointer to an interrupt information structure: |
| • hInterrupt |
Internal interrupt handle, as received from
WD_CardRegister [2.8] in
I.Int.hInterrupt
|
| • dwOptions |
Interrupt options bit-mask. Can be set to zero or to: • INTERRUPT_CMD_COPY: if set, WinDriver will copy
the data received from the read commands that were used to acknowledge
the interrupt, in the kernel mode, back to the user mode. The data will
be available to the user when the interrupt handler routine
(func) is called.
|
| • Cmd |
An array of transfer commands information structures that define the
operations to be performed at the kernel level upon the detection of an
interrupt, or NULL if no transfer commands are required.
NOTE: • Memory allocated for the transfer commands must remain available until the interrupts are disabled . • When handling level-sensitive interrupts (such as PCI interrupts) in the user mode (without a Kernel PlugIn driver), you must use this array to define the hardware-specific commands for acknowledging the interrupts in the kernel, immediately when they are received. The commands in the array can be either of the following: • A read/write transfer command that conforms to the following format: <dir><p>_[S]<size> – see
the description of pTrans->cmdTrans in section 2.11.
|
| • Cmd (continued) |
• CMD_MASK:
an interrupt mask command for determining the source of the interrupt: When
this command is set, upon the arrival of an interrupt in the kernel WinDriver
masks the value of the previous read command in the WD_TRANSFER
commands array with the mask that is set in the relevant Data
field union member of the mask transfer command. For example, for a
CmdWD_TRANSFER
array, if
Cmd[i-1].cmdTrans is
RM_BYTE, WinDriver performs the following mask:
Cmd[i-1].Data.Byte &
Cmd[i].Data.Byte
. If the mask is successful, the driver claims ownership of the
interrupt and when the control is returned to the user mode, the interrupt
handler routine that was passed to the interrupt enable function is invoked;
otherwise, the driver rejects ownership of the interrupt, the interrupt
handler routine is not invoked and the subsequent transfer commands in the
array are not executed.(Acceptance and rejection of the interrupt is relevant only when handling legacy interrupts; since MSI/MSI-X interrupts are not shared, WinDriver will always accept control of such interrupts.) NOTE: A CMD_MASK command must be preceded by a read transfer
command (RM_XXX / RP_XXX).">
|
| • dwCmds | Number of transfer commands in the Cmd array |
| • kpCall | Kernel PlugIn message information structure: |
| * hKernelPlugIn |
Handle to Kernel PlugIn returned from
WD_KernelPlugInOpen [6.1].
|
| • dwEnabledIntType |
Updated by the function to indicate the type of interrupt enabled for the
device. Can be set to any of the following values: • INTERRUPT_MESSAGE_X: Extended Message-Signaled Interrupts (MSI-X). *
• INTERRUPT_MESSAGE: Message-Signaled Interrupts (MSI). *• INTERRUPT_LEVEL_SENSITIVE: Legacy
level-sensitive interrupts.• 0: Default interrupt type – Legacy
edge-triggered interrupts.NOTE: * The Windows APIs do not distinguish between MSI and MSI-X; therefore, on this OS the WinDriver functions set the INTERRUPT_MESSAGE flag for both MSI and MSI-X.** This field normally relevant only in the case of PCI devices that support more than one type of interrupt. |
| func |
The interrupt handler routine, which will be called once for every
interrupt occurrence. (Note: The INT_HANDLER function type
is defined in windrvr_int_thread.h).
|
| pData |
Pointer to the data to be passed as the argument to the interrupt handler
routine (func)
|
WD_STATUS_SUCCESS(0) on success, or
an appropriate error code otherwise [A].
InterruptEnable uses the low-level
WD_IntEnable [3.2],
WD_IntWait [3.3] and
WD_IntCount [3.4] functions
and replaces the need to call these functions separately, although this is
still possible.
InterruptEnable
will fail with a WD_NO_DEVICE_OBJECT error [A].
To
improve the interrupt handling rate on Windows 7/Vista/Server 2008/Server 2003/XP/2000 and Linux,
consider using WinDriver's Kernel PlugIn feature (see the WinDriver PCI Manual).
VOID DLLCALLCONV interrupt_handler(PVOID pData)
{
WD_INTERRUPT *pIntrp = (WD_INTERRUPT *)pData;
/* Implement your interrupt handler routine here */
printf("Got interrupt %d\n", pIntrp->dwCounter);
}
....
main()
{
WD_CARD_REGISTER cardReg;
WD_INTERRUPT Intrp;
HANDLE hWD, thread_handle;
....
hWD = WD_Open();
BZERO(cardReg);
cardReg.Card.dwItems = 1;
cardReg.Card.Item[0].item = ITEM_INTERRUPT;
cardReg.Card.Item[0].fNotSharable = TRUE;
cardReg.Card.Item[0].I.Int.dwInterrupt = MY_IRQ;
cardReg.Card.Item[0].I.Int.dwOptions = 0;
....
WD_CardRegister(hWd, &cardReg);
....
PVOID pdata = NULL;
BZERO (Intrp);
Intrp.hInterrupt = cardReg.Card.Item[0].I.Int.hInterrupt;
Intrp.Cmd = NULL;
Intrp.dwCmds = 0;
Intrp.dwOptions = 0;
printf("starting interrupt thread\n");
pData = &Intrp;
if (InterruptEnable(&thread_handle, hWD, &Intrp,
interrupt_handler, pdata))
{
printf ("failed enabling interrupt\n")
}
else
{
printf("Press Enter to uninstall interrupt\n");
fgets(line, sizeof(line), stdin);
InterruptDisable(thread_handle); /* Calls WD_IntDisable() */
}
WD_CardUnregister(hWD, &cardReg);
....
}