18a978a17SVictor Perevertkin //
28a978a17SVictor Perevertkin //    Copyright (C) Microsoft.  All rights reserved.
38a978a17SVictor Perevertkin //
4*1f377076SVictor Perevertkin #include "../pnppriv.hpp"
58a978a17SVictor Perevertkin 
68a978a17SVictor Perevertkin #include <initguid.h>
78a978a17SVictor Perevertkin #include <wdmguid.h>
88a978a17SVictor Perevertkin 
98a978a17SVictor Perevertkin extern "C" {
108a978a17SVictor Perevertkin #if defined(EVENT_TRACING)
118a978a17SVictor Perevertkin #include "FxPkgPnpKM.tmh"
128a978a17SVictor Perevertkin #endif
138a978a17SVictor Perevertkin }
148a978a17SVictor Perevertkin 
158a978a17SVictor Perevertkin NTSTATUS
FilterResourceRequirements(__in IO_RESOURCE_REQUIREMENTS_LIST ** IoList)168a978a17SVictor Perevertkin FxPkgPnp::FilterResourceRequirements(
178a978a17SVictor Perevertkin     __in IO_RESOURCE_REQUIREMENTS_LIST **IoList
188a978a17SVictor Perevertkin     )
198a978a17SVictor Perevertkin /*++
208a978a17SVictor Perevertkin 
218a978a17SVictor Perevertkin Routine Description:
228a978a17SVictor Perevertkin 
238a978a17SVictor Perevertkin     This routine traverses one or more alternate _IO_RESOURCE_LISTs in the input
248a978a17SVictor Perevertkin     IO_RESOURCE_REQUIREMENTS_LIST looking for interrupt descriptor and applies
258a978a17SVictor Perevertkin     the policy set by driver in the interrupt object to the resource descriptor.
268a978a17SVictor Perevertkin 
278a978a17SVictor Perevertkin     LBI - Line based interrupt
288a978a17SVictor Perevertkin     MSI - Message Signalled interrupt
298a978a17SVictor Perevertkin 
308a978a17SVictor Perevertkin     Here are the assumptions made about the order of descriptors.
318a978a17SVictor Perevertkin 
328a978a17SVictor Perevertkin     - An IoRequirementList can have one or more alternate IoResourceList
338a978a17SVictor Perevertkin     - Each IoResourceList can have one or more resource descriptors
348a978a17SVictor Perevertkin     - A descriptor can be default (unique), preferred, or alternate descriptors
358a978a17SVictor Perevertkin     - A preferred descriptor can have zero or more alternate descriptors (P, A, A, A..)
368a978a17SVictor Perevertkin     - In an IoResourceList, there can be one or more LBI descriptors
378a978a17SVictor Perevertkin       (non-pci devices)(P,A,P,A)
388a978a17SVictor Perevertkin     - In an IoResourceList, there can be only one preferred MSI 2.2
398a978a17SVictor Perevertkin       (single or multi message) descriptor
408a978a17SVictor Perevertkin     - In an IoResourceList, there cannot be MSI2.2 and MSI-X descriptors
418a978a17SVictor Perevertkin     - In an IoResourceList, there can be one or more MSI-X descriptor
428a978a17SVictor Perevertkin     - An alternate descriptor cannot be a very first descriptor in the list
438a978a17SVictor Perevertkin 
448a978a17SVictor Perevertkin 
458a978a17SVictor Perevertkin     Now with that assumption, this routines parses the list looking for interrupt
468a978a17SVictor Perevertkin     descriptor.
478a978a17SVictor Perevertkin 
488a978a17SVictor Perevertkin     - If it finds a LBI, it starts with the very first interrupt object and applies
498a978a17SVictor Perevertkin       the policy set by the driver to the resource descriptor.
508a978a17SVictor Perevertkin     - If it's finds an MSI2.2 then it starts with the first interrupt object and applies
518a978a17SVictor Perevertkin       the policy. If the MSI2.2 is a multi-message one then it loops thru looking for
528a978a17SVictor Perevertkin       as many interrupt object as there are messages. It doesn't fail the IRP, if the
538a978a17SVictor Perevertkin       interrupt objects are less than the messages.
548a978a17SVictor Perevertkin     - If there is an alternate descriptor then it applies the same policy from the
558a978a17SVictor Perevertkin       interrupt object that it used for the preceding preferred descriptor.
568a978a17SVictor Perevertkin     - Framework always uses FULLY_SPECIFIED connection type for both LBI and MSI
578a978a17SVictor Perevertkin       interrupts including MSI-X
588a978a17SVictor Perevertkin     - Framework will apply the policy on the descriptor set by the driver only
598a978a17SVictor Perevertkin       if the policy is already not included in the resource descriptor. This is
608a978a17SVictor Perevertkin       to allow the policy set in the registry to take precedence over the hard
618a978a17SVictor Perevertkin       coded driver policy.
628a978a17SVictor Perevertkin     - If the driver registers filter resource requirement and applies the policy
638a978a17SVictor Perevertkin       on its own (by escaping to WDM) then framework doesn't override that.
648a978a17SVictor Perevertkin 
658a978a17SVictor Perevertkin Arguments:
668a978a17SVictor Perevertkin 
678a978a17SVictor Perevertkin     IoList - Pointer to the list part of an IRP_MN_FILTER_RESOURCE_REQUIREMENTS.
688a978a17SVictor Perevertkin 
698a978a17SVictor Perevertkin Return Value:
708a978a17SVictor Perevertkin 
718a978a17SVictor Perevertkin     NTSTATUS
728a978a17SVictor Perevertkin 
738a978a17SVictor Perevertkin --*/
748a978a17SVictor Perevertkin {
758a978a17SVictor Perevertkin     ULONG altResListIndex;
768a978a17SVictor Perevertkin     PIO_RESOURCE_REQUIREMENTS_LIST pIoRequirementList;
778a978a17SVictor Perevertkin     PIO_RESOURCE_LIST pIoResList;
788a978a17SVictor Perevertkin 
798a978a17SVictor Perevertkin     pIoRequirementList = *IoList;
808a978a17SVictor Perevertkin 
818a978a17SVictor Perevertkin     if (pIoRequirementList == NULL) {
828a978a17SVictor Perevertkin         return STATUS_SUCCESS;
838a978a17SVictor Perevertkin     }
848a978a17SVictor Perevertkin 
858a978a17SVictor Perevertkin     if (IsListEmpty(&m_InterruptListHead)) {
868a978a17SVictor Perevertkin         //
878a978a17SVictor Perevertkin         // No interrupt objects created to filter resource requirements.
888a978a17SVictor Perevertkin         //
898a978a17SVictor Perevertkin         return STATUS_SUCCESS;
908a978a17SVictor Perevertkin     }
918a978a17SVictor Perevertkin 
928a978a17SVictor Perevertkin     pIoResList = pIoRequirementList->List;
938a978a17SVictor Perevertkin 
948a978a17SVictor Perevertkin     //
958a978a17SVictor Perevertkin     // Parse one or more alternative resource lists.
968a978a17SVictor Perevertkin     //
978a978a17SVictor Perevertkin     for (altResListIndex = 0;
988a978a17SVictor Perevertkin          altResListIndex < pIoRequirementList->AlternativeLists;
998a978a17SVictor Perevertkin          altResListIndex++) {
1008a978a17SVictor Perevertkin         PLIST_ENTRY pIntListEntryForMSI;
1018a978a17SVictor Perevertkin         PLIST_ENTRY pIntListEntryForLBI;
1028a978a17SVictor Perevertkin         BOOLEAN multiMessageMSI22Found;
1038a978a17SVictor Perevertkin         BOOLEAN previousDescMSI;
1048a978a17SVictor Perevertkin         ULONG descIndex;
1058a978a17SVictor Perevertkin 
1068a978a17SVictor Perevertkin         multiMessageMSI22Found = FALSE;
1078a978a17SVictor Perevertkin         previousDescMSI = FALSE;
1088a978a17SVictor Perevertkin 
1098a978a17SVictor Perevertkin         pIntListEntryForMSI = &m_InterruptListHead;
1108a978a17SVictor Perevertkin         pIntListEntryForLBI = &m_InterruptListHead;
1118a978a17SVictor Perevertkin 
1128a978a17SVictor Perevertkin         //
1138a978a17SVictor Perevertkin         // Traverse each _IO_RESOURCE_LISTs looking for interrupt descriptors
1148a978a17SVictor Perevertkin         // and call FilterResourceRequirements method so that it can apply
1158a978a17SVictor Perevertkin         // policy set on the interrupt object into the resource-descriptor.
1168a978a17SVictor Perevertkin         //
1178a978a17SVictor Perevertkin 
1188a978a17SVictor Perevertkin         for (descIndex = 0; descIndex < pIoResList->Count; descIndex++) {
1198a978a17SVictor Perevertkin             ULONG messageCount;
1208a978a17SVictor Perevertkin             PIO_RESOURCE_DESCRIPTOR pIoDesc;
1218a978a17SVictor Perevertkin             FxInterrupt* pInterruptInstance;
1228a978a17SVictor Perevertkin 
1238a978a17SVictor Perevertkin             pIoDesc = &pIoResList->Descriptors[descIndex];
1248a978a17SVictor Perevertkin 
1258a978a17SVictor Perevertkin             switch (pIoDesc->Type) {
1268a978a17SVictor Perevertkin             case CmResourceTypeInterrupt:
1278a978a17SVictor Perevertkin 
1288a978a17SVictor Perevertkin                 if (FxInterrupt::_IsMessageInterrupt(pIoDesc->Flags)) {
1298a978a17SVictor Perevertkin 
1308a978a17SVictor Perevertkin                     previousDescMSI = TRUE;
1318a978a17SVictor Perevertkin 
1328a978a17SVictor Perevertkin                     //
1338a978a17SVictor Perevertkin                     // We will advance to the next interrupt object if the resource
1348a978a17SVictor Perevertkin                     // is not an alternate resource descriptor. A resource list can
1358a978a17SVictor Perevertkin                     // have a preferred and zero or more alternate resource descriptors
1368a978a17SVictor Perevertkin                     // for the same resource. We need to apply the same policy on the
1378a978a17SVictor Perevertkin                     // alternate desc that we applied on the preferred one in case one
1388a978a17SVictor Perevertkin                     // of the alernate desc is selected for this device. An alternate
1398a978a17SVictor Perevertkin                     // resource descriptor can't be the first descriptor in a list.
1408a978a17SVictor Perevertkin                     //
1418a978a17SVictor Perevertkin                     if ((pIoDesc->Option & IO_RESOURCE_ALTERNATIVE) == 0) {
1428a978a17SVictor Perevertkin                         pIntListEntryForMSI = pIntListEntryForMSI->Flink;
1438a978a17SVictor Perevertkin                     }
1448a978a17SVictor Perevertkin 
1458a978a17SVictor Perevertkin                     if (pIntListEntryForMSI == &m_InterruptListHead) {
1468a978a17SVictor Perevertkin                         DoTraceLevelMessage(
1478a978a17SVictor Perevertkin                             GetDriverGlobals(), TRACE_LEVEL_WARNING, TRACINGPNP,
1488a978a17SVictor Perevertkin                             "Not enough interrupt objects created for MSI by WDFDEVICE 0x%p ",
1498a978a17SVictor Perevertkin                             m_Device->GetHandle());
1508a978a17SVictor Perevertkin                         break;
1518a978a17SVictor Perevertkin                     }
1528a978a17SVictor Perevertkin 
1538a978a17SVictor Perevertkin                     pInterruptInstance = CONTAINING_RECORD(pIntListEntryForMSI, FxInterrupt, m_PnpList);
1548a978a17SVictor Perevertkin                     messageCount = pIoDesc->u.Interrupt.MaximumVector - pIoDesc->u.Interrupt.MinimumVector + 1;
1558a978a17SVictor Perevertkin 
1568a978a17SVictor Perevertkin                     if (messageCount > 1) {
1578a978a17SVictor Perevertkin                         //
1588a978a17SVictor Perevertkin                         //  PCI spec guarantees that there can be only one preferred/default
1598a978a17SVictor Perevertkin                         //  MSI 2.2 descriptor in a single list.
1608a978a17SVictor Perevertkin                         //
1618a978a17SVictor Perevertkin                         if ((pIoDesc->Option & IO_RESOURCE_ALTERNATIVE) == 0) {
1628a978a17SVictor Perevertkin #if DBG
1638a978a17SVictor Perevertkin                             ASSERT(multiMessageMSI22Found == FALSE);
1648a978a17SVictor Perevertkin #else
1658a978a17SVictor Perevertkin                             UNREFERENCED_PARAMETER(multiMessageMSI22Found);
1668a978a17SVictor Perevertkin #endif
1678a978a17SVictor Perevertkin                             multiMessageMSI22Found = TRUE;
1688a978a17SVictor Perevertkin 
1698a978a17SVictor Perevertkin                         }
1708a978a17SVictor Perevertkin                     }
1718a978a17SVictor Perevertkin                     else {
1728a978a17SVictor Perevertkin                         //
1738a978a17SVictor Perevertkin                         //  This is either single message MSI 2.2 or MSI-X interrupts
1748a978a17SVictor Perevertkin                         //
1758a978a17SVictor Perevertkin                         DO_NOTHING();
1768a978a17SVictor Perevertkin                     }
1778a978a17SVictor Perevertkin 
1788a978a17SVictor Perevertkin                     pInterruptInstance->FilterResourceRequirements(pIoDesc);
1798a978a17SVictor Perevertkin                 }
1808a978a17SVictor Perevertkin                 else {
1818a978a17SVictor Perevertkin 
1828a978a17SVictor Perevertkin                     //
1838a978a17SVictor Perevertkin                     // We will advance to next interrupt object if the desc is not an alternate
1848a978a17SVictor Perevertkin                     // descriptor. For non PCI devices, the first LBI interrupt desc can't be an
1858a978a17SVictor Perevertkin                     // alternate descriptor.
1868a978a17SVictor Perevertkin                     //
1878a978a17SVictor Perevertkin                     if ((pIoDesc->Option & IO_RESOURCE_ALTERNATIVE) == 0) {
1888a978a17SVictor Perevertkin                         pIntListEntryForLBI = pIntListEntryForLBI->Flink;
1898a978a17SVictor Perevertkin                     }
1908a978a17SVictor Perevertkin 
1918a978a17SVictor Perevertkin                     //
1928a978a17SVictor Perevertkin                     // An LBI can be first alternate resource if there are preceding MSI(X) descriptors
1938a978a17SVictor Perevertkin                     // listed in the list. In that case, this descriptor is the alternate interrupt resource
1948a978a17SVictor Perevertkin                     // for all of the MSI messages. As a result, we will use the first interrupt object from
1958a978a17SVictor Perevertkin                     // the list if this ends up being assigned by the system instead of MSI.
1968a978a17SVictor Perevertkin                     //
1978a978a17SVictor Perevertkin                     if (previousDescMSI) {
1988a978a17SVictor Perevertkin                         ASSERT(pIoDesc->Option & IO_RESOURCE_ALTERNATIVE);
1998a978a17SVictor Perevertkin                         pIntListEntryForLBI = m_InterruptListHead.Flink;
2008a978a17SVictor Perevertkin                         previousDescMSI = FALSE;
2018a978a17SVictor Perevertkin                     }
2028a978a17SVictor Perevertkin 
2038a978a17SVictor Perevertkin                     //
2048a978a17SVictor Perevertkin                     // There can be one or more LBI interrupts and each LBI interrupt
2058a978a17SVictor Perevertkin                     // could have zero or more alternate descriptors.
2068a978a17SVictor Perevertkin                     //
2078a978a17SVictor Perevertkin                     if (pIntListEntryForLBI == &m_InterruptListHead) {
2088a978a17SVictor Perevertkin                         DoTraceLevelMessage(
2098a978a17SVictor Perevertkin                             GetDriverGlobals(), TRACE_LEVEL_WARNING, TRACINGPNP,
2108a978a17SVictor Perevertkin                             "Not enough interrupt objects created for LBI by WDFDEVICE 0x%p ",
2118a978a17SVictor Perevertkin                             m_Device->GetHandle());
2128a978a17SVictor Perevertkin                         break;
2138a978a17SVictor Perevertkin                     }
2148a978a17SVictor Perevertkin 
2158a978a17SVictor Perevertkin                     pInterruptInstance = CONTAINING_RECORD(pIntListEntryForLBI, FxInterrupt, m_PnpList);
2168a978a17SVictor Perevertkin 
2178a978a17SVictor Perevertkin                     pInterruptInstance->FilterResourceRequirements(pIoDesc);
2188a978a17SVictor Perevertkin                 }
2198a978a17SVictor Perevertkin 
2208a978a17SVictor Perevertkin                 break;
2218a978a17SVictor Perevertkin 
2228a978a17SVictor Perevertkin             default:
2238a978a17SVictor Perevertkin                 break;
2248a978a17SVictor Perevertkin             }
2258a978a17SVictor Perevertkin         }
2268a978a17SVictor Perevertkin 
2278a978a17SVictor Perevertkin         //
2288a978a17SVictor Perevertkin         // Since the Descriptors is a variable length list, you cannot get to the next
2298a978a17SVictor Perevertkin         // alternate list by doing pIoRequirementList->List[altResListIndex].
2308a978a17SVictor Perevertkin         // Descriptors[descIndex] will now point to the end of the descriptor list.
2318a978a17SVictor Perevertkin         // If there is another alternate list, it would be begin there.
2328a978a17SVictor Perevertkin         //
2338a978a17SVictor Perevertkin         pIoResList = (PIO_RESOURCE_LIST) &pIoResList->Descriptors[descIndex];
2348a978a17SVictor Perevertkin     }
2358a978a17SVictor Perevertkin 
2368a978a17SVictor Perevertkin     return STATUS_SUCCESS;
2378a978a17SVictor Perevertkin }
2388a978a17SVictor Perevertkin 
2398a978a17SVictor Perevertkin _Must_inspect_result_
2408a978a17SVictor Perevertkin NTSTATUS
AllocateDmaEnablerList(VOID)2418a978a17SVictor Perevertkin FxPkgPnp::AllocateDmaEnablerList(
2428a978a17SVictor Perevertkin     VOID
2438a978a17SVictor Perevertkin     )
2448a978a17SVictor Perevertkin {
2458a978a17SVictor Perevertkin     FxSpinLockTransactionedList* pList;
2468a978a17SVictor Perevertkin     NTSTATUS status;
2478a978a17SVictor Perevertkin     KIRQL irql;
2488a978a17SVictor Perevertkin 
2498a978a17SVictor Perevertkin     if (m_DmaEnablerList != NULL) {
2508a978a17SVictor Perevertkin         return STATUS_SUCCESS;
2518a978a17SVictor Perevertkin     }
2528a978a17SVictor Perevertkin 
2538a978a17SVictor Perevertkin     Lock(&irql);
2548a978a17SVictor Perevertkin     if (m_DmaEnablerList == NULL) {
2558a978a17SVictor Perevertkin         pList = new (GetDriverGlobals()) FxSpinLockTransactionedList();
2568a978a17SVictor Perevertkin 
2578a978a17SVictor Perevertkin         if (pList != NULL) {
2588a978a17SVictor Perevertkin             m_DmaEnablerList = pList;
2598a978a17SVictor Perevertkin             status = STATUS_SUCCESS;
2608a978a17SVictor Perevertkin         }
2618a978a17SVictor Perevertkin         else {
2628a978a17SVictor Perevertkin             status = STATUS_INSUFFICIENT_RESOURCES;
2638a978a17SVictor Perevertkin         }
2648a978a17SVictor Perevertkin     }
2658a978a17SVictor Perevertkin     else {
2668a978a17SVictor Perevertkin         //
2678a978a17SVictor Perevertkin         // Already have a DMA list
2688a978a17SVictor Perevertkin         //
2698a978a17SVictor Perevertkin         status = STATUS_SUCCESS;
2708a978a17SVictor Perevertkin     }
2718a978a17SVictor Perevertkin     Unlock(irql);
2728a978a17SVictor Perevertkin 
2738a978a17SVictor Perevertkin     return status;
2748a978a17SVictor Perevertkin }
2758a978a17SVictor Perevertkin 
2768a978a17SVictor Perevertkin VOID
AddDmaEnabler(__in FxDmaEnabler * Enabler)2778a978a17SVictor Perevertkin FxPkgPnp::AddDmaEnabler(
2788a978a17SVictor Perevertkin     __in FxDmaEnabler* Enabler
2798a978a17SVictor Perevertkin     )
2808a978a17SVictor Perevertkin {
2818a978a17SVictor Perevertkin     DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
2828a978a17SVictor Perevertkin                         "Adding DmaEnabler %p, WDFDMAENABLER %p",
2838a978a17SVictor Perevertkin                         Enabler, Enabler->GetObjectHandle());
2848a978a17SVictor Perevertkin 
2858a978a17SVictor Perevertkin     m_DmaEnablerList->Add(GetDriverGlobals(), &Enabler->m_TransactionLink);
2868a978a17SVictor Perevertkin }
2878a978a17SVictor Perevertkin 
2888a978a17SVictor Perevertkin VOID
RemoveDmaEnabler(__in FxDmaEnabler * Enabler)2898a978a17SVictor Perevertkin FxPkgPnp::RemoveDmaEnabler(
2908a978a17SVictor Perevertkin     __in FxDmaEnabler* Enabler
2918a978a17SVictor Perevertkin     )
2928a978a17SVictor Perevertkin {
2938a978a17SVictor Perevertkin     DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
2948a978a17SVictor Perevertkin                         "Removing DmaEnabler %p, WDFDMAENABLER %p",
2958a978a17SVictor Perevertkin                         Enabler, Enabler->GetObjectHandle());
2968a978a17SVictor Perevertkin 
2978a978a17SVictor Perevertkin     m_DmaEnablerList->Remove(GetDriverGlobals(), &Enabler->m_TransactionLink);
2988a978a17SVictor Perevertkin }
2998a978a17SVictor Perevertkin 
3008a978a17SVictor Perevertkin VOID
WriteStateToRegistry(__in HANDLE RegKey,__in PUNICODE_STRING ValueName,__in ULONG Value)3018a978a17SVictor Perevertkin FxPkgPnp::WriteStateToRegistry(
3028a978a17SVictor Perevertkin     __in HANDLE RegKey,
3038a978a17SVictor Perevertkin     __in PUNICODE_STRING ValueName,
3048a978a17SVictor Perevertkin     __in ULONG Value
3058a978a17SVictor Perevertkin     )
3068a978a17SVictor Perevertkin {
3078a978a17SVictor Perevertkin     ZwSetValueKey(RegKey, ValueName, 0, REG_DWORD, &Value, sizeof(Value));
3088a978a17SVictor Perevertkin }
3098a978a17SVictor Perevertkin 
310*1f377076SVictor Perevertkin // NTSTATUS __REACTOS__
311*1f377076SVictor Perevertkin // FxPkgPnp::UpdateWmiInstanceForS0Idle(
312*1f377076SVictor Perevertkin //     __in FxWmiInstanceAction Action
313*1f377076SVictor Perevertkin //     )
314*1f377076SVictor Perevertkin // {
315*1f377076SVictor Perevertkin //     FxWmiProvider* pProvider;
316*1f377076SVictor Perevertkin //     NTSTATUS status;
3178a978a17SVictor Perevertkin 
318*1f377076SVictor Perevertkin //     switch(Action) {
319*1f377076SVictor Perevertkin //     case AddInstance:
320*1f377076SVictor Perevertkin //         if (m_PowerPolicyMachine.m_Owner->m_IdleSettings.WmiInstance == NULL) {
321*1f377076SVictor Perevertkin //             FxWmiInstanceInternalCallbacks cb;
3228a978a17SVictor Perevertkin 
323*1f377076SVictor Perevertkin //             cb.SetInstance = _S0IdleSetInstance;
324*1f377076SVictor Perevertkin //             cb.QueryInstance = _S0IdleQueryInstance;
325*1f377076SVictor Perevertkin //             cb.SetItem = _S0IdleSetItem;
3268a978a17SVictor Perevertkin 
327*1f377076SVictor Perevertkin //             status = RegisterPowerPolicyWmiInstance(
328*1f377076SVictor Perevertkin //                 &GUID_POWER_DEVICE_ENABLE,
329*1f377076SVictor Perevertkin //                 &cb,
330*1f377076SVictor Perevertkin //                 &m_PowerPolicyMachine.m_Owner->m_IdleSettings.WmiInstance);
3318a978a17SVictor Perevertkin 
332*1f377076SVictor Perevertkin //             if (!NT_SUCCESS(status)) {
333*1f377076SVictor Perevertkin //                 return status;
334*1f377076SVictor Perevertkin //             }
335*1f377076SVictor Perevertkin //         }
336*1f377076SVictor Perevertkin //         else {
337*1f377076SVictor Perevertkin //             pProvider = m_PowerPolicyMachine.m_Owner->m_IdleSettings.
338*1f377076SVictor Perevertkin //                 WmiInstance->GetProvider();
3398a978a17SVictor Perevertkin 
340*1f377076SVictor Perevertkin //             //
341*1f377076SVictor Perevertkin //             // Enable the WMI GUID by adding the instance back to the provider's
342*1f377076SVictor Perevertkin //             // list.  If there is an error, ignore it.  It just means we were
343*1f377076SVictor Perevertkin //             // racing with another thread removing or adding the instance.
344*1f377076SVictor Perevertkin //             //
345*1f377076SVictor Perevertkin //             (void) pProvider->AddInstance(
346*1f377076SVictor Perevertkin //                 m_PowerPolicyMachine.m_Owner->m_IdleSettings.WmiInstance,
347*1f377076SVictor Perevertkin //                 TRUE
348*1f377076SVictor Perevertkin //                 );
349*1f377076SVictor Perevertkin //         }
350*1f377076SVictor Perevertkin //         break;
3518a978a17SVictor Perevertkin 
352*1f377076SVictor Perevertkin //     case RemoveInstance:
353*1f377076SVictor Perevertkin //         if (m_PowerPolicyMachine.m_Owner->m_IdleSettings.WmiInstance != NULL) {
354*1f377076SVictor Perevertkin //             //
355*1f377076SVictor Perevertkin //             // Disable the WMI guid by removing it from the provider's list of
356*1f377076SVictor Perevertkin //             // instances.
357*1f377076SVictor Perevertkin //             //
358*1f377076SVictor Perevertkin //             pProvider = m_PowerPolicyMachine.m_Owner->m_IdleSettings.
359*1f377076SVictor Perevertkin //                 WmiInstance->GetProvider();
3608a978a17SVictor Perevertkin 
361*1f377076SVictor Perevertkin //             pProvider->RemoveInstance(
362*1f377076SVictor Perevertkin //                 m_PowerPolicyMachine.m_Owner->m_IdleSettings.WmiInstance
363*1f377076SVictor Perevertkin //                 );
364*1f377076SVictor Perevertkin //         }
365*1f377076SVictor Perevertkin //         break;
3668a978a17SVictor Perevertkin 
367*1f377076SVictor Perevertkin //     default:
368*1f377076SVictor Perevertkin //         ASSERT(FALSE);
369*1f377076SVictor Perevertkin //         break;
370*1f377076SVictor Perevertkin //     }
3718a978a17SVictor Perevertkin 
372*1f377076SVictor Perevertkin //     return STATUS_SUCCESS;;
373*1f377076SVictor Perevertkin // }
3748a978a17SVictor Perevertkin 
3758a978a17SVictor Perevertkin VOID
ReadRegistryS0Idle(__in PCUNICODE_STRING ValueName,__out BOOLEAN * Enabled)3768a978a17SVictor Perevertkin FxPkgPnp::ReadRegistryS0Idle(
3778a978a17SVictor Perevertkin     __in  PCUNICODE_STRING ValueName,
3788a978a17SVictor Perevertkin     __out BOOLEAN *Enabled
3798a978a17SVictor Perevertkin     )
3808a978a17SVictor Perevertkin {
3818a978a17SVictor Perevertkin     NTSTATUS status;
3828a978a17SVictor Perevertkin     FxAutoRegKey hKey;
3838a978a17SVictor Perevertkin 
3848a978a17SVictor Perevertkin     status = m_Device->OpenSettingsKey(&hKey.m_Key, STANDARD_RIGHTS_READ);
3858a978a17SVictor Perevertkin 
3868a978a17SVictor Perevertkin     //
3878a978a17SVictor Perevertkin     // Modify the value of Enabled only if success
3888a978a17SVictor Perevertkin     //
3898a978a17SVictor Perevertkin     if (NT_SUCCESS(status)) {
3908a978a17SVictor Perevertkin         ULONG value;
3918a978a17SVictor Perevertkin 
3928a978a17SVictor Perevertkin         status = FxRegKey::_QueryULong(
3938a978a17SVictor Perevertkin             hKey.m_Key, ValueName, &value);
3948a978a17SVictor Perevertkin 
3958a978a17SVictor Perevertkin         if (NT_SUCCESS(status)) {
3968a978a17SVictor Perevertkin             //
3978a978a17SVictor Perevertkin             // Normalize the ULONG value into a BOOLEAN
3988a978a17SVictor Perevertkin             //
3998a978a17SVictor Perevertkin             *Enabled = (value == FALSE) ? FALSE : TRUE;
4008a978a17SVictor Perevertkin         }
4018a978a17SVictor Perevertkin     }
4028a978a17SVictor Perevertkin }
4038a978a17SVictor Perevertkin 
404*1f377076SVictor Perevertkin // NTSTATUS __REACTOS__
405*1f377076SVictor Perevertkin // FxPkgPnp::UpdateWmiInstanceForSxWake(
406*1f377076SVictor Perevertkin //     __in FxWmiInstanceAction Action
407*1f377076SVictor Perevertkin //     )
408*1f377076SVictor Perevertkin // {
409*1f377076SVictor Perevertkin //     FxWmiProvider* pProvider;
410*1f377076SVictor Perevertkin //     NTSTATUS status;
4118a978a17SVictor Perevertkin 
412*1f377076SVictor Perevertkin //     switch(Action) {
413*1f377076SVictor Perevertkin //     case AddInstance:
414*1f377076SVictor Perevertkin //         if (m_PowerPolicyMachine.m_Owner->m_WakeSettings.WmiInstance == NULL) {
415*1f377076SVictor Perevertkin //             FxWmiInstanceInternalCallbacks cb;
4168a978a17SVictor Perevertkin 
417*1f377076SVictor Perevertkin //             cb.SetInstance = _SxWakeSetInstance;
418*1f377076SVictor Perevertkin //             cb.QueryInstance = _SxWakeQueryInstance;
419*1f377076SVictor Perevertkin //             cb.SetItem = _SxWakeSetItem;
4208a978a17SVictor Perevertkin 
421*1f377076SVictor Perevertkin //             status = RegisterPowerPolicyWmiInstance(
422*1f377076SVictor Perevertkin //                 &GUID_POWER_DEVICE_WAKE_ENABLE,
423*1f377076SVictor Perevertkin //                 &cb,
424*1f377076SVictor Perevertkin //                 &m_PowerPolicyMachine.m_Owner->m_WakeSettings.WmiInstance);
4258a978a17SVictor Perevertkin 
426*1f377076SVictor Perevertkin //             if (!NT_SUCCESS(status)) {
427*1f377076SVictor Perevertkin //                 return status;
428*1f377076SVictor Perevertkin //             }
429*1f377076SVictor Perevertkin //         } else {
430*1f377076SVictor Perevertkin //             pProvider = m_PowerPolicyMachine.m_Owner->m_WakeSettings.
431*1f377076SVictor Perevertkin //                 WmiInstance->GetProvider();
4328a978a17SVictor Perevertkin 
433*1f377076SVictor Perevertkin //             //
434*1f377076SVictor Perevertkin //             // Enable the WMI GUID by adding the instance back to the provider's
435*1f377076SVictor Perevertkin //             // list.  If there is an error, ignore it.  It just means we were
436*1f377076SVictor Perevertkin //             // racing with another thread removing or adding the instance.
437*1f377076SVictor Perevertkin //             //
438*1f377076SVictor Perevertkin //             (void) pProvider->AddInstance(
439*1f377076SVictor Perevertkin //                 m_PowerPolicyMachine.m_Owner->m_WakeSettings.WmiInstance,
440*1f377076SVictor Perevertkin //                 TRUE
441*1f377076SVictor Perevertkin //                 );
442*1f377076SVictor Perevertkin //         }
443*1f377076SVictor Perevertkin //         break;
4448a978a17SVictor Perevertkin 
445*1f377076SVictor Perevertkin //     case RemoveInstance:
446*1f377076SVictor Perevertkin //         if (m_PowerPolicyMachine.m_Owner->m_WakeSettings.WmiInstance != NULL) {
447*1f377076SVictor Perevertkin //             //
448*1f377076SVictor Perevertkin //             // Disable the WMI guid by removing it from the provider's list of
449*1f377076SVictor Perevertkin //             // instances.
450*1f377076SVictor Perevertkin //             //
451*1f377076SVictor Perevertkin //             pProvider = m_PowerPolicyMachine.m_Owner->m_WakeSettings.
452*1f377076SVictor Perevertkin //                 WmiInstance->GetProvider();
4538a978a17SVictor Perevertkin 
454*1f377076SVictor Perevertkin //             pProvider->RemoveInstance(
455*1f377076SVictor Perevertkin //                 m_PowerPolicyMachine.m_Owner->m_WakeSettings.WmiInstance
456*1f377076SVictor Perevertkin //                 );
457*1f377076SVictor Perevertkin //         }
458*1f377076SVictor Perevertkin //         break;
4598a978a17SVictor Perevertkin 
460*1f377076SVictor Perevertkin //     default:
461*1f377076SVictor Perevertkin //         ASSERT(FALSE);
462*1f377076SVictor Perevertkin //         break;
463*1f377076SVictor Perevertkin //     }
4648a978a17SVictor Perevertkin 
465*1f377076SVictor Perevertkin //     return STATUS_SUCCESS;
466*1f377076SVictor Perevertkin // }
4678a978a17SVictor Perevertkin 
4688a978a17SVictor Perevertkin VOID
ReadRegistrySxWake(__in PCUNICODE_STRING ValueName,__out BOOLEAN * Enabled)4698a978a17SVictor Perevertkin FxPkgPnp::ReadRegistrySxWake(
4708a978a17SVictor Perevertkin     __in  PCUNICODE_STRING ValueName,
4718a978a17SVictor Perevertkin     __out BOOLEAN *Enabled
4728a978a17SVictor Perevertkin     )
4738a978a17SVictor Perevertkin {
4748a978a17SVictor Perevertkin     FxAutoRegKey hKey;
4758a978a17SVictor Perevertkin     NTSTATUS status;
4768a978a17SVictor Perevertkin 
4778a978a17SVictor Perevertkin     status = m_Device->OpenSettingsKey(&hKey.m_Key, STANDARD_RIGHTS_READ);
4788a978a17SVictor Perevertkin 
4798a978a17SVictor Perevertkin     //
4808a978a17SVictor Perevertkin     // Modify the value of Enabled only if success
4818a978a17SVictor Perevertkin     //
4828a978a17SVictor Perevertkin     if (NT_SUCCESS(status)) {
4838a978a17SVictor Perevertkin         ULONG value;
4848a978a17SVictor Perevertkin 
4858a978a17SVictor Perevertkin         status = FxRegKey::_QueryULong(
4868a978a17SVictor Perevertkin             hKey.m_Key, ValueName, &value);
4878a978a17SVictor Perevertkin 
4888a978a17SVictor Perevertkin         if (NT_SUCCESS(status)) {
4898a978a17SVictor Perevertkin             //
4908a978a17SVictor Perevertkin             // Normalize the ULONG value into a BOOLEAN
4918a978a17SVictor Perevertkin             //
4928a978a17SVictor Perevertkin             *Enabled = (value == FALSE) ? FALSE : TRUE;
4938a978a17SVictor Perevertkin         }
4948a978a17SVictor Perevertkin     }
4958a978a17SVictor Perevertkin }
4968a978a17SVictor Perevertkin 
4978a978a17SVictor Perevertkin VOID
PnpPassThroughQIWorker(__in MxDeviceObject * Device,__inout FxIrp * Irp,__inout FxIrp * ForwardIrp)4988a978a17SVictor Perevertkin PnpPassThroughQIWorker(
4998a978a17SVictor Perevertkin     __in    MxDeviceObject* Device,
5008a978a17SVictor Perevertkin     __inout FxIrp* Irp,
5018a978a17SVictor Perevertkin     __inout FxIrp* ForwardIrp
5028a978a17SVictor Perevertkin     )
5038a978a17SVictor Perevertkin {
5048a978a17SVictor Perevertkin     PIO_STACK_LOCATION pFwdStack, pCurStack;
5058a978a17SVictor Perevertkin 
5068a978a17SVictor Perevertkin     pCurStack = Irp->GetCurrentIrpStackLocation();
5078a978a17SVictor Perevertkin 
5088a978a17SVictor Perevertkin     ForwardIrp->SetStatus(STATUS_NOT_SUPPORTED);
5098a978a17SVictor Perevertkin 
5108a978a17SVictor Perevertkin     pFwdStack = ForwardIrp->GetNextIrpStackLocation();
5118a978a17SVictor Perevertkin     pFwdStack->MajorFunction = Irp->GetMajorFunction();
5128a978a17SVictor Perevertkin     pFwdStack->MinorFunction = Irp->GetMinorFunction();
5138a978a17SVictor Perevertkin 
5148a978a17SVictor Perevertkin     RtlCopyMemory(&pFwdStack->Parameters.QueryInterface,
5158a978a17SVictor Perevertkin                   &pCurStack->Parameters.QueryInterface,
5168a978a17SVictor Perevertkin                   sizeof(pFwdStack->Parameters.QueryInterface));
5178a978a17SVictor Perevertkin 
5188a978a17SVictor Perevertkin     ForwardIrp->SetInformation(Irp->GetInformation());
5198a978a17SVictor Perevertkin     ForwardIrp->SendIrpSynchronously(Device->GetObject());
5208a978a17SVictor Perevertkin 
5218a978a17SVictor Perevertkin     pFwdStack = ForwardIrp->GetNextIrpStackLocation();
5228a978a17SVictor Perevertkin 
5238a978a17SVictor Perevertkin     RtlCopyMemory(&pCurStack->Parameters.QueryInterface,
5248a978a17SVictor Perevertkin                   &pFwdStack->Parameters.QueryInterface,
5258a978a17SVictor Perevertkin                   sizeof(pCurStack->Parameters.QueryInterface));
5268a978a17SVictor Perevertkin }
5278a978a17SVictor Perevertkin 
5288a978a17SVictor Perevertkin VOID
RevokeDmaEnablerResources(__in FxDmaEnabler * DmaEnabler)5298a978a17SVictor Perevertkin FxPkgPnp::RevokeDmaEnablerResources(
5308a978a17SVictor Perevertkin     __in FxDmaEnabler *DmaEnabler
5318a978a17SVictor Perevertkin     )
5328a978a17SVictor Perevertkin {
533*1f377076SVictor Perevertkin     // DmaEnabler->RevokeResources();
534*1f377076SVictor Perevertkin     ROSWDFNOTIMPLEMENTED;
5358a978a17SVictor Perevertkin }
5368a978a17SVictor Perevertkin 
5378a978a17SVictor Perevertkin VOID
QueryForD3ColdInterface(VOID)5388a978a17SVictor Perevertkin FxPkgPnp::QueryForD3ColdInterface(
5398a978a17SVictor Perevertkin     VOID
5408a978a17SVictor Perevertkin     )
5418a978a17SVictor Perevertkin {
5428a978a17SVictor Perevertkin     MxDeviceObject deviceObject;
5438a978a17SVictor Perevertkin     PDEVICE_OBJECT topOfStack;
5448a978a17SVictor Perevertkin     PDEVICE_OBJECT pdo;
5458a978a17SVictor Perevertkin     FxAutoIrp irp;
5468a978a17SVictor Perevertkin     NTSTATUS status;
5478a978a17SVictor Perevertkin 
5488a978a17SVictor Perevertkin     //
5498a978a17SVictor Perevertkin     // This function can be invoked multiple times, particularly if filters
5508a978a17SVictor Perevertkin     // send IRP_MN_QUERY_CAPABILITIES.  So bail out if the interface has already
5518a978a17SVictor Perevertkin     // been acquired.
5528a978a17SVictor Perevertkin     //
5538a978a17SVictor Perevertkin 
5548a978a17SVictor Perevertkin     if ((m_D3ColdInterface.InterfaceDereference != NULL) ||
5558a978a17SVictor Perevertkin         (m_D3ColdInterface.GetIdleWakeInfo != NULL) ||
5568a978a17SVictor Perevertkin         (m_D3ColdInterface.SetD3ColdSupport != NULL)) {
5578a978a17SVictor Perevertkin         return;
5588a978a17SVictor Perevertkin     }
5598a978a17SVictor Perevertkin 
5608a978a17SVictor Perevertkin     pdo = m_Device->GetPhysicalDevice();
5618a978a17SVictor Perevertkin 
5628a978a17SVictor Perevertkin     if (pdo == NULL) {
5638a978a17SVictor Perevertkin         return;
5648a978a17SVictor Perevertkin     }
5658a978a17SVictor Perevertkin 
5668a978a17SVictor Perevertkin     //
5678a978a17SVictor Perevertkin     // Get the top of stack device object, even though normal filters and the
5688a978a17SVictor Perevertkin     // FDO may not have been added to the stack yet to ensure that this
5698a978a17SVictor Perevertkin     // query-interface is seen by bus filters.  Specifically, in a PCI device
5708a978a17SVictor Perevertkin     // which is soldered to the motherboard, ACPI will be on the stack and it
5718a978a17SVictor Perevertkin     // needs to see this IRP.
5728a978a17SVictor Perevertkin     //
5738a978a17SVictor Perevertkin     topOfStack = IoGetAttachedDeviceReference(pdo);
5748a978a17SVictor Perevertkin     deviceObject.SetObject(topOfStack);
5758a978a17SVictor Perevertkin     if (deviceObject.GetObject() != NULL) {
5768a978a17SVictor Perevertkin         irp.SetIrp(FxIrp::AllocateIrp(deviceObject.GetStackSize()));
5778a978a17SVictor Perevertkin         if (irp.GetIrp() == NULL) {
5788a978a17SVictor Perevertkin 
5798a978a17SVictor Perevertkin             DoTraceLevelMessage(
5808a978a17SVictor Perevertkin                 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
5818a978a17SVictor Perevertkin                 "Failed to allocate IRP to get D3COLD_SUPPORT_INTERFACE from !devobj %p",
5828a978a17SVictor Perevertkin                 pdo);
5838a978a17SVictor Perevertkin         } else {
5848a978a17SVictor Perevertkin 
5858a978a17SVictor Perevertkin             //
5868a978a17SVictor Perevertkin             // Initialize the Irp
5878a978a17SVictor Perevertkin             //
5888a978a17SVictor Perevertkin             irp.SetStatus(STATUS_NOT_SUPPORTED);
5898a978a17SVictor Perevertkin 
5908a978a17SVictor Perevertkin             irp.ClearNextStack();
5918a978a17SVictor Perevertkin             irp.SetMajorFunction(IRP_MJ_PNP);
5928a978a17SVictor Perevertkin             irp.SetMinorFunction(IRP_MN_QUERY_INTERFACE);
5938a978a17SVictor Perevertkin             irp.SetParameterQueryInterfaceType(&GUID_D3COLD_SUPPORT_INTERFACE);
5948a978a17SVictor Perevertkin             irp.SetParameterQueryInterfaceVersion(D3COLD_SUPPORT_INTERFACE_VERSION);
5958a978a17SVictor Perevertkin             irp.SetParameterQueryInterfaceSize(sizeof(m_D3ColdInterface));
5968a978a17SVictor Perevertkin             irp.SetParameterQueryInterfaceInterfaceSpecificData(NULL);
5978a978a17SVictor Perevertkin             irp.SetParameterQueryInterfaceInterface((PINTERFACE)&m_D3ColdInterface);
5988a978a17SVictor Perevertkin 
5998a978a17SVictor Perevertkin             status = irp.SendIrpSynchronously(deviceObject.GetObject());
6008a978a17SVictor Perevertkin 
6018a978a17SVictor Perevertkin             if (!NT_SUCCESS(status)) {
6028a978a17SVictor Perevertkin                 DoTraceLevelMessage(
6038a978a17SVictor Perevertkin                     GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
6048a978a17SVictor Perevertkin                     "!devobj %p declined to supply D3COLD_SUPPORT_INTERFACE",
6058a978a17SVictor Perevertkin                     pdo);
6068a978a17SVictor Perevertkin 
6078a978a17SVictor Perevertkin                 RtlZeroMemory(&m_D3ColdInterface, sizeof(m_D3ColdInterface));
6088a978a17SVictor Perevertkin             }
6098a978a17SVictor Perevertkin         }
6108a978a17SVictor Perevertkin     }
6118a978a17SVictor Perevertkin     ObDereferenceObject(topOfStack);
6128a978a17SVictor Perevertkin }
6138a978a17SVictor Perevertkin 
6148a978a17SVictor Perevertkin VOID
DropD3ColdInterface(VOID)6158a978a17SVictor Perevertkin FxPkgPnp::DropD3ColdInterface(
6168a978a17SVictor Perevertkin     VOID
6178a978a17SVictor Perevertkin     )
6188a978a17SVictor Perevertkin {
6198a978a17SVictor Perevertkin     if (m_D3ColdInterface.InterfaceDereference != NULL) {
6208a978a17SVictor Perevertkin         m_D3ColdInterface.InterfaceDereference(m_D3ColdInterface.Context);
6218a978a17SVictor Perevertkin     }
6228a978a17SVictor Perevertkin 
6238a978a17SVictor Perevertkin     RtlZeroMemory(&m_D3ColdInterface, sizeof(m_D3ColdInterface));
6248a978a17SVictor Perevertkin }
6258a978a17SVictor Perevertkin 
626