1 /* 2 * PROJECT: ReactOS Storport Driver 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Miniport interface code 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 InitializeConfiguration( 21 _In_ PPORT_CONFIGURATION_INFORMATION PortConfig, 22 _In_ PHW_INITIALIZATION_DATA InitData, 23 _In_ ULONG BusNumber, 24 _In_ ULONG SlotNumber) 25 { 26 PCONFIGURATION_INFORMATION ConfigInfo; 27 ULONG i; 28 29 DPRINT1("InitializeConfiguration(%p %p %lu %lu)\n", 30 PortConfig, InitData, BusNumber, SlotNumber); 31 32 /* Get the configurration information */ 33 ConfigInfo = IoGetConfigurationInformation(); 34 35 /* Initialize the port configuration */ 36 RtlZeroMemory(PortConfig, 37 sizeof(PORT_CONFIGURATION_INFORMATION)); 38 39 PortConfig->Length = sizeof(PORT_CONFIGURATION_INFORMATION); 40 PortConfig->SystemIoBusNumber = BusNumber; 41 PortConfig->SlotNumber = SlotNumber; 42 PortConfig->AdapterInterfaceType = InitData->AdapterInterfaceType; 43 44 PortConfig->MaximumTransferLength = SP_UNINITIALIZED_VALUE; 45 PortConfig->DmaChannel = SP_UNINITIALIZED_VALUE; 46 PortConfig->DmaPort = SP_UNINITIALIZED_VALUE; 47 48 PortConfig->InterruptMode = LevelSensitive; 49 50 PortConfig->Master = TRUE; 51 PortConfig->AtdiskPrimaryClaimed = ConfigInfo->AtDiskPrimaryAddressClaimed; 52 PortConfig->AtdiskSecondaryClaimed = ConfigInfo->AtDiskSecondaryAddressClaimed; 53 PortConfig->Dma32BitAddresses = TRUE; 54 PortConfig->DemandMode = FALSE; 55 PortConfig->MapBuffers = InitData->MapBuffers; 56 57 PortConfig->NeedPhysicalAddresses = TRUE; 58 PortConfig->TaggedQueuing = TRUE; 59 PortConfig->AutoRequestSense = TRUE; 60 PortConfig->MultipleRequestPerLu = TRUE; 61 PortConfig->ReceiveEvent = InitData->ReceiveEvent; 62 PortConfig->RealModeInitialized = FALSE; 63 PortConfig->BufferAccessScsiPortControlled = TRUE; 64 PortConfig->MaximumNumberOfTargets = SCSI_MAXIMUM_TARGETS_PER_BUS; 65 66 PortConfig->SpecificLuExtensionSize = InitData->SpecificLuExtensionSize; 67 PortConfig->SrbExtensionSize = InitData->SrbExtensionSize; 68 PortConfig->MaximumNumberOfLogicalUnits = SCSI_MAXIMUM_LOGICAL_UNITS; 69 PortConfig->WmiDataProvider = TRUE; 70 71 PortConfig->NumberOfAccessRanges = InitData->NumberOfAccessRanges; 72 DPRINT1("NumberOfAccessRanges: %lu\n", PortConfig->NumberOfAccessRanges); 73 if (PortConfig->NumberOfAccessRanges != 0) 74 { 75 PortConfig->AccessRanges = ExAllocatePoolWithTag(NonPagedPool, 76 PortConfig->NumberOfAccessRanges * sizeof(ACCESS_RANGE), 77 TAG_ACCRESS_RANGE); 78 if (PortConfig->AccessRanges == NULL) 79 return STATUS_NO_MEMORY; 80 81 RtlZeroMemory(PortConfig->AccessRanges, 82 PortConfig->NumberOfAccessRanges * sizeof(ACCESS_RANGE)); 83 } 84 85 for (i = 0; i < RTL_NUMBER_OF(PortConfig->InitiatorBusId); i++) 86 { 87 PortConfig->InitiatorBusId[i] = (CCHAR)SP_UNINITIALIZED_VALUE; 88 } 89 90 return STATUS_SUCCESS; 91 } 92 93 94 static 95 VOID 96 AssignResourcesToConfiguration( 97 _In_ PPORT_CONFIGURATION_INFORMATION PortConfiguration, 98 _In_ PCM_RESOURCE_LIST ResourceList, 99 _In_ ULONG NumberOfAccessRanges) 100 { 101 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor; 102 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; 103 PCM_PARTIAL_RESOURCE_LIST PartialResourceList; 104 PACCESS_RANGE AccessRange; 105 INT i, j; 106 ULONG RangeNumber = 0, Interrupt = 0, Dma = 0; 107 108 DPRINT1("AssignResourceToConfiguration(%p %p %lu)\n", 109 PortConfiguration, ResourceList, NumberOfAccessRanges); 110 111 FullDescriptor = &ResourceList->List[0]; 112 for (i = 0; i < ResourceList->Count; i++) 113 { 114 PartialResourceList = &FullDescriptor->PartialResourceList; 115 116 for (j = 0; j < PartialResourceList->Count; j++) 117 { 118 PartialDescriptor = &PartialResourceList->PartialDescriptors[j]; 119 120 switch (PartialDescriptor->Type) 121 { 122 case CmResourceTypePort: 123 DPRINT1("Port: 0x%I64x (0x%lx)\n", 124 PartialDescriptor->u.Port.Start.QuadPart, 125 PartialDescriptor->u.Port.Length); 126 if (RangeNumber < NumberOfAccessRanges) 127 { 128 AccessRange = &((*(PortConfiguration->AccessRanges))[RangeNumber]); 129 AccessRange->RangeStart = PartialDescriptor->u.Port.Start; 130 AccessRange->RangeLength = PartialDescriptor->u.Port.Length; 131 AccessRange->RangeInMemory = FALSE; 132 RangeNumber++; 133 } 134 break; 135 136 case CmResourceTypeMemory: 137 DPRINT1("Memory: 0x%I64x (0x%lx)\n", 138 PartialDescriptor->u.Memory.Start.QuadPart, 139 PartialDescriptor->u.Memory.Length); 140 if (RangeNumber < NumberOfAccessRanges) 141 { 142 AccessRange = &((*(PortConfiguration->AccessRanges))[RangeNumber]); 143 AccessRange->RangeStart = PartialDescriptor->u.Memory.Start; 144 AccessRange->RangeLength = PartialDescriptor->u.Memory.Length; 145 AccessRange->RangeInMemory = TRUE; 146 RangeNumber++; 147 } 148 break; 149 150 case CmResourceTypeInterrupt: 151 DPRINT1("Interrupt: Level %lu Vector %lu\n", 152 PartialDescriptor->u.Interrupt.Level, 153 PartialDescriptor->u.Interrupt.Vector); 154 if (Interrupt == 0) 155 { 156 /* Copy interrupt data */ 157 PortConfiguration->BusInterruptLevel = PartialDescriptor->u.Interrupt.Level; 158 PortConfiguration->BusInterruptVector = PartialDescriptor->u.Interrupt.Vector; 159 160 /* Set interrupt mode accordingly to the resource */ 161 if (PartialDescriptor->Flags == CM_RESOURCE_INTERRUPT_LATCHED) 162 { 163 PortConfiguration->InterruptMode = Latched; 164 } 165 else if (PartialDescriptor->Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE) 166 { 167 PortConfiguration->InterruptMode = LevelSensitive; 168 } 169 } 170 else if (Interrupt == 1) 171 { 172 /* Copy interrupt data */ 173 PortConfiguration->BusInterruptLevel2 = PartialDescriptor->u.Interrupt.Level; 174 PortConfiguration->BusInterruptVector2 = PartialDescriptor->u.Interrupt.Vector; 175 176 /* Set interrupt mode accordingly to the resource */ 177 if (PartialDescriptor->Flags == CM_RESOURCE_INTERRUPT_LATCHED) 178 { 179 PortConfiguration->InterruptMode2 = Latched; 180 } 181 else if (PartialDescriptor->Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE) 182 { 183 PortConfiguration->InterruptMode2 = LevelSensitive; 184 } 185 } 186 Interrupt++; 187 break; 188 189 case CmResourceTypeDma: 190 DPRINT1("Dma: Channel: %lu Port: %lu\n", 191 PartialDescriptor->u.Dma.Channel, 192 PartialDescriptor->u.Dma.Port); 193 if (Dma == 0) 194 { 195 PortConfiguration->DmaChannel = PartialDescriptor->u.Dma.Channel; 196 PortConfiguration->DmaPort = PartialDescriptor->u.Dma.Port; 197 198 if (PartialDescriptor->Flags & CM_RESOURCE_DMA_8) 199 PortConfiguration->DmaWidth = Width8Bits; 200 else if ((PartialDescriptor->Flags & CM_RESOURCE_DMA_16) || 201 (PartialDescriptor->Flags & CM_RESOURCE_DMA_8_AND_16)) 202 PortConfiguration->DmaWidth = Width16Bits; 203 else if (PartialDescriptor->Flags & CM_RESOURCE_DMA_32) 204 PortConfiguration->DmaWidth = Width32Bits; 205 } 206 else if (Dma == 1) 207 { 208 PortConfiguration->DmaChannel2 = PartialDescriptor->u.Dma.Channel; 209 PortConfiguration->DmaPort2 = PartialDescriptor->u.Dma.Port; 210 211 if (PartialDescriptor->Flags & CM_RESOURCE_DMA_8) 212 PortConfiguration->DmaWidth2 = Width8Bits; 213 else if ((PartialDescriptor->Flags & CM_RESOURCE_DMA_16) || 214 (PartialDescriptor->Flags & CM_RESOURCE_DMA_8_AND_16)) 215 PortConfiguration->DmaWidth2 = Width16Bits; 216 else if (PartialDescriptor->Flags & CM_RESOURCE_DMA_32) 217 PortConfiguration->DmaWidth2 = Width32Bits; 218 } 219 Dma++; 220 break; 221 222 default: 223 DPRINT1("Other: %u\n", PartialDescriptor->Type); 224 break; 225 } 226 } 227 228 /* Advance to next CM_FULL_RESOURCE_DESCRIPTOR block in memory. */ 229 FullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)(FullDescriptor->PartialResourceList.PartialDescriptors + 230 FullDescriptor->PartialResourceList.Count); 231 } 232 } 233 234 235 NTSTATUS 236 MiniportInitialize( 237 _In_ PMINIPORT Miniport, 238 _In_ PFDO_DEVICE_EXTENSION DeviceExtension, 239 _In_ PHW_INITIALIZATION_DATA InitData) 240 { 241 PMINIPORT_DEVICE_EXTENSION MiniportExtension; 242 ULONG Size; 243 NTSTATUS Status; 244 245 DPRINT1("MiniportInitialize(%p %p %p)\n", 246 Miniport, DeviceExtension, InitData); 247 248 Miniport->DeviceExtension = DeviceExtension; 249 Miniport->InitData = InitData; 250 251 /* Calculate the miniport device extension size */ 252 Size = sizeof(MINIPORT_DEVICE_EXTENSION) + 253 Miniport->InitData->DeviceExtensionSize; 254 255 /* Allocate and initialize the miniport device extension */ 256 MiniportExtension = ExAllocatePoolWithTag(NonPagedPool, 257 Size, 258 TAG_MINIPORT_DATA); 259 if (MiniportExtension == NULL) 260 return STATUS_NO_MEMORY; 261 262 RtlZeroMemory(MiniportExtension, Size); 263 264 MiniportExtension->Miniport = Miniport; 265 Miniport->MiniportExtension = MiniportExtension; 266 267 /* Initialize the port configuration */ 268 Status = InitializeConfiguration(&Miniport->PortConfig, 269 InitData, 270 DeviceExtension->BusNumber, 271 DeviceExtension->SlotNumber); 272 if (!NT_SUCCESS(Status)) 273 return Status; 274 275 /* Assign the resources to the port configuration */ 276 AssignResourcesToConfiguration(&Miniport->PortConfig, 277 DeviceExtension->AllocatedResources, 278 InitData->NumberOfAccessRanges); 279 280 return STATUS_SUCCESS; 281 } 282 283 284 NTSTATUS 285 MiniportFindAdapter( 286 _In_ PMINIPORT Miniport) 287 { 288 BOOLEAN Reserved = FALSE; 289 ULONG Result; 290 NTSTATUS Status; 291 292 DPRINT1("MiniportFindAdapter(%p)\n", Miniport); 293 294 /* Call the miniport HwFindAdapter routine */ 295 Result = Miniport->InitData->HwFindAdapter(&Miniport->MiniportExtension->HwDeviceExtension, 296 NULL, 297 NULL, 298 NULL, 299 &Miniport->PortConfig, 300 &Reserved); 301 DPRINT1("HwFindAdapter() returned %lu\n", Result); 302 303 /* Convert the result to a status code */ 304 switch (Result) 305 { 306 case SP_RETURN_NOT_FOUND: 307 DPRINT1("SP_RETURN_NOT_FOUND\n"); 308 Status = STATUS_NOT_FOUND; 309 break; 310 311 case SP_RETURN_FOUND: 312 DPRINT1("SP_RETURN_FOUND\n"); 313 Status = STATUS_SUCCESS; 314 break; 315 316 case SP_RETURN_ERROR: 317 DPRINT1("SP_RETURN_ERROR\n"); 318 Status = STATUS_ADAPTER_HARDWARE_ERROR; 319 break; 320 321 case SP_RETURN_BAD_CONFIG: 322 DPRINT1("SP_RETURN_BAD_CONFIG\n"); 323 Status = STATUS_DEVICE_CONFIGURATION_ERROR; 324 break; 325 326 default: 327 DPRINT1("Unknown result: %lu\n", Result); 328 Status = STATUS_INTERNAL_ERROR; 329 break; 330 } 331 332 return Status; 333 } 334 335 336 NTSTATUS 337 MiniportHwInitialize( 338 _In_ PMINIPORT Miniport) 339 { 340 BOOLEAN Result; 341 342 DPRINT1("MiniportHwInitialize(%p)\n", Miniport); 343 344 /* Call the miniport HwInitialize routine */ 345 Result = Miniport->InitData->HwInitialize(&Miniport->MiniportExtension->HwDeviceExtension); 346 DPRINT1("HwInitialize() returned %u\n", Result); 347 348 return Result ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; 349 } 350 351 352 BOOLEAN 353 MiniportHwInterrupt( 354 _In_ PMINIPORT Miniport) 355 { 356 BOOLEAN Result; 357 358 DPRINT1("MiniportHwInterrupt(%p)\n", 359 Miniport); 360 361 Result = Miniport->InitData->HwInterrupt(&Miniport->MiniportExtension->HwDeviceExtension); 362 DPRINT1("HwInterrupt() returned %u\n", Result); 363 364 return Result; 365 } 366 367 368 BOOLEAN 369 MiniportStartIo( 370 _In_ PMINIPORT Miniport, 371 _In_ PSCSI_REQUEST_BLOCK Srb) 372 { 373 BOOLEAN Result; 374 375 DPRINT1("MiniportHwStartIo(%p %p)\n", 376 Miniport, Srb); 377 378 Result = Miniport->InitData->HwStartIo(&Miniport->MiniportExtension->HwDeviceExtension, Srb); 379 DPRINT1("HwStartIo() returned %u\n", Result); 380 381 return Result; 382 } 383 384 /* EOF */ 385