1 /*
2 * PROJECT: ReactOS Storport Driver
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Storport helper functions
5 * COPYRIGHT: Copyright 2017 Eric Kohl (eric.kohl@reactos.org)
6 */
7
8 /* INCLUDES *******************************************************************/
9
10 #include "precomp.h"
11
12 #define NDEBUG
13 #include <debug.h>
14
15
16 /* FUNCTIONS ******************************************************************/
17
18 NTSTATUS
19 NTAPI
ForwardIrpAndForget(_In_ PDEVICE_OBJECT LowerDevice,_In_ PIRP Irp)20 ForwardIrpAndForget(
21 _In_ PDEVICE_OBJECT LowerDevice,
22 _In_ PIRP Irp)
23 {
24 ASSERT(LowerDevice);
25
26 IoSkipCurrentIrpStackLocation(Irp);
27 return IoCallDriver(LowerDevice, Irp);
28 }
29
30
31 INTERFACE_TYPE
GetBusInterface(PDEVICE_OBJECT DeviceObject)32 GetBusInterface(
33 PDEVICE_OBJECT DeviceObject)
34 {
35 GUID Guid;
36 ULONG Length;
37 NTSTATUS Status;
38
39 Status = IoGetDeviceProperty(DeviceObject,
40 DevicePropertyBusTypeGuid,
41 sizeof(Guid),
42 &Guid,
43 &Length);
44 if (!NT_SUCCESS(Status))
45 return InterfaceTypeUndefined;
46
47 if (RtlCompareMemory(&Guid, &GUID_BUS_TYPE_PCMCIA, sizeof(GUID)) == sizeof(GUID))
48 return PCMCIABus;
49 else if (RtlCompareMemory(&Guid, &GUID_BUS_TYPE_PCI, sizeof(GUID)) == sizeof(GUID))
50 return PCIBus;
51 else if (RtlCompareMemory(&Guid, &GUID_BUS_TYPE_ISAPNP, sizeof(GUID)) == sizeof(GUID))
52 return PNPISABus;
53
54 return InterfaceTypeUndefined;
55 }
56
57
58 static
59 ULONG
GetResourceListSize(PCM_RESOURCE_LIST ResourceList)60 GetResourceListSize(
61 PCM_RESOURCE_LIST ResourceList)
62 {
63 PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
64 ULONG Size;
65
66 DPRINT1("GetResourceListSize(%p)\n", ResourceList);
67
68 Size = sizeof(CM_RESOURCE_LIST);
69 if (ResourceList->Count == 0)
70 {
71 DPRINT1("Size: 0x%lx (%u)\n", Size, Size);
72 return Size;
73 }
74
75 DPRINT1("ResourceList->Count: %lu\n", ResourceList->Count);
76
77 Descriptor = &ResourceList->List[0];
78
79 DPRINT1("PartialResourceList->Count: %lu\n", Descriptor->PartialResourceList.Count);
80
81 /* Add the size of the partial descriptors */
82 if (Descriptor->PartialResourceList.Count > 1)
83 Size += (Descriptor->PartialResourceList.Count - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
84
85 DPRINT1("Size: 0x%lx (%u)\n", Size, Size);
86 return Size;
87 }
88
89
90 PCM_RESOURCE_LIST
CopyResourceList(POOL_TYPE PoolType,PCM_RESOURCE_LIST Source)91 CopyResourceList(
92 POOL_TYPE PoolType,
93 PCM_RESOURCE_LIST Source)
94 {
95 PCM_RESOURCE_LIST Destination;
96 ULONG Size;
97
98 DPRINT1("CopyResourceList(%lu %p)\n",
99 PoolType, Source);
100
101 /* Get the size of the resource list */
102 Size = GetResourceListSize(Source);
103
104 /* Allocate a new buffer */
105 Destination = ExAllocatePoolWithTag(PoolType,
106 Size,
107 TAG_RESOURCE_LIST);
108 if (Destination == NULL)
109 return NULL;
110
111 /* Copy the resource list */
112 RtlCopyMemory(Destination,
113 Source,
114 Size);
115
116 return Destination;
117 }
118
119
120 NTSTATUS
QueryBusInterface(PDEVICE_OBJECT DeviceObject,PGUID Guid,USHORT Size,USHORT Version,PBUS_INTERFACE_STANDARD Interface,PVOID InterfaceSpecificData)121 QueryBusInterface(
122 PDEVICE_OBJECT DeviceObject,
123 PGUID Guid,
124 USHORT Size,
125 USHORT Version,
126 PBUS_INTERFACE_STANDARD Interface,
127 PVOID InterfaceSpecificData)
128 {
129 KEVENT Event;
130 NTSTATUS Status;
131 PIRP Irp;
132 IO_STATUS_BLOCK IoStatus;
133 PIO_STACK_LOCATION Stack;
134
135 KeInitializeEvent(&Event, NotificationEvent, FALSE);
136
137 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
138 DeviceObject,
139 NULL,
140 0,
141 NULL,
142 &Event,
143 &IoStatus);
144 if (Irp == NULL)
145 return STATUS_INSUFFICIENT_RESOURCES;
146
147 Stack = IoGetNextIrpStackLocation(Irp);
148
149 Stack->MajorFunction = IRP_MJ_PNP;
150 Stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
151 Stack->Parameters.QueryInterface.InterfaceType = Guid;
152 Stack->Parameters.QueryInterface.Size = Size;
153 Stack->Parameters.QueryInterface.Version = Version;
154 Stack->Parameters.QueryInterface.Interface = (PINTERFACE)Interface;
155 Stack->Parameters.QueryInterface.InterfaceSpecificData = InterfaceSpecificData;
156
157 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
158
159 Status = IoCallDriver(DeviceObject, Irp);
160 if (Status == STATUS_PENDING)
161 {
162 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
163
164 Status=IoStatus.Status;
165 }
166
167 return Status;
168 }
169
170
171 BOOLEAN
TranslateResourceListAddress(PFDO_DEVICE_EXTENSION DeviceExtension,INTERFACE_TYPE BusType,ULONG SystemIoBusNumber,STOR_PHYSICAL_ADDRESS IoAddress,ULONG NumberOfBytes,BOOLEAN InIoSpace,PPHYSICAL_ADDRESS TranslatedAddress)172 TranslateResourceListAddress(
173 PFDO_DEVICE_EXTENSION DeviceExtension,
174 INTERFACE_TYPE BusType,
175 ULONG SystemIoBusNumber,
176 STOR_PHYSICAL_ADDRESS IoAddress,
177 ULONG NumberOfBytes,
178 BOOLEAN InIoSpace,
179 PPHYSICAL_ADDRESS TranslatedAddress)
180 {
181 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptorA, FullDescriptorT;
182 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptorA, PartialDescriptorT;
183 INT i, j;
184
185 DPRINT1("TranslateResourceListAddress(%p)\n", DeviceExtension);
186
187 FullDescriptorA = DeviceExtension->AllocatedResources->List;
188 FullDescriptorT = DeviceExtension->TranslatedResources->List;
189 for (i = 0; i < DeviceExtension->AllocatedResources->Count; i++)
190 {
191 for (j = 0; j < FullDescriptorA->PartialResourceList.Count; j++)
192 {
193 PartialDescriptorA = FullDescriptorA->PartialResourceList.PartialDescriptors + j;
194 PartialDescriptorT = FullDescriptorT->PartialResourceList.PartialDescriptors + j;
195
196 switch (PartialDescriptorA->Type)
197 {
198 case CmResourceTypePort:
199 DPRINT1("Port: 0x%I64x (0x%lx)\n",
200 PartialDescriptorA->u.Port.Start.QuadPart,
201 PartialDescriptorA->u.Port.Length);
202 if (InIoSpace &&
203 IoAddress.QuadPart >= PartialDescriptorA->u.Port.Start.QuadPart &&
204 IoAddress.QuadPart + NumberOfBytes <= PartialDescriptorA->u.Port.Start.QuadPart + PartialDescriptorA->u.Port.Length)
205 {
206 TranslatedAddress->QuadPart = PartialDescriptorT->u.Port.Start.QuadPart +
207 (IoAddress.QuadPart - PartialDescriptorA->u.Port.Start.QuadPart);
208 return TRUE;
209 }
210 break;
211
212 case CmResourceTypeMemory:
213 DPRINT1("Memory: 0x%I64x (0x%lx)\n",
214 PartialDescriptorA->u.Memory.Start.QuadPart,
215 PartialDescriptorA->u.Memory.Length);
216 if (!InIoSpace &&
217 IoAddress.QuadPart >= PartialDescriptorA->u.Memory.Start.QuadPart &&
218 IoAddress.QuadPart + NumberOfBytes <= PartialDescriptorA->u.Memory.Start.QuadPart + PartialDescriptorA->u.Memory.Length)
219 {
220 TranslatedAddress->QuadPart = PartialDescriptorT->u.Memory.Start.QuadPart +
221 (IoAddress.QuadPart - PartialDescriptorA->u.Memory.Start.QuadPart);
222 return TRUE;
223 }
224 break;
225 }
226 }
227
228 /* Advance to next CM_FULL_RESOURCE_DESCRIPTOR block in memory. */
229 FullDescriptorA = (PCM_FULL_RESOURCE_DESCRIPTOR)(FullDescriptorA->PartialResourceList.PartialDescriptors +
230 FullDescriptorA->PartialResourceList.Count);
231
232 FullDescriptorT = (PCM_FULL_RESOURCE_DESCRIPTOR)(FullDescriptorT->PartialResourceList.PartialDescriptors +
233 FullDescriptorT->PartialResourceList.Count);
234 }
235
236 return FALSE;
237 }
238
239
240 NTSTATUS
GetResourceListInterrupt(PFDO_DEVICE_EXTENSION DeviceExtension,PULONG Vector,PKIRQL Irql,KINTERRUPT_MODE * InterruptMode,PBOOLEAN ShareVector,PKAFFINITY Affinity)241 GetResourceListInterrupt(
242 PFDO_DEVICE_EXTENSION DeviceExtension,
243 PULONG Vector,
244 PKIRQL Irql,
245 KINTERRUPT_MODE *InterruptMode,
246 PBOOLEAN ShareVector,
247 PKAFFINITY Affinity)
248 {
249 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor;
250 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
251 INT i, j;
252
253 DPRINT1("GetResourceListInterrupt(%p)\n",
254 DeviceExtension);
255
256 FullDescriptor = DeviceExtension->TranslatedResources->List;
257 for (i = 0; i < DeviceExtension->TranslatedResources->Count; i++)
258 {
259 for (j = 0; j < FullDescriptor->PartialResourceList.Count; j++)
260 {
261 PartialDescriptor = FullDescriptor->PartialResourceList.PartialDescriptors + j;
262
263 switch (PartialDescriptor->Type)
264 {
265 case CmResourceTypeInterrupt:
266 DPRINT1("Interrupt: Level %lu Vector %lu\n",
267 PartialDescriptor->u.Interrupt.Level,
268 PartialDescriptor->u.Interrupt.Vector);
269
270 *Vector = PartialDescriptor->u.Interrupt.Vector;
271 *Irql = (KIRQL)PartialDescriptor->u.Interrupt.Level;
272 *InterruptMode = (PartialDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED) ? Latched : LevelSensitive;
273 *ShareVector = (PartialDescriptor->ShareDisposition == CmResourceShareShared) ? TRUE : FALSE;
274 *Affinity = PartialDescriptor->u.Interrupt.Affinity;
275
276 return STATUS_SUCCESS;
277 }
278 }
279
280 /* Advance to next CM_FULL_RESOURCE_DESCRIPTOR block in memory. */
281 FullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)(FullDescriptor->PartialResourceList.PartialDescriptors +
282 FullDescriptor->PartialResourceList.Count);
283 }
284
285 return STATUS_NOT_FOUND;
286 }
287
288
289 NTSTATUS
AllocateAddressMapping(PMAPPED_ADDRESS * MappedAddressList,STOR_PHYSICAL_ADDRESS IoAddress,PVOID MappedAddress,ULONG NumberOfBytes,ULONG BusNumber)290 AllocateAddressMapping(
291 PMAPPED_ADDRESS *MappedAddressList,
292 STOR_PHYSICAL_ADDRESS IoAddress,
293 PVOID MappedAddress,
294 ULONG NumberOfBytes,
295 ULONG BusNumber)
296 {
297 PMAPPED_ADDRESS Mapping;
298
299 DPRINT1("AllocateAddressMapping()\n");
300
301 Mapping = ExAllocatePoolWithTag(NonPagedPool,
302 sizeof(MAPPED_ADDRESS),
303 TAG_ADDRESS_MAPPING);
304 if (Mapping == NULL)
305 {
306 DPRINT1("No memory!\n");
307 return STATUS_NO_MEMORY;
308 }
309
310 RtlZeroMemory(Mapping, sizeof(MAPPED_ADDRESS));
311
312 Mapping->NextMappedAddress = *MappedAddressList;
313 *MappedAddressList = Mapping;
314
315 Mapping->IoAddress = IoAddress;
316 Mapping->MappedAddress = MappedAddress;
317 Mapping->NumberOfBytes = NumberOfBytes;
318 Mapping->BusNumber = BusNumber;
319
320 return STATUS_SUCCESS;
321 }
322
323 /* EOF */
324