f74fd3516fafa1360bdadd5653a50a877a4379fc
[reactos.git] / drivers / storage / port / storport / misc.c
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 static
19 NTSTATUS
20 NTAPI
21 ForwardIrpAndWaitCompletion(
22 _In_ PDEVICE_OBJECT DeviceObject,
23 _In_ PIRP Irp,
24 _In_ PVOID Context)
25 {
26 if (Irp->PendingReturned)
27 KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
28 return STATUS_MORE_PROCESSING_REQUIRED;
29 }
30
31
32 NTSTATUS
33 ForwardIrpAndWait(
34 _In_ PDEVICE_OBJECT LowerDevice,
35 _In_ PIRP Irp)
36 {
37 KEVENT Event;
38 NTSTATUS Status;
39
40 ASSERT(LowerDevice);
41
42 KeInitializeEvent(&Event, NotificationEvent, FALSE);
43 IoCopyCurrentIrpStackLocationToNext(Irp);
44
45 IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE);
46
47 Status = IoCallDriver(LowerDevice, Irp);
48 if (Status == STATUS_PENDING)
49 {
50 Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
51 if (NT_SUCCESS(Status))
52 Status = Irp->IoStatus.Status;
53 }
54
55 return Status;
56 }
57
58
59 NTSTATUS
60 NTAPI
61 ForwardIrpAndForget(
62 _In_ PDEVICE_OBJECT LowerDevice,
63 _In_ PIRP Irp)
64 {
65 ASSERT(LowerDevice);
66
67 IoSkipCurrentIrpStackLocation(Irp);
68 return IoCallDriver(LowerDevice, Irp);
69 }
70
71
72 INTERFACE_TYPE
73 GetBusInterface(
74 PDEVICE_OBJECT DeviceObject)
75 {
76 GUID Guid;
77 ULONG Length;
78 NTSTATUS Status;
79
80 Status = IoGetDeviceProperty(DeviceObject,
81 DevicePropertyBusTypeGuid,
82 sizeof(Guid),
83 &Guid,
84 &Length);
85 if (!NT_SUCCESS(Status))
86 return InterfaceTypeUndefined;
87
88 if (RtlCompareMemory(&Guid, &GUID_BUS_TYPE_PCMCIA, sizeof(GUID)) == sizeof(GUID))
89 return PCMCIABus;
90 else if (RtlCompareMemory(&Guid, &GUID_BUS_TYPE_PCI, sizeof(GUID)) == sizeof(GUID))
91 return PCIBus;
92 else if (RtlCompareMemory(&Guid, &GUID_BUS_TYPE_ISAPNP, sizeof(GUID)) == sizeof(GUID))
93 return PNPISABus;
94
95 return InterfaceTypeUndefined;
96 }
97
98
99 static
100 ULONG
101 GetResourceListSize(
102 PCM_RESOURCE_LIST ResourceList)
103 {
104 PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
105 INT i;
106 ULONG Size;
107
108 DPRINT1("GetResourceListSize(%p)\n", ResourceList);
109
110 Size = sizeof(CM_RESOURCE_LIST);
111 if (ResourceList->Count == 0)
112 {
113 DPRINT1("Size: 0x%lx (%u)\n", Size, Size);
114 return Size;
115 }
116
117 DPRINT1("ResourceList->Count: %lu\n", ResourceList->Count);
118
119 Descriptor = &ResourceList->List[0];
120 for (i = 0; i < ResourceList->Count; i++)
121 {
122 /* Process resources in CM_FULL_RESOURCE_DESCRIPTOR block number ix. */
123
124 DPRINT1("PartialResourceList->Count: %lu\n", Descriptor->PartialResourceList.Count);
125
126 /* Add the size of the current full descriptor */
127 Size += sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
128 (Descriptor->PartialResourceList.Count - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
129
130 /* Advance to next CM_FULL_RESOURCE_DESCRIPTOR block in memory. */
131 Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)(Descriptor->PartialResourceList.PartialDescriptors +
132 Descriptor->PartialResourceList.Count);
133 }
134
135 DPRINT1("Size: 0x%lx (%u)\n", Size, Size);
136 return Size;
137 }
138
139
140 PCM_RESOURCE_LIST
141 CopyResourceList(
142 POOL_TYPE PoolType,
143 PCM_RESOURCE_LIST Source)
144 {
145 PCM_RESOURCE_LIST Destination;
146 ULONG Size;
147
148 DPRINT1("CopyResourceList(%lu %p)\n",
149 PoolType, Source);
150
151 /* Get the size of the resource list */
152 Size = GetResourceListSize(Source);
153
154 /* Allocate a new buffer */
155 Destination = ExAllocatePoolWithTag(PoolType,
156 Size,
157 TAG_RESOURCE_LIST);
158 if (Destination == NULL)
159 return NULL;
160
161 /* Copy the resource list */
162 RtlCopyMemory(Destination,
163 Source,
164 Size);
165
166 return Destination;
167 }
168
169
170 NTSTATUS
171 QueryBusInterface(
172 PDEVICE_OBJECT DeviceObject,
173 PGUID Guid,
174 USHORT Size,
175 USHORT Version,
176 PBUS_INTERFACE_STANDARD Interface,
177 PVOID InterfaceSpecificData)
178 {
179 KEVENT Event;
180 NTSTATUS Status;
181 PIRP Irp;
182 IO_STATUS_BLOCK IoStatus;
183 PIO_STACK_LOCATION Stack;
184
185 KeInitializeEvent(&Event, NotificationEvent, FALSE);
186
187 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
188 DeviceObject,
189 NULL,
190 0,
191 NULL,
192 &Event,
193 &IoStatus);
194 if (Irp == NULL)
195 return STATUS_INSUFFICIENT_RESOURCES;
196
197 Stack = IoGetNextIrpStackLocation(Irp);
198
199 Stack->MajorFunction = IRP_MJ_PNP;
200 Stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
201 Stack->Parameters.QueryInterface.InterfaceType = Guid;
202 Stack->Parameters.QueryInterface.Size = Size;
203 Stack->Parameters.QueryInterface.Version = Version;
204 Stack->Parameters.QueryInterface.Interface = (PINTERFACE)Interface;
205 Stack->Parameters.QueryInterface.InterfaceSpecificData = InterfaceSpecificData;
206
207 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
208
209 Status = IoCallDriver(DeviceObject, Irp);
210 if (Status == STATUS_PENDING)
211 {
212 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
213
214 Status=IoStatus.Status;
215 }
216
217 return Status;
218 }
219
220
221 BOOLEAN
222 TranslateResourceListAddress(
223 PFDO_DEVICE_EXTENSION DeviceExtension,
224 INTERFACE_TYPE BusType,
225 ULONG SystemIoBusNumber,
226 STOR_PHYSICAL_ADDRESS IoAddress,
227 ULONG NumberOfBytes,
228 BOOLEAN InIoSpace,
229 PPHYSICAL_ADDRESS TranslatedAddress)
230 {
231 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptorA, FullDescriptorT;
232 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptorA, PartialDescriptorT;
233 INT i, j;
234
235 DPRINT1("TranslateResourceListAddress(%p)\n", DeviceExtension);
236
237 FullDescriptorA = DeviceExtension->AllocatedResources->List;
238 FullDescriptorT = DeviceExtension->TranslatedResources->List;
239 for (i = 0; i < DeviceExtension->AllocatedResources->Count; i++)
240 {
241 for (j = 0; j < FullDescriptorA->PartialResourceList.Count; j++)
242 {
243 PartialDescriptorA = FullDescriptorA->PartialResourceList.PartialDescriptors + j;
244 PartialDescriptorT = FullDescriptorT->PartialResourceList.PartialDescriptors + j;
245
246 switch (PartialDescriptorA->Type)
247 {
248 case CmResourceTypePort:
249 DPRINT1("Port: 0x%I64x (0x%lx)\n",
250 PartialDescriptorA->u.Port.Start.QuadPart,
251 PartialDescriptorA->u.Port.Length);
252 if (InIoSpace &&
253 IoAddress.QuadPart >= PartialDescriptorA->u.Port.Start.QuadPart &&
254 IoAddress.QuadPart + NumberOfBytes <= PartialDescriptorA->u.Port.Start.QuadPart + PartialDescriptorA->u.Port.Length)
255 {
256 TranslatedAddress->QuadPart = PartialDescriptorT->u.Port.Start.QuadPart +
257 (IoAddress.QuadPart - PartialDescriptorA->u.Port.Start.QuadPart);
258 return TRUE;
259 }
260 break;
261
262 case CmResourceTypeMemory:
263 DPRINT1("Memory: 0x%I64x (0x%lx)\n",
264 PartialDescriptorA->u.Memory.Start.QuadPart,
265 PartialDescriptorA->u.Memory.Length);
266 if (!InIoSpace &&
267 IoAddress.QuadPart >= PartialDescriptorA->u.Memory.Start.QuadPart &&
268 IoAddress.QuadPart + NumberOfBytes <= PartialDescriptorA->u.Memory.Start.QuadPart + PartialDescriptorA->u.Memory.Length)
269 {
270 TranslatedAddress->QuadPart = PartialDescriptorT->u.Memory.Start.QuadPart +
271 (IoAddress.QuadPart - PartialDescriptorA->u.Memory.Start.QuadPart);
272 return TRUE;
273 }
274 break;
275 }
276 }
277
278 /* Advance to next CM_FULL_RESOURCE_DESCRIPTOR block in memory. */
279 FullDescriptorA = (PCM_FULL_RESOURCE_DESCRIPTOR)(FullDescriptorA->PartialResourceList.PartialDescriptors +
280 FullDescriptorA->PartialResourceList.Count);
281
282 FullDescriptorT = (PCM_FULL_RESOURCE_DESCRIPTOR)(FullDescriptorT->PartialResourceList.PartialDescriptors +
283 FullDescriptorT->PartialResourceList.Count);
284 }
285
286 return FALSE;
287 }
288
289
290 NTSTATUS
291 GetResourceListInterrupt(
292 PFDO_DEVICE_EXTENSION DeviceExtension,
293 PULONG Vector,
294 PKIRQL Irql,
295 KINTERRUPT_MODE *InterruptMode,
296 PBOOLEAN ShareVector,
297 PKAFFINITY Affinity)
298 {
299 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor;
300 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
301 INT i, j;
302
303 DPRINT1("GetResourceListInterrupt(%p)\n",
304 DeviceExtension);
305
306 FullDescriptor = DeviceExtension->TranslatedResources->List;
307 for (i = 0; i < DeviceExtension->TranslatedResources->Count; i++)
308 {
309 for (j = 0; j < FullDescriptor->PartialResourceList.Count; j++)
310 {
311 PartialDescriptor = FullDescriptor->PartialResourceList.PartialDescriptors + j;
312
313 switch (PartialDescriptor->Type)
314 {
315 case CmResourceTypeInterrupt:
316 DPRINT1("Interrupt: Level %lu Vector %lu\n",
317 PartialDescriptor->u.Interrupt.Level,
318 PartialDescriptor->u.Interrupt.Vector);
319
320 *Vector = PartialDescriptor->u.Interrupt.Vector;
321 *Irql = (KIRQL)PartialDescriptor->u.Interrupt.Level;
322 *InterruptMode = (PartialDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED) ? Latched : LevelSensitive;
323 *ShareVector = (PartialDescriptor->ShareDisposition == CmResourceShareShared) ? TRUE : FALSE;
324 *Affinity = PartialDescriptor->u.Interrupt.Affinity;
325
326 return STATUS_SUCCESS;
327 }
328 }
329
330 /* Advance to next CM_FULL_RESOURCE_DESCRIPTOR block in memory. */
331 FullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)(FullDescriptor->PartialResourceList.PartialDescriptors +
332 FullDescriptor->PartialResourceList.Count);
333 }
334
335 return STATUS_NOT_FOUND;
336 }
337
338
339 NTSTATUS
340 AllocateAddressMapping(
341 PMAPPED_ADDRESS *MappedAddressList,
342 STOR_PHYSICAL_ADDRESS IoAddress,
343 PVOID MappedAddress,
344 ULONG NumberOfBytes,
345 ULONG BusNumber)
346 {
347 PMAPPED_ADDRESS Mapping;
348
349 DPRINT1("AllocateAddressMapping()\n");
350
351 Mapping = ExAllocatePoolWithTag(NonPagedPool,
352 sizeof(MAPPED_ADDRESS),
353 TAG_ADDRESS_MAPPING);
354 if (Mapping == NULL)
355 {
356 DPRINT1("No memory!\n");
357 return STATUS_NO_MEMORY;
358 }
359
360 RtlZeroMemory(Mapping, sizeof(MAPPED_ADDRESS));
361
362 Mapping->NextMappedAddress = *MappedAddressList;
363 *MappedAddressList = Mapping;
364
365 Mapping->IoAddress = IoAddress;
366 Mapping->MappedAddress = MappedAddress;
367 Mapping->NumberOfBytes = NumberOfBytes;
368 Mapping->BusNumber = BusNumber;
369
370 return STATUS_SUCCESS;
371 }
372
373 #if defined(_M_AMD64)
374 /* KeQuerySystemTime is an inline function,
375 so we cannot forward the export to ntoskrnl */
376 STORPORT_API
377 VOID
378 NTAPI
379 StorPortQuerySystemTime(
380 _Out_ PLARGE_INTEGER CurrentTime)
381 {
382 KeQuerySystemTime(CurrentTime);
383 }
384 #endif /* defined(_M_AMD64) */
385
386 /* EOF */