1*8a978a17SVictor Perevertkin /*++
2*8a978a17SVictor Perevertkin 
3*8a978a17SVictor Perevertkin Copyright (c) Microsoft Corporation
4*8a978a17SVictor Perevertkin 
5*8a978a17SVictor Perevertkin Module Name:
6*8a978a17SVictor Perevertkin 
7*8a978a17SVictor Perevertkin     FxResourceCollection.cpp
8*8a978a17SVictor Perevertkin 
9*8a978a17SVictor Perevertkin Abstract:
10*8a978a17SVictor Perevertkin 
11*8a978a17SVictor Perevertkin     This module implements a base object for derived collection classes and
12*8a978a17SVictor Perevertkin     the derived collection classes.
13*8a978a17SVictor Perevertkin 
14*8a978a17SVictor Perevertkin Author:
15*8a978a17SVictor Perevertkin 
16*8a978a17SVictor Perevertkin 
17*8a978a17SVictor Perevertkin 
18*8a978a17SVictor Perevertkin Environment:
19*8a978a17SVictor Perevertkin 
20*8a978a17SVictor Perevertkin     User mode only
21*8a978a17SVictor Perevertkin 
22*8a978a17SVictor Perevertkin Revision History:
23*8a978a17SVictor Perevertkin 
24*8a978a17SVictor Perevertkin --*/
25*8a978a17SVictor Perevertkin 
26*8a978a17SVictor Perevertkin #include "FxSupportPch.hpp"
27*8a978a17SVictor Perevertkin #include <intsafe.h>
28*8a978a17SVictor Perevertkin 
29*8a978a17SVictor Perevertkin #if defined(EVENT_TRACING)
30*8a978a17SVictor Perevertkin // Tracing support
31*8a978a17SVictor Perevertkin extern "C" {
32*8a978a17SVictor Perevertkin #include "FxResourceCollectionUm.tmh"
33*8a978a17SVictor Perevertkin }
34*8a978a17SVictor Perevertkin #endif
35*8a978a17SVictor Perevertkin 
~FxCmResList()36*8a978a17SVictor Perevertkin FxCmResList::~FxCmResList()
37*8a978a17SVictor Perevertkin {
38*8a978a17SVictor Perevertkin     DeleteRegisterResourceTable();
39*8a978a17SVictor Perevertkin     DeletePortResourceTable();
40*8a978a17SVictor Perevertkin }
41*8a978a17SVictor Perevertkin 
42*8a978a17SVictor Perevertkin NTSTATUS
BuildRegisterResourceTable(VOID)43*8a978a17SVictor Perevertkin FxCmResList::BuildRegisterResourceTable(
44*8a978a17SVictor Perevertkin     VOID
45*8a978a17SVictor Perevertkin     )
46*8a978a17SVictor Perevertkin {
47*8a978a17SVictor Perevertkin     ULONG count;
48*8a978a17SVictor Perevertkin     ULONG i, index;
49*8a978a17SVictor Perevertkin     PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
50*8a978a17SVictor Perevertkin     ULONG numRegisterDesc;
51*8a978a17SVictor Perevertkin     BOOLEAN locked = FALSE;
52*8a978a17SVictor Perevertkin     NTSTATUS status;
53*8a978a17SVictor Perevertkin 
54*8a978a17SVictor Perevertkin     count = GetCount();
55*8a978a17SVictor Perevertkin     numRegisterDesc = 0;
56*8a978a17SVictor Perevertkin 
57*8a978a17SVictor Perevertkin     //
58*8a978a17SVictor Perevertkin     // count number of register descriptors
59*8a978a17SVictor Perevertkin     //
60*8a978a17SVictor Perevertkin     for (i = 0; i < count; i++) {
61*8a978a17SVictor Perevertkin         desc = GetDescriptor(i);
62*8a978a17SVictor Perevertkin         if (desc == NULL) {
63*8a978a17SVictor Perevertkin             status = STATUS_INVALID_DEVICE_STATE;
64*8a978a17SVictor Perevertkin             DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
65*8a978a17SVictor Perevertkin                         "Resource Descriptor not found %!STATUS!", status);
66*8a978a17SVictor Perevertkin             goto exit;
67*8a978a17SVictor Perevertkin         }
68*8a978a17SVictor Perevertkin 
69*8a978a17SVictor Perevertkin         if (desc->Type == CmResourceTypeMemory ||
70*8a978a17SVictor Perevertkin             desc->Type == CmResourceTypeMemoryLarge) {
71*8a978a17SVictor Perevertkin             numRegisterDesc++;
72*8a978a17SVictor Perevertkin         }
73*8a978a17SVictor Perevertkin     }
74*8a978a17SVictor Perevertkin 
75*8a978a17SVictor Perevertkin     if (numRegisterDesc == 0) {
76*8a978a17SVictor Perevertkin         return STATUS_SUCCESS;
77*8a978a17SVictor Perevertkin     }
78*8a978a17SVictor Perevertkin 
79*8a978a17SVictor Perevertkin     //
80*8a978a17SVictor Perevertkin     // allocate table
81*8a978a17SVictor Perevertkin     //
82*8a978a17SVictor Perevertkin     LockResourceTable();
83*8a978a17SVictor Perevertkin     locked = TRUE;
84*8a978a17SVictor Perevertkin 
85*8a978a17SVictor Perevertkin     status =  FxRegisterResourceInfo::_CreateAndInit(
86*8a978a17SVictor Perevertkin                                                     GetDriverGlobals(),
87*8a978a17SVictor Perevertkin                                                     numRegisterDesc,
88*8a978a17SVictor Perevertkin                                                     &m_RegisterResourceTable
89*8a978a17SVictor Perevertkin                                                     );
90*8a978a17SVictor Perevertkin     if (!NT_SUCCESS(status)) {
91*8a978a17SVictor Perevertkin         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
92*8a978a17SVictor Perevertkin                     "Failed to allocate memory for resource table"
93*8a978a17SVictor Perevertkin                     " %!STATUS!", status);
94*8a978a17SVictor Perevertkin         goto exit;
95*8a978a17SVictor Perevertkin     }
96*8a978a17SVictor Perevertkin     m_RegisterResourceTableSizeCe = numRegisterDesc;
97*8a978a17SVictor Perevertkin 
98*8a978a17SVictor Perevertkin     //
99*8a978a17SVictor Perevertkin     // Populate table
100*8a978a17SVictor Perevertkin     //
101*8a978a17SVictor Perevertkin     index = 0;
102*8a978a17SVictor Perevertkin     for (i = 0; i < count; i++) {
103*8a978a17SVictor Perevertkin         desc = GetDescriptor(i);
104*8a978a17SVictor Perevertkin         if (desc == NULL) {
105*8a978a17SVictor Perevertkin             status = STATUS_INVALID_DEVICE_STATE;
106*8a978a17SVictor Perevertkin             DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
107*8a978a17SVictor Perevertkin                         "Resource Descriptor not found %!STATUS!", status);
108*8a978a17SVictor Perevertkin             goto exit;
109*8a978a17SVictor Perevertkin         }
110*8a978a17SVictor Perevertkin 
111*8a978a17SVictor Perevertkin         if (desc->Type == CmResourceTypeMemory ||
112*8a978a17SVictor Perevertkin             desc->Type == CmResourceTypeMemoryLarge) {
113*8a978a17SVictor Perevertkin             SIZE_T len;
114*8a978a17SVictor Perevertkin             PHYSICAL_ADDRESS pa;
115*8a978a17SVictor Perevertkin 
116*8a978a17SVictor Perevertkin             //
117*8a978a17SVictor Perevertkin             // This will populate Length and StartPa
118*8a978a17SVictor Perevertkin             //
119*8a978a17SVictor Perevertkin             len = GetResourceLength(desc, &pa);
120*8a978a17SVictor Perevertkin             if (len) {
121*8a978a17SVictor Perevertkin                 m_RegisterResourceTable[index].SetPhysicalAddress(pa, len);
122*8a978a17SVictor Perevertkin             }
123*8a978a17SVictor Perevertkin 
124*8a978a17SVictor Perevertkin             index++;
125*8a978a17SVictor Perevertkin         }
126*8a978a17SVictor Perevertkin     }
127*8a978a17SVictor Perevertkin 
128*8a978a17SVictor Perevertkin exit:
129*8a978a17SVictor Perevertkin 
130*8a978a17SVictor Perevertkin     if (!NT_SUCCESS(status)) {
131*8a978a17SVictor Perevertkin         if (m_RegisterResourceTable != NULL) {
132*8a978a17SVictor Perevertkin             delete [] m_RegisterResourceTable;
133*8a978a17SVictor Perevertkin             m_RegisterResourceTable = NULL;
134*8a978a17SVictor Perevertkin             m_RegisterResourceTableSizeCe = 0;
135*8a978a17SVictor Perevertkin         }
136*8a978a17SVictor Perevertkin     }
137*8a978a17SVictor Perevertkin 
138*8a978a17SVictor Perevertkin     if (locked) {
139*8a978a17SVictor Perevertkin         UnlockResourceTable();
140*8a978a17SVictor Perevertkin     }
141*8a978a17SVictor Perevertkin 
142*8a978a17SVictor Perevertkin     return status;
143*8a978a17SVictor Perevertkin }
144*8a978a17SVictor Perevertkin 
145*8a978a17SVictor Perevertkin NTSTATUS
BuildPortResourceTable(VOID)146*8a978a17SVictor Perevertkin FxCmResList::BuildPortResourceTable(
147*8a978a17SVictor Perevertkin     VOID
148*8a978a17SVictor Perevertkin     )
149*8a978a17SVictor Perevertkin {
150*8a978a17SVictor Perevertkin     ULONG count;
151*8a978a17SVictor Perevertkin     ULONG i, index;
152*8a978a17SVictor Perevertkin     PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
153*8a978a17SVictor Perevertkin     ULONG numPortDesc;
154*8a978a17SVictor Perevertkin     BOOLEAN locked = FALSE;
155*8a978a17SVictor Perevertkin     NTSTATUS status;
156*8a978a17SVictor Perevertkin 
157*8a978a17SVictor Perevertkin     count = GetCount();
158*8a978a17SVictor Perevertkin     numPortDesc = 0;
159*8a978a17SVictor Perevertkin 
160*8a978a17SVictor Perevertkin     //
161*8a978a17SVictor Perevertkin     // count number of register descriptors
162*8a978a17SVictor Perevertkin     //
163*8a978a17SVictor Perevertkin     for (i = 0; i < count; i++) {
164*8a978a17SVictor Perevertkin         desc = GetDescriptor(i);
165*8a978a17SVictor Perevertkin         if (desc == NULL) {
166*8a978a17SVictor Perevertkin             status = STATUS_INVALID_DEVICE_STATE;
167*8a978a17SVictor Perevertkin             DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
168*8a978a17SVictor Perevertkin                         "Resource Descriptor not found %!STATUS!", status);
169*8a978a17SVictor Perevertkin             goto exit;
170*8a978a17SVictor Perevertkin         }
171*8a978a17SVictor Perevertkin 
172*8a978a17SVictor Perevertkin         if (desc->Type == CmResourceTypePort) {
173*8a978a17SVictor Perevertkin             numPortDesc++;
174*8a978a17SVictor Perevertkin         }
175*8a978a17SVictor Perevertkin     }
176*8a978a17SVictor Perevertkin 
177*8a978a17SVictor Perevertkin     if (numPortDesc == 0) {
178*8a978a17SVictor Perevertkin         return STATUS_SUCCESS;
179*8a978a17SVictor Perevertkin     }
180*8a978a17SVictor Perevertkin 
181*8a978a17SVictor Perevertkin     //
182*8a978a17SVictor Perevertkin     // allocate table
183*8a978a17SVictor Perevertkin     //
184*8a978a17SVictor Perevertkin     LockResourceTable();
185*8a978a17SVictor Perevertkin     locked = TRUE;
186*8a978a17SVictor Perevertkin 
187*8a978a17SVictor Perevertkin     status =  FxPortResourceInfo::_CreateAndInit(
188*8a978a17SVictor Perevertkin                                                 GetDriverGlobals(),
189*8a978a17SVictor Perevertkin                                                 numPortDesc,
190*8a978a17SVictor Perevertkin                                                 &m_PortResourceTable
191*8a978a17SVictor Perevertkin                                                 );
192*8a978a17SVictor Perevertkin     if (!NT_SUCCESS(status)) {
193*8a978a17SVictor Perevertkin         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
194*8a978a17SVictor Perevertkin                     "Failed to allocate memory for resource table"
195*8a978a17SVictor Perevertkin                     " %!STATUS!", status);
196*8a978a17SVictor Perevertkin         goto exit;
197*8a978a17SVictor Perevertkin     }
198*8a978a17SVictor Perevertkin     m_PortResourceTableSizeCe = numPortDesc;
199*8a978a17SVictor Perevertkin 
200*8a978a17SVictor Perevertkin     //
201*8a978a17SVictor Perevertkin     // Populate table
202*8a978a17SVictor Perevertkin     //
203*8a978a17SVictor Perevertkin     index = 0;
204*8a978a17SVictor Perevertkin     for (i = 0; i < count; i++) {
205*8a978a17SVictor Perevertkin         desc = GetDescriptor(i);
206*8a978a17SVictor Perevertkin         if (desc == NULL) {
207*8a978a17SVictor Perevertkin             status = STATUS_INVALID_DEVICE_STATE;
208*8a978a17SVictor Perevertkin             DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
209*8a978a17SVictor Perevertkin                         "Resource Descriptor not found %!STATUS!", status);
210*8a978a17SVictor Perevertkin             goto exit;
211*8a978a17SVictor Perevertkin         }
212*8a978a17SVictor Perevertkin 
213*8a978a17SVictor Perevertkin         if (desc->Type == CmResourceTypePort) {
214*8a978a17SVictor Perevertkin             SIZE_T len;
215*8a978a17SVictor Perevertkin             PHYSICAL_ADDRESS pa;
216*8a978a17SVictor Perevertkin 
217*8a978a17SVictor Perevertkin             //
218*8a978a17SVictor Perevertkin             // This will populate Length, StartPa and EndPa
219*8a978a17SVictor Perevertkin             //
220*8a978a17SVictor Perevertkin             len = GetResourceLength(desc, &pa);
221*8a978a17SVictor Perevertkin             if (len) {
222*8a978a17SVictor Perevertkin                 m_PortResourceTable[index].SetPhysicalAddress(pa, len);
223*8a978a17SVictor Perevertkin             }
224*8a978a17SVictor Perevertkin 
225*8a978a17SVictor Perevertkin             index++;
226*8a978a17SVictor Perevertkin         }
227*8a978a17SVictor Perevertkin     }
228*8a978a17SVictor Perevertkin 
229*8a978a17SVictor Perevertkin exit:
230*8a978a17SVictor Perevertkin 
231*8a978a17SVictor Perevertkin     if (!NT_SUCCESS(status)) {
232*8a978a17SVictor Perevertkin         if (m_PortResourceTable != NULL) {
233*8a978a17SVictor Perevertkin             delete [] m_PortResourceTable;
234*8a978a17SVictor Perevertkin             m_PortResourceTable = NULL;
235*8a978a17SVictor Perevertkin             m_PortResourceTableSizeCe = 0;
236*8a978a17SVictor Perevertkin         }
237*8a978a17SVictor Perevertkin     }
238*8a978a17SVictor Perevertkin 
239*8a978a17SVictor Perevertkin     if (locked) {
240*8a978a17SVictor Perevertkin         UnlockResourceTable();
241*8a978a17SVictor Perevertkin     }
242*8a978a17SVictor Perevertkin 
243*8a978a17SVictor Perevertkin     return status;
244*8a978a17SVictor Perevertkin }
245*8a978a17SVictor Perevertkin 
246*8a978a17SVictor Perevertkin 
247*8a978a17SVictor Perevertkin VOID
UpdateRegisterResourceEntryLocked(__in FxRegisterResourceInfo * Entry,__in PVOID SystemMappedAddress,__in SIZE_T NumberOfBytes,__in PVOID UsermodeMappedAddress)248*8a978a17SVictor Perevertkin FxCmResList::UpdateRegisterResourceEntryLocked(
249*8a978a17SVictor Perevertkin     __in FxRegisterResourceInfo* Entry,
250*8a978a17SVictor Perevertkin     __in PVOID SystemMappedAddress,
251*8a978a17SVictor Perevertkin     __in SIZE_T NumberOfBytes,
252*8a978a17SVictor Perevertkin     __in PVOID UsermodeMappedAddress
253*8a978a17SVictor Perevertkin     )
254*8a978a17SVictor Perevertkin {
255*8a978a17SVictor Perevertkin     Entry->SetMappedAddress(SystemMappedAddress, NumberOfBytes, UsermodeMappedAddress);
256*8a978a17SVictor Perevertkin }
257*8a978a17SVictor Perevertkin 
258*8a978a17SVictor Perevertkin VOID
ClearRegisterResourceEntryLocked(__in FxRegisterResourceInfo * Entry)259*8a978a17SVictor Perevertkin FxCmResList::ClearRegisterResourceEntryLocked(
260*8a978a17SVictor Perevertkin     __in FxRegisterResourceInfo* Entry
261*8a978a17SVictor Perevertkin     )
262*8a978a17SVictor Perevertkin {
263*8a978a17SVictor Perevertkin     Entry->ClearMappedAddress();
264*8a978a17SVictor Perevertkin }
265*8a978a17SVictor Perevertkin 
266*8a978a17SVictor Perevertkin HRESULT
ValidateRegisterPhysicalAddressRange(__in PHYSICAL_ADDRESS PhysicalAddress,__in SIZE_T Size,__out FxRegisterResourceInfo ** TableEntry)267*8a978a17SVictor Perevertkin FxCmResList::ValidateRegisterPhysicalAddressRange (
268*8a978a17SVictor Perevertkin     __in PHYSICAL_ADDRESS PhysicalAddress,
269*8a978a17SVictor Perevertkin     __in SIZE_T Size,
270*8a978a17SVictor Perevertkin     __out FxRegisterResourceInfo** TableEntry
271*8a978a17SVictor Perevertkin     )
272*8a978a17SVictor Perevertkin /*++
273*8a978a17SVictor Perevertkin 
274*8a978a17SVictor Perevertkin Routine Description:
275*8a978a17SVictor Perevertkin 
276*8a978a17SVictor Perevertkin     This routine checks whether the physical address range is part of the resources
277*8a978a17SVictor Perevertkin     assigned to the device by pnp manager. It also returns the table entry
278*8a978a17SVictor Perevertkin     corresponding to the physical address range from register resource table.
279*8a978a17SVictor Perevertkin 
280*8a978a17SVictor Perevertkin Arguments:
281*8a978a17SVictor Perevertkin 
282*8a978a17SVictor Perevertkin     PhysicalAddress - Supplies physical address to validate
283*8a978a17SVictor Perevertkin 
284*8a978a17SVictor Perevertkin     Size - Supplies size of address range in bytes.
285*8a978a17SVictor Perevertkin 
286*8a978a17SVictor Perevertkin     TableEntry - Supplies a pointer to store the table entry that corresponds to
287*8a978a17SVictor Perevertkin                  this physical address.
288*8a978a17SVictor Perevertkin 
289*8a978a17SVictor Perevertkin Return Value:
290*8a978a17SVictor Perevertkin 
291*8a978a17SVictor Perevertkin     HRESULT
292*8a978a17SVictor Perevertkin 
293*8a978a17SVictor Perevertkin     S_OK if physical address is one assigned by pnp manager to this device.
294*8a978a17SVictor Perevertkin     E_INAVLIDARG otherwise.
295*8a978a17SVictor Perevertkin 
296*8a978a17SVictor Perevertkin --*/
297*8a978a17SVictor Perevertkin {
298*8a978a17SVictor Perevertkin     ULONG i;
299*8a978a17SVictor Perevertkin     HRESULT hr;
300*8a978a17SVictor Perevertkin     ULONGLONG driverStartPa, driverEndPa, systemStartPa, systemEndPa;
301*8a978a17SVictor Perevertkin     ULONGLONG tmp;
302*8a978a17SVictor Perevertkin     FxRegisterResourceInfo* entry = NULL;
303*8a978a17SVictor Perevertkin 
304*8a978a17SVictor Perevertkin     *TableEntry = NULL;
305*8a978a17SVictor Perevertkin 
306*8a978a17SVictor Perevertkin     //
307*8a978a17SVictor Perevertkin     // Physical address is of LONGLONG type (signed) we need to cast it to
308*8a978a17SVictor Perevertkin     // ULONGLONG for comparision because in a LONGLONG comprison, the
309*8a978a17SVictor Perevertkin     // result is different when highest bit is set vs when it is not set.
310*8a978a17SVictor Perevertkin     //
311*8a978a17SVictor Perevertkin     driverStartPa = PhysicalAddress.QuadPart;
312*8a978a17SVictor Perevertkin 
313*8a978a17SVictor Perevertkin     //
314*8a978a17SVictor Perevertkin     //  driverEndPa = driverStartPa + Size - 1;
315*8a978a17SVictor Perevertkin     //
316*8a978a17SVictor Perevertkin     hr = ULongLongAdd(driverStartPa, Size, &tmp);
317*8a978a17SVictor Perevertkin     FX_VERIFY_WITH_NAME(DRIVER(BadArgument, TODO), CHECK("Integer overflow occurred"
318*8a978a17SVictor Perevertkin         "when computing register address range", SUCCEEDED(hr)),
319*8a978a17SVictor Perevertkin         GetDriverGlobals()->Public.DriverName);
320*8a978a17SVictor Perevertkin 
321*8a978a17SVictor Perevertkin     driverEndPa = tmp - 1;
322*8a978a17SVictor Perevertkin 
323*8a978a17SVictor Perevertkin     //
324*8a978a17SVictor Perevertkin     // We allow one physical address range mapping only. The base address and
325*8a978a17SVictor Perevertkin     // length can be flexible within the assigned range.
326*8a978a17SVictor Perevertkin     //
327*8a978a17SVictor Perevertkin     for (i = 0; i < m_RegisterResourceTableSizeCe; i++) {
328*8a978a17SVictor Perevertkin         entry = &m_RegisterResourceTable[i];
329*8a978a17SVictor Perevertkin 
330*8a978a17SVictor Perevertkin         //
331*8a978a17SVictor Perevertkin         // No need to do int overflow safe additon here since start address and
332*8a978a17SVictor Perevertkin         // length are assigned by pnp manager. Note that we don't store endPa in
333*8a978a17SVictor Perevertkin         // resource table the way we do for SystemVa is because endPa is not
334*8a978a17SVictor Perevertkin         // needed in hot path so can be computed using length.
335*8a978a17SVictor Perevertkin         //
336*8a978a17SVictor Perevertkin         systemStartPa = entry->m_StartPa.QuadPart;
337*8a978a17SVictor Perevertkin         systemEndPa  = systemStartPa + entry->m_Length - 1;
338*8a978a17SVictor Perevertkin 
339*8a978a17SVictor Perevertkin         if (driverStartPa >= systemStartPa &&
340*8a978a17SVictor Perevertkin             driverEndPa <= systemEndPa) {
341*8a978a17SVictor Perevertkin 
342*8a978a17SVictor Perevertkin             FX_VERIFY_WITH_NAME(DRIVER(BadArgument, TODO), CHECK("Attempt to do multiple "
343*8a978a17SVictor Perevertkin                 "mapping of same resource, or multiple mapping in same resource"
344*8a978a17SVictor Perevertkin                 " range",
345*8a978a17SVictor Perevertkin                 (entry->m_StartSystemVa == NULL)), GetDriverGlobals()->Public.DriverName);
346*8a978a17SVictor Perevertkin             FX_VERIFY_WITH_NAME(INTERNAL, CHECK_NULL(entry->m_EndSystemVa),
347*8a978a17SVictor Perevertkin                 GetDriverGlobals()->Public.DriverName);
348*8a978a17SVictor Perevertkin             FX_VERIFY_WITH_NAME(INTERNAL, CHECK_NULL(entry->m_StartUsermodeVa),
349*8a978a17SVictor Perevertkin                 GetDriverGlobals()->Public.DriverName);
350*8a978a17SVictor Perevertkin             FX_VERIFY_WITH_NAME(INTERNAL, CHECK("Mapped length not zero",
351*8a978a17SVictor Perevertkin                 (entry->m_MappedLength == 0)), GetDriverGlobals()->Public.DriverName);
352*8a978a17SVictor Perevertkin 
353*8a978a17SVictor Perevertkin             *TableEntry = entry;
354*8a978a17SVictor Perevertkin 
355*8a978a17SVictor Perevertkin             return S_OK;
356*8a978a17SVictor Perevertkin         }
357*8a978a17SVictor Perevertkin     }
358*8a978a17SVictor Perevertkin 
359*8a978a17SVictor Perevertkin     return E_INVALIDARG;
360*8a978a17SVictor Perevertkin }
361*8a978a17SVictor Perevertkin 
362*8a978a17SVictor Perevertkin HRESULT
ValidateAndClearMapping(__in PVOID Address,__in SIZE_T Length)363*8a978a17SVictor Perevertkin FxCmResList::ValidateAndClearMapping(
364*8a978a17SVictor Perevertkin     __in PVOID Address,
365*8a978a17SVictor Perevertkin     __in SIZE_T Length
366*8a978a17SVictor Perevertkin     )
367*8a978a17SVictor Perevertkin /*++
368*8a978a17SVictor Perevertkin 
369*8a978a17SVictor Perevertkin Routine Description:
370*8a978a17SVictor Perevertkin 
371*8a978a17SVictor Perevertkin     This routine checks whether the mapped system base address and size is part
372*8a978a17SVictor Perevertkin     of the resources assigned to the device by pnp manager. If so it clears the
373*8a978a17SVictor Perevertkin     system and usermode address mapping from the table.
374*8a978a17SVictor Perevertkin 
375*8a978a17SVictor Perevertkin Arguments:
376*8a978a17SVictor Perevertkin 
377*8a978a17SVictor Perevertkin     Address - Supplies system base address to validate
378*8a978a17SVictor Perevertkin 
379*8a978a17SVictor Perevertkin     Size - Supplies size of address range in bytes.
380*8a978a17SVictor Perevertkin 
381*8a978a17SVictor Perevertkin Return Value:
382*8a978a17SVictor Perevertkin 
383*8a978a17SVictor Perevertkin     HRESULT
384*8a978a17SVictor Perevertkin 
385*8a978a17SVictor Perevertkin     S_OK if system address is one mapped to a register resource.
386*8a978a17SVictor Perevertkin     E_INAVLIDARG otherwise.
387*8a978a17SVictor Perevertkin 
388*8a978a17SVictor Perevertkin --*/
389*8a978a17SVictor Perevertkin {
390*8a978a17SVictor Perevertkin     HRESULT hr = E_INVALIDARG;
391*8a978a17SVictor Perevertkin     ULONG i;
392*8a978a17SVictor Perevertkin     FxRegisterResourceInfo* entry = NULL;
393*8a978a17SVictor Perevertkin 
394*8a978a17SVictor Perevertkin     LockResourceTable();
395*8a978a17SVictor Perevertkin 
396*8a978a17SVictor Perevertkin     for (i = 0; i < m_RegisterResourceTableSizeCe; i++) {
397*8a978a17SVictor Perevertkin         entry = &m_RegisterResourceTable[i];
398*8a978a17SVictor Perevertkin 
399*8a978a17SVictor Perevertkin         if (NULL != entry->m_StartSystemVa &&
400*8a978a17SVictor Perevertkin             Address == entry->m_StartSystemVa &&
401*8a978a17SVictor Perevertkin             Length == entry->m_MappedLength) {
402*8a978a17SVictor Perevertkin             //
403*8a978a17SVictor Perevertkin             // there is a valid mapping. clear it.
404*8a978a17SVictor Perevertkin             //
405*8a978a17SVictor Perevertkin             FX_VERIFY_WITH_NAME(INTERNAL, CHECK_NOT_NULL(entry->m_EndSystemVa),
406*8a978a17SVictor Perevertkin                 GetDriverGlobals()->Public.DriverName);
407*8a978a17SVictor Perevertkin 
408*8a978a17SVictor Perevertkin             ClearRegisterResourceEntryLocked(entry);
409*8a978a17SVictor Perevertkin 
410*8a978a17SVictor Perevertkin             hr = S_OK;
411*8a978a17SVictor Perevertkin             break;
412*8a978a17SVictor Perevertkin         }
413*8a978a17SVictor Perevertkin     }
414*8a978a17SVictor Perevertkin 
415*8a978a17SVictor Perevertkin     UnlockResourceTable();
416*8a978a17SVictor Perevertkin 
417*8a978a17SVictor Perevertkin     return hr;
418*8a978a17SVictor Perevertkin }
419*8a978a17SVictor Perevertkin 
420*8a978a17SVictor Perevertkin HRESULT
ValidateRegisterSystemBaseAddress(__in PVOID Address,__out PVOID * UsermodeBaseAddress)421*8a978a17SVictor Perevertkin FxCmResList::ValidateRegisterSystemBaseAddress (
422*8a978a17SVictor Perevertkin     __in PVOID Address,
423*8a978a17SVictor Perevertkin     __out PVOID* UsermodeBaseAddress
424*8a978a17SVictor Perevertkin     )
425*8a978a17SVictor Perevertkin /*++
426*8a978a17SVictor Perevertkin 
427*8a978a17SVictor Perevertkin Routine Description:
428*8a978a17SVictor Perevertkin 
429*8a978a17SVictor Perevertkin     This routine checks whether the mapped system base address and size is part
430*8a978a17SVictor Perevertkin     of the resources assigned to the device by pnp manager. If so, it returns
431*8a978a17SVictor Perevertkin     corresponding user-mode mapped base address. It is applicable
432*8a978a17SVictor Perevertkin     only when registers are mapped to user-mode.
433*8a978a17SVictor Perevertkin 
434*8a978a17SVictor Perevertkin Arguments:
435*8a978a17SVictor Perevertkin 
436*8a978a17SVictor Perevertkin     Address - Supplies system base address to validate
437*8a978a17SVictor Perevertkin 
438*8a978a17SVictor Perevertkin Return Value:
439*8a978a17SVictor Perevertkin 
440*8a978a17SVictor Perevertkin     HRESULT
441*8a978a17SVictor Perevertkin 
442*8a978a17SVictor Perevertkin     S_OK if system address is one mapped to a register resource.
443*8a978a17SVictor Perevertkin     E_INAVLIDARG otherwise.
444*8a978a17SVictor Perevertkin 
445*8a978a17SVictor Perevertkin --*/
446*8a978a17SVictor Perevertkin {
447*8a978a17SVictor Perevertkin     ULONG i;
448*8a978a17SVictor Perevertkin     FxRegisterResourceInfo* entry = NULL;
449*8a978a17SVictor Perevertkin 
450*8a978a17SVictor Perevertkin     LockResourceTable();
451*8a978a17SVictor Perevertkin     for (i = 0; i < m_RegisterResourceTableSizeCe; i++) {
452*8a978a17SVictor Perevertkin         entry = &m_RegisterResourceTable[i];
453*8a978a17SVictor Perevertkin 
454*8a978a17SVictor Perevertkin         if (Address == entry->m_StartSystemVa) {
455*8a978a17SVictor Perevertkin 
456*8a978a17SVictor Perevertkin             FX_VERIFY_WITH_NAME(INTERNAL, CHECK_NOT_NULL(entry->m_StartUsermodeVa),
457*8a978a17SVictor Perevertkin                 GetDriverGlobals()->Public.DriverName);
458*8a978a17SVictor Perevertkin 
459*8a978a17SVictor Perevertkin             *UsermodeBaseAddress = entry->m_StartUsermodeVa;
460*8a978a17SVictor Perevertkin 
461*8a978a17SVictor Perevertkin             UnlockResourceTable();
462*8a978a17SVictor Perevertkin             return S_OK;
463*8a978a17SVictor Perevertkin         }
464*8a978a17SVictor Perevertkin     }
465*8a978a17SVictor Perevertkin 
466*8a978a17SVictor Perevertkin     UnlockResourceTable();
467*8a978a17SVictor Perevertkin     return E_INVALIDARG;
468*8a978a17SVictor Perevertkin }
469*8a978a17SVictor Perevertkin 
470*8a978a17SVictor Perevertkin HRESULT
ValidateRegisterSystemAddressRange(__in PVOID SystemAddress,__in SIZE_T Length,__out_opt PVOID * UsermodeAddress)471*8a978a17SVictor Perevertkin FxCmResList::ValidateRegisterSystemAddressRange (
472*8a978a17SVictor Perevertkin     __in PVOID SystemAddress,
473*8a978a17SVictor Perevertkin     __in SIZE_T Length,
474*8a978a17SVictor Perevertkin     __out_opt PVOID* UsermodeAddress
475*8a978a17SVictor Perevertkin     )
476*8a978a17SVictor Perevertkin /*++
477*8a978a17SVictor Perevertkin 
478*8a978a17SVictor Perevertkin Routine Description:
479*8a978a17SVictor Perevertkin 
480*8a978a17SVictor Perevertkin     This routine checks whether given system mapped address and length is within
481*8a978a17SVictor Perevertkin     one of the assigned resource ranges. Optionally, tt computes the usermode
482*8a978a17SVictor Perevertkin     address corresponding to the system address.
483*8a978a17SVictor Perevertkin 
484*8a978a17SVictor Perevertkin Arguments:
485*8a978a17SVictor Perevertkin 
486*8a978a17SVictor Perevertkin     Address - Supplies register address to validate
487*8a978a17SVictor Perevertkin 
488*8a978a17SVictor Perevertkin     Size - Supplies size of address range in bytes.
489*8a978a17SVictor Perevertkin 
490*8a978a17SVictor Perevertkin     UsermodeAddress - returns usermode address corresponding to system address
491*8a978a17SVictor Perevertkin 
492*8a978a17SVictor Perevertkin Return Value:
493*8a978a17SVictor Perevertkin 
494*8a978a17SVictor Perevertkin     HRESULT
495*8a978a17SVictor Perevertkin 
496*8a978a17SVictor Perevertkin     S_OK if system address range is valid.
497*8a978a17SVictor Perevertkin     E_INAVLIDARG otherwise.
498*8a978a17SVictor Perevertkin 
499*8a978a17SVictor Perevertkin --*/
500*8a978a17SVictor Perevertkin {
501*8a978a17SVictor Perevertkin     HRESULT hr = E_INVALIDARG;
502*8a978a17SVictor Perevertkin     FxRegisterResourceInfo* entry = NULL;
503*8a978a17SVictor Perevertkin     SIZE_T offset = 0;
504*8a978a17SVictor Perevertkin     ULONG i;
505*8a978a17SVictor Perevertkin     PVOID start = NULL;
506*8a978a17SVictor Perevertkin     PVOID end  = NULL;
507*8a978a17SVictor Perevertkin     ULONG_PTR tmp;
508*8a978a17SVictor Perevertkin 
509*8a978a17SVictor Perevertkin     //
510*8a978a17SVictor Perevertkin     // compute system address range to look for
511*8a978a17SVictor Perevertkin     //
512*8a978a17SVictor Perevertkin     start = SystemAddress;
513*8a978a17SVictor Perevertkin 
514*8a978a17SVictor Perevertkin     //
515*8a978a17SVictor Perevertkin     // Use interger overflow safe functions
516*8a978a17SVictor Perevertkin     // end = ((PUCHAR)SystemAddress) + Length - 1;
517*8a978a17SVictor Perevertkin     //
518*8a978a17SVictor Perevertkin     hr = ULongPtrAdd((ULONG_PTR) start, Length, &tmp);
519*8a978a17SVictor Perevertkin     FX_VERIFY_WITH_NAME(DRIVER(BadArgument, TODO), CHECK("Integer overflow occurred"
520*8a978a17SVictor Perevertkin         "when computing register address range", SUCCEEDED(hr)),
521*8a978a17SVictor Perevertkin         GetDriverGlobals()->Public.DriverName);
522*8a978a17SVictor Perevertkin 
523*8a978a17SVictor Perevertkin     end = (PVOID)(tmp - 1);
524*8a978a17SVictor Perevertkin 
525*8a978a17SVictor Perevertkin     //
526*8a978a17SVictor Perevertkin     // check if range is in the register resource table
527*8a978a17SVictor Perevertkin     //
528*8a978a17SVictor Perevertkin     hr = E_INVALIDARG;
529*8a978a17SVictor Perevertkin     for (i = 0; i < m_RegisterResourceTableSizeCe; i++) {
530*8a978a17SVictor Perevertkin         entry = &m_RegisterResourceTable[i];
531*8a978a17SVictor Perevertkin 
532*8a978a17SVictor Perevertkin         if (start >= entry->m_StartSystemVa &&
533*8a978a17SVictor Perevertkin             end <= entry->m_EndSystemVa) {
534*8a978a17SVictor Perevertkin             hr = S_OK;
535*8a978a17SVictor Perevertkin             break;
536*8a978a17SVictor Perevertkin         }
537*8a978a17SVictor Perevertkin     }
538*8a978a17SVictor Perevertkin 
539*8a978a17SVictor Perevertkin     //
540*8a978a17SVictor Perevertkin     // compute the corresponding usermode address
541*8a978a17SVictor Perevertkin     //
542*8a978a17SVictor Perevertkin     if (SUCCEEDED(hr) && UsermodeAddress != NULL) {
543*8a978a17SVictor Perevertkin         offset = ((PUCHAR)SystemAddress) - ((PUCHAR)entry->m_StartSystemVa);
544*8a978a17SVictor Perevertkin         *UsermodeAddress = ((PUCHAR)entry->m_StartUsermodeVa) + offset;
545*8a978a17SVictor Perevertkin     }
546*8a978a17SVictor Perevertkin 
547*8a978a17SVictor Perevertkin     return hr;
548*8a978a17SVictor Perevertkin }
549*8a978a17SVictor Perevertkin 
550*8a978a17SVictor Perevertkin SIZE_T
GetResourceLength(__in PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,__out_opt PHYSICAL_ADDRESS * Start)551*8a978a17SVictor Perevertkin FxCmResList::GetResourceLength(
552*8a978a17SVictor Perevertkin     __in PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,
553*8a978a17SVictor Perevertkin     __out_opt PHYSICAL_ADDRESS* Start
554*8a978a17SVictor Perevertkin     )
555*8a978a17SVictor Perevertkin /*++
556*8a978a17SVictor Perevertkin 
557*8a978a17SVictor Perevertkin Routine Description:
558*8a978a17SVictor Perevertkin 
559*8a978a17SVictor Perevertkin     This routine decodes the length from a CmPartialResourceDescriptor
560*8a978a17SVictor Perevertkin     describing a memory resource.
561*8a978a17SVictor Perevertkin 
562*8a978a17SVictor Perevertkin Arguments:
563*8a978a17SVictor Perevertkin 
564*8a978a17SVictor Perevertkin     Descriptor - Supplies resource descriptor from which to decode length
565*8a978a17SVictor Perevertkin 
566*8a978a17SVictor Perevertkin     Start - Supplies optional buffer into which start address will be stored.
567*8a978a17SVictor Perevertkin 
568*8a978a17SVictor Perevertkin Return Value:
569*8a978a17SVictor Perevertkin 
570*8a978a17SVictor Perevertkin     Decoded Length
571*8a978a17SVictor Perevertkin 
572*8a978a17SVictor Perevertkin --*/
573*8a978a17SVictor Perevertkin {
574*8a978a17SVictor Perevertkin     ULONGLONG length;
575*8a978a17SVictor Perevertkin 
576*8a978a17SVictor Perevertkin     length = 0;
577*8a978a17SVictor Perevertkin 
578*8a978a17SVictor Perevertkin     ASSERT((Descriptor->Type == CmResourceTypeMemory) ||
579*8a978a17SVictor Perevertkin           (Descriptor->Type == CmResourceTypeMemoryLarge) ||
580*8a978a17SVictor Perevertkin           (Descriptor->Type == CmResourceTypePort));
581*8a978a17SVictor Perevertkin 
582*8a978a17SVictor Perevertkin     //
583*8a978a17SVictor Perevertkin     // If it is not large memory resource than length is in u.Memory.Length.
584*8a978a17SVictor Perevertkin     // For large memory resource, the length is given by different fields in
585*8a978a17SVictor Perevertkin     // CM_PARTIAL_RESOURCE_DESCRIPTOR structure.
586*8a978a17SVictor Perevertkin     //
587*8a978a17SVictor Perevertkin     if ((Descriptor->Type == CmResourceTypeMemory) ||
588*8a978a17SVictor Perevertkin         (Descriptor->Type == CmResourceTypePort)) {
589*8a978a17SVictor Perevertkin         length = Descriptor->u.Memory.Length;
590*8a978a17SVictor Perevertkin 
591*8a978a17SVictor Perevertkin     } else if (Descriptor->Flags & CM_RESOURCE_MEMORY_LARGE_40) {
592*8a978a17SVictor Perevertkin         length = (((ULONGLONG)Descriptor->u.Memory40.Length40) << 8);
593*8a978a17SVictor Perevertkin 
594*8a978a17SVictor Perevertkin     } else if (Descriptor->Flags & CM_RESOURCE_MEMORY_LARGE_48) {
595*8a978a17SVictor Perevertkin         length = (((ULONGLONG)Descriptor->u.Memory48.Length48) << 16);
596*8a978a17SVictor Perevertkin 
597*8a978a17SVictor Perevertkin     } else if (Descriptor->Flags & CM_RESOURCE_MEMORY_LARGE_64) {
598*8a978a17SVictor Perevertkin         length = (((ULONGLONG)Descriptor->u.Memory64.Length64) << 32);
599*8a978a17SVictor Perevertkin 
600*8a978a17SVictor Perevertkin     } else {
601*8a978a17SVictor Perevertkin         //
602*8a978a17SVictor Perevertkin         // It should not be possible to get here.
603*8a978a17SVictor Perevertkin         //
604*8a978a17SVictor Perevertkin         ASSERT(FALSE);
605*8a978a17SVictor Perevertkin     }
606*8a978a17SVictor Perevertkin 
607*8a978a17SVictor Perevertkin     if (Start != NULL) {
608*8a978a17SVictor Perevertkin         *Start = Descriptor->u.Generic.Start;
609*8a978a17SVictor Perevertkin     }
610*8a978a17SVictor Perevertkin 
611*8a978a17SVictor Perevertkin     //
612*8a978a17SVictor Perevertkin     // large memory descriptor is only supported on 64-bit so the casting
613*8a978a17SVictor Perevertkin     // below is ok.
614*8a978a17SVictor Perevertkin     //
615*8a978a17SVictor Perevertkin     return (SIZE_T) length;
616*8a978a17SVictor Perevertkin }
617*8a978a17SVictor Perevertkin 
618*8a978a17SVictor Perevertkin HRESULT
MapIoSpaceWorker(__in PHYSICAL_ADDRESS PhysicalAddress,__in SIZE_T NumberOfBytes,__in MEMORY_CACHING_TYPE CacheType,__deref_out VOID ** PseudoBaseAddress)619*8a978a17SVictor Perevertkin FxCmResList::MapIoSpaceWorker(
620*8a978a17SVictor Perevertkin     __in PHYSICAL_ADDRESS PhysicalAddress,
621*8a978a17SVictor Perevertkin     __in SIZE_T NumberOfBytes,
622*8a978a17SVictor Perevertkin     __in MEMORY_CACHING_TYPE  CacheType,
623*8a978a17SVictor Perevertkin     __deref_out VOID** PseudoBaseAddress
624*8a978a17SVictor Perevertkin     )
625*8a978a17SVictor Perevertkin {
626*8a978a17SVictor Perevertkin     IWudfDeviceStack *deviceStack;
627*8a978a17SVictor Perevertkin     PVOID systemAddress;
628*8a978a17SVictor Perevertkin     PVOID usermodeAddress;
629*8a978a17SVictor Perevertkin     HRESULT hr;
630*8a978a17SVictor Perevertkin     FxRegisterResourceInfo* resEntry;
631*8a978a17SVictor Perevertkin 
632*8a978a17SVictor Perevertkin     //
633*8a978a17SVictor Perevertkin     // check if this physical resource is among the assigned resources.
634*8a978a17SVictor Perevertkin     // If it is, retrieve the table entry corresponding to to register res.
635*8a978a17SVictor Perevertkin     //
636*8a978a17SVictor Perevertkin     LockResourceTable();
637*8a978a17SVictor Perevertkin 
638*8a978a17SVictor Perevertkin     hr = ValidateRegisterPhysicalAddressRange(PhysicalAddress,
639*8a978a17SVictor Perevertkin                                               NumberOfBytes,
640*8a978a17SVictor Perevertkin                                               &resEntry);
641*8a978a17SVictor Perevertkin 
642*8a978a17SVictor Perevertkin     FX_VERIFY_WITH_NAME(DRIVER(BadArgument, TODO),
643*8a978a17SVictor Perevertkin         CHECK("Invalid physical address or number of bytes provided",
644*8a978a17SVictor Perevertkin         (SUCCEEDED(hr))), GetDriverGlobals()->Public.DriverName);
645*8a978a17SVictor Perevertkin 
646*8a978a17SVictor Perevertkin     *PseudoBaseAddress = NULL;
647*8a978a17SVictor Perevertkin 
648*8a978a17SVictor Perevertkin     //
649*8a978a17SVictor Perevertkin     // Call host
650*8a978a17SVictor Perevertkin     //
651*8a978a17SVictor Perevertkin     deviceStack = GetDevice()->GetDeviceStack();
652*8a978a17SVictor Perevertkin     systemAddress = NULL;
653*8a978a17SVictor Perevertkin     usermodeAddress = NULL;
654*8a978a17SVictor Perevertkin 
655*8a978a17SVictor Perevertkin     if(GetDevice()->AreRegistersMappedToUsermode()) {
656*8a978a17SVictor Perevertkin         hr = deviceStack->MapIoSpace(PhysicalAddress,
657*8a978a17SVictor Perevertkin                                 NumberOfBytes,
658*8a978a17SVictor Perevertkin                                 CacheType,
659*8a978a17SVictor Perevertkin                                 &systemAddress,
660*8a978a17SVictor Perevertkin                                 &usermodeAddress);
661*8a978a17SVictor Perevertkin     }
662*8a978a17SVictor Perevertkin     else {
663*8a978a17SVictor Perevertkin         hr = deviceStack->MapIoSpace(PhysicalAddress,
664*8a978a17SVictor Perevertkin                                 NumberOfBytes,
665*8a978a17SVictor Perevertkin                                 CacheType,
666*8a978a17SVictor Perevertkin                                 &systemAddress,
667*8a978a17SVictor Perevertkin                                 NULL);
668*8a978a17SVictor Perevertkin     }
669*8a978a17SVictor Perevertkin 
670*8a978a17SVictor Perevertkin     if (SUCCEEDED(hr)) {
671*8a978a17SVictor Perevertkin         //
672*8a978a17SVictor Perevertkin         // update the mapped resource list entry and add it to list
673*8a978a17SVictor Perevertkin         //
674*8a978a17SVictor Perevertkin         UpdateRegisterResourceEntryLocked(resEntry,
675*8a978a17SVictor Perevertkin                                           systemAddress,
676*8a978a17SVictor Perevertkin                                           NumberOfBytes,
677*8a978a17SVictor Perevertkin                                           usermodeAddress);
678*8a978a17SVictor Perevertkin 
679*8a978a17SVictor Perevertkin         //
680*8a978a17SVictor Perevertkin         // Convert system address to pseudo (opaque) base address
681*8a978a17SVictor Perevertkin         //
682*8a978a17SVictor Perevertkin         *PseudoBaseAddress = GetDevice()->GetPseudoAddressFromSystemAddress(
683*8a978a17SVictor Perevertkin                                                             systemAddress
684*8a978a17SVictor Perevertkin                                                             );
685*8a978a17SVictor Perevertkin     }
686*8a978a17SVictor Perevertkin 
687*8a978a17SVictor Perevertkin     UnlockResourceTable();
688*8a978a17SVictor Perevertkin 
689*8a978a17SVictor Perevertkin     return hr;
690*8a978a17SVictor Perevertkin }
691*8a978a17SVictor Perevertkin 
692*8a978a17SVictor Perevertkin VOID
ValidateResourceUnmap(VOID)693*8a978a17SVictor Perevertkin FxCmResList::ValidateResourceUnmap(
694*8a978a17SVictor Perevertkin     VOID
695*8a978a17SVictor Perevertkin     )
696*8a978a17SVictor Perevertkin {
697*8a978a17SVictor Perevertkin     ULONG i;
698*8a978a17SVictor Perevertkin     FxRegisterResourceInfo* entry = NULL;
699*8a978a17SVictor Perevertkin 
700*8a978a17SVictor Perevertkin     //
701*8a978a17SVictor Perevertkin     // make sure driver has unmapped its resources. No need to
702*8a978a17SVictor Perevertkin     // acquire the resource validation table lock as this is called in
703*8a978a17SVictor Perevertkin     // ReleaseHardware pnp callback and cannot race with another framework
704*8a978a17SVictor Perevertkin     // pnp callback that updates this table (PrepareHardware) so no invalid
705*8a978a17SVictor Perevertkin     // access. If a driver thread unmaps after ReleaseHardware return then also
706*8a978a17SVictor Perevertkin     // it will be a valid access of table entry.
707*8a978a17SVictor Perevertkin     //
708*8a978a17SVictor Perevertkin 
709*8a978a17SVictor Perevertkin     for (i = 0; i < m_RegisterResourceTableSizeCe; i++) {
710*8a978a17SVictor Perevertkin         entry = &m_RegisterResourceTable[i];
711*8a978a17SVictor Perevertkin 
712*8a978a17SVictor Perevertkin         FX_VERIFY_WITH_NAME(DRIVER(BadArgument, TODO), CHECK("Driver did not unmap its "
713*8a978a17SVictor Perevertkin             "register resources", (entry->m_StartSystemVa == NULL)), GetDriverGlobals()->Public.DriverName);
714*8a978a17SVictor Perevertkin     }
715*8a978a17SVictor Perevertkin }
716*8a978a17SVictor Perevertkin 
717*8a978a17SVictor Perevertkin HRESULT
ValidatePortAddressRange(__in PVOID Address,__in SIZE_T Length)718*8a978a17SVictor Perevertkin FxCmResList::ValidatePortAddressRange(
719*8a978a17SVictor Perevertkin     __in PVOID Address,
720*8a978a17SVictor Perevertkin     __in SIZE_T Length
721*8a978a17SVictor Perevertkin     )
722*8a978a17SVictor Perevertkin {
723*8a978a17SVictor Perevertkin     ULONG i;
724*8a978a17SVictor Perevertkin     HRESULT hr;
725*8a978a17SVictor Perevertkin     ULONGLONG driverStartPa, driverEndPa, systemStartPa, systemEndPa;
726*8a978a17SVictor Perevertkin     ULONGLONG tmp;
727*8a978a17SVictor Perevertkin     FxPortResourceInfo* entry = NULL;
728*8a978a17SVictor Perevertkin 
729*8a978a17SVictor Perevertkin     driverStartPa = (ULONGLONG)Address;
730*8a978a17SVictor Perevertkin 
731*8a978a17SVictor Perevertkin     //
732*8a978a17SVictor Perevertkin     //  driverEndPa = driverStartPa + Length - 1;
733*8a978a17SVictor Perevertkin     //
734*8a978a17SVictor Perevertkin     hr = ULongLongAdd(driverStartPa, Length, &tmp);
735*8a978a17SVictor Perevertkin     FX_VERIFY_WITH_NAME(DRIVER(BadArgument, TODO), CHECK("Integer overflow occurred"
736*8a978a17SVictor Perevertkin         "when computing port address range", SUCCEEDED(hr)),
737*8a978a17SVictor Perevertkin         GetDriverGlobals()->Public.DriverName);
738*8a978a17SVictor Perevertkin 
739*8a978a17SVictor Perevertkin     driverEndPa = tmp - 1;
740*8a978a17SVictor Perevertkin 
741*8a978a17SVictor Perevertkin     for (i = 0; i < m_PortResourceTableSizeCe; i++) {
742*8a978a17SVictor Perevertkin         entry = &m_PortResourceTable[i];
743*8a978a17SVictor Perevertkin 
744*8a978a17SVictor Perevertkin         systemStartPa = entry->m_StartPa.QuadPart;
745*8a978a17SVictor Perevertkin         systemEndPa = entry->m_EndPa.QuadPart;
746*8a978a17SVictor Perevertkin 
747*8a978a17SVictor Perevertkin         if (driverStartPa >= systemStartPa  &&
748*8a978a17SVictor Perevertkin             driverEndPa <= systemEndPa) {
749*8a978a17SVictor Perevertkin             return S_OK;
750*8a978a17SVictor Perevertkin         }
751*8a978a17SVictor Perevertkin     }
752*8a978a17SVictor Perevertkin 
753*8a978a17SVictor Perevertkin     return E_INVALIDARG;
754*8a978a17SVictor Perevertkin }
755*8a978a17SVictor Perevertkin 
756*8a978a17SVictor Perevertkin _Must_inspect_result_
757*8a978a17SVictor Perevertkin NTSTATUS
CheckForConnectionResources(VOID)758*8a978a17SVictor Perevertkin FxCmResList::CheckForConnectionResources(
759*8a978a17SVictor Perevertkin     VOID
760*8a978a17SVictor Perevertkin     )
761*8a978a17SVictor Perevertkin {
762*8a978a17SVictor Perevertkin     NTSTATUS status;
763*8a978a17SVictor Perevertkin     ULONG i;
764*8a978a17SVictor Perevertkin     ULONG count;
765*8a978a17SVictor Perevertkin     PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor;
766*8a978a17SVictor Perevertkin 
767*8a978a17SVictor Perevertkin     status = STATUS_SUCCESS;
768*8a978a17SVictor Perevertkin     count = GetCount();
769*8a978a17SVictor Perevertkin 
770*8a978a17SVictor Perevertkin     for (i = 0; i < count; i++) {
771*8a978a17SVictor Perevertkin         pDescriptor = GetDescriptor(i);
772*8a978a17SVictor Perevertkin         if (pDescriptor == NULL) {
773*8a978a17SVictor Perevertkin             status = STATUS_INVALID_DEVICE_STATE;
774*8a978a17SVictor Perevertkin             DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
775*8a978a17SVictor Perevertkin                         "Resource Descriptor not found %!STATUS!", status);
776*8a978a17SVictor Perevertkin             goto exit;
777*8a978a17SVictor Perevertkin         }
778*8a978a17SVictor Perevertkin 
779*8a978a17SVictor Perevertkin         if (pDescriptor->Type == CmResourceTypeConnection) {
780*8a978a17SVictor Perevertkin             m_HasConnectionResources = TRUE;
781*8a978a17SVictor Perevertkin             break;
782*8a978a17SVictor Perevertkin         }
783*8a978a17SVictor Perevertkin     }
784*8a978a17SVictor Perevertkin 
785*8a978a17SVictor Perevertkin exit:
786*8a978a17SVictor Perevertkin     return status;
787*8a978a17SVictor Perevertkin }
788*8a978a17SVictor Perevertkin 
789