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 = -1; //SP_UNINITIALIZED_VALUE; 45 PortConfig->DmaChannel = -1; //SP_UNINITIALIZED_VALUE; 46 PortConfig->DmaPort = -1; //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 = 128; 65 66 PortConfig->SpecificLuExtensionSize = InitData->SpecificLuExtensionSize; 67 PortConfig->SrbExtensionSize = InitData->SrbExtensionSize; 68 PortConfig->MaximumNumberOfLogicalUnits = 1; 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 < 7; i++) 86 PortConfig->InitiatorBusId[i] = 0xff; 87 88 return STATUS_SUCCESS; 89 } 90 91 92 static 93 VOID 94 AssignResourcesToConfiguration( 95 _In_ PPORT_CONFIGURATION_INFORMATION PortConfiguration, 96 _In_ PCM_RESOURCE_LIST ResourceList, 97 _In_ ULONG NumberOfAccessRanges) 98 { 99 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor; 100 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; 101 PCM_PARTIAL_RESOURCE_LIST PartialResourceList; 102 PACCESS_RANGE AccessRange; 103 INT i, j; 104 ULONG RangeNumber = 0, Interrupt = 0, Dma = 0; 105 106 DPRINT1("AssignResourceToConfiguration(%p %p %lu)\n", 107 PortConfiguration, ResourceList, NumberOfAccessRanges); 108 109 FullDescriptor = &ResourceList->List[0]; 110 for (i = 0; i < ResourceList->Count; i++) 111 { 112 PartialResourceList = &FullDescriptor->PartialResourceList; 113 114 for (j = 0; j < PartialResourceList->Count; j++) 115 { 116 PartialDescriptor = &PartialResourceList->PartialDescriptors[j]; 117 118 switch (PartialDescriptor->Type) 119 { 120 case CmResourceTypePort: 121 DPRINT1("Port: 0x%I64x (0x%lx)\n", 122 PartialDescriptor->u.Port.Start.QuadPart, 123 PartialDescriptor->u.Port.Length); 124 if (RangeNumber < NumberOfAccessRanges) 125 { 126 AccessRange = &((*(PortConfiguration->AccessRanges))[RangeNumber]); 127 AccessRange->RangeStart = PartialDescriptor->u.Port.Start; 128 AccessRange->RangeLength = PartialDescriptor->u.Port.Length; 129 AccessRange->RangeInMemory = FALSE; 130 RangeNumber++; 131 } 132 break; 133 134 case CmResourceTypeMemory: 135 DPRINT1("Memory: 0x%I64x (0x%lx)\n", 136 PartialDescriptor->u.Memory.Start.QuadPart, 137 PartialDescriptor->u.Memory.Length); 138 if (RangeNumber < NumberOfAccessRanges) 139 { 140 AccessRange = &((*(PortConfiguration->AccessRanges))[RangeNumber]); 141 AccessRange->RangeStart = PartialDescriptor->u.Memory.Start; 142 AccessRange->RangeLength = PartialDescriptor->u.Memory.Length; 143 AccessRange->RangeInMemory = TRUE; 144 RangeNumber++; 145 } 146 break; 147 148 case CmResourceTypeInterrupt: 149 DPRINT1("Interrupt: Level %lu Vector %lu\n", 150 PartialDescriptor->u.Interrupt.Level, 151 PartialDescriptor->u.Interrupt.Vector); 152 if (Interrupt == 0) 153 { 154 /* Copy interrupt data */ 155 PortConfiguration->BusInterruptLevel = PartialDescriptor->u.Interrupt.Level; 156 PortConfiguration->BusInterruptVector = PartialDescriptor->u.Interrupt.Vector; 157 158 /* Set interrupt mode accordingly to the resource */ 159 if (PartialDescriptor->Flags == CM_RESOURCE_INTERRUPT_LATCHED) 160 { 161 PortConfiguration->InterruptMode = Latched; 162 } 163 else if (PartialDescriptor->Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE) 164 { 165 PortConfiguration->InterruptMode = LevelSensitive; 166 } 167 } 168 else if (Interrupt == 1) 169 { 170 /* Copy interrupt data */ 171 PortConfiguration->BusInterruptLevel2 = PartialDescriptor->u.Interrupt.Level; 172 PortConfiguration->BusInterruptVector2 = PartialDescriptor->u.Interrupt.Vector; 173 174 /* Set interrupt mode accordingly to the resource */ 175 if (PartialDescriptor->Flags == CM_RESOURCE_INTERRUPT_LATCHED) 176 { 177 PortConfiguration->InterruptMode2 = Latched; 178 } 179 else if (PartialDescriptor->Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE) 180 { 181 PortConfiguration->InterruptMode2 = LevelSensitive; 182 } 183 } 184 Interrupt++; 185 break; 186 187 case CmResourceTypeDma: 188 DPRINT1("Dma: Channel: %lu Port: %lu\n", 189 PartialDescriptor->u.Dma.Channel, 190 PartialDescriptor->u.Dma.Port); 191 if (Dma == 0) 192 { 193 PortConfiguration->DmaChannel = PartialDescriptor->u.Dma.Channel; 194 PortConfiguration->DmaPort = PartialDescriptor->u.Dma.Port; 195 196 if (PartialDescriptor->Flags & CM_RESOURCE_DMA_8) 197 PortConfiguration->DmaWidth = Width8Bits; 198 else if ((PartialDescriptor->Flags & CM_RESOURCE_DMA_16) || 199 (PartialDescriptor->Flags & CM_RESOURCE_DMA_8_AND_16)) 200 PortConfiguration->DmaWidth = Width16Bits; 201 else if (PartialDescriptor->Flags & CM_RESOURCE_DMA_32) 202 PortConfiguration->DmaWidth = Width32Bits; 203 } 204 else if (Dma == 1) 205 { 206 PortConfiguration->DmaChannel2 = PartialDescriptor->u.Dma.Channel; 207 PortConfiguration->DmaPort2 = PartialDescriptor->u.Dma.Port; 208 209 if (PartialDescriptor->Flags & CM_RESOURCE_DMA_8) 210 PortConfiguration->DmaWidth2 = Width8Bits; 211 else if ((PartialDescriptor->Flags & CM_RESOURCE_DMA_16) || 212 (PartialDescriptor->Flags & CM_RESOURCE_DMA_8_AND_16)) 213 PortConfiguration->DmaWidth2 = Width16Bits; 214 else if (PartialDescriptor->Flags & CM_RESOURCE_DMA_32) 215 PortConfiguration->DmaWidth2 = Width32Bits; 216 } 217 Dma++; 218 break; 219 220 default: 221 DPRINT1("Other: %u\n", PartialDescriptor->Type); 222 break; 223 } 224 } 225 226 /* Advance to next CM_FULL_RESOURCE_DESCRIPTOR block in memory. */ 227 FullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)(FullDescriptor->PartialResourceList.PartialDescriptors + 228 FullDescriptor->PartialResourceList.Count); 229 } 230 } 231 232 233 NTSTATUS 234 MiniportInitialize( 235 _In_ PMINIPORT Miniport, 236 _In_ PFDO_DEVICE_EXTENSION DeviceExtension, 237 _In_ PHW_INITIALIZATION_DATA InitData) 238 { 239 PMINIPORT_DEVICE_EXTENSION MiniportExtension; 240 ULONG Size; 241 NTSTATUS Status; 242 243 DPRINT1("MiniportInitialize(%p %p %p)\n", 244 Miniport, DeviceExtension, InitData); 245 246 Miniport->DeviceExtension = DeviceExtension; 247 Miniport->InitData = InitData; 248 249 /* Calculate the miniport device extension size */ 250 Size = sizeof(MINIPORT_DEVICE_EXTENSION) + 251 Miniport->InitData->DeviceExtensionSize; 252 253 /* Allocate and initialize the miniport device extension */ 254 MiniportExtension = ExAllocatePoolWithTag(NonPagedPool, 255 Size, 256 TAG_MINIPORT_DATA); 257 if (MiniportExtension == NULL) 258 return STATUS_NO_MEMORY; 259 260 RtlZeroMemory(MiniportExtension, Size); 261 262 MiniportExtension->Miniport = Miniport; 263 Miniport->MiniportExtension = MiniportExtension; 264 265 /* Initialize the port configuration */ 266 Status = InitializeConfiguration(&Miniport->PortConfig, 267 InitData, 268 DeviceExtension->BusNumber, 269 DeviceExtension->SlotNumber); 270 if (!NT_SUCCESS(Status)) 271 return Status; 272 273 /* Assign the resources to the port configuration */ 274 AssignResourcesToConfiguration(&Miniport->PortConfig, 275 DeviceExtension->AllocatedResources, 276 InitData->NumberOfAccessRanges); 277 278 return STATUS_SUCCESS; 279 } 280 281 282 NTSTATUS 283 MiniportFindAdapter( 284 _In_ PMINIPORT Miniport) 285 { 286 BOOLEAN Reserved = FALSE; 287 ULONG Result; 288 NTSTATUS Status; 289 290 DPRINT1("MiniportFindAdapter(%p)\n", Miniport); 291 292 /* Call the miniport HwFindAdapter routine */ 293 Result = Miniport->InitData->HwFindAdapter(&Miniport->MiniportExtension->HwDeviceExtension, 294 NULL, 295 NULL, 296 NULL, 297 &Miniport->PortConfig, 298 &Reserved); 299 DPRINT1("HwFindAdapter() returned %lu\n", Result); 300 301 /* Convert the result to a status code */ 302 switch (Result) 303 { 304 case SP_RETURN_NOT_FOUND: 305 DPRINT1("SP_RETURN_NOT_FOUND\n"); 306 Status = STATUS_NOT_FOUND; 307 break; 308 309 case SP_RETURN_FOUND: 310 DPRINT1("SP_RETURN_FOUND\n"); 311 Status = STATUS_SUCCESS; 312 break; 313 314 case SP_RETURN_ERROR: 315 DPRINT1("SP_RETURN_ERROR\n"); 316 Status = STATUS_ADAPTER_HARDWARE_ERROR; 317 break; 318 319 case SP_RETURN_BAD_CONFIG: 320 DPRINT1("SP_RETURN_BAD_CONFIG\n"); 321 Status = STATUS_DEVICE_CONFIGURATION_ERROR; 322 break; 323 324 default: 325 DPRINT1("Unknown result: %lu\n", Result); 326 Status = STATUS_INTERNAL_ERROR; 327 break; 328 } 329 330 return Status; 331 } 332 333 334 NTSTATUS 335 MiniportHwInitialize( 336 _In_ PMINIPORT Miniport) 337 { 338 BOOLEAN Result; 339 340 DPRINT1("MiniportHwInitialize(%p)\n", Miniport); 341 342 /* Call the miniport HwInitialize routine */ 343 Result = Miniport->InitData->HwInitialize(&Miniport->MiniportExtension->HwDeviceExtension); 344 DPRINT1("HwInitialize() returned %u\n", Result); 345 346 return Result ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; 347 } 348 349 350 BOOLEAN 351 MiniportHwInterrupt( 352 _In_ PMINIPORT Miniport) 353 { 354 BOOLEAN Result; 355 356 DPRINT1("MiniportHwInterrupt(%p)\n", 357 Miniport); 358 359 Result = Miniport->InitData->HwInterrupt(&Miniport->MiniportExtension->HwDeviceExtension); 360 DPRINT1("HwInterrupt() returned %u\n", Result); 361 362 return Result; 363 } 364 365 /* EOF */ 366