ReactOS  0.4.15-dev-2996-gf777e6b
interruptobject.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  Both kernel and user mode
21 
22 Revision History:
23 
24 
25 
26 
27 
28 --*/
29 
30 #include "pnppriv.hpp"
31 
32 // Tracing support
33 extern "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 //
53 typedef 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 //
91 typedef struct _WDF_INTERRUPT_CONFIG_V1_11_BETA {
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 
149  m_Interrupt = NULL;
150 
152 
155 
157 
161 
163  m_WaitLock = NULL;
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 
189  m_CanQueue = FALSE;
191 #endif
192 
195 
197 
199  m_Connected = FALSE;
201  m_Enabled = FALSE;
203 
205 
206  // This field is init later on.
208 
211 
212  Reset();
213 
214  // This is set up by Initialize
215  m_SpinLock = NULL;
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  //
229  m_SetPolicy = FALSE;
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 
266 NTSTATUS
268  VOID
269  )
270 /*++
271 
272 Routine Description:
273  This routine is used to create a state machine that
274  is used to manage a wake capable interrupt machine
275 
276 Arguments:
277 
278 Return 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!.",
297  m_Device, 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!.",
307  m_Device, 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!.",
321  m_Device, 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 
337 exit:
338  if (!NT_SUCCESS(status)) {
339  if (NULL != fxWakeInterruptMachine) {
340  delete fxWakeInterruptMachine;
341  }
342  }
343  return status;
344 }
345 
346 VOID
348  VOID
349 /*++
350 
351 Routine Description:
352  This routine is called by the interrupt wake machine to invoke
353  the Evt for the ISR
354 
355 Arguments:
356 
357 Return 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 
378 BOOLEAN
380  VOID
381  )
382 /*++
383 
384 Routine 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 
390 Arguments:
391 
392 Return 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(),
410 
411  //
412  // State machine stores the return value of the callback in the
413  // m_Claimed member variable
414  //
416 }
417 
418 
420 NTSTATUS
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 
482 NTSTATUS
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  //
516  m_Device = Device;
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,
563  FxResourceCm,
564  m_DescriptorClone))->m_Descriptor;
565 
566  cmDescTrans = &(CONTAINING_RECORD(Configuration->InterruptTranslated,
567  FxResourceCm,
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 
584 NTSTATUS
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) {
734  ASSERT(NULL == m_SpinLock);
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  //
787  if (m_EvtInterruptWorkItem != NULL ||
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 
813 VOID
815  VOID
816  )
817 /*++
818 
819 Routine 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 
824 Arguments:
825  None
826 
827 Return 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  //
850  ResetInternal();
851 }
852 
853 //
854 // This is an API call from the device driver to delete this INTERRUPT.
855 //
856 VOID
858  VOID
859  )
860 {
861  if (m_AddedToList) {
862  //
863  // Pop this off of PnP's list of interrupts.
864  //
866  }
867 
868  if (m_CmTranslatedResource != NULL) {
869  //
870  // This can happen if driver explicitly deletes the interrupt in its
871  // release hardware callback.
872  //
873  RevokeResources();
874  }
875 
877  delete m_WakeInterruptMachine;
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 //
890 VOID
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 //
914 BOOLEAN
916  VOID
917  )
918 {
919  // MarkPassiveDispose() in Initialize ensures this
921 
922  FlushAndRundown();
923 
924  return TRUE;
925 }
926 
927 VOID
931  )
932 /*++
933 
934 Routine 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 
939 Arguments:
940 
941  CmDescRaw - A CmResourceDescriptor that describes raw interrupt resources
942 
943  CmDescTrans - A CmResourceDescriptor that describes translated interrupt
944  resources
945 
946 Return 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;
988  CmDescTrans->Flags & CM_RESOURCE_INTERRUPT_LATCHED ? Latched : LevelSensitive;
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  //
1002  m_InterruptInfo.MessageSignaled = _IsMessageInterrupt(CmDescTrans->Flags);
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 
1078 VOID
1080  VOID
1081  )
1082 /*++
1083 
1084 Routine Description:
1085 
1086  This function tells an interrupt object that it no longer owns any resources.
1087 
1088 Arguments:
1089 
1090  none
1091 
1092 Return 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 
1125 VOID
1130  )
1131 /*++
1132 
1133 Routine Description:
1134 
1135  This function fills in the policy member variables. These values will be
1136  used in IRP_MN_FILTER_RESOURCE_REQUIREMENTS.
1137 
1138 Arguments:
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 
1147 Return 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;
1168  m_Priority = Priority;
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 
1188 NTSTATUS
1190  __in ULONG NotifyFlags
1191  )
1192 /*++
1193 
1194 Routine 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 
1201 Arguments:
1202  NotifyFlags - combination of values from the enum NotifyResourcesFlags
1203 
1204 Return Value:
1205 
1206  NTSTATUS
1207 
1208 --*/
1209 {
1211  NTSTATUS status;
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  //
1230  if (IsSoftDisconnectCapable() &&
1231  (NotifyFlags & NotifyResourcesExplicitPowerup)){
1232 
1233  ReportActive(TRUE);
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 
1264  ASSERT(m_Interrupt == NULL);
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  //
1271  status = ConnectInternal();
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 {
1314  ASSERT(m_Interrupt != NULL);
1315  }
1316 
1317 Enable:
1318 
1319  //
1320  // Enable the interrupt at the hardware.
1321  //
1322  status = InterruptEnable();
1323  if (!NT_SUCCESS(status)) {
1326  "EvtInterruptEnable WDFDEVICE %p, WDFINTERRUPT %p, PKINTERRUPT %p "
1327  "returned %!STATUS!", m_Device->GetHandle(), GetHandle(),
1328  m_Interrupt, status);
1329 
1330  return status;
1331  }
1332 
1333  m_Enabled = TRUE;
1334 
1335  return status;
1336 }
1337 
1339 NTSTATUS
1341  __in ULONG NotifyFlags
1342  )
1343 /*++
1344 
1345 Routine 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 
1351 Arguments:
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 
1356 Return 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) &&
1398  (IsSoftDisconnectCapable() == FALSE) &&
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  //
1406  ASSERT(NotifyFlags & NotifyResourcesForceDisconnect);
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  //
1416  ASSERT(m_Enabled == FALSE);
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!",
1466  m_Device->GetHandle(),
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  //
1508  FlushQueuedDpcs();
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  //
1523  if (IsSoftDisconnectCapable() &&
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 
1546 Disconnect:
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 
1561  m_Connected = FALSE;
1562 
1563 #if FX_IS_KERNEL_MODE
1564  m_Active = FALSE;
1565 #endif
1566 
1567 Exit:
1569 
1570  return finalStatus;
1571 }
1572 
1573 
1575 NTSTATUS
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 
1609 NTSTATUS
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 //
1645 VOID
1647 {
1648  FxObject* pObject;
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  //
1661  FlushQueuedDpcs();
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 //
1687 NTSTATUS
1689  VOID
1690  )
1691 {
1692  NTSTATUS status;
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 
1716 BOOLEAN
1718  __in PVOID SyncContext
1719  )
1720 {
1722 
1723  p = (FxInterruptEnableParameters*) SyncContext;
1724 
1725  p->ReturnVal = p->Interrupt->InterruptEnableInvokeCallback();
1726 
1727  return TRUE;
1728 }
1729 
1730 NTSTATUS
1732  VOID
1733  )
1734 {
1736 
1737  params.Interrupt = this;
1738  params.ReturnVal = STATUS_SUCCESS;
1739 
1740  if (m_EvtInterruptEnable) {
1742  }
1743 
1744  return params.ReturnVal;
1745 }
1746 
1747 //
1748 // Disable interrupts
1749 //
1750 NTSTATUS
1752  VOID
1753  )
1754 {
1755  NTSTATUS status;
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 
1780 BOOLEAN
1782  __in PVOID SyncContext
1783  )
1784 {
1786 
1787  p = (FxInterruptDisableParameters*) SyncContext;
1788 
1789  p->ReturnVal = p->Interrupt->InterruptDisableInvokeCallback();
1790 
1791  return TRUE;
1792 }
1793 
1794 NTSTATUS
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 
1811 BOOLEAN
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 
1848 VOID
1851  )
1852 /*++
1853 
1854 Routine Description:
1855  Thunk used to invoke EvtInterruptWorkItem at passive-level
1856 
1857 --*/
1858 {
1860  ((FxInterrupt*)DeferredContext)->WorkItemHandler();
1861 }
1862 
1863 VOID
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 
1876 VOID
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  //
1898  ASSERT(m_WaitLock != NULL);
1899  m_WaitLock->AcquireLock(GetDriverGlobals(), NULL);
1900  }
1901 }
1902 #pragma prefast(pop)
1903 
1904 BOOLEAN
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 
1917  ASSERT(m_WaitLock != NULL);
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 
1931 VOID
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  //
1954  ASSERT(m_WaitLock != NULL);
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 
1961 BOOLEAN
1963  __in PVOID SyncContext
1964  )
1965 {
1967  BOOLEAN result;
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 
1989 BOOLEAN
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 
FxWaitLock * m_WaitLock
Definition: fxinterrupt.hpp:77
NTSTATUS InterruptEnableInvokeCallback(VOID)
CfxDevice * m_Device
Definition: fxobject.hpp:329
_Must_inspect_result_ NTSTATUS Initialize(__in CfxDevice *Device, __in FxObject *Parent, __in PWDF_INTERRUPT_CONFIG Configuration)
#define DO_POWER_PAGABLE
virtual VOID DeleteObject(VOID)
FxObject * pObject
__inline BOOLEAN IsPassiveConnect(VOID)
static MdDeferredRoutineType _InterruptDpcThunk
static EVT_SYSTEMWORKITEM _InterruptWorkItemCallback
static MdInterruptServiceRoutineType _InterruptThunk
virtual BOOLEAN Dispose(VOID)
static _Must_inspect_result_ NTSTATUS _Create(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in PVOID WdmObject, __out FxSystemWorkItem **pObject)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Must_inspect_result_ NTSTATUS ConnectInternal(VOID)
VOID AssignResources(__in PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescRaw, __in PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescTrans)
PFN_WDF_INTERRUPT_ISR EvtInterruptIsr
BOOLEAN m_AddedToList
PFN_WDF_INTERRUPT_DISABLE EvtInterruptDisable
Definition: wdf19.h:1195
MdDeviceObject __inline GetDeviceObject(VOID)
Definition: fxdevice.hpp:174
_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
GLuint64EXT * result
Definition: glext.h:11304
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
WDF_TRI_STATE ShareVector
Definition: wdf19.h:1179
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
VOID InvokeWakeInterruptEvtIsr(VOID)
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_INTERRUPT_CONFIG Configuration
Definition: wdfinterrupt.h:372
VOID WakeInterruptCreated(VOID)
Definition: fxpkgpnp.hpp:4074
VOID RevokeResourcesInternal(VOID)
#define __in_opt
Definition: dbghelp.h:38
#define TRUE
Definition: types.h:120
WDFDEVICE __inline GetHandle(VOID)
Definition: fxdevice.hpp:237
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
enum _WDF_TRI_STATE WDF_TRI_STATE
static MdInterruptSynchronizeRoutineType _InterruptMarkDisconnecting
VOID FlushQueuedWorkitem(VOID)
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_INTERRUPT_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFINTERRUPT * Interrupt
Definition: wdfinterrupt.h:372
VOID Reset(VOID)
BOOLEAN m_IsEdgeTriggeredNonMsiInterrupt
BOOLEAN m_CreatedInPrepareHardware
LONG NTSTATUS
Definition: precomp.h:26
VOID MarkPassiveDispose(__in FxObjectLockState State=ObjectLock)
Definition: fxobject.hpp:944
_In_ ULONGLONG _In_ ULONGLONG _In_ BOOLEAN Enable
Definition: ntddpcm.h:140
PFN_WDF_INTERRUPT_DISABLE m_EvtInterruptDisable
BOOLEAN m_DisposeWaitLock
Definition: fxinterrupt.hpp:98
static __inline KIRQL MxAcquireInterruptSpinLock(_Inout_ PKINTERRUPT Interrupt)
Definition: mxgeneralkm.h:767
RD_INTERRUPT_CONTEXT m_RdInterruptContext
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
BOOLEAN m_CanQueue
ULONG DbgWaitForWakeInterruptIsrTimeoutInSec
Definition: fxglobals.h:534
BOOLEAN IsUserModeFramework
Definition: fxglobals.h:825
NTSTATUS InterruptEnable(VOID)
WDF_TRI_STATE m_ShareVector
Definition: fxinterrupt.hpp:54
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), Fdo, FX_TYPE_DEVICE,(PVOID *)&pFdo)
FxSystemWorkItem * m_SystemWorkItem
Definition: fxinterrupt.hpp:87
WDFSPINLOCK SpinLock
Definition: wdf19.h:1177
Definition: dhcpd.h:245
virtual VOID SetDeviceTelemetryInfoFlags(_In_ FxDeviceInfoFlags Flag)
Definition: fxdevice.hpp:1807
VOID WaitForSignal(__in MxEvent *Event, __in PCSTR ReasonForWaiting, __in PVOID Handle, __in ULONG WarningTimeoutInSec, __in ULONG WaitSignalFlags)
Definition: globals.cpp:1705
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
#define RELEASE(_tag)
Definition: fxobject.hpp:50
if(dx==0 &&dy==0)
Definition: linetemp.h:174
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
_Must_inspect_result_ NTSTATUS Init(__inout FxPkgPnp *Pnp, __in PFN_PNP_EVENT_WORKER WorkerRoutine, __in PVOID WorkerContext=NULL)
Definition: eventqueue.cpp:370
_Must_inspect_result_ NTSTATUS Disconnect(__in ULONG NotifyFlags)
VOID AssignResourcesInternal(__in PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescRaw, __in PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescTrans, __in PWDF_INTERRUPT_INFO InterruptConfig)
BOOLEAN m_Disconnecting
_Must_inspect_result_ NTSTATUS Connect(__in ULONG NotifyFlags)
MxEvent * GetSelfPointer(VOID)
Definition: mxevent.h:110
PCM_PARTIAL_RESOURCE_DESCRIPTOR m_CmTranslatedResource
_Must_inspect_result_ NTSTATUS ForceDisconnect(VOID)
VOID FlushAndRundownInternal(VOID)
__inline BOOLEAN TryToEnqueue(__in PFN_WDF_SYSTEMWORKITEM CallbackFunc, __in PVOID Parameter)
static FxDeviceBase * _SearchForDevice(__in FxObject *Object, __out_opt IFxHasCallbacks **Callbacks)
VOID RevokeResources(VOID)
UCHAR KIRQL
Definition: env_spec_w32.h:591
PFN_WDF_INTERRUPT_ENABLE EvtInterruptEnable
Definition: wdf19.h:1193
CLIPBOARD_GLOBALS Globals
Definition: clipbrd.c:13
CHECK_RETURN_IF_USER_MODE __inline NTSTATUS Initialize(__in EVENT_TYPE Type, __in BOOLEAN InitialState)
Definition: mxeventkm.h:55
PFN_WDF_INTERRUPT_ENABLE EvtInterruptEnable
_Must_inspect_result_ NTSTATUS Initialize(__in PFX_DRIVER_GLOBALS DriverGlobals)
Definition: eventqueue.cpp:55
#define FALSE
Definition: types.h:117
VOID OnPostReleaseHardware(VOID)
GLenum const GLfloat * params
Definition: glext.h:5645
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
BOOLEAN m_ForceDisconnected
KAFFINITY TargetProcessorSet
Definition: wdfinterrupt.h:306
EVT_WDF_INTERRUPT_SYNCHRONIZE * PFN_WDF_INTERRUPT_SYNCHRONIZE
Definition: wdfinterrupt.h:115
struct _WDF_INTERRUPT_CONFIG_V1_9 WDF_INTERRUPT_CONFIG_V1_9
MdLock & Get()
Definition: mxlock.h:43
volatile KIRQL m_SynchronizeIrql
Definition: fxinterrupt.hpp:67
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
#define ADDREF(_tag)
Definition: fxobject.hpp:49
static MdInterruptSynchronizeRoutineType _InterruptSynchronizeThunk
WDF_INTERRUPT_POLICY m_Policy
VOID ReportActive(_In_ BOOLEAN Internal=FALSE)
VOID MarkDisposeOverride(__in FxObjectLockState State=ObjectLock)
Definition: fxobject.hpp:1101
#define STATUS_WDF_INCOMPATIBLE_EXECUTION_LEVEL
Definition: wdfstatus.h:198
#define __out
Definition: dbghelp.h:62
VOID DisconnectInternal(VOID)
PFN_WDF_INTERRUPT_WORKITEM EvtInterruptWorkItem
struct _WDF_INTERRUPT_CONFIG_V1_11_BETA WDF_INTERRUPT_CONFIG_V1_11_BETA
enum _WDF_INTERRUPT_POLICY WDF_INTERRUPT_POLICY
unsigned char BOOLEAN
struct _KINTERRUPT * m_Interrupt
Definition: fxinterrupt.hpp:59
BOOLEAN IsSoftDisconnectCapable(VOID)
BOOLEAN m_Enabled
BOOLEAN _SynchronizeExecution(__in MdInterrupt Interrupt, __in MdInterruptSynchronizeRoutine SynchronizeRoutine, __in PVOID SynchronizeContext)
PWDF_INTERRUPT_INFO GetInfo(VOID)
WDF_INTERRUPT_PRIORITY m_Priority
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
BOOLEAN m_FloatingSave
VOID ProcessEvent(__in FxWakeInterruptEvents Event)
PCM_PARTIAL_RESOURCE_DESCRIPTOR InterruptTranslated
BOOLEAN IsLevelTriggered(__in ULONG Flags)
int64_t LONGLONG
Definition: typedefs.h:68
static MdInterruptSynchronizeRoutineType _InterruptEnableThunk
KINTERRUPT_MODE Mode
Definition: wdfinterrupt.h:311
VOID FlushQueuedDpcs(VOID)
PFX_DRIVER_GLOBALS pFxDriverGlobals
BOOLEAN m_PassiveHandlingByRedirector
FX_VERIFY(INTERNAL, CHECK_NOT_NULL(LoaderInterface->pIWudfHost))
#define ASSERT(a)
Definition: mode.c:44
NTSTATUS InterruptDisable(VOID)
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
EVT_WDF_INTERRUPT_WORKITEM * PFN_WDF_INTERRUPT_WORKITEM
Definition: wdfinterrupt.h:153
FxInterrupt * pFxInterrupt
enum _WDF_INTERRUPT_PRIORITY WDF_INTERRUPT_PRIORITY
uint64_t ULONGLONG
Definition: typedefs.h:67
static void Exit(void)
Definition: sock.c:1331
struct _WDF_INTERRUPT_CONFIG_V1_11_BETA * PWDF_INTERRUPT_CONFIG_V1_11_BETA
_In_ WDFINTERRUPT _In_ WDF_INTERRUPT_POLICY _In_ WDF_INTERRUPT_PRIORITY _In_ KAFFINITY TargetProcessorSet
Definition: wdfinterrupt.h:651
PFN_WDF_INTERRUPT_DISABLE EvtInterruptDisable
ULONG __inline GetDeviceObjectFlags(VOID)
Definition: fxdevice.hpp:192
BOOLEAN m_PassiveHandling
LIST_ENTRY m_PnpList
VOID FlushAndRundown(VOID)
VOID SetPolicyInternal(__in WDF_INTERRUPT_POLICY Policy, __in WDF_INTERRUPT_PRIORITY Priority, __in PGROUP_AFFINITY TargetProcessorSet)
PFN_WDF_INTERRUPT_WORKITEM m_EvtInterruptWorkItem
EVT_WDF_INTERRUPT_ISR * PFN_WDF_INTERRUPT_ISR
Definition: wdfinterrupt.h:94
static __inline KIRQL MxGetCurrentIrql()
Definition: mxgeneralkm.h:86
ULONG m_InterruptObjectCount
Definition: fxpkgpnp.hpp:4308
BOOLEAN m_Active
PFN_WDF_INTERRUPT_ISR EvtInterruptIsr
Definition: wdf19.h:1189
EVT_WDF_INTERRUPT_ENABLE * PFN_WDF_INTERRUPT_ENABLE
Definition: wdfinterrupt.h:175
_Must_inspect_result_ __inline BOOLEAN FxIsProcessorGroupSupported(VOID)
Definition: fxglobalskm.h:734
BOOLEAN m_UseSoftDisconnect
GLbitfield flags
Definition: glext.h:7161
BOOLEAN m_SetPolicy
BOOLEAN m_Connected
_In_ WDFINTERRUPT _In_ WDF_INTERRUPT_POLICY _In_ WDF_INTERRUPT_PRIORITY Priority
Definition: wdfinterrupt.h:651
PFN_WDF_INTERRUPT_DPC EvtInterruptDpc
Definition: wdf19.h:1191
VOID ReleaseLock(VOID)
VOID SetPolicy(__in WDF_INTERRUPT_POLICY Policy, __in WDF_INTERRUPT_PRIORITY Priority, __in PGROUP_AFFINITY TargetProcessorSet)
__inline WDF_DEVICE_PNP_STATE GetDevicePnpState()
Definition: fxdevice.hpp:1149
MdLock * m_SpinLock
Definition: fxinterrupt.hpp:64
BOOLEAN Synchronize(__in PFN_WDF_INTERRUPT_SYNCHRONIZE Callback, __in WDFCONTEXT Context)
_Must_inspect_result_ NTSTATUS InitializeWorker(__in FxObject *Parent, __in PWDF_INTERRUPT_CONFIG Configuration)
CfxDeviceBase * m_DeviceBase
Definition: fxobject.hpp:328
struct _WDF_INTERRUPT_CONFIG_V1_9 * PWDF_INTERRUPT_CONFIG_V1_9
FxCallbackLock * m_CallbackLock
Definition: fxinterrupt.hpp:93
VOID MarkNoDeleteDDI(__in FxObjectLockState State=ObjectLock)
Definition: fxobject.hpp:1118
__inline BOOLEAN IsWakeCapable(VOID)
static __inline VOID MxReleaseInterruptSpinLock(_Inout_ PKINTERRUPT Interrupt, _In_ KIRQL OldIrql)
Definition: mxgeneralkm.h:776
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define _Must_inspect_result_
Definition: ms_sal.h:558
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
FxLibraryGlobalsType FxLibraryGlobals
Definition: globals.cpp:95
KIRQL m_OldIrql
Definition: fxinterrupt.hpp:66
PFN_WDF_INTERRUPT_ISR m_EvtInterruptIsr
PFN_WDF_INTERRUPT_ENABLE m_EvtInterruptEnable
FxPkgPnp * m_PkgPnp
Definition: fxdevice.hpp:670
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
_In_ WDFINTERRUPT _In_ PFN_WDF_INTERRUPT_SYNCHRONIZE Callback
Definition: wdfinterrupt.h:456
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
FORCEINLINE VOID WDF_OBJECT_ATTRIBUTES_INIT(_Out_ PWDF_OBJECT_ATTRIBUTES Attributes)
Definition: wdfobject.h:147
#define TRACINGPNP
Definition: dbgtrace.h:67
__inline PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxobject.hpp:734
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
PFX_DRIVER_GLOBALS fxDriverGlobals
USHORT WDFTYPE
Definition: fxtypes.h:29
static MdInterruptSynchronizeRoutineType _InterruptDisableThunk
static VOID _ProcessEventInner(__inout FxPkgPnp *PkgPnp, __inout FxPostProcessInfo *Info, __in PVOID WorkerContext)
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
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
VOID ResetInternal(VOID)
#define NULL
Definition: types.h:112
_Must_inspect_result_ NTSTATUS ForceReconnect(VOID)
EVT_WDF_INTERRUPT_DISABLE * PFN_WDF_INTERRUPT_DISABLE
Definition: wdfinterrupt.h:197
BOOLEAN TryToAcquireLock(VOID)
_Must_inspect_result_ NTSTATUS InitializeInternal(__in FxObject *Parent, __in PWDF_INTERRUPT_CONFIG Configuration)
WDFINTERRUPT GetHandle(VOID)
BOOLEAN QueueWorkItemForIsr(VOID)
_Must_inspect_result_ NTSTATUS CreateWakeInterruptMachine(VOID)
FxInterrupt(__in PFX_DRIVER_GLOBALS FxDriverGlobals)
VOID DeleteFromFailedCreate(VOID)
Definition: fxobject.cpp:391
PFN_WDF_INTERRUPT_SYNCHRONIZE Callback
MxLock m_BuiltInSpinLock
Definition: fxinterrupt.hpp:72
struct tagContext Context
Definition: acpixf.h:1034
FxInterruptWaitblock * m_InterruptWaitblock
VOID AddInterruptObject(__in FxInterrupt *Interrupt)
Definition: fxpkgpnp.cpp:5928
#define CM_RESOURCE_INTERRUPT_LATCHED
Definition: cmtypes.h:144
_Must_inspect_result_ __inline BOOLEAN FxIsPassiveLevelInterruptSupported(VOID)
Definition: fxglobals.h:1081
return &pObject m_DescriptorClone
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
BOOLEAN WakeInterruptIsr(VOID)
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)
PFN_WDF_INTERRUPT_DPC m_EvtInterruptDpc
GROUP_AFFINITY m_Processors
virtual VOID DeleteObject(VOID)
PFN_WDF_INTERRUPT_DPC EvtInterruptDpc
#define STATUS_SUCCESS
Definition: shellext.h:65
virtual ~FxInterrupt(VOID)
void exit(int exitcode)
Definition: _exit.c:33
FxWakeInterruptMachine * m_WakeInterruptMachine
$USHORT Group
Definition: ntbasedef.h:661
GLfloat GLfloat p
Definition: glext.h:8902
VOID NTAPI KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
Definition: dpc.c:712
VOID ReportInactive(_In_ BOOLEAN Internal=FALSE)
_In_ WDFINTERRUPT _In_ WDF_INTERRUPT_POLICY Policy
Definition: wdfinterrupt.h:651
static int callbacks
Definition: xmllint.c:873
VOID SetActiveForWake(__in BOOLEAN ActiveForWake)
VOID AcquireLock(VOID)
#define __in
Definition: dbghelp.h:35
static BOOLEAN _IsMessageInterrupt(__in USHORT ResourceFlags)
BOOLEAN AutomaticSerialization
Definition: wdf19.h:1186
NTSTATUS InterruptDisableInvokeCallback(VOID)
static SERVICE_STATUS status
Definition: service.c:31
PCM_PARTIAL_RESOURCE_DESCRIPTOR InterruptRaw
BOOLEAN IsActiveForWake(VOID)
struct _KINTERRUPT * m_InterruptCaptured
VOID RemoveInterruptObject(__in FxInterrupt *Interrupt)
Definition: fxpkgpnp.cpp:5965
static __inline BOOLEAN MxInsertQueueDpc(__inout PRKDPC Dpc, __in_opt PVOID SystemArgument1, __in_opt PVOID SystemArgument2)
Definition: mxgeneralkm.h:786
WDF_INTERRUPT_INFO m_InterruptInfo
FxVerifierDbgBreakPoint(pFxDriverGlobals)
EVT_WDF_INTERRUPT_DPC * PFN_WDF_INTERRUPT_DPC
Definition: wdfinterrupt.h:134
_Must_inspect_result_ _In_ WDFDMAENABLER _In_ _In_opt_ PWDF_OBJECT_ATTRIBUTES Attributes
struct _KINTERRUPT * GetInterruptPtr(VOID)
FORCEINLINE VOID WDF_INTERRUPT_INFO_INIT(_Out_ PWDF_INTERRUPT_INFO Info)
Definition: wdfinterrupt.h:325
Definition: ps.c:97
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:675