xref: /reactos/drivers/storage/port/storport/misc.c (revision 9393fc32)
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     ULONG Size;
106 
107     DPRINT1("GetResourceListSize(%p)\n", ResourceList);
108 
109     Size = sizeof(CM_RESOURCE_LIST);
110     if (ResourceList->Count == 0)
111     {
112         DPRINT1("Size: 0x%lx (%u)\n", Size, Size);
113         return Size;
114     }
115 
116     DPRINT1("ResourceList->Count: %lu\n", ResourceList->Count);
117 
118     Descriptor = &ResourceList->List[0];
119 
120     DPRINT1("PartialResourceList->Count: %lu\n", Descriptor->PartialResourceList.Count);
121 
122     /* Add the size of the partial descriptors */
123     if (Descriptor->PartialResourceList.Count > 1)
124         Size += (Descriptor->PartialResourceList.Count - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
125 
126     DPRINT1("Size: 0x%lx (%u)\n", Size, Size);
127     return Size;
128 }
129 
130 
131 PCM_RESOURCE_LIST
132 CopyResourceList(
133     POOL_TYPE PoolType,
134     PCM_RESOURCE_LIST Source)
135 {
136     PCM_RESOURCE_LIST Destination;
137     ULONG Size;
138 
139     DPRINT1("CopyResourceList(%lu %p)\n",
140             PoolType, Source);
141 
142     /* Get the size of the resource list */
143     Size = GetResourceListSize(Source);
144 
145     /* Allocate a new buffer */
146     Destination = ExAllocatePoolWithTag(PoolType,
147                                         Size,
148                                         TAG_RESOURCE_LIST);
149     if (Destination == NULL)
150         return NULL;
151 
152     /* Copy the resource list */
153     RtlCopyMemory(Destination,
154                   Source,
155                   Size);
156 
157     return Destination;
158 }
159 
160 
161 NTSTATUS
162 QueryBusInterface(
163     PDEVICE_OBJECT DeviceObject,
164     PGUID Guid,
165     USHORT Size,
166     USHORT Version,
167     PBUS_INTERFACE_STANDARD Interface,
168     PVOID InterfaceSpecificData)
169 {
170     KEVENT Event;
171     NTSTATUS Status;
172     PIRP Irp;
173     IO_STATUS_BLOCK IoStatus;
174     PIO_STACK_LOCATION Stack;
175 
176     KeInitializeEvent(&Event, NotificationEvent, FALSE);
177 
178     Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
179                                        DeviceObject,
180                                        NULL,
181                                        0,
182                                        NULL,
183                                        &Event,
184                                        &IoStatus);
185     if (Irp == NULL)
186         return STATUS_INSUFFICIENT_RESOURCES;
187 
188     Stack = IoGetNextIrpStackLocation(Irp);
189 
190     Stack->MajorFunction = IRP_MJ_PNP;
191     Stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
192     Stack->Parameters.QueryInterface.InterfaceType = Guid;
193     Stack->Parameters.QueryInterface.Size = Size;
194     Stack->Parameters.QueryInterface.Version = Version;
195     Stack->Parameters.QueryInterface.Interface = (PINTERFACE)Interface;
196     Stack->Parameters.QueryInterface.InterfaceSpecificData = InterfaceSpecificData;
197 
198     Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
199 
200     Status = IoCallDriver(DeviceObject, Irp);
201     if (Status == STATUS_PENDING)
202     {
203         KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
204 
205         Status=IoStatus.Status;
206     }
207 
208     return Status;
209 }
210 
211 
212 BOOLEAN
213 TranslateResourceListAddress(
214     PFDO_DEVICE_EXTENSION DeviceExtension,
215     INTERFACE_TYPE BusType,
216     ULONG SystemIoBusNumber,
217     STOR_PHYSICAL_ADDRESS IoAddress,
218     ULONG NumberOfBytes,
219     BOOLEAN InIoSpace,
220     PPHYSICAL_ADDRESS TranslatedAddress)
221 {
222     PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptorA, FullDescriptorT;
223     PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptorA, PartialDescriptorT;
224     INT i, j;
225 
226     DPRINT1("TranslateResourceListAddress(%p)\n", DeviceExtension);
227 
228     FullDescriptorA = DeviceExtension->AllocatedResources->List;
229     FullDescriptorT = DeviceExtension->TranslatedResources->List;
230     for (i = 0; i < DeviceExtension->AllocatedResources->Count; i++)
231     {
232         for (j = 0; j < FullDescriptorA->PartialResourceList.Count; j++)
233         {
234             PartialDescriptorA = FullDescriptorA->PartialResourceList.PartialDescriptors + j;
235             PartialDescriptorT = FullDescriptorT->PartialResourceList.PartialDescriptors + j;
236 
237             switch (PartialDescriptorA->Type)
238             {
239                 case CmResourceTypePort:
240                     DPRINT1("Port: 0x%I64x (0x%lx)\n",
241                             PartialDescriptorA->u.Port.Start.QuadPart,
242                             PartialDescriptorA->u.Port.Length);
243                     if (InIoSpace &&
244                         IoAddress.QuadPart >= PartialDescriptorA->u.Port.Start.QuadPart &&
245                         IoAddress.QuadPart + NumberOfBytes <= PartialDescriptorA->u.Port.Start.QuadPart + PartialDescriptorA->u.Port.Length)
246                     {
247                         TranslatedAddress->QuadPart = PartialDescriptorT->u.Port.Start.QuadPart +
248                                                       (IoAddress.QuadPart - PartialDescriptorA->u.Port.Start.QuadPart);
249                         return TRUE;
250                     }
251                     break;
252 
253                 case CmResourceTypeMemory:
254                     DPRINT1("Memory: 0x%I64x (0x%lx)\n",
255                             PartialDescriptorA->u.Memory.Start.QuadPart,
256                             PartialDescriptorA->u.Memory.Length);
257                     if (!InIoSpace &&
258                         IoAddress.QuadPart >= PartialDescriptorA->u.Memory.Start.QuadPart &&
259                         IoAddress.QuadPart + NumberOfBytes <= PartialDescriptorA->u.Memory.Start.QuadPart + PartialDescriptorA->u.Memory.Length)
260                     {
261                         TranslatedAddress->QuadPart = PartialDescriptorT->u.Memory.Start.QuadPart +
262                                                       (IoAddress.QuadPart - PartialDescriptorA->u.Memory.Start.QuadPart);
263                         return TRUE;
264                     }
265                     break;
266             }
267         }
268 
269         /* Advance to next CM_FULL_RESOURCE_DESCRIPTOR block in memory. */
270         FullDescriptorA = (PCM_FULL_RESOURCE_DESCRIPTOR)(FullDescriptorA->PartialResourceList.PartialDescriptors +
271                                                          FullDescriptorA->PartialResourceList.Count);
272 
273         FullDescriptorT = (PCM_FULL_RESOURCE_DESCRIPTOR)(FullDescriptorT->PartialResourceList.PartialDescriptors +
274                                                          FullDescriptorT->PartialResourceList.Count);
275     }
276 
277     return FALSE;
278 }
279 
280 
281 NTSTATUS
282 GetResourceListInterrupt(
283     PFDO_DEVICE_EXTENSION DeviceExtension,
284     PULONG Vector,
285     PKIRQL Irql,
286     KINTERRUPT_MODE *InterruptMode,
287     PBOOLEAN ShareVector,
288     PKAFFINITY Affinity)
289 {
290     PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor;
291     PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
292     INT i, j;
293 
294     DPRINT1("GetResourceListInterrupt(%p)\n",
295             DeviceExtension);
296 
297     FullDescriptor = DeviceExtension->TranslatedResources->List;
298     for (i = 0; i < DeviceExtension->TranslatedResources->Count; i++)
299     {
300         for (j = 0; j < FullDescriptor->PartialResourceList.Count; j++)
301         {
302             PartialDescriptor = FullDescriptor->PartialResourceList.PartialDescriptors + j;
303 
304             switch (PartialDescriptor->Type)
305             {
306                 case CmResourceTypeInterrupt:
307                     DPRINT1("Interrupt: Level %lu  Vector %lu\n",
308                             PartialDescriptor->u.Interrupt.Level,
309                             PartialDescriptor->u.Interrupt.Vector);
310 
311                     *Vector = PartialDescriptor->u.Interrupt.Vector;
312                     *Irql = (KIRQL)PartialDescriptor->u.Interrupt.Level;
313                     *InterruptMode = (PartialDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED) ? Latched : LevelSensitive;
314                     *ShareVector = (PartialDescriptor->ShareDisposition == CmResourceShareShared) ? TRUE : FALSE;
315                     *Affinity = PartialDescriptor->u.Interrupt.Affinity;
316 
317                     return STATUS_SUCCESS;
318             }
319         }
320 
321         /* Advance to next CM_FULL_RESOURCE_DESCRIPTOR block in memory. */
322         FullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)(FullDescriptor->PartialResourceList.PartialDescriptors +
323                                                         FullDescriptor->PartialResourceList.Count);
324     }
325 
326     return STATUS_NOT_FOUND;
327 }
328 
329 
330 NTSTATUS
331 AllocateAddressMapping(
332     PMAPPED_ADDRESS *MappedAddressList,
333     STOR_PHYSICAL_ADDRESS IoAddress,
334     PVOID MappedAddress,
335     ULONG NumberOfBytes,
336     ULONG BusNumber)
337 {
338     PMAPPED_ADDRESS Mapping;
339 
340     DPRINT1("AllocateAddressMapping()\n");
341 
342     Mapping = ExAllocatePoolWithTag(NonPagedPool,
343                                     sizeof(MAPPED_ADDRESS),
344                                     TAG_ADDRESS_MAPPING);
345     if (Mapping == NULL)
346     {
347         DPRINT1("No memory!\n");
348         return STATUS_NO_MEMORY;
349     }
350 
351     RtlZeroMemory(Mapping, sizeof(MAPPED_ADDRESS));
352 
353     Mapping->NextMappedAddress = *MappedAddressList;
354     *MappedAddressList = Mapping;
355 
356     Mapping->IoAddress = IoAddress;
357     Mapping->MappedAddress = MappedAddress;
358     Mapping->NumberOfBytes = NumberOfBytes;
359     Mapping->BusNumber = BusNumber;
360 
361     return STATUS_SUCCESS;
362 }
363 
364 /* EOF */
365