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