ReactOS 0.4.16-dev-303-g11d5cb8
interruptobjectkm.cpp
Go to the documentation of this file.
1/*++
2
3Copyright (c) Microsoft Corporation
4
5Module Name:
6
7 InterruptObject.cpp
8
9Abstract:
10
11 This module implements a frameworks managed interrupt object
12
13Author:
14
15
16
17
18Environment:
19
20 Kernel mode only
21
22Revision 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
51VOID
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
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
99VOID
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
131 VOID
132 )
133{
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
153 }
154 else {
155 connectParams.Version = CONNECT_FULLY_SPECIFIED;
156 }
157
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
176VOID
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;
193
194 //
195 // Disconnect the interrupt.
196 //
198
199 RtlZeroMemory(&params, sizeof(params));
200
203 }
204 else {
206 }
207
208 params.ConnectionContext.InterruptObject = interruptObject;
209
211
212 return;
213}
214
215VOID
217 __inout PIO_RESOURCE_DESCRIPTOR IoResourceDescriptor
218 )
219/*++
220
221Routine 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
228Arguments:
229
230 IoResourceDescriptor - Pointer to descriptor that matches this interrupt object
231
232Return 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
282VOID
284 VOID
285 )
286{
287 KeFlushQueuedDpcs();
288}
289
292 __in struct _KINTERRUPT *Interrupt,
294 )
295
296/*++
297
298Routine Description:
299
300 This is the C routine called by the kernels INTERRUPT handler
301
302Arguments:
303
304Return Value:
305
306--*/
307
308{
309 FxInterrupt* interrupt;
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
377VOID
379 __in PKDPC Dpc,
383 )
384/*++
385
386Routine 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
403
405 }
406 else {
408 interrupt);
409 }
410}
411
412VOID
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) {
433 }
434}
435
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
456VOID
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
513VOID
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
unsigned char BOOLEAN
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn UINT32 *TableIdx 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:732
LONG NTSTATUS
Definition: precomp.h:26
virtual void Lock(__out PKIRQL PreviousIrql)=0
virtual void Unlock(__in KIRQL PreviousIrql)=0
MdDeviceObject __inline GetPhysicalDevice(VOID)
Definition: fxdevice.hpp:228
WDFDEVICE __inline GetHandle(VOID)
Definition: fxdevice.hpp:237
FxPkgPnp * m_PkgPnp
Definition: fxdevice.hpp:670
BOOLEAN m_DisposeWaitLock
Definition: fxinterrupt.hpp:98
BOOLEAN m_FloatingSave
VOID FlushQueuedDpcs(VOID)
BOOLEAN m_PassiveHandling
VOID ReportActive(_In_ BOOLEAN Internal=FALSE)
static EVT_SYSTEMWORKITEM _InterruptWorkItemCallback
FxCallbackLock * m_CallbackLock
Definition: fxinterrupt.hpp:93
static MdDeferredRoutineType _InterruptDpcThunk
BOOLEAN m_IsEdgeTriggeredNonMsiInterrupt
FxWaitLock * m_WaitLock
Definition: fxinterrupt.hpp:77
static MdInterruptSynchronizeRoutineType _InterruptMarkDisconnecting
volatile KIRQL m_SynchronizeIrql
Definition: fxinterrupt.hpp:67
WDF_INTERRUPT_PRIORITY m_Priority
PFN_WDF_INTERRUPT_DPC m_EvtInterruptDpc
VOID AcquireLock(VOID)
__inline BOOLEAN IsWakeCapable(VOID)
VOID ReleaseLock(VOID)
struct _KINTERRUPT * m_InterruptCaptured
PFN_WDF_INTERRUPT_ISR m_EvtInterruptIsr
BOOLEAN m_Connected
BOOLEAN WakeInterruptIsr(VOID)
static MdInterruptServiceRoutineType _InterruptThunk
VOID DisconnectInternal(VOID)
WDF_TRI_STATE m_ShareVector
Definition: fxinterrupt.hpp:54
BOOLEAN m_Disconnecting
VOID FlushAndRundownInternal(VOID)
MdLock * m_SpinLock
Definition: fxinterrupt.hpp:64
_Must_inspect_result_ NTSTATUS ConnectInternal(VOID)
WDF_INTERRUPT_POLICY m_Policy
VOID WorkItemHandler(VOID)
BOOLEAN QueueDpcForIsr(VOID)
GROUP_AFFINITY m_Processors
_Must_inspect_result_ NTSTATUS InitializeInternal(__in FxObject *Parent, __in PWDF_INTERRUPT_CONFIG Configuration)
WDFINTERRUPT GetHandle(VOID)
struct _KINTERRUPT * m_Interrupt
Definition: fxinterrupt.hpp:59
BOOLEAN m_SetPolicy
FxSystemWorkItem * m_SystemWorkItem
Definition: fxinterrupt.hpp:87
VOID FilterResourceRequirements(__inout PIO_RESOURCE_DESCRIPTOR IoResourceDescriptor)
WDF_INTERRUPT_INFO m_InterruptInfo
PFN_WDF_INTERRUPT_WORKITEM m_EvtInterruptWorkItem
VOID ReportInactive(_In_ BOOLEAN Internal=FALSE)
BOOLEAN m_Active
VOID DpcHandler(__in_opt PVOID SystemArgument1, __in_opt PVOID SystemArgument2)
virtual VOID DeleteObject(VOID)
__inline PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxobject.hpp:734
CfxDevice * m_Device
Definition: fxobject.hpp:329
PFN_IO_REPORT_INTERRUPT_INACTIVE m_IoReportInterruptInactive
Definition: fxpkgpnp.hpp:4294
PFN_IO_DISCONNECT_INTERRUPT_EX m_IoDisconnectInterruptEx
Definition: fxpkgpnp.hpp:4289
PFN_IO_REPORT_INTERRUPT_ACTIVE m_IoReportInterruptActive
Definition: fxpkgpnp.hpp:4293
PFN_IO_CONNECT_INTERRUPT_EX m_IoConnectInterruptEx
Definition: fxpkgpnp.hpp:4288
__inline BOOLEAN TryToEnqueue(__in PFN_WDF_SYSTEMWORKITEM CallbackFunc, __in PVOID Parameter)
#define __in
Definition: dbghelp.h:35
#define __inout
Definition: dbghelp.h:50
#define __in_opt
Definition: dbghelp.h:38
#define TRACINGPNP
Definition: dbgtrace.h:67
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
BOOLEAN NTAPI KeInsertQueueDpc(IN PKDPC Dpc, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: dpc.c:725
KIRQL irql
Definition: wave.h:1
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
FX_TRACK_DRIVER(fxDriverGlobals)
FxVerifierDbgBreakPoint(pFxDriverGlobals)
_Must_inspect_result_ __inline BOOLEAN FxIsProcessorGroupSupported(VOID)
Definition: fxglobalskm.h:734
FxInterrupt * pFxInterrupt
FORCEINLINE VOID FxPerfTracePassiveInterrupt(_In_ PVOID DriverCallback)
FORCEINLINE VOID FxPerfTraceInterrupt(_In_ PVOID DriverCallback)
FORCEINLINE VOID FxPerfTraceDpc(_In_ PVOID DriverCallback)
FORCEINLINE VOID FxPerfTraceWorkItem(_In_ PVOID DriverCallback)
GLenum const GLfloat * params
Definition: glext.h:5645
GLuint64EXT * result
Definition: glext.h:11304
@ Internal
Definition: hwresource.cpp:137
#define ASSERT(a)
Definition: mode.c:44
#define DO_NOTHING()
Definition: mxgeneral.h:32
#define CM_RESOURCE_INTERRUPT_POLICY_INCLUDED
Definition: cmtypes.h:146
#define _Must_inspect_result_
Definition: no_sal2.h:62
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
FxLibraryGlobalsType FxLibraryGlobals
Definition: globals.cpp:95
enum _IRQ_DEVICE_POLICY IRQ_DEVICE_POLICY
enum _IRQ_PRIORITY IRQ_PRIORITY
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
PFN_IO_CONNECT_INTERRUPT_EX IoConnectInterruptEx
Definition: fxglobals.h:730
$USHORT Group
Definition: ntbasedef.h:669
KAFFINITY Mask
Definition: ntbasedef.h:668
IO_CONNECT_INTERRUPT_FULLY_SPECIFIED_PARAMETERS FullySpecified
Definition: iotypes.h:397
union _IO_REPORT_INTERRUPT_ACTIVE_STATE_PARAMETERS::@3962 ConnectionContext
Definition: ketypes.h:699
KAFFINITY TargetProcessorSet
Definition: wdfinterrupt.h:306
KINTERRUPT_MODE Mode
Definition: wdfinterrupt.h:311
#define GetHandle(h)
Definition: treelist.c:116
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:112
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_INTERRUPT_CONFIG Configuration
Definition: wdfinterrupt.h:374
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_INTERRUPT_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFINTERRUPT * Interrupt
Definition: wdfinterrupt.h:379
@ WdfTrue
Definition: wdftypes.h:88
@ WdfUseDefault
Definition: wdftypes.h:89
@ WdfFalse
Definition: wdftypes.h:87
@ CmResourceShareDeviceExclusive
Definition: cmtypes.h:241
@ CmResourceShareShared
Definition: cmtypes.h:243
_In_ PKSERVICE_ROUTINE _In_opt_ PVOID ServiceContext
Definition: iofuncs.h:801
#define CONNECT_FULLY_SPECIFIED_GROUP
#define CONNECT_FULLY_SPECIFIED
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:688
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:687
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:689