ReactOS  0.4.15-dev-2534-geba00d1
interruptobjectkm.cpp
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7  InterruptObject.cpp
8 
9 Abstract:
10 
11  This module implements a frameworks managed interrupt object
12 
13 Author:
14 
15 
16 
17 
18 Environment:
19 
20  Kernel mode only
21 
22 Revision History:
23 
24 
25 
26 
27 
28 
29 --*/
30 
31 #include "pnppriv.hpp"
32 
33 // Tracing support
34 // #include "InterruptObjectKm.tmh"
35 
41  )
42 {
45 
46  DO_NOTHING();
47 
48  return STATUS_SUCCESS;
49 }
50 
51 VOID
55  )
56 {
59 
61 
63 
64  //
65  // Call the drivers registered DpcForIsr event callback
66  //
67  if (m_CallbackLock != NULL) {
68  KIRQL irql = 0;
69 
73  }
74  else {
76  }
77 
78  return;
79 }
80 
81 BOOLEAN
83  VOID
84  )
85 {
86  BOOLEAN queued;
87 
88  //
89  // Using this function is optional,
90  // but the caller better have registered a handler
91  //
93 
94  queued = KeInsertQueueDpc(&m_Dpc, this, NULL);
95 
96  return queued;
97 }
98 
99 VOID
101  VOID
102  )
103 {
105 
107 
108  //
109  // Call the drivers registered WorkItemForIsr event callback
110  //
111  if (m_CallbackLock != NULL) {
112  KIRQL irql = 0;
113 
115 
119  }
120  else {
123  }
124 
125  return;
126 }
127 
129 NTSTATUS
131  VOID
132  )
133 {
134  IO_CONNECT_INTERRUPT_PARAMETERS connectParams;
135  FxPkgPnp* fxPkgPnp;
136 
137  fxPkgPnp = m_Device->m_PkgPnp;
138 
139  //
140  // Tell the PnP Manager to connect the interrupt.
141  //
142  ASSERT(fxPkgPnp->m_IoConnectInterruptEx != NULL);
143 
144  //
145  // We're running on Longhorn or later (or somebody backported the new
146  // interrupt code,) so tell the PnP manager everything we can about this
147  // device.
148  //
149  RtlZeroMemory(&connectParams, sizeof(connectParams));
150 
152  connectParams.Version = CONNECT_FULLY_SPECIFIED_GROUP;
153  }
154  else {
155  connectParams.Version = CONNECT_FULLY_SPECIFIED;
156  }
157 
159  connectParams.FullySpecified.InterruptObject = &m_Interrupt;
161  connectParams.FullySpecified.ServiceContext = this;
162  connectParams.FullySpecified.SpinLock = m_SpinLock;
165  connectParams.FullySpecified.Irql = m_InterruptInfo.Irql;
167  connectParams.FullySpecified.Group = m_InterruptInfo.Group;
169  connectParams.FullySpecified.ShareVector =
172 
173  return fxPkgPnp->m_IoConnectInterruptEx(&connectParams);
174 }
175 
176 VOID
178  VOID
179  )
180 {
182  PKINTERRUPT interruptObject;
183  FxPkgPnp* fxPkgPnp;
184 
185  fxPkgPnp = m_Device->m_PkgPnp;
186 
187  //
188  // Now null these pointers so that we can catch anyone trying to use them
189  // erroneously.
190  //
191  interruptObject = m_Interrupt;
192  m_Interrupt = NULL;
193 
194  //
195  // Disconnect the interrupt.
196  //
197  ASSERT(fxPkgPnp->m_IoDisconnectInterruptEx != NULL);
198 
199  RtlZeroMemory(&params, sizeof(params));
200 
203  }
204  else {
206  }
207 
208  params.ConnectionContext.InterruptObject = interruptObject;
209 
210  fxPkgPnp->m_IoDisconnectInterruptEx(&params);
211 
212  return;
213 }
214 
215 VOID
217  __inout PIO_RESOURCE_DESCRIPTOR IoResourceDescriptor
218  )
219 /*++
220 
221 Routine Description:
222 
223  This function allows an interrupt object to change the
224  IoResourceRequirementsList that the PnP Manager sends during
225  IRP_MN_FILTER_RESOURCE_REQUIREMENTS. This function takes a single
226  IoResourceDescriptor and applies default or user specified policy.
227 
228 Arguments:
229 
230  IoResourceDescriptor - Pointer to descriptor that matches this interrupt object
231 
232 Return Value:
233 
234  VOID
235 
236 --*/
237 {
238  //
239  // Set sharing policy.
240  //
241  switch (m_ShareVector) {
242  case WdfTrue:
243  //
244  // Override the bus driver's value, explicitly sharing this interrupt.
245  //
246  IoResourceDescriptor->ShareDisposition = CmResourceShareShared;
247  break;
248 
249  case WdfFalse:
250  //
251  // Override the bus driver's value, explicitly claiming this interrupt
252  // as non-shared.
253  //
254  IoResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
255  break;
256 
257  case WdfUseDefault:
258  default:
259  //
260  // Leave the bus driver's value alone.
261  //
262  break;
263  }
264 
265  //
266  // Apply policy. Only do this if we are running on an OS which supports
267  // the notion of Interrupt Policy and if the policy is not already included
268  // by the bus driver based on registry settings.
269  //
271  m_SetPolicy &&
272  (IoResourceDescriptor->Flags & CM_RESOURCE_INTERRUPT_POLICY_INCLUDED) == 0x0) {
273 
274  IoResourceDescriptor->Flags |= CM_RESOURCE_INTERRUPT_POLICY_INCLUDED;
275  IoResourceDescriptor->u.Interrupt.AffinityPolicy = (IRQ_DEVICE_POLICY)m_Policy;
276  IoResourceDescriptor->u.Interrupt.PriorityPolicy = (IRQ_PRIORITY)m_Priority;
277  IoResourceDescriptor->u.Interrupt.TargetedProcessors = m_Processors.Mask;
278  IoResourceDescriptor->u.Interrupt.Group = m_Processors.Group;
279  }
280 }
281 
282 VOID
284  VOID
285  )
286 {
288 }
289 
290 BOOLEAN
292  __in struct _KINTERRUPT *Interrupt,
294  )
295 
296 /*++
297 
298 Routine Description:
299 
300  This is the C routine called by the kernels INTERRUPT handler
301 
302 Arguments:
303 
304 Return Value:
305 
306 --*/
307 
308 {
309  FxInterrupt* interrupt;
310  BOOLEAN result;
311 
313 
314  interrupt = (FxInterrupt*)ServiceContext;
315  ASSERT( interrupt->m_EvtInterruptIsr != NULL );
316 
317  if (interrupt->m_IsEdgeTriggeredNonMsiInterrupt == TRUE) {
318  //
319  // If KMDF is in the process of disconnecting this interrupt, discard it.
320  //
321  if (interrupt->m_Disconnecting == TRUE) {
322  return FALSE;
323  }
324 
325  //
326  // Captures the interrupt object as a backup in case interrupts start
327  // to arrive before IoConnectInterruptEx sets FxInterrupt.m_Interrupt.
328  //
329  interrupt->m_InterruptCaptured = Interrupt;
330  }
331  //
332  // If the interrupt is not connected, treat this as spurious interrupt.
333  //
334  else if (NULL == interrupt->m_Interrupt) {
335  return FALSE;
336  }
337 
338  if (interrupt->IsWakeCapable()) {
339  //
340  // if it is a wake capable interrupt, we will hand it off
341  // to the state machine so that it can power up the device
342  // if required and then invoke the ISR callback
343  //
344  ASSERT(interrupt->m_PassiveHandling);
346  return interrupt->WakeInterruptIsr();
347  }
348 
349  if (interrupt->m_PassiveHandling) {
351 
352  //
353  // Acquire our internal passive-lock after the kernel acquired its own
354  // passive-lock and before invoking the callback.
355  //
356  interrupt->AcquireLock();
357 
359 
360  result = interrupt->m_EvtInterruptIsr(
361  interrupt->GetHandle(),
362  interrupt->m_InterruptInfo.MessageNumber);
363  interrupt->ReleaseLock();
364  }
365  else {
366 
368 
369  result = interrupt->m_EvtInterruptIsr(
370  interrupt->GetHandle(),
371  interrupt->m_InterruptInfo.MessageNumber);
372  }
373 
374  return result;
375 }
376 
377 VOID
379  __in PKDPC Dpc,
383  )
384 /*++
385 
386 Routine Description:
387 
388  Thunk used to invoke EvtInterruptDpc at DPC-level, or to queue a work-item
389  for invoking EvtInterruptWorkItem at passive-level.
390 
391 --*/
392 {
393  FxInterrupt* interrupt;
394 
396 
398  interrupt = (FxInterrupt*) DeferredContext;
399 
400  if (interrupt->m_SystemWorkItem == NULL) {
401 
402  FxPerfTraceDpc(&interrupt->m_EvtInterruptDpc);
403 
405  }
406  else {
408  interrupt);
409  }
410 }
411 
412 VOID
414  VOID
415  )
416 {
417  //
418  // Rundown the workitem.
419  //
420  if (m_SystemWorkItem != NULL) {
423  }
424 
425  //
426  // If present, delete the default passive-lock.
427  //
428  if (m_DisposeWaitLock) {
429  ASSERT(m_WaitLock != NULL);
431  m_WaitLock = NULL;
433  }
434 }
435 
436 BOOLEAN
438  _In_opt_ PVOID SyncContext
439  )
440 {
442 
443  ASSERT(SyncContext != NULL);
444  pFxInterrupt = (FxInterrupt*)SyncContext;
445 
446  //
447  // This callback is invoked only if m_IsEdgeTriggeredNonMsiInterrupt
448  // is TRUE. This will cause _InterruptThunk to discard subsequent
449  // interrupts until m_Disconnecting is reset to FALSE.
450  //
452 
453  return TRUE;
454 }
455 
456 VOID
459  )
460 {
462  FxPkgPnp* fxPkgPnp;
463 
464  fxPkgPnp = m_Device->m_PkgPnp;
465 
466  if (Internal == FALSE) {
467  //
468  // if the interrupt is not connected, you can't report active or inactive
469  //
470  if(m_Connected == FALSE || m_Interrupt == NULL) {
473  "Driver is reporting WDFINTERRUPT %p as being active even though"
474  " it is not connected.", GetHandle());
476  return;
477  }
478 
479  if (fxPkgPnp->m_IoReportInterruptActive == NULL) {
482  "Driver is calling DDI WdfInterruptReportActive() on an OS that "
483  "doesn't support the DDI.");
485  return;
486  }
487  }
488 
489  //
490  // No need to report active if interrupt is already active
491  //
492  if (m_Active) {
493  return;
494  }
495 
496  RtlZeroMemory(&parameters, sizeof(parameters));
497 
500  }
501  else {
502  parameters.Version = CONNECT_FULLY_SPECIFIED;
503  }
504 
506 
507  fxPkgPnp->m_IoReportInterruptActive(&parameters);
508  m_Active = TRUE;
509 
510  return;
511 }
512 
513 VOID
516  )
517 {
519  FxPkgPnp* fxPkgPnp;
520 
521  fxPkgPnp = m_Device->m_PkgPnp;
522 
523  if (Internal == FALSE) {
524  //
525  // if the interrupt is not connected, you can't report active or inactive
526  //
527  if(m_Connected == FALSE || m_Interrupt == NULL) {
530  "Driver is reporting WDFINTERRUPT %p as being inactive even though"
531  " it is not connected.", GetHandle());
533  return;
534  }
535 
536  if (fxPkgPnp->m_IoReportInterruptInactive == NULL) {
539  "Driver is calling DDI WdfInterruptReportInactive() on an OS that "
540  "doesn't support the DDI.");
542  return;
543  }
544  }
545 
546  //
547  // No need to report Inactive if interrupt is already Inactive
548  //
549  if (m_Active == FALSE) {
550  return;
551  }
552 
553  RtlZeroMemory(&parameters, sizeof(parameters));
554 
557  }
558  else {
559  parameters.Version = CONNECT_FULLY_SPECIFIED;
560  }
561 
563 
564  fxPkgPnp->m_IoReportInterruptInactive(&parameters);
565  m_Active = FALSE;
566 
567  return;
568 }
569 
FxWaitLock * m_WaitLock
Definition: fxinterrupt.hpp:77
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
CfxDevice * m_Device
Definition: fxobject.hpp:329
virtual VOID DeleteObject(VOID)
static MdDeferredRoutineType _InterruptDpcThunk
enum _IRQ_DEVICE_POLICY IRQ_DEVICE_POLICY
#define _Must_inspect_result_
Definition: no_sal2.h:62
static EVT_SYSTEMWORKITEM _InterruptWorkItemCallback
static MdInterruptServiceRoutineType _InterruptThunk
_Must_inspect_result_ NTSTATUS ConnectInternal(VOID)
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:107
GLint x0
Definition: linetemp.h:95
GLuint64EXT * result
Definition: glext.h:11304
VOID DpcHandler(__in_opt PVOID SystemArgument1, __in_opt PVOID SystemArgument2)
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_INTERRUPT_CONFIG Configuration
Definition: wdfinterrupt.h:372
#define __in_opt
Definition: dbghelp.h:38
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
WDFDEVICE __inline GetHandle(VOID)
Definition: fxdevice.hpp:237
#define CONNECT_FULLY_SPECIFIED_GROUP
static MdInterruptSynchronizeRoutineType _InterruptMarkDisconnecting
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_INTERRUPT_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFINTERRUPT * Interrupt
Definition: wdfinterrupt.h:372
BOOLEAN m_IsEdgeTriggeredNonMsiInterrupt
BOOLEAN NTAPI KeInsertQueueDpc(IN PKDPC Dpc, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: dpc.c:724
LONG NTSTATUS
Definition: precomp.h:26
#define CONNECT_FULLY_SPECIFIED
BOOLEAN m_DisposeWaitLock
Definition: fxinterrupt.hpp:98
WDF_TRI_STATE m_ShareVector
Definition: fxinterrupt.hpp:54
KIRQL irql
Definition: wave.h:1
FxSystemWorkItem * m_SystemWorkItem
Definition: fxinterrupt.hpp:87
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn BOOLEAN Physical UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 ACPI_BUFFER *RetPathPtr ACPI_OBJECT_HANDLER void *Data ACPI_OBJECT_HANDLER void **Data ACPI_STRING ACPI_OBJECT_LIST ACPI_BUFFER *ReturnObjectBuffer ACPI_DEVICE_INFO **ReturnBuffer ACPI_HANDLE Parent
Definition: acpixf.h:728
BOOLEAN QueueDpcForIsr(VOID)
BOOLEAN m_Disconnecting
#define _In_opt_
Definition: no_sal2.h:212
VOID FlushAndRundownInternal(VOID)
__inline BOOLEAN TryToEnqueue(__in PFN_WDF_SYSTEMWORKITEM CallbackFunc, __in PVOID Parameter)
UCHAR KIRQL
Definition: env_spec_w32.h:591
enum _IRQ_PRIORITY IRQ_PRIORITY
PFN_IO_DISCONNECT_INTERRUPT_EX m_IoDisconnectInterruptEx
Definition: fxpkgpnp.hpp:4289
#define FALSE
Definition: types.h:117
GLenum const GLfloat * params
Definition: glext.h:5645
KAFFINITY TargetProcessorSet
Definition: wdfinterrupt.h:306
volatile KIRQL m_SynchronizeIrql
Definition: fxinterrupt.hpp:67
FORCEINLINE VOID FxPerfTraceWorkItem(_In_ PVOID DriverCallback)
WDF_INTERRUPT_POLICY m_Policy
#define CM_RESOURCE_INTERRUPT_POLICY_INCLUDED
Definition: cmtypes.h:146
VOID ReportActive(_In_ BOOLEAN Internal=FALSE)
virtual void Lock(__out PKIRQL PreviousIrql)=0
VOID DisconnectInternal(VOID)
unsigned char BOOLEAN
struct _KINTERRUPT * m_Interrupt
Definition: fxinterrupt.hpp:59
IO_CONNECT_INTERRUPT_FULLY_SPECIFIED_PARAMETERS FullySpecified
Definition: iotypes.h:397
WDF_INTERRUPT_PRIORITY m_Priority
BOOLEAN m_FloatingSave
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:675
KINTERRUPT_MODE Mode
Definition: wdfinterrupt.h:311
VOID FlushQueuedDpcs(VOID)
MdDeviceObject __inline GetPhysicalDevice(VOID)
Definition: fxdevice.hpp:228
#define ASSERT(a)
Definition: mode.c:45
FORCEINLINE VOID FxPerfTraceDpc(_In_ PVOID DriverCallback)
FxInterrupt * pFxInterrupt
KAFFINITY Mask
Definition: ntbasedef.h:660
BOOLEAN m_PassiveHandling
PFN_WDF_INTERRUPT_WORKITEM m_EvtInterruptWorkItem
VOID FilterResourceRequirements(__inout PIO_RESOURCE_DESCRIPTOR IoResourceDescriptor)
BOOLEAN m_Active
_In_ PKSERVICE_ROUTINE _In_opt_ PVOID ServiceContext
Definition: iofuncs.h:800
_Must_inspect_result_ __inline BOOLEAN FxIsProcessorGroupSupported(VOID)
Definition: fxglobalskm.h:734
BOOLEAN m_SetPolicy
BOOLEAN m_Connected
VOID ReleaseLock(VOID)
MdLock * m_SpinLock
Definition: fxinterrupt.hpp:64
VOID WorkItemHandler(VOID)
Definition: ketypes.h:687
FxCallbackLock * m_CallbackLock
Definition: fxinterrupt.hpp:93
#define __inout
Definition: dbghelp.h:50
__inline BOOLEAN IsWakeCapable(VOID)
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
FxLibraryGlobalsType FxLibraryGlobals
Definition: globals.cpp:95
PFN_WDF_INTERRUPT_ISR m_EvtInterruptIsr
virtual void Unlock(__in KIRQL PreviousIrql)=0
FxPkgPnp * m_PkgPnp
Definition: fxdevice.hpp:670
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:675
#define _In_
Definition: no_sal2.h:158
#define TRACINGPNP
Definition: dbgtrace.h:67
__inline PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxobject.hpp:734
union _IO_REPORT_INTERRUPT_ACTIVE_STATE_PARAMETERS::@3741 ConnectionContext
PFN_IO_CONNECT_INTERRUPT_EX m_IoConnectInterruptEx
Definition: fxpkgpnp.hpp:4288
PFN_IO_REPORT_INTERRUPT_INACTIVE m_IoReportInterruptInactive
Definition: fxpkgpnp.hpp:4294
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
#define NULL
Definition: types.h:112
FORCEINLINE VOID FxPerfTraceInterrupt(_In_ PVOID DriverCallback)
_Must_inspect_result_ NTSTATUS InitializeInternal(__in FxObject *Parent, __in PWDF_INTERRUPT_CONFIG Configuration)
WDFINTERRUPT GetHandle(VOID)
FX_TRACK_DRIVER(fxDriverGlobals)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
BOOLEAN WakeInterruptIsr(VOID)
PFN_WDF_INTERRUPT_DPC m_EvtInterruptDpc
GROUP_AFFINITY m_Processors
PFN_IO_CONNECT_INTERRUPT_EX IoConnectInterruptEx
Definition: fxglobals.h:730
#define STATUS_SUCCESS
Definition: shellext.h:65
PFN_IO_REPORT_INTERRUPT_ACTIVE m_IoReportInterruptActive
Definition: fxpkgpnp.hpp:4293
$USHORT Group
Definition: ntbasedef.h:661
VOID ReportInactive(_In_ BOOLEAN Internal=FALSE)
VOID AcquireLock(VOID)
#define __in
Definition: dbghelp.h:35
FORCEINLINE VOID FxPerfTracePassiveInterrupt(_In_ PVOID DriverCallback)
VOID NTAPI KeFlushQueuedDpcs(VOID)
Definition: dpc.c:918
struct _KINTERRUPT * m_InterruptCaptured
WDF_INTERRUPT_INFO m_InterruptInfo
FxVerifierDbgBreakPoint(pFxDriverGlobals)
#define DO_NOTHING()
Definition: mxgeneral.h:32
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:675