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