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