ReactOS 0.4.16-dev-297-gc569aee
interruptobject.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 Both kernel and user mode
21
22Revision History:
23
24
25
26
27
28--*/
29
30#include "pnppriv.hpp"
31
32// Tracing support
33extern "C" {
34#if defined(EVENT_TRACING)
35#include "InterruptObject.tmh"
36#endif
37}
38
39//
40// We need three parameters for KeSynchronizeExecution so we use this
41// structure on the stack since its a synchronous call
42//
47};
48
49//
50// At this time we are unable to include wdf19.h in the share code, thus for
51// now we simply cut and paste the needed structures.
52//
53typedef struct _WDF_INTERRUPT_CONFIG_V1_9 {
54 ULONG Size;
55
56 //
57 // If this interrupt is to be synchronized with other interrupt(s) assigned
58 // to the same WDFDEVICE, create a WDFSPINLOCK and assign it to each of the
59 // WDFINTERRUPTs config.
60 //
61 WDFSPINLOCK SpinLock;
62
64
66
67 //
68 // Automatic Serialization of the DpcForIsr
69 //
71
72 // Event Callbacks
74
76
78
80
82
83//
84// The interrupt config structure has changed post win8-Beta. This is a
85// temporary definition to allow beta drivers to load on post-beta builds.
86// Note that size of win8-beta and win8-postbeta structure is different only on
87// non-x64 platforms, but the fact that size is same on amd64 is harmless because
88// the struture gets zero'out by init macro, and the default value of the new
89// field is 0 on amd64.
90//
92 ULONG Size;
93
94 //
95 // If this interrupt is to be synchronized with other interrupt(s) assigned
96 // to the same WDFDEVICE, create a WDFSPINLOCK and assign it to each of the
97 // WDFINTERRUPTs config.
98 //
99 WDFSPINLOCK SpinLock;
100
102
104
105 //
106 // DIRQL handling: automatic serialization of the DpcForIsr/WaitItemForIsr.
107 // Passive-level handling: automatic serialization of all callbacks.
108 //
110
111 //
112 // Event Callbacks
113 //
119
120 //
121 // These fields are only used when interrupt is created in
122 // EvtDevicePrepareHardware callback.
123 //
126
127 //
128 // Optional passive lock for handling interrupts at passive-level.
129 //
130 WDFWAITLOCK WaitLock;
131
132 //
133 // TRUE: handle interrupt at passive-level.
134 // FALSE: handle interrupt at DIRQL level. This is the default.
135 //
137
139
140//
141// Public constructors
142//
145 ) :
147{
148
150
152
155
157
161
165
167
168 //
169 // We want platform specific behavior for soft disconnect to avoid any
170 // compat issues on existing platforms. In later versions (after 1.11) the
171 // platform differenciation could be removed.
172 //
173#if defined(_ARM_)
175#else
177#endif
178
179#if FX_IS_KERNEL_MODE
181
182 m_Active = FALSE;
184
185#elif FX_IS_USER_MODE
186
191#endif
192
195
197
203
205
206 // This field is init later on.
208
211
212 Reset();
213
214 // This is set up by Initialize
216
217 //
218 // MSI Support
219 //
221
222 //
223 // WdfIrqPolicyOneCloseProcessor is a safe policy to use. It ensures that
224 // old devices continue to work without any change in their functionality.
225 //
230
232
233 //
234 // Driver writer can only create WDFINTERRUPTs, not delete them
235 //
239}
240
242{
243
244 //
245 // If this hits, its because someone destroyed the INTERRUPT by
246 // removing too many references by mistake without calling WdfObjectDelete
247 //
248 if( m_Interrupt != NULL ) {
251 "Destroy Interrupt destroyed without calling WdfObjectDelete, or "
252 "by Framework processing DeviceRemove. Possible reference count problem?");
254 }
255
256 if (m_Device != NULL) {
259 "Destroy Interrupt destroyed without calling WdfObjectDelete, or "
260 "by Framework processing DeviceRemove. Possible reference count problem?");
262 }
263}
264
268 VOID
269 )
270/*++
271
272Routine Description:
273 This routine is used to create a state machine that
274 is used to manage a wake capable interrupt machine
275
276Arguments:
277
278Return Value:
279 None
280
281--*/
282{
284 FxWakeInterruptMachine * fxWakeInterruptMachine = NULL;
285
287
288 fxWakeInterruptMachine = new (m_Device->m_PkgPnp->GetDriverGlobals())
290
291 if (NULL == fxWakeInterruptMachine) {
296 "WDFDEVICE 0x%p failed to allocate FxWakeInterruptMachine. %!STATUS!.",
298 goto exit;
299 }
300
301 status = fxWakeInterruptMachine->Initialize(m_Device->m_PkgPnp->GetDriverGlobals());
302 if (!NT_SUCCESS(status)) {
306 "WDFDEVICE 0x%p failed to initialize FxWakeInterruptMachine. %!STATUS!.",
308 goto exit;
309 }
310
311 status = fxWakeInterruptMachine->Init(
314 fxWakeInterruptMachine
315 );
316 if (!NT_SUCCESS(status)) {
320 "WDFDEVICE 0x%p failed to init FxWakeInterruptMachine. %!STATUS!.",
322 goto exit;
323 }
324
325 m_WakeInterruptMachine = fxWakeInterruptMachine;
326
327 fxWakeInterruptMachine->m_IsrEvent.Initialize(SynchronizationEvent,FALSE);
328
330
334 "WDFDEVICE 0x%p created wake interrupt",
335 m_Device);
336
337exit:
338 if (!NT_SUCCESS(status)) {
339 if (NULL != fxWakeInterruptMachine) {
340 delete fxWakeInterruptMachine;
341 }
342 }
343 return status;
344}
345
346VOID
348 VOID
349/*++
350
351Routine Description:
352 This routine is called by the interrupt wake machine to invoke
353 the Evt for the ISR
354
355Arguments:
356
357Return Value:
358 None
359
360--*/
361 )
362{
365
366 //
367 // Acquire our internal passive-lock after the kernel acquired its own
368 // passive-lock and before invoking the callback.
369 //
370 AcquireLock();
371
373 GetHandle(),
375 ReleaseLock();
376}
377
380 VOID
381 )
382/*++
383
384Routine Description:
385 This is the ISR for a wake interrupt. This queues an event into the
386 state machine. State machine will take care of waking the device if
387 the device is in Dx and then invoking the driver callback for the
388 interrupt.
389
390Arguments:
391
392Return Value:
393 None
394
395--*/
396{
398
399 //
400 // Queue an event in the state machine
401 //
403
405 "Wake Interrupt ISR is stuck waiting for the device"
406 "to power back up and driver calllback to be processed",
407 GetHandle(),
408 GetDriverGlobals()->DbgWaitForWakeInterruptIsrTimeoutInSec,
410
411 //
412 // State machine stores the return value of the callback in the
413 // m_Claimed member variable
414 //
416}
417
418
422 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
428 )
429{
432
433 pFxInterrupt = new (FxDriverGlobals, Attributes)
434 FxInterrupt(FxDriverGlobals);
435
436 if (pFxInterrupt == NULL) {
438
440 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
441 "not enough memory to allocate WDFINTERRUPT for WDFDEVICE %p, "
442 "%!STATUS!", Device, status);
443
444 return status;
445 }
446
447 if (NULL == Parent) {
448 Parent = Device;
449 }
450
452
453 if (NT_SUCCESS(status)) {
455 if (!NT_SUCCESS(status)) {
457 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
458 "FxInterrupt Commit failed %!STATUS!", status);
459 }
460 }
461
462 if (NT_SUCCESS(status)) {
464 }
465 else {
467 return status;
468 }
469
470 if (Configuration->CanWakeDevice) {
472 }
473
474 if (!NT_SUCCESS(status)) {
476 }
477
478 return status;
479}
480
487 )
488{
490 FxPkgPnp* pkgPnp;
491
494
495 //
496 // DIRQL handling: FxInterrupt can be parented by, and optionally
497 // serialize its DpcForIsr or WorItemForIsr with an FxDevice or
498 // FxIoQueue.
499 //
500 // Passive handling: FxInterrupt can be parented by, and optionally
501 // serialize its WorItemForIsr with an FxDevice or FxIoQueue.
502
503 //
504 // Add a reference to the device object we are associated with. We will be
505 // notified in Dispose to release this reference.
506 //
507 Device->ADDREF(this);
508
509 //
510 // It is important to store the Device only after taking the reference
511 // because Dispose checks for m_Device != NULL to release the reference. If
512 // assign it here and then take the reference later, we can return failure
513 // in between the assignment and reference and then release a reference that
514 // was not taken in Dispose.
515 //
517 pkgPnp = m_Device->m_PkgPnp;
518
519 //
520 // NOTE: Since Dispose always releases this reference, we *must* take this
521 // reference, so that even if we return error, the reference is
522 // still there to be removed on cleanup.
523 //
525
526 //
527 // Values always supplied by the caller
528 //
529 m_ShareVector = Configuration->ShareVector;
530 m_FloatingSave = Configuration->FloatingSave;
531
532 m_EvtInterruptEnable = Configuration->EvtInterruptEnable;
533 m_EvtInterruptDisable = Configuration->EvtInterruptDisable;
534
535 //
536 // Do further initialization
537 //
539 if (!NT_SUCCESS(status)) {
540 return status;
541 }
542
543 //
544 // Update the message number used for MSI support
545 //
547
548 //
549 // This logic is executed when the driver creates interrupts in its
550 // EvtDevicePrepareHardware callback.
551 //
552 if (Configuration->InterruptRaw != NULL) {
553
554 ASSERT(Configuration->InterruptTranslated != NULL);
556
558
559 //
560 // Get the real resource descriptors not the copies.
561 //
562 cmDescRaw = &(CONTAINING_RECORD(Configuration->InterruptRaw,
564 m_DescriptorClone))->m_Descriptor;
565
566 cmDescTrans = &(CONTAINING_RECORD(Configuration->InterruptTranslated,
568 m_DescriptorClone))->m_Descriptor;
569 //
570 // Assign resources to this interrupt.
571 //
572 FxInterrupt::AssignResources(cmDescRaw, cmDescTrans);
573 }
574
575 // Add this interrupt to the list of them being kept in the PnP package.
576 pkgPnp->AddInterruptObject(this);
577
579
580 return STATUS_SUCCESS;
581}
582
588 )
589{
590 FxObject* tmpObject;
593 CfxDeviceBase* deviceBase;
594 BOOLEAN passiveCallbacks;
595
597 const WDFTYPE parentType = Parent->GetType();
598
599 //
600 // Init interrupt's callbacks.
601 //
602 m_EvtInterruptIsr = Configuration->EvtInterruptIsr;
603 m_EvtInterruptDpc = Configuration->EvtInterruptDpc;
604 m_EvtInterruptWorkItem = Configuration->EvtInterruptWorkItem;
605
606 //
607 // Init soft disconnect configuration
608 //
609 switch (Configuration->ReportInactiveOnPowerDown) {
610 case WdfTrue:
612 break;
613
614 case WdfFalse:
616 break;
617
618 case WdfUseDefault:
619 default:
620 //
621 // Leave the driver's value alone.
622 //
623 break;
624 }
625
626 //
627 // TRUE if passive-level interrupt handling is enabled for this interrupt.
628 //
629 m_PassiveHandling = Configuration->PassiveHandling;
630
631 //
632 // If the caller specified a spinlock we use it.
633 //
634 if (Configuration->SpinLock != NULL) {
635 FxSpinLock* pFxSpinLock;
636
638 Configuration->SpinLock,
640 (PVOID*)&pFxSpinLock);
641
642 pFxSpinLock->SetInterruptSpinLock();
643
644 m_SpinLock = pFxSpinLock->GetLock();
645 }
646 else if (m_PassiveHandling == FALSE) {
647 //
648 // If the caller does not specify a spinlock, and this is
649 // a DIRQL interrupt we use a built in one.
650 // Originally this logic was added to allow Acquire/Release Lock
651 // to work on W2K platforms that does not support
652 // KeAcquireInterruptSpinLock.
653 //
655 }
656
657 //
658 // Automatic serialization: the DPC or work-item is synchronized with
659 // the parent's callback lock.
660 //
661
662 //
663 // Get the first ancestor that implements callbacks.
664 //
666
667 //
668 // Validate parent:
669 // - the specified device (from API) must be one of the ancestors.
670 // - the parent can only be a queue or a device.
671 //
672 if (m_DeviceBase == NULL || deviceBase != m_DeviceBase ||
673 (parentType != FX_TYPE_QUEUE && parentType != FX_TYPE_DEVICE)) {
677 "The specified object 0x%p is not a valid parent for a "
678 "WDFINTERRUPT, WDF_INTERRUPT_CONFIG structure 0x%p passed, "
679 "%!STATUS!", Parent->GetObjectHandle(), Configuration, status);
680
681 return status;
682 }
683
684 //
685 // If automatic-serialization is off, m_CallbackLock is NULL.
686 // else if parent doesn't use locking, m_CallbackLock is NULL.
687 // else if work-item ISR callback set, m_CallbackLock is a passive lock.
688 // else m_CallbackLock is a spin-lock.
689 //
690 // Note: logic retrieves the parent's callback lock when automatic
691 // serialization is on even if work-item or DPC callbacks are not set,
692 // this is not to break the existing behavior/validation.
693 //
694 if (Configuration->EvtInterruptWorkItem != NULL) {
695 passiveCallbacks = TRUE;
696 }
697 else if (Configuration->EvtInterruptDpc != NULL) {
698 passiveCallbacks = FALSE;
699 }
700 else if (m_PassiveHandling) {
701 passiveCallbacks = TRUE;
702 }
703 else {
704 passiveCallbacks = FALSE;
705 }
706
708 callbacks, // IFxHasCallbacks*
709 Configuration->AutomaticSerialization,
710 passiveCallbacks,
712 &tmpObject // No reference count is taken.
713 );
714 if (!NT_SUCCESS(status)) {
715 //
716 // We should never incur this error.
717 //
719 return status;
720 }
721
722 //
723 // If the parent is a queue, the queue inherits the deletion constraints of the
724 // interrupt object, i.e., driver cannot manually delete the queue.
725 //
726 if (FX_TYPE_QUEUE == parentType) {
727 ((FxIoQueue*)Parent)->SetInterruptQueue();
728 }
729
730 //
731 // Passive-level handling: init wait-lock.
732 //
733 if (m_PassiveHandling) {
735
736 //
737 //If the caller specified a waitlock, we use it.
738 //
739 if (Configuration->WaitLock != NULL) {
742 Configuration->WaitLock,
744 (PVOID*)&m_WaitLock);
745 }
746
747 //
748 // Use a default lock if none was specified.
749 //
750 if (NULL == m_WaitLock) {
751 WDFWAITLOCK waitLock = NULL;
752 WDF_OBJECT_ATTRIBUTES attributes;
753
754 WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
755
758 &attributes,
759 NULL,
760 FALSE,
761 &waitLock);
762
763 if (!NT_SUCCESS(status)) {
765 "Could not allocate waitlock, %!STATUS!",
766 status);
767 return status;
768 }
769
771 waitLock,
773 (PVOID*)&m_WaitLock);
774 //
775 // Explicitly dispose this wait-lock object.
776 //
778 }
779 }
780
781 //
782 // If needed, initialize the interrupt's workitem.
783 // Alloacte workitem if driver specified EvtInterruptWorkitem.
784 // In addition, for Umdf, allocate workitem if driver alternatively
785 // specified EvtInterruptDpc. Note that driver is not allwed to specify both.
786 //
793
794 if (!NT_SUCCESS(status)) {
796 "Could not allocate workitem, %!STATUS!",
797 status);
798 return status;
799 }
800 }
801
802 //
803 // Do mode-apecific initialization
804 //
806 if (!NT_SUCCESS(status)) {
807 return status;
808 }
809
810 return STATUS_SUCCESS;
811}
812
813VOID
815 VOID
816 )
817/*++
818
819Routine Description:
820 Resets the interrupt info and synchronize irql for the interrupt. The pnp
821 state machine will call this function every time new resources are assigned
822 to the device.
823
824Arguments:
825 None
826
827Return Value:
828 None
829
830 --*/
831{
832 //
833 // Other values in m_InterruptInfo survive a reset, so RtlZeroMemory is not
834 // an option. Manually set the fields that need resetting.
835 //
837 m_InterruptInfo.Group = 0;
842
844
845 //
846 // Do mode-specific reset.
847 // For KMDF, it's a no-op.
848 // For UMDF, a message is sent to reflector to reset the interrupt info.
849 //
851}
852
853//
854// This is an API call from the device driver to delete this INTERRUPT.
855//
856VOID
858 VOID
859 )
860{
861 if (m_AddedToList) {
862 //
863 // Pop this off of PnP's list of interrupts.
864 //
866 }
867
869 //
870 // This can happen if driver explicitly deletes the interrupt in its
871 // release hardware callback.
872 //
874 }
875
879 }
880
881 //
882 // Use the base FxObject's DeleteObject implementation which will Dispose us
883 //
884 FxNonPagedObject::DeleteObject(); // __super call
885}
886
887//
888// Called by the PnP package after the driver's release hardware callback.
889//
890VOID
892 VOID
893 )
894{
896 // Delete this interrupt.
897 DeleteObject();
898 }
899}
900
903 VOID
904 )
905{
906 return &m_InterruptInfo;
907}
908
909//
910// Called from the parent when the parent is being removed.
911//
912// Must ensure that any races with Delete are handled properly
913//
916 VOID
917 )
918{
919 // MarkPassiveDispose() in Initialize ensures this
921
923
924 return TRUE;
925}
926
927VOID
931 )
932/*++
933
934Routine Description:
935
936 This function allows an interrupt object to know what resources have been
937 assigned to it. It will be called as part of IRP_MN_START_DEVICE.
938
939Arguments:
940
941 CmDescRaw - A CmResourceDescriptor that describes raw interrupt resources
942
943 CmDescTrans - A CmResourceDescriptor that describes translated interrupt
944 resources
945
946Return Value:
947
948 VOID
949
950--*/
951{
952 if (CmDescTrans->u.Interrupt.Group > 0 &&
954 //
955 // This should never happen.
956 //
958 }
959
960#if FX_IS_USER_MODE
961 //
962 // For UMDF, see if this is level-triggered interrupt in which case we need
963 // reflector to handle it at passive level. Also, level-triggered
964 // support is present only on Win8 and newer. Note that, for KMDF, driver
965 // would have provided the choice of handling at passive level so we know
966 // that early on for KMDF, however for UMDF, driver can't specify the choice
967 // and UMDF figures out whether to handle at passive or not by looking at
968 // the interrupt type in resources.
969 //
970 if (IsLevelTriggered(CmDescTrans->Flags) &&
973 }
974#endif
975
976 if (IsPassiveConnect() && _IsMessageInterrupt(CmDescTrans->Flags)) {
979 "Driver cannot specify PassiveHandling for MSI interrupts.");
981 // IoConnectInterruptEx will fail later on.
982 }
983
984 m_InterruptInfo.Group = CmDescTrans->u.Interrupt.Group;
985 m_InterruptInfo.TargetProcessorSet = CmDescTrans->u.Interrupt.Affinity;
986 m_InterruptInfo.ShareDisposition = CmDescTrans->ShareDisposition;
989
990 //
991 // Interrupt's IRQL.
992 //
993 m_InterruptInfo.Irql = (KIRQL)CmDescTrans->u.Interrupt.Level;
994
995 if (IsPassiveConnect()) {
997 }
998
999 //
1000 // Note if this is an MSI interrupt
1001 //
1003
1004 //
1005 // Edge-triggered interrupts that are ActiveBoth are made stateful by the OS
1006 // (GPIO buttons driver) to track buttons' press/release state. This is because
1007 // the driver may not have the ability to read the state directly from the hardware.
1008 //
1009 // There is no way to identify ActiveBoth interrupts since KINTERRUPT_POLARITY is
1010 // not exposed to client drivers, so we decided to apply this logic to all
1011 // edge-triggered non-MSI interrupts.
1012 //
1015
1017 CmDescRaw->u.MessageInterrupt.Raw.MessageCount > 1) {
1018 //
1019 // This is an assignment for a multi-message PCI 2.2-style resource.
1020 // Thus the vector and message data have to be deduced.
1021 //
1022 m_InterruptInfo.Vector = CmDescTrans->u.Interrupt.Vector + m_InterruptInfo.MessageNumber;
1023
1025 }
1026 else {
1027 //
1028 // This is an assignment for a single interrupt, either line-based or
1029 // PCI 2.2 single-message MSI, or PCI 3.0 MSI-X-style resource.
1030 //
1031 m_InterruptInfo.Vector = CmDescTrans->u.Interrupt.Vector;
1032
1035 }
1036 else {
1037 if (IsLevelTriggered(CmDescTrans->Flags)) {
1039 }
1040 else {
1042 }
1043 }
1044 }
1045
1046 if (IsPassiveConnect()) {
1048 }
1049
1050 //
1051 // Do mode-specific work. For KMDF, it's a no-op.
1052 // For UMDF, send a sync message to Reflector to assign resources.
1053 //
1054 AssignResourcesInternal(CmDescRaw, CmDescTrans, &m_InterruptInfo);
1055
1056 //
1057 // Weak ref to the translated resource interrupt descriptor.
1058 // It is valid from prepare hardware callback to release hardware callback.
1059 //
1060 m_CmTranslatedResource = CmDescTrans;
1061
1064 "Is MSI? %d, MSI-ID %d, AffinityPolicy %!WDF_INTERRUPT_POLICY!, "
1065 "Priority %!WDF_INTERRUPT_PRIORITY!, Group %d, Affinity 0x%I64x, "
1066 "Irql 0x%x, Vector 0x%x\n",
1069 m_Policy,
1070 m_Priority,
1071 m_InterruptInfo.Group,
1075
1076}
1077
1078VOID
1080 VOID
1081 )
1082/*++
1083
1084Routine Description:
1085
1086 This function tells an interrupt object that it no longer owns any resources.
1087
1088Arguments:
1089
1090 none
1091
1092Return Value:
1093
1094 VOID
1095
1096--*/
1097{
1098 ULONG messageNumber;
1099
1100 //
1101 // The message # doesn't change, so we must preserve it.
1102 //
1103 messageNumber = m_InterruptInfo.MessageNumber;
1104
1105 //
1106 // This will zero out all the fields and init the size (as the structure
1107 // can be resued again say after a rebalance).
1108 //
1110
1111 m_InterruptInfo.MessageNumber = messageNumber;
1112
1113 //
1114 // Used by interrupts created during 'EvtDevicePrepareHardware' callback.
1115 //
1117
1118 //
1119 // Do mode-specific work. For KMDF, it's a no-op.
1120 // For UMDF, send a sync message to Reflector.
1121 //
1123}
1124
1125VOID
1130 )
1131/*++
1132
1133Routine Description:
1134
1135 This function fills in the policy member variables. These values will be
1136 used in IRP_MN_FILTER_RESOURCE_REQUIREMENTS.
1137
1138Arguments:
1139
1140 Policy - Strategy for assigning target processors
1141
1142 Priority - DIRQL preference
1143
1144 TargetProcessorSet - Processors which should receive this interrupt, if
1145 the policy is "SpecifyProcessors."
1146
1147Return Value:
1148
1149 VOID
1150
1151--*/
1152{
1153 //
1154 // We cannot apply policy for interrupts created during prepare hardware.
1155 //
1159 "You cannot apply policy at this stage for WDFINTERRUPT 0x%p "
1160 "For interrupts created in EvtDevicePrepareHardware you must use "
1161 "EvtDeviceFilter APIs or use a pre-process routine to handle the "
1162 "IRP_MN_FILTER_RESOURCE_REQUIREMENT, %!STATUS!",
1165 }
1166
1167 m_Policy = Policy;
1170
1171 //
1172 // Make sure OS supports processor groups, default to group 0 otherwise.
1173 //
1175 m_Processors.Group = 0;
1176 }
1177
1178 m_SetPolicy = TRUE;
1179
1180 //
1181 // Do mode-specific work. This function does nothing for KMDF.
1182 // It sends a message to reflector for UMDF.
1183 //
1185}
1186
1190 __in ULONG NotifyFlags
1191 )
1192/*++
1193
1194Routine Description:
1195
1196 This function is the external interface for connecting the interrupt. It
1197 calls the PnP manager to connect the interrupt (only if the operation is
1198 not occurring in a non power pageable state). Then it calls
1199 EvtInterruptEnable at DIRQL and EvtInterruptPostEnable at PASSIVE_LEVEL.
1200
1201Arguments:
1202 NotifyFlags - combination of values from the enum NotifyResourcesFlags
1203
1204Return Value:
1205
1206 NTSTATUS
1207
1208--*/
1209{
1212
1214
1215 if ((NotifyFlags & NotifyResourcesExplicitPowerup) &&
1216 IsActiveForWake()) {
1217 //
1218 // If an interrupt is marked as wakeable and the device has been set to
1219 // wake via a driver-owned ISR, leave the interrupt connected.
1220 //
1222
1223 return STATUS_SUCCESS;
1224 }
1225
1226 //
1227 // See if we need to just do soft connect. We do soft connect on explicit
1228 // power up if driver opted-in for that.
1229 //
1231 (NotifyFlags & NotifyResourcesExplicitPowerup)){
1232
1234
1236 goto Enable;
1237 }
1238
1239 //
1240 // We should either be disconnected or being asked to connect in the NP path
1241 //
1242 ASSERT(m_Connected == FALSE || (NotifyFlags & NotifyResourcesNP));
1243
1244 if (m_ForceDisconnected) {
1245 return STATUS_SUCCESS;
1246 }
1247
1248 //
1249 // Check to see if this interrupt object was actually assigned any
1250 // resources. If it wasn't, then don't attempt to connect. A WDFINTERRUPT
1251 // object won't be assigned any resources if the underlying device wasn't
1252 // granted any by the PnP manager.
1253 //
1254 if (m_InterruptInfo.Vector == 0) {
1255 return STATUS_SUCCESS;
1256 }
1257
1258 //
1259 // If we are in an NP path, the interrupt remained connected while the device
1260 // went into Dx so there is no need to reconnect it.
1261 //
1262 if ((NotifyFlags & NotifyResourcesNP) == 0) {
1263
1266
1267 //
1268 // Call pnp manager to connect the interrupt. For KMDF, we call
1269 // kernel DDI, whereas for UMDF, we send a sync message to redirector.
1270 //
1272
1273 if (!NT_SUCCESS(status)) {
1274 m_Interrupt = NULL;
1275
1278 "IoConnectInterrupt(Ex) Failed,"
1279 " SpinLock 0x%p,"
1280 " Vector 0x%x,"
1281 " IRQL 0x%x,"
1282 " Synchronize IRQL 0x%x,"
1283 " Mode 0x%x,"
1284 " ShareVector %s,"
1285 " ProcessorGroup %d,"
1286 " ProcessorEnableMask 0x%I64x,"
1287 " FloatingSave %s,"
1288 " %!STATUS!",
1289 m_SpinLock,
1295 CmResourceShareShared ? "True" : "False",
1296 m_InterruptInfo.Group,
1298 m_FloatingSave ? "True" : "False",
1299 status
1300 );
1301
1302 return status;
1303 }
1304
1305 m_Connected = TRUE;
1306
1307#if FX_IS_KERNEL_MODE
1308 m_Active = TRUE;
1309#endif
1310
1311 }
1312 else {
1315 }
1316
1317Enable:
1318
1319 //
1320 // Enable the interrupt at the hardware.
1321 //
1323 if (!NT_SUCCESS(status)) {
1326 "EvtInterruptEnable WDFDEVICE %p, WDFINTERRUPT %p, PKINTERRUPT %p "
1327 "returned %!STATUS!", m_Device->GetHandle(), GetHandle(),
1329
1330 return status;
1331 }
1332
1333 m_Enabled = TRUE;
1334
1335 return status;
1336}
1337
1341 __in ULONG NotifyFlags
1342 )
1343/*++
1344
1345Routine Description:
1346
1347 This function is the external interface for disconnecting the interrupt. It
1348 calls the Io manager to disconnect. Then it calls EvtInterruptPreDisable at
1349 PASSIVE_LEVEL and EvtInterruptDisable at DIRQL.
1350
1351Arguments:
1352
1353 Surprise - Indicates that we are disconnecting due to a surprise-remove,
1354 which means that we shouldn't do anything that touches hardware.
1355
1356Return Value:
1357
1358 NTSTATUS
1359
1360--*/
1361{
1363 NTSTATUS status, finalStatus;
1364
1365 finalStatus = STATUS_SUCCESS;
1367
1368 //
1369 // Check to see if this interrupt object was actually assigned any
1370 // resources. If it wasn't, then don't attempt to disconnect. A
1371 // WDFINTERRUPT object won't be assigned any resources if the underlying
1372 // device wasn't granted any by the PnP manager.
1373 //
1374
1375 if (m_InterruptInfo.Vector == 0) {
1376 return STATUS_SUCCESS;
1377 }
1378
1379 if (IsWakeCapable() &&
1380 (NotifyFlags & NotifyResourcesArmedForWake)) {
1381 //
1382 // If an interrupt is marked as wakeable and the device has been set to
1383 // wake via a driver-owned ISR, leave the interrupt connected.
1384 //
1386
1388
1389 return STATUS_SUCCESS;
1390 }
1391
1392 //
1393 // This takes care of the power-up failure path for interrupt that doesnt
1394 // support soft disconnect. The interrupt has already been hard
1395 // disconnected in power-up failure path.
1396 //
1397 if ((NotifyFlags & NotifyResourcesDisconnectInactive) &&
1399 (IsActiveForWake() == FALSE)) {
1400 //
1401 // We got here to disconnect an inactive interrupt. But if
1402 // this interrupt is not Soft Disconnect capable then it was
1403 // never made inactive in the first place so nothing to do here.
1404 // It should already be hard disconnected by now.
1405 //
1407
1408 return STATUS_SUCCESS;
1409 }
1410
1411
1412 if (m_Connected == FALSE) {
1413 //
1414 // No way we can be not connect and enabled
1415 //
1417
1418 //
1419 // if m_Connected is FALSE because the driver forcefully disconnected
1420 // the interrupt we still want to disconnect the actual interrupt object
1421 // if the caller wants to force disconnect (e.g., the device is being
1422 // removed)
1423 //
1424 if (m_Interrupt != NULL &&
1425 (NotifyFlags & NotifyResourcesForceDisconnect)) {
1426 //
1427 // If the driver lets the state machine handle the interrupt state
1428 // we should never get here so make sure the driver forced the issue.
1429 //
1431
1432 goto Disconnect;
1433 }
1434
1435 return STATUS_SUCCESS;
1436 }
1437
1438 if (m_Enabled && ((NotifyFlags & NotifyResourcesSurpriseRemoved) == 0)) {
1439
1440 //
1441 //
1442 // For wake capable interrupts it is possible to enter this path
1443 // with NotifyResourcesDisconnectInactive flag if the device fails
1444 // to power up after the interrupt was left connected during Dx
1445 //
1446 if (IsWakeCapable() == FALSE) {
1447 ASSERT((NotifyFlags & NotifyResourcesDisconnectInactive) == 0);
1448 }
1449
1450 //
1451 // Disable the interrupt at the hardware.
1452 //
1454
1455 m_Enabled = FALSE;
1456
1457 if (!NT_SUCCESS(status)) {
1458 //
1459 // Even upon failure we continue because we don't want to leave
1460 // the interrupt connected when we tear down the stack.
1461 //
1464 "EvtInterruptDisable WDFDEVICE %p, WDFINTERRUPT %p, "
1465 "PKINTERRUPT %p returned %!STATUS!",
1468
1469 //
1470 // Overwrite the previous value. Not a big deal since both are
1471 // errors.
1472 //
1473 finalStatus = status;
1474 }
1475 }
1476
1477#if FX_IS_KERNEL_MODE
1478 //
1479 // Some edge-triggered interrupts may fire before the connection process is
1480 // finished and m_Interrupt is set. To accomodate them, we save the KINTERRUPT
1481 // in _InterruptThunk to m_InterruptCaptured which serves as a backup for
1482 // m_Interrupt. Now we need to NULL m_InterruptCaptured and ensure that
1483 // _InterruptThunk will not re-capture it.
1484 //
1486 //
1487 // Synchronize the setting of m_Disconnecting with any running ISRs.
1488 // No new ISR callbacks will run after _SynchronizeExecution returns,
1489 // until m_Disconnecting is set to FALSE again.
1490 //
1491 if (m_Interrupt != NULL) {
1493 }
1494
1495 //
1496 // Because m_Disconnecting was set, we know the ISR
1497 // will not re-capture the KINTERRUPT again.
1498 //
1500 }
1501#endif
1502
1503 //
1504 // Now flush queued callbacks so that we know that nobody is still trying to
1505 // synchronize against this interrupt. For KMDF this will flush DPCs and
1506 // for UMDF this will send a message to reflector to flush queued DPCs.
1507 //
1509
1510#if FX_IS_KERNEL_MODE
1511 //
1512 // Rundown the workitem if present (passive-level interrupt support or KMDF).
1513 // Not needed for UMDF since reflector doesn't use workitem for isr.
1514 //
1516
1517#endif
1518
1519 //
1520 // See if we need to just do soft disconnect. Soft disconnect is done only
1521 // during explicit power down.
1522 //
1524 (NotifyFlags & NotifyResourcesExplicitPowerDown)) {
1526
1527 goto Exit;
1528 }
1529
1530 //
1531 // In the NP path we disable the interrupt but do not disconnect the
1532 // interrupt. (That is b/c IoDisconnectInterrupt is a pagable function and
1533 // calling it could cause paging I/O on this device which will be unserviceable
1534 // because it is in Dx.
1535 //
1536 if (NotifyFlags & NotifyResourcesNP) {
1537 //
1538 // If we are in the NP path, force disconnect should not be set. Force
1539 // disconnect is setup during a query remove/stop power down.
1540 //
1541 ASSERT((NotifyFlags & NotifyResourcesForceDisconnect) == 0);
1542
1543 goto Exit;
1544 }
1545
1547 //
1548 // Disconnect the interrupt. For KMDF, this calls the kernel DDI, and for
1549 // UMDF, sends a sync message to reflector.
1550 //
1552
1553 if (IsActiveForWake()) {
1554 //
1555 // Since the interrupt has been disconnected, it not longer active
1556 // for wake
1557 //
1559 }
1560
1562
1563#if FX_IS_KERNEL_MODE
1564 m_Active = FALSE;
1565#endif
1566
1567Exit:
1569
1570 return finalStatus;
1571}
1572
1573
1577 VOID
1578 )
1579{
1580 ULONG flags;
1581
1582 //
1583 // Since we have no context or coordination of power state when these calls
1584 // are made, our only recourse is to see if the device is power pagable or
1585 // not and use that as the basis for our flags.
1586 //
1589 }
1590 else {
1592 }
1593
1594 //
1595 // Log the event because the driver is not allow the state machine to handle
1596 // the interrupt's state.
1597 //
1600 "Force disconnect called on WDFDEVICE %p, WDFINTERRUPT %p, PKINTERRUPT %p",
1602
1604
1605 return Disconnect(flags);
1606}
1607
1611 VOID
1612 )
1613{
1614 ULONG flags;
1615
1616 //
1617 // Since we have no context or coordination of power state when these calls
1618 // are made, our only recourse is to see if the device is power pagable or
1619 // not and use that as the basis for our flags.
1620 //
1623 }
1624 else {
1626 }
1627
1628 //
1629 // Log the event because the driver is not allow the state machine to handle
1630 // the interrupt's state.
1631 //
1634 "Force connect called on WDFDEVICE %p, WDFINTERRUPT %p, PKINTERRUPT %p",
1636
1638
1639 return Connect(flags);
1640}
1641
1642//
1643// Called by the system work item to finish the rundown
1644//
1645VOID
1647{
1649
1650 //
1651 // This called at PASSIVE_LEVEL which is required for
1652 // IoDisconnectInterrupt and KeFlushQueuedDpcs
1653 //
1655
1656 //
1657 // If we have the KeFlushQueuedDpcs function call it
1658 // to ensure the DPC routine is no longer running before
1659 // we release the final reference to memory and the framework objects
1660 //
1662
1663 //
1664 // Do mode-specific work.
1665 //
1667
1668 //
1669 // Release the reference taken in FxInterrupt::Initialize
1670 //
1671 if (m_Device != NULL) {
1672 pObject = m_Device;
1673 m_Device = NULL;
1674
1675 pObject->RELEASE(this);
1676 }
1677
1678 //
1679 // Release the reference taken in FxInterrupt::Initialize
1680 //
1682}
1683
1684//
1685// Enable interrupts
1686//
1689 VOID
1690 )
1691{
1693
1694 if (m_PassiveHandling) {
1695 //
1696 // Passive-level interrupt handling: acquire our internal passive-lock
1697 // after the kernel acquired its own passive-lock and before invoking
1698 // the callback.
1699 //
1700 AcquireLock();
1702 m_Device->GetHandle());
1703 ReleaseLock();
1704 }
1705 else {
1706 //
1707 // DIRQL interrupt handling: invoke the callback.
1708 //
1710 m_Device->GetHandle());
1711 }
1712
1713 return status;
1714}
1715
1716BOOLEAN
1718 __in PVOID SyncContext
1719 )
1720{
1722
1723 p = (FxInterruptEnableParameters*) SyncContext;
1724
1725 p->ReturnVal = p->Interrupt->InterruptEnableInvokeCallback();
1726
1727 return TRUE;
1728}
1729
1732 VOID
1733 )
1734{
1736
1737 params.Interrupt = this;
1738 params.ReturnVal = STATUS_SUCCESS;
1739
1742 }
1743
1744 return params.ReturnVal;
1745}
1746
1747//
1748// Disable interrupts
1749//
1752 VOID
1753 )
1754{
1756
1757 if (m_PassiveHandling) {
1758 //
1759 // Passive-level interrupt handling: acquire our internal passive-lock
1760 // after the kernel acquired its own passive-lock and before invoking
1761 // the callback.
1762 //
1763 AcquireLock();
1765 m_Device->GetHandle());
1766 ReleaseLock();
1767 }
1768 else {
1769 //
1770 // DIRQL interrupt handling: invoke the callback.
1771 //
1773 m_Device->GetHandle());
1774 }
1775
1776 return status;
1777}
1778
1779
1780BOOLEAN
1782 __in PVOID SyncContext
1783 )
1784{
1786
1787 p = (FxInterruptDisableParameters*) SyncContext;
1788
1789 p->ReturnVal = p->Interrupt->InterruptDisableInvokeCallback();
1790
1791 return TRUE;
1792}
1793
1796 VOID
1797 )
1798{
1800
1801 params.Interrupt = this;
1802 params.ReturnVal = STATUS_SUCCESS;
1803
1804 if (m_EvtInterruptDisable != NULL) {
1806 }
1807
1808 return params.ReturnVal;
1809}
1810
1811BOOLEAN
1813 VOID
1814 )
1815{
1816 BOOLEAN queued;
1817
1818 //
1819 // Using this function is optional,
1820 // but the caller better have registered a handler
1821 //
1822#if ((FX_CORE_MODE)==(FX_CORE_KERNEL_MODE))
1824#else
1826#endif
1827
1829 //
1830 // Note: if the caller runs at DIRQL, the function returns the result
1831 // of KeInsertQueueDpc() and not that of WorkItem.TryToQueue().
1832 // The latter result is lost. Docs should clarify this behavior.
1833 //
1834#if ((FX_CORE_MODE)==(FX_CORE_KERNEL_MODE))
1835 queued = Mx::MxInsertQueueDpc(&m_Dpc, this, NULL);
1836#else
1837 queued = FALSE;
1838 FX_VERIFY(INTERNAL, TRAPMSG("Not expected"));
1839#endif
1840 }
1841 else {
1843 }
1844
1845 return queued;
1846}
1847
1848VOID
1851 )
1852/*++
1853
1854Routine Description:
1855 Thunk used to invoke EvtInterruptWorkItem at passive-level
1856
1857--*/
1858{
1860 ((FxInterrupt*)DeferredContext)->WorkItemHandler();
1861}
1862
1863VOID
1865 VOID
1866 )
1867{
1868 if (m_SystemWorkItem != NULL) {
1870 }
1871}
1872
1873#pragma prefast(push)
1874#pragma prefast(disable:__WARNING_UNEXPECTED_IRQL_CHANGE, "Used unannotated pointers previously")
1875
1876VOID
1878 )
1879{
1880 if (FALSE == m_PassiveHandling) {
1881 struct _KINTERRUPT* kinterrupt = GetInterruptPtr();
1882
1883 //
1884 // DIRQL interrupt handling.
1885 //
1886 ASSERTMSG("Can't synchronize when the interrupt isn't connected: ",
1887 kinterrupt != NULL);
1888
1889 if (NULL != kinterrupt) {
1891 }
1892 }
1893 else {
1894 //
1895 // Passive-level interrupt handling when automatic serialization is off.
1896 //
1899 m_WaitLock->AcquireLock(GetDriverGlobals(), NULL);
1900 }
1901}
1902#pragma prefast(pop)
1903
1904BOOLEAN
1906 )
1907{
1908 LONGLONG timeout = 0;
1909
1910 ASSERTMSG("TryToAcquireLock is only available for passive-level "
1911 "interrupt handling: ", m_PassiveHandling);
1912
1913 if (FALSE == m_PassiveHandling) {
1914 return FALSE;
1915 }
1916
1919
1920 //
1921 // Passive-level interrupt handling. Automatic serialization is off.
1922 //
1923 return FxWaitLockInternal::IsLockAcquired(
1924 m_WaitLock->AcquireLock(GetDriverGlobals(), &timeout)
1925 );
1926}
1927
1928#pragma prefast(push)
1929#pragma prefast(disable:__WARNING_UNEXPECTED_IRQL_CHANGE, "Used unannotated pointers previously")
1930
1931VOID
1933 )
1934{
1935 if (FALSE == m_PassiveHandling) {
1936 struct _KINTERRUPT* kinterrupt = GetInterruptPtr();
1937
1938 //
1939 // DIRQL interrupt handling.
1940 //
1941 ASSERTMSG("Can't synchronize when the interrupt isn't connected: ",
1942 kinterrupt != NULL);
1943
1944 if (NULL != kinterrupt) {
1945#pragma prefast(suppress:__WARNING_CALLER_FAILING_TO_HOLD, "Unable to annotate ReleaseLock for this case.");
1947 }
1948 }
1949 else {
1950 //
1951 // Passive-level interrupt handling when automatic serialization is off.
1952 //
1955#pragma prefast(suppress:__WARNING_CALLER_FAILING_TO_HOLD, "Unable to annotate ReleaseLock for this case.");
1956 m_WaitLock->ReleaseLock(GetDriverGlobals());
1957 }
1958}
1959#pragma prefast(pop)
1960
1961BOOLEAN
1963 __in PVOID SyncContext
1964 )
1965{
1968
1969 p = (FxInterruptSyncParameters*) SyncContext;
1970
1971 if (p->Interrupt->m_PassiveHandling) {
1973 //
1974 // Passive-level interrupt handling: acquire our internal passive-lock
1975 // after the kernel acquired its own passive-lock and before invoking
1976 // the callback.
1977 //
1978 p->Interrupt->AcquireLock();
1979 result = p->Callback(p->Interrupt->GetHandle(), p->Context);
1980 p->Interrupt->ReleaseLock();
1981 }
1982 else {
1983 result = p->Callback(p->Interrupt->GetHandle(), p->Context);
1984 }
1985
1986 return result;
1987}
1988
1989BOOLEAN
1993 )
1994{
1995 struct _KINTERRUPT* kinterrupt;
1997
1998 params.Interrupt = this;
1999 params.Callback = Callback;
2000 params.Context = Context;
2001
2002 kinterrupt = GetInterruptPtr();
2003
2004#if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
2005 ASSERTMSG("Can't synchronize when the interrupt isn't connected: ",
2006 kinterrupt != NULL);
2007#endif
2008
2009 return _SynchronizeExecution(kinterrupt,
2011 &params);
2012}
2013
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
static FxDeviceBase * _SearchForDevice(__in FxObject *Object, __out_opt IFxHasCallbacks **Callbacks)
ULONG __inline GetDeviceObjectFlags(VOID)
Definition: fxdevice.hpp:192
WDFDEVICE __inline GetHandle(VOID)
Definition: fxdevice.hpp:237
MdDeviceObject __inline GetDeviceObject(VOID)
Definition: fxdevice.hpp:174
FxPkgPnp * m_PkgPnp
Definition: fxdevice.hpp:670
__inline WDF_DEVICE_PNP_STATE GetDevicePnpState()
Definition: fxdevice.hpp:1149
virtual VOID SetDeviceTelemetryInfoFlags(_In_ FxDeviceInfoFlags Flag)
Definition: fxdevice.hpp:1807
PFN_WDF_INTERRUPT_ENABLE m_EvtInterruptEnable
PWDF_INTERRUPT_INFO GetInfo(VOID)
BOOLEAN m_DisposeWaitLock
Definition: fxinterrupt.hpp:98
static MdInterruptSynchronizeRoutineType _InterruptDisableThunk
BOOLEAN m_FloatingSave
static MdInterruptSynchronizeRoutineType _InterruptSynchronizeThunk
VOID FlushAndRundown(VOID)
_Must_inspect_result_ NTSTATUS Connect(__in ULONG NotifyFlags)
VOID FlushQueuedDpcs(VOID)
_Must_inspect_result_ NTSTATUS ForceReconnect(VOID)
BOOLEAN m_PassiveHandling
BOOLEAN IsLevelTriggered(__in ULONG Flags)
VOID ReportActive(_In_ BOOLEAN Internal=FALSE)
struct _KINTERRUPT * GetInterruptPtr(VOID)
static EVT_SYSTEMWORKITEM _InterruptWorkItemCallback
FxCallbackLock * m_CallbackLock
Definition: fxinterrupt.hpp:93
static MdDeferredRoutineType _InterruptDpcThunk
VOID FlushQueuedWorkitem(VOID)
VOID InvokeWakeInterruptEvtIsr(VOID)
BOOLEAN m_IsEdgeTriggeredNonMsiInterrupt
FxWaitLock * m_WaitLock
Definition: fxinterrupt.hpp:77
RD_INTERRUPT_CONTEXT m_RdInterruptContext
static MdInterruptSynchronizeRoutineType _InterruptMarkDisconnecting
BOOLEAN m_CreatedInPrepareHardware
volatile KIRQL m_SynchronizeIrql
Definition: fxinterrupt.hpp:67
MxLock m_BuiltInSpinLock
Definition: fxinterrupt.hpp:72
WDF_INTERRUPT_PRIORITY m_Priority
PFN_WDF_INTERRUPT_DPC m_EvtInterruptDpc
VOID Reset(VOID)
VOID AcquireLock(VOID)
BOOLEAN m_ForceDisconnected
VOID AssignResources(__in PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescRaw, __in PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescTrans)
__inline BOOLEAN IsWakeCapable(VOID)
VOID ReleaseLock(VOID)
VOID OnPostReleaseHardware(VOID)
NTSTATUS InterruptDisable(VOID)
__inline BOOLEAN IsPassiveConnect(VOID)
PCM_PARTIAL_RESOURCE_DESCRIPTOR m_CmTranslatedResource
BOOLEAN Synchronize(__in PFN_WDF_INTERRUPT_SYNCHRONIZE Callback, __in WDFCONTEXT Context)
_Must_inspect_result_ NTSTATUS Initialize(__in CfxDevice *Device, __in FxObject *Parent, __in PWDF_INTERRUPT_CONFIG Configuration)
BOOLEAN IsSoftDisconnectCapable(VOID)
NTSTATUS InterruptEnableInvokeCallback(VOID)
struct _KINTERRUPT * m_InterruptCaptured
VOID SetPolicyInternal(__in WDF_INTERRUPT_POLICY Policy, __in WDF_INTERRUPT_PRIORITY Priority, __in PGROUP_AFFINITY TargetProcessorSet)
FxWakeInterruptMachine * m_WakeInterruptMachine
PFN_WDF_INTERRUPT_ISR m_EvtInterruptIsr
virtual ~FxInterrupt(VOID)
BOOLEAN m_Connected
static _Must_inspect_result_ NTSTATUS _CreateAndInit(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in CfxDevice *Device, __in_opt FxObject *Parent, __in PWDF_OBJECT_ATTRIBUTES Attributes, __in PWDF_INTERRUPT_CONFIG Configuration, __out FxInterrupt **Interrupt)
BOOLEAN WakeInterruptIsr(VOID)
BOOLEAN m_PassiveHandlingByRedirector
FxInterruptWaitblock * m_InterruptWaitblock
static MdInterruptServiceRoutineType _InterruptThunk
VOID DisconnectInternal(VOID)
WDF_TRI_STATE m_ShareVector
Definition: fxinterrupt.hpp:54
PFN_WDF_INTERRUPT_DISABLE m_EvtInterruptDisable
static BOOLEAN _IsMessageInterrupt(__in USHORT ResourceFlags)
VOID SetPolicy(__in WDF_INTERRUPT_POLICY Policy, __in WDF_INTERRUPT_PRIORITY Priority, __in PGROUP_AFFINITY TargetProcessorSet)
BOOLEAN m_Enabled
BOOLEAN m_Disconnecting
VOID FlushAndRundownInternal(VOID)
VOID AssignResourcesInternal(__in PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescRaw, __in PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescTrans, __in PWDF_INTERRUPT_INFO InterruptConfig)
_Must_inspect_result_ NTSTATUS Disconnect(__in ULONG NotifyFlags)
MdLock * m_SpinLock
Definition: fxinterrupt.hpp:64
BOOLEAN QueueWorkItemForIsr(VOID)
VOID RevokeResources(VOID)
FxInterrupt(__in PFX_DRIVER_GLOBALS FxDriverGlobals)
BOOLEAN m_UseSoftDisconnect
_Must_inspect_result_ NTSTATUS ConnectInternal(VOID)
virtual VOID DeleteObject(VOID)
KIRQL m_OldIrql
Definition: fxinterrupt.hpp:66
NTSTATUS InterruptDisableInvokeCallback(VOID)
VOID SetActiveForWake(__in BOOLEAN ActiveForWake)
WDF_INTERRUPT_POLICY m_Policy
_Must_inspect_result_ NTSTATUS CreateWakeInterruptMachine(VOID)
GROUP_AFFINITY m_Processors
LIST_ENTRY m_PnpList
_Must_inspect_result_ NTSTATUS InitializeInternal(__in FxObject *Parent, __in PWDF_INTERRUPT_CONFIG Configuration)
BOOLEAN TryToAcquireLock(VOID)
BOOLEAN m_AddedToList
VOID ResetInternal(VOID)
struct _KINTERRUPT * m_Interrupt
Definition: fxinterrupt.hpp:59
BOOLEAN m_SetPolicy
BOOLEAN IsActiveForWake(VOID)
FxSystemWorkItem * m_SystemWorkItem
Definition: fxinterrupt.hpp:87
WDF_INTERRUPT_INFO m_InterruptInfo
virtual BOOLEAN Dispose(VOID)
_Must_inspect_result_ NTSTATUS InitializeWorker(__in FxObject *Parent, __in PWDF_INTERRUPT_CONFIG Configuration)
PFN_WDF_INTERRUPT_WORKITEM m_EvtInterruptWorkItem
static MdInterruptSynchronizeRoutineType _InterruptEnableThunk
VOID ReportInactive(_In_ BOOLEAN Internal=FALSE)
BOOLEAN m_Active
_Must_inspect_result_ NTSTATUS ForceDisconnect(VOID)
VOID RevokeResourcesInternal(VOID)
NTSTATUS InterruptEnable(VOID)
BOOLEAN m_CanQueue
VOID MarkPassiveDispose(__in FxObjectLockState State=ObjectLock)
Definition: fxobject.hpp:944
virtual VOID DeleteObject(VOID)
__inline PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxobject.hpp:734
CfxDevice * m_Device
Definition: fxobject.hpp:329
static _Must_inspect_result_ NTSTATUS _GetEffectiveLock(__in FxObject *Object, __in_opt IFxHasCallbacks *Callbacks, __in BOOLEAN AutomaticLocking, __in BOOLEAN PassiveCallbacks, __out FxCallbackLock **CallbackLock, __out_opt FxObject **CallbackLockObject)
Definition: fxobject.cpp:1044
CfxDeviceBase * m_DeviceBase
Definition: fxobject.hpp:328
VOID MarkNoDeleteDDI(__in FxObjectLockState State=ObjectLock)
Definition: fxobject.hpp:1118
VOID DeleteFromFailedCreate(VOID)
Definition: fxobject.cpp:391
VOID MarkDisposeOverride(__in FxObjectLockState State=ObjectLock)
Definition: fxobject.hpp:1101
_Must_inspect_result_ NTSTATUS Commit(__in_opt PWDF_OBJECT_ATTRIBUTES Attributes, __out_opt WDFOBJECT *ObjectHandle, __in_opt FxObject *Parent=NULL, __in BOOLEAN AssignDriverAsDefaultParent=TRUE)
Definition: fxobject.cpp:904
VOID AddInterruptObject(__in FxInterrupt *Interrupt)
Definition: fxpkgpnp.cpp:5928
ULONG m_InterruptObjectCount
Definition: fxpkgpnp.hpp:4308
VOID WakeInterruptCreated(VOID)
Definition: fxpkgpnp.hpp:4074
VOID RemoveInterruptObject(__in FxInterrupt *Interrupt)
Definition: fxpkgpnp.cpp:5965
MdLock * GetLock(VOID)
Definition: fxspinlock.hpp:65
VOID SetInterruptSpinLock(VOID)
Definition: fxspinlock.hpp:73
static _Must_inspect_result_ NTSTATUS _Create(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in PVOID WdmObject, __out FxSystemWorkItem **pObject)
__inline BOOLEAN TryToEnqueue(__in PFN_WDF_SYSTEMWORKITEM CallbackFunc, __in PVOID Parameter)
static _Must_inspect_result_ NTSTATUS _Create(__in PFX_DRIVER_GLOBALS DriverGlobals, __in_opt PWDF_OBJECT_ATTRIBUTES Attributes, __in_opt FxObject *ParentObject, __in BOOLEAN AssignDriverAsDefaultParent, __out WDFWAITLOCK *LockHandle)
Definition: fxwaitlock.cpp:32
static VOID _ProcessEventInner(__inout FxPkgPnp *PkgPnp, __inout FxPostProcessInfo *Info, __in PVOID WorkerContext)
VOID ProcessEvent(__in FxWakeInterruptEvents Event)
CHECK_RETURN_IF_USER_MODE __inline NTSTATUS Initialize(__in EVENT_TYPE Type, __in BOOLEAN InitialState)
Definition: mxeventkm.h:55
MxEvent * GetSelfPointer(VOID)
Definition: mxevent.h:110
MdLock & Get()
Definition: mxlock.h:43
static __inline KIRQL MxAcquireInterruptSpinLock(_Inout_ PKINTERRUPT Interrupt)
Definition: mxgeneralkm.h:767
static __inline VOID MxReleaseInterruptSpinLock(_Inout_ PKINTERRUPT Interrupt, _In_ KIRQL OldIrql)
Definition: mxgeneralkm.h:776
static __inline BOOLEAN MxInsertQueueDpc(__inout PRKDPC Dpc, __in_opt PVOID SystemArgument1, __in_opt PVOID SystemArgument2)
Definition: mxgeneralkm.h:786
static __inline KIRQL MxGetCurrentIrql()
Definition: mxgeneralkm.h:86
CLIPBOARD_GLOBALS Globals
Definition: clipbrd.c:13
#define __in
Definition: dbghelp.h:35
#define __in_opt
Definition: dbghelp.h:38
#define __out
Definition: dbghelp.h:62
#define TRACINGPNP
Definition: dbgtrace.h:67
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
VOID NTAPI KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
Definition: dpc.c:712
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
FX_VERIFY(INTERNAL, CHECK_NOT_NULL(LoaderInterface->pIWudfHost))
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
PFX_DRIVER_GLOBALS pFxDriverGlobals
PFX_DRIVER_GLOBALS fxDriverGlobals
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), Fdo, FX_TYPE_DEVICE,(PVOID *)&pFdo)
FxVerifierDbgBreakPoint(pFxDriverGlobals)
_Must_inspect_result_ __inline BOOLEAN FxIsPassiveLevelInterruptSupported(VOID)
Definition: fxglobals.h:1081
@ WaitSignalBreakUnderDebugger
Definition: fxglobals.h:85
@ WaitSignalBreakUnderVerifier
Definition: fxglobals.h:84
_Must_inspect_result_ __inline BOOLEAN FxIsProcessorGroupSupported(VOID)
Definition: fxglobalskm.h:734
BOOLEAN _SynchronizeExecution(__in MdInterrupt Interrupt, __in MdInterruptSynchronizeRoutine SynchronizeRoutine, __in PVOID SynchronizeContext)
FxInterrupt * pFxInterrupt
@ ObjectDoNotLock
Definition: fxobject.hpp:128
#define ADDREF(_tag)
Definition: fxobject.hpp:49
#define RELEASE(_tag)
Definition: fxobject.hpp:50
FxObject * pObject
@ NotifyResourcesExplicitPowerup
Definition: fxpkgpnp.hpp:211
@ NotifyResourcesNoFlags
Definition: fxpkgpnp.hpp:207
@ NotifyResourcesForceDisconnect
Definition: fxpkgpnp.hpp:210
@ NotifyResourcesNP
Definition: fxpkgpnp.hpp:208
@ NotifyResourcesExplicitPowerDown
Definition: fxpkgpnp.hpp:212
@ NotifyResourcesSurpriseRemoved
Definition: fxpkgpnp.hpp:209
@ NotifyResourcesDisconnectInactive
Definition: fxpkgpnp.hpp:213
@ NotifyResourcesArmedForWake
Definition: fxpkgpnp.hpp:214
pKey DeleteObject()
return &pObject m_DescriptorClone
@ DeviceInfoLineBasedEdgeTriggeredInterrupt
@ DeviceInfoMsi22MultiMessageInterrupt
@ DeviceInfoMsiXOrSingleMsi22Interrupt
@ DeviceInfoLineBasedLevelTriggeredInterrupt
Definition: fxtelemetry.hpp:99
@ DeviceInfoPassiveLevelInterrupt
USHORT WDFTYPE
Definition: fxtypes.h:29
@ FX_TYPE_DEVICE
Definition: fxtypes.h:47
@ FX_TYPE_QUEUE
Definition: fxtypes.h:48
@ FX_TYPE_INTERRUPT
Definition: fxtypes.h:80
@ FX_TYPE_WAIT_LOCK
Definition: fxtypes.h:76
@ FX_TYPE_SPIN_LOCK
Definition: fxtypes.h:77
GLenum const GLfloat * params
Definition: glext.h:5645
GLbitfield flags
Definition: glext.h:7161
GLfloat GLfloat p
Definition: glext.h:8902
GLuint64EXT * result
Definition: glext.h:11304
struct _WDF_INTERRUPT_CONFIG_V1_9 * PWDF_INTERRUPT_CONFIG_V1_9
struct _WDF_INTERRUPT_CONFIG_V1_11_BETA * PWDF_INTERRUPT_CONFIG_V1_11_BETA
struct _WDF_INTERRUPT_CONFIG_V1_11_BETA WDF_INTERRUPT_CONFIG_V1_11_BETA
struct _WDF_INTERRUPT_CONFIG_V1_9 WDF_INTERRUPT_CONFIG_V1_9
_In_ PKSPIN_CONNECT Connect
Definition: ks.h:4536
if(dx< 0)
Definition: linetemp.h:194
#define ASSERT(a)
Definition: mode.c:44
#define CM_RESOURCE_INTERRUPT_LATCHED
Definition: cmtypes.h:144
#define _Must_inspect_result_
Definition: no_sal2.h:62
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
_In_ ULONGLONG _In_ ULONGLONG _In_ BOOLEAN Enable
Definition: ntddpcm.h:142
@ SynchronizationEvent
FxLibraryGlobalsType FxLibraryGlobals
Definition: globals.cpp:95
@ Latched
Definition: miniport.h:81
@ LevelSensitive
Definition: miniport.h:80
#define exit(n)
Definition: config.h:202
#define STATUS_SUCCESS
Definition: shellext.h:65
static void Exit(void)
Definition: sock.c:1330
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
_Must_inspect_result_ NTSTATUS Initialize(__in PFX_DRIVER_GLOBALS DriverGlobals)
Definition: eventqueue.cpp:55
PFN_WDF_INTERRUPT_SYNCHRONIZE Callback
BOOLEAN IsUserModeFramework
Definition: fxglobals.h:825
_Must_inspect_result_ NTSTATUS Init(__inout FxPkgPnp *Pnp, __in PFN_PNP_EVENT_WORKER WorkerRoutine, __in PVOID WorkerContext=NULL)
Definition: eventqueue.cpp:370
VOID WaitForSignal(__in MxEvent *Event, __in PCSTR ReasonForWaiting, __in PVOID Handle, __in ULONG WarningTimeoutInSec, __in ULONG WaitSignalFlags)
Definition: globals.cpp:1705
$USHORT Group
Definition: ntbasedef.h:669
PCM_PARTIAL_RESOURCE_DESCRIPTOR InterruptTranslated
PFN_WDF_INTERRUPT_WORKITEM EvtInterruptWorkItem
PFN_WDF_INTERRUPT_DPC EvtInterruptDpc
PCM_PARTIAL_RESOURCE_DESCRIPTOR InterruptRaw
PFN_WDF_INTERRUPT_ENABLE EvtInterruptEnable
PFN_WDF_INTERRUPT_ISR EvtInterruptIsr
PFN_WDF_INTERRUPT_DISABLE EvtInterruptDisable
PFN_WDF_INTERRUPT_DISABLE EvtInterruptDisable
Definition: wdf19.h:1195
PFN_WDF_INTERRUPT_DPC EvtInterruptDpc
Definition: wdf19.h:1191
WDFSPINLOCK SpinLock
Definition: wdf19.h:1177
WDF_TRI_STATE ShareVector
Definition: wdf19.h:1179
PFN_WDF_INTERRUPT_ENABLE EvtInterruptEnable
Definition: wdf19.h:1193
BOOLEAN AutomaticSerialization
Definition: wdf19.h:1186
PFN_WDF_INTERRUPT_ISR EvtInterruptIsr
Definition: wdf19.h:1189
KAFFINITY TargetProcessorSet
Definition: wdfinterrupt.h:306
KINTERRUPT_MODE Mode
Definition: wdfinterrupt.h:311
Definition: ps.c:97
Definition: dhcpd.h:245
#define GetHandle(h)
Definition: treelist.c:116
int64_t LONGLONG
Definition: typedefs.h:68
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
_Must_inspect_result_ _In_ WDFDMAENABLER _In_ _In_opt_ PWDF_OBJECT_ATTRIBUTES Attributes
@ WdfDevStatePnpInit
Definition: wdfdevice.h:69
EVT_WDF_INTERRUPT_DISABLE * PFN_WDF_INTERRUPT_DISABLE
Definition: wdfinterrupt.h:197
_In_ WDFINTERRUPT _In_ WDF_INTERRUPT_POLICY _In_ WDF_INTERRUPT_PRIORITY _In_ KAFFINITY TargetProcessorSet
Definition: wdfinterrupt.h:658
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_INTERRUPT_CONFIG Configuration
Definition: wdfinterrupt.h:374
@ WdfIrqPriorityUndefined
Definition: wdfinterrupt.h:66
_In_ WDFINTERRUPT _In_ WDF_INTERRUPT_POLICY _In_ WDF_INTERRUPT_PRIORITY Priority
Definition: wdfinterrupt.h:655
enum _WDF_INTERRUPT_PRIORITY WDF_INTERRUPT_PRIORITY
enum _WDF_INTERRUPT_POLICY WDF_INTERRUPT_POLICY
EVT_WDF_INTERRUPT_DPC * PFN_WDF_INTERRUPT_DPC
Definition: wdfinterrupt.h:134
EVT_WDF_INTERRUPT_ISR * PFN_WDF_INTERRUPT_ISR
Definition: wdfinterrupt.h:94
FORCEINLINE VOID WDF_INTERRUPT_INFO_INIT(_Out_ PWDF_INTERRUPT_INFO Info)
Definition: wdfinterrupt.h:325
EVT_WDF_INTERRUPT_WORKITEM * PFN_WDF_INTERRUPT_WORKITEM
Definition: wdfinterrupt.h:153
_In_ WDFINTERRUPT _In_ PFN_WDF_INTERRUPT_SYNCHRONIZE Callback
Definition: wdfinterrupt.h:458
@ WdfIrqPolicyOneCloseProcessor
Definition: wdfinterrupt.h:59
EVT_WDF_INTERRUPT_SYNCHRONIZE * PFN_WDF_INTERRUPT_SYNCHRONIZE
Definition: wdfinterrupt.h:115
EVT_WDF_INTERRUPT_ENABLE * PFN_WDF_INTERRUPT_ENABLE
Definition: wdfinterrupt.h:175
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_INTERRUPT_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFINTERRUPT * Interrupt
Definition: wdfinterrupt.h:379
_In_ WDFINTERRUPT _In_ WDF_INTERRUPT_POLICY Policy
Definition: wdfinterrupt.h:653
FORCEINLINE VOID WDF_OBJECT_ATTRIBUTES_INIT(_Out_ PWDF_OBJECT_ATTRIBUTES Attributes)
Definition: wdfobject.h:147
#define STATUS_WDF_INCOMPATIBLE_EXECUTION_LEVEL
Definition: wdfstatus.h:198
@ WdfTrue
Definition: wdftypes.h:88
@ WdfUseDefault
Definition: wdftypes.h:89
@ WdfFalse
Definition: wdftypes.h:87
enum _WDF_TRI_STATE WDF_TRI_STATE
@ CmResourceShareShared
Definition: cmtypes.h:243
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
#define DO_POWER_PAGABLE
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:687
static int callbacks
Definition: xmllint.c:838