bcbdb05912a609af5a83db7ab210d262a2f2c8bf
[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 /* EOF */