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)
8 /* INCLUDES *******************************************************************/
16 /* FUNCTIONS ******************************************************************/
20 InitializeConfiguration(
21 _In_ PPORT_CONFIGURATION_INFORMATION PortConfig
,
22 _In_ PHW_INITIALIZATION_DATA InitData
,
24 _In_ ULONG SlotNumber
)
26 PCONFIGURATION_INFORMATION ConfigInfo
;
29 DPRINT1("InitializeConfiguration(%p %p %lu %lu)\n",
30 PortConfig
, InitData
, BusNumber
, SlotNumber
);
32 /* Get the configurration information */
33 ConfigInfo
= IoGetConfigurationInformation();
35 /* Initialize the port configuration */
36 RtlZeroMemory(PortConfig
,
37 sizeof(PORT_CONFIGURATION_INFORMATION
));
39 PortConfig
->Length
= sizeof(PORT_CONFIGURATION_INFORMATION
);
40 PortConfig
->SystemIoBusNumber
= BusNumber
;
41 PortConfig
->SlotNumber
= SlotNumber
;
42 PortConfig
->AdapterInterfaceType
= InitData
->AdapterInterfaceType
;
44 PortConfig
->MaximumTransferLength
= SP_UNINITIALIZED_VALUE
;
45 PortConfig
->DmaChannel
= SP_UNINITIALIZED_VALUE
;
46 PortConfig
->DmaPort
= SP_UNINITIALIZED_VALUE
;
48 PortConfig
->InterruptMode
= LevelSensitive
;
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
;
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
;
66 PortConfig
->SpecificLuExtensionSize
= InitData
->SpecificLuExtensionSize
;
67 PortConfig
->SrbExtensionSize
= InitData
->SrbExtensionSize
;
68 PortConfig
->MaximumNumberOfLogicalUnits
= SCSI_MAXIMUM_LOGICAL_UNITS
;
69 PortConfig
->WmiDataProvider
= TRUE
;
71 PortConfig
->NumberOfAccessRanges
= InitData
->NumberOfAccessRanges
;
72 DPRINT1("NumberOfAccessRanges: %lu\n", PortConfig
->NumberOfAccessRanges
);
73 if (PortConfig
->NumberOfAccessRanges
!= 0)
75 PortConfig
->AccessRanges
= ExAllocatePoolWithTag(NonPagedPool
,
76 PortConfig
->NumberOfAccessRanges
* sizeof(ACCESS_RANGE
),
78 if (PortConfig
->AccessRanges
== NULL
)
79 return STATUS_NO_MEMORY
;
81 RtlZeroMemory(PortConfig
->AccessRanges
,
82 PortConfig
->NumberOfAccessRanges
* sizeof(ACCESS_RANGE
));
85 for (i
= 0; i
< RTL_NUMBER_OF(PortConfig
->InitiatorBusId
); i
++)
87 PortConfig
->InitiatorBusId
[i
] = (CCHAR
)SP_UNINITIALIZED_VALUE
;
90 return STATUS_SUCCESS
;
96 AssignResourcesToConfiguration(
97 _In_ PPORT_CONFIGURATION_INFORMATION PortConfiguration
,
98 _In_ PCM_RESOURCE_LIST ResourceList
,
99 _In_ ULONG NumberOfAccessRanges
)
101 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor
;
102 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
103 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
104 PACCESS_RANGE AccessRange
;
106 ULONG RangeNumber
= 0, Interrupt
= 0, Dma
= 0;
108 DPRINT1("AssignResourceToConfiguration(%p %p %lu)\n",
109 PortConfiguration
, ResourceList
, NumberOfAccessRanges
);
111 FullDescriptor
= &ResourceList
->List
[0];
112 for (i
= 0; i
< ResourceList
->Count
; i
++)
114 PartialResourceList
= &FullDescriptor
->PartialResourceList
;
116 for (j
= 0; j
< PartialResourceList
->Count
; j
++)
118 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[j
];
120 switch (PartialDescriptor
->Type
)
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
)
128 AccessRange
= &((*(PortConfiguration
->AccessRanges
))[RangeNumber
]);
129 AccessRange
->RangeStart
= PartialDescriptor
->u
.Port
.Start
;
130 AccessRange
->RangeLength
= PartialDescriptor
->u
.Port
.Length
;
131 AccessRange
->RangeInMemory
= FALSE
;
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
)
142 AccessRange
= &((*(PortConfiguration
->AccessRanges
))[RangeNumber
]);
143 AccessRange
->RangeStart
= PartialDescriptor
->u
.Memory
.Start
;
144 AccessRange
->RangeLength
= PartialDescriptor
->u
.Memory
.Length
;
145 AccessRange
->RangeInMemory
= TRUE
;
150 case CmResourceTypeInterrupt
:
151 DPRINT1("Interrupt: Level %lu Vector %lu\n",
152 PartialDescriptor
->u
.Interrupt
.Level
,
153 PartialDescriptor
->u
.Interrupt
.Vector
);
156 /* Copy interrupt data */
157 PortConfiguration
->BusInterruptLevel
= PartialDescriptor
->u
.Interrupt
.Level
;
158 PortConfiguration
->BusInterruptVector
= PartialDescriptor
->u
.Interrupt
.Vector
;
160 /* Set interrupt mode accordingly to the resource */
161 if (PartialDescriptor
->Flags
== CM_RESOURCE_INTERRUPT_LATCHED
)
163 PortConfiguration
->InterruptMode
= Latched
;
165 else if (PartialDescriptor
->Flags
== CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE
)
167 PortConfiguration
->InterruptMode
= LevelSensitive
;
170 else if (Interrupt
== 1)
172 /* Copy interrupt data */
173 PortConfiguration
->BusInterruptLevel2
= PartialDescriptor
->u
.Interrupt
.Level
;
174 PortConfiguration
->BusInterruptVector2
= PartialDescriptor
->u
.Interrupt
.Vector
;
176 /* Set interrupt mode accordingly to the resource */
177 if (PartialDescriptor
->Flags
== CM_RESOURCE_INTERRUPT_LATCHED
)
179 PortConfiguration
->InterruptMode2
= Latched
;
181 else if (PartialDescriptor
->Flags
== CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE
)
183 PortConfiguration
->InterruptMode2
= LevelSensitive
;
189 case CmResourceTypeDma
:
190 DPRINT1("Dma: Channel: %lu Port: %lu\n",
191 PartialDescriptor
->u
.Dma
.Channel
,
192 PartialDescriptor
->u
.Dma
.Port
);
195 PortConfiguration
->DmaChannel
= PartialDescriptor
->u
.Dma
.Channel
;
196 PortConfiguration
->DmaPort
= PartialDescriptor
->u
.Dma
.Port
;
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
;
208 PortConfiguration
->DmaChannel2
= PartialDescriptor
->u
.Dma
.Channel
;
209 PortConfiguration
->DmaPort2
= PartialDescriptor
->u
.Dma
.Port
;
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
;
223 DPRINT1("Other: %u\n", PartialDescriptor
->Type
);
228 /* Advance to next CM_FULL_RESOURCE_DESCRIPTOR block in memory. */
229 FullDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)(FullDescriptor
->PartialResourceList
.PartialDescriptors
+
230 FullDescriptor
->PartialResourceList
.Count
);
237 _In_ PMINIPORT Miniport
,
238 _In_ PFDO_DEVICE_EXTENSION DeviceExtension
,
239 _In_ PHW_INITIALIZATION_DATA InitData
)
241 PMINIPORT_DEVICE_EXTENSION MiniportExtension
;
245 DPRINT1("MiniportInitialize(%p %p %p)\n",
246 Miniport
, DeviceExtension
, InitData
);
248 Miniport
->DeviceExtension
= DeviceExtension
;
249 Miniport
->InitData
= InitData
;
251 /* Calculate the miniport device extension size */
252 Size
= sizeof(MINIPORT_DEVICE_EXTENSION
) +
253 Miniport
->InitData
->DeviceExtensionSize
;
255 /* Allocate and initialize the miniport device extension */
256 MiniportExtension
= ExAllocatePoolWithTag(NonPagedPool
,
259 if (MiniportExtension
== NULL
)
260 return STATUS_NO_MEMORY
;
262 RtlZeroMemory(MiniportExtension
, Size
);
264 MiniportExtension
->Miniport
= Miniport
;
265 Miniport
->MiniportExtension
= MiniportExtension
;
267 /* Initialize the port configuration */
268 Status
= InitializeConfiguration(&Miniport
->PortConfig
,
270 DeviceExtension
->BusNumber
,
271 DeviceExtension
->SlotNumber
);
272 if (!NT_SUCCESS(Status
))
275 /* Assign the resources to the port configuration */
276 AssignResourcesToConfiguration(&Miniport
->PortConfig
,
277 DeviceExtension
->AllocatedResources
,
278 InitData
->NumberOfAccessRanges
);
280 return STATUS_SUCCESS
;
286 _In_ PMINIPORT Miniport
)
288 BOOLEAN Reserved
= FALSE
;
292 DPRINT1("MiniportFindAdapter(%p)\n", Miniport
);
294 /* Call the miniport HwFindAdapter routine */
295 Result
= Miniport
->InitData
->HwFindAdapter(&Miniport
->MiniportExtension
->HwDeviceExtension
,
299 &Miniport
->PortConfig
,
301 DPRINT1("HwFindAdapter() returned %lu\n", Result
);
303 /* Convert the result to a status code */
306 case SP_RETURN_NOT_FOUND
:
307 DPRINT1("SP_RETURN_NOT_FOUND\n");
308 Status
= STATUS_NOT_FOUND
;
311 case SP_RETURN_FOUND
:
312 DPRINT1("SP_RETURN_FOUND\n");
313 Status
= STATUS_SUCCESS
;
316 case SP_RETURN_ERROR
:
317 DPRINT1("SP_RETURN_ERROR\n");
318 Status
= STATUS_ADAPTER_HARDWARE_ERROR
;
321 case SP_RETURN_BAD_CONFIG
:
322 DPRINT1("SP_RETURN_BAD_CONFIG\n");
323 Status
= STATUS_DEVICE_CONFIGURATION_ERROR
;
327 DPRINT1("Unknown result: %lu\n", Result
);
328 Status
= STATUS_INTERNAL_ERROR
;
337 MiniportHwInitialize(
338 _In_ PMINIPORT Miniport
)
342 DPRINT1("MiniportHwInitialize(%p)\n", Miniport
);
344 /* Call the miniport HwInitialize routine */
345 Result
= Miniport
->InitData
->HwInitialize(&Miniport
->MiniportExtension
->HwDeviceExtension
);
346 DPRINT1("HwInitialize() returned %u\n", Result
);
348 return Result
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
;
354 _In_ PMINIPORT Miniport
)
358 DPRINT1("MiniportHwInterrupt(%p)\n",
361 Result
= Miniport
->InitData
->HwInterrupt(&Miniport
->MiniportExtension
->HwDeviceExtension
);
362 DPRINT1("HwInterrupt() returned %u\n", Result
);
370 _In_ PMINIPORT Miniport
,
371 _In_ PSCSI_REQUEST_BLOCK Srb
)
375 DPRINT1("MiniportHwStartIo(%p %p)\n",
378 Result
= Miniport
->InitData
->HwStartIo(&Miniport
->MiniportExtension
->HwDeviceExtension
, Srb
);
379 DPRINT1("HwStartIo() returned %u\n", Result
);