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