xref: /reactos/drivers/storage/port/storport/misc.c (revision ba3f0743)
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 */
387