1 /*
2 * SCSI_PORT_TIMER_STATES
3 *
4 * DESCRIPTION
5 * An enumeration containing the states in the timer DFA
6 */
7
8 #pragma once
9
10 #include <ntifs.h>
11 #include <stdio.h>
12 #include <scsi.h>
13 #include <ntddscsi.h>
14 #include <ntdddisk.h>
15 #include <mountdev.h>
16
17 #ifdef DBG
18 #include <debug/driverdbg.h>
19 #endif
20
21 #define TAG_SCSIPORT 'ISCS'
22
23 /* Defines how many logical unit arrays will be in a device extension */
24 #define LUS_NUMBER 8
25
26 #define MAX_SG_LIST 17
27
28 /* Flags */
29 #define SCSI_PORT_DEVICE_BUSY 0x00001
30 #define SCSI_PORT_LU_ACTIVE 0x00002
31 #define SCSI_PORT_NOTIFICATION_NEEDED 0x00004
32 #define SCSI_PORT_NEXT_REQUEST_READY 0x00008
33 #define SCSI_PORT_FLUSH_ADAPTERS 0x00010
34 #define SCSI_PORT_MAP_TRANSFER 0x00020
35 #define SCSI_PORT_RESET 0x00080
36 #define SCSI_PORT_RESET_REQUEST 0x00100
37 #define SCSI_PORT_RESET_REPORTED 0x00200
38 #define SCSI_PORT_REQUEST_PENDING 0x00800
39 #define SCSI_PORT_DISCONNECT_ALLOWED 0x01000
40 #define SCSI_PORT_DISABLE_INT_REQUESET 0x02000
41 #define SCSI_PORT_DISABLE_INTERRUPTS 0x04000
42 #define SCSI_PORT_ENABLE_INT_REQUEST 0x08000
43 #define SCSI_PORT_TIMER_NEEDED 0x10000
44
45 /* LUN Extension flags*/
46 #define LUNEX_FROZEN_QUEUE 0x0001
47 #define LUNEX_NEED_REQUEST_SENSE 0x0004
48 #define LUNEX_BUSY 0x0008
49 #define LUNEX_FULL_QUEUE 0x0010
50 #define LUNEX_REQUEST_PENDING 0x0020
51 #define SCSI_PORT_SCAN_IN_PROGRESS 0x8000
52
53 // we need this to be compatible with ReactOS' classpnp (which is compiled with NTDDI_WIN8)
54 typedef struct _STORAGE_ADAPTER_DESCRIPTOR_WIN8 {
55 ULONG Version;
56 ULONG Size;
57 ULONG MaximumTransferLength;
58 ULONG MaximumPhysicalPages;
59 ULONG AlignmentMask;
60 BOOLEAN AdapterUsesPio;
61 BOOLEAN AdapterScansDown;
62 BOOLEAN CommandQueueing;
63 BOOLEAN AcceleratedTransfer;
64 UCHAR BusType;
65 USHORT BusMajorVersion;
66 USHORT BusMinorVersion;
67 UCHAR SrbType;
68 UCHAR AddressType;
69 } STORAGE_ADAPTER_DESCRIPTOR_WIN8, *PSTORAGE_ADAPTER_DESCRIPTOR_WIN8;
70
71 typedef enum _SCSI_PORT_TIMER_STATES
72 {
73 IDETimerIdle,
74 IDETimerCmdWait,
75 IDETimerResetWaitForBusyNegate,
76 IDETimerResetWaitForDrdyAssert
77 } SCSI_PORT_TIMER_STATES;
78
79 typedef struct _CONFIGURATION_INFO
80 {
81 /* Identify info */
82 ULONG AdapterNumber;
83 ULONG LastAdapterNumber;
84 ULONG BusNumber;
85
86 /* Registry related */
87 HANDLE BusKey;
88 HANDLE ServiceKey;
89 HANDLE DeviceKey;
90
91 /* Features */
92 BOOLEAN DisableTaggedQueueing;
93 BOOLEAN DisableMultipleLun;
94
95 /* Parameters */
96 PVOID Parameter;
97 PACCESS_RANGE AccessRanges;
98 } CONFIGURATION_INFO, *PCONFIGURATION_INFO;
99
100 typedef struct _SCSI_PORT_DEVICE_BASE
101 {
102 LIST_ENTRY List;
103
104 PVOID MappedAddress;
105 ULONG NumberOfBytes;
106 SCSI_PHYSICAL_ADDRESS IoAddress;
107 ULONG SystemIoBusNumber;
108 } SCSI_PORT_DEVICE_BASE, *PSCSI_PORT_DEVICE_BASE;
109
110 typedef struct _SCSI_SG_ADDRESS
111 {
112 PHYSICAL_ADDRESS PhysicalAddress;
113 ULONG Length;
114 } SCSI_SG_ADDRESS, *PSCSI_SG_ADDRESS;
115
116 typedef struct _SCSI_REQUEST_BLOCK_INFO
117 {
118 LIST_ENTRY Requests;
119 PSCSI_REQUEST_BLOCK Srb;
120 PCHAR DataOffset;
121 PVOID SaveSenseRequest;
122
123 ULONG SequenceNumber;
124
125 /* DMA stuff */
126 PVOID BaseOfMapRegister;
127 ULONG NumberOfMapRegisters;
128
129 struct _SCSI_REQUEST_BLOCK_INFO *CompletedRequests;
130
131 /* Scatter-gather list */
132 PSCSI_SG_ADDRESS ScatterGather;
133 SCSI_SG_ADDRESS ScatterGatherList[MAX_SG_LIST];
134 } SCSI_REQUEST_BLOCK_INFO, *PSCSI_REQUEST_BLOCK_INFO;
135
136 typedef struct _SCSI_PORT_COMMON_EXTENSION
137 {
138 PDEVICE_OBJECT DeviceObject;
139 PDEVICE_OBJECT LowerDevice;
140 BOOLEAN IsFDO;
141 } SCSI_PORT_COMMON_EXTENSION, *PSCSI_PORT_COMMON_EXTENSION;
142
143 // PDO device
144 typedef struct _SCSI_PORT_LUN_EXTENSION
145 {
146 SCSI_PORT_COMMON_EXTENSION Common;
147
148 UCHAR PathId;
149 UCHAR TargetId;
150 UCHAR Lun;
151
152 ULONG Flags;
153
154 LIST_ENTRY LunEntry;
155
156 BOOLEAN DeviceClaimed;
157
158 INQUIRYDATA InquiryData;
159
160 KDEVICE_QUEUE DeviceQueue;
161 ULONG SortKey;
162 ULONG QueueCount;
163 ULONG MaxQueueCount;
164
165 ULONG AttemptCount;
166 LONG RequestTimeout;
167
168 PIRP BusyRequest;
169 PIRP PendingRequest;
170
171 struct _SCSI_PORT_LUN_EXTENSION *ReadyLun;
172 struct _SCSI_PORT_LUN_EXTENSION *CompletedAbortRequests;
173
174 SCSI_REQUEST_BLOCK_INFO SrbInfo;
175
176 HANDLE RegistryMapKey;
177
178 /* More data? */
179
180 UCHAR MiniportLunExtension[1]; /* must be the last entry */
181 } SCSI_PORT_LUN_EXTENSION, *PSCSI_PORT_LUN_EXTENSION;
182
183 /* Structures for inquiries support */
184
185 typedef struct _SCSI_BUS_INFO
186 {
187 LIST_ENTRY LunsListHead;
188 UCHAR LogicalUnitsCount;
189 UCHAR TargetsCount;
190 UCHAR BusIdentifier;
191 HANDLE RegistryMapKey;
192 } SCSI_BUS_INFO, *PSCSI_BUS_INFO;
193
194 typedef struct _SCSI_PORT_INTERRUPT_DATA
195 {
196 ULONG Flags; /* Interrupt-time flags */
197 PSCSI_REQUEST_BLOCK_INFO CompletedRequests; /* Linked list of Srb info data */
198 PSCSI_PORT_LUN_EXTENSION CompletedAbort;
199 PSCSI_PORT_LUN_EXTENSION ReadyLun;
200 PHW_TIMER HwScsiTimer;
201 ULONG MiniportTimerValue;
202 } SCSI_PORT_INTERRUPT_DATA, *PSCSI_PORT_INTERRUPT_DATA;
203
204
205 /* Only for interrupt data saving function */
206 typedef struct _SCSI_PORT_SAVE_INTERRUPT
207 {
208 PSCSI_PORT_INTERRUPT_DATA InterruptData;
209 struct _SCSI_PORT_DEVICE_EXTENSION *DeviceExtension;
210 } SCSI_PORT_SAVE_INTERRUPT, *PSCSI_PORT_SAVE_INTERRUPT;
211
212 /*
213 * SCSI_PORT_DEVICE_EXTENSION
214 *
215 * DESCRIPTION
216 * First part of the port objects device extension. The second
217 * part is the miniport-specific device extension.
218 */
219
220 #ifdef _WIN64
221 #define ALIGNAS_PTR DECLSPEC_ALIGN(8)
222 #else
223 #define ALIGNAS_PTR DECLSPEC_ALIGN(4)
224 #endif
225
226 // FDO
227 typedef struct _SCSI_PORT_DEVICE_EXTENSION
228 {
229 SCSI_PORT_COMMON_EXTENSION Common;
230
231 ULONG Length;
232 ULONG MiniPortExtensionSize;
233 PPORT_CONFIGURATION_INFORMATION PortConfig;
234 PSCSI_BUS_INFO Buses; // children LUNs are stored here
235 PVOID NonCachedExtension;
236 ULONG PortNumber;
237
238 LONG ActiveRequestCounter;
239 ULONG SrbFlags;
240 ULONG Flags;
241
242 UCHAR NumberOfBuses;
243 ULONG MaxTargedIds;
244 ULONG MaxLunCount;
245
246 KSPIN_LOCK IrqLock; /* Used when there are 2 irqs */
247 ULONG SequenceNumber; /* Global sequence number for packets */
248 KSPIN_LOCK SpinLock;
249 PKINTERRUPT Interrupt[2];
250 PIRP CurrentIrp;
251 ULONG IrpFlags;
252
253 SCSI_PORT_TIMER_STATES TimerState;
254 LONG TimerCount;
255
256 KTIMER MiniportTimer;
257 KDPC MiniportTimerDpc;
258
259 PMAPPED_ADDRESS MappedAddressList;
260
261 ULONG LunExtensionSize;
262
263 SCSI_PORT_INTERRUPT_DATA InterruptData;
264
265 /* SRB extension stuff*/
266 ULONG SrbExtensionSize;
267 PVOID SrbExtensionBuffer;
268 PVOID FreeSrbExtensions;
269
270 /* SRB information */
271 PSCSI_REQUEST_BLOCK_INFO SrbInfo;
272 PSCSI_REQUEST_BLOCK_INFO FreeSrbInfo;
273 ULONG SrbDataCount;
274
275 IO_SCSI_CAPABILITIES PortCapabilities;
276
277 PCONTROLLER_OBJECT ControllerObject;
278
279 PHW_INITIALIZE HwInitialize;
280 PHW_STARTIO HwStartIo;
281 PHW_INTERRUPT HwInterrupt;
282 PHW_RESET_BUS HwResetBus;
283 PHW_DMA_STARTED HwDmaStarted;
284 PHW_TIMER HwScsiTimer;
285
286 PSCSI_REQUEST_BLOCK OriginalSrb;
287 SCSI_REQUEST_BLOCK InternalSrb;
288 SENSE_DATA InternalSenseData;
289
290 /* DMA related stuff */
291 PADAPTER_OBJECT AdapterObject;
292 ULONG MapRegisterCount;
293 BOOLEAN MapBuffers;
294 BOOLEAN MapRegisters;
295 PVOID MapRegisterBase;
296
297 /* Features */
298 BOOLEAN CachesData;
299 BOOLEAN SupportsTaggedQueuing;
300 BOOLEAN SupportsAutoSense;
301 BOOLEAN MultipleReqsPerLun;
302 BOOLEAN ReceiveEvent;
303
304 PHYSICAL_ADDRESS PhysicalAddress;
305 ULONG CommonBufferLength;
306 ULONG InterruptLevel[2];
307 ULONG IoAddress;
308
309 BOOLEAN NeedSrbExtensionAlloc;
310 BOOLEAN NeedSrbDataAlloc;
311
312 ULONG RequestsNumber;
313
314 ULONG InterruptCount;
315
316 UNICODE_STRING DeviceName;
317 UNICODE_STRING InterfaceName;
318 BOOLEAN DeviceStarted;
319 UINT8 TotalLUCount;
320
321 // use the pointer alignment here, some miniport drivers rely on this
322 // moreover, it has to be the last member
323 ALIGNAS_PTR UCHAR MiniPortDeviceExtension[];
324 } SCSI_PORT_DEVICE_EXTENSION, *PSCSI_PORT_DEVICE_EXTENSION;
325
326 typedef struct _RESETBUS_PARAMS
327 {
328 ULONG PathId;
329 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
330 } RESETBUS_PARAMS, *PRESETBUS_PARAMS;
331
332 typedef struct _SCSIPORT_DRIVER_EXTENSION
333 {
334 PDRIVER_OBJECT DriverObject;
335 UNICODE_STRING RegistryPath;
336 BOOLEAN IsLegacyDriver;
337 } SCSI_PORT_DRIVER_EXTENSION, *PSCSI_PORT_DRIVER_EXTENSION;
338
339 FORCEINLINE
340 BOOLEAN
VerifyIrpOutBufferSize(_In_ PIRP Irp,_In_ SIZE_T Size)341 VerifyIrpOutBufferSize(
342 _In_ PIRP Irp,
343 _In_ SIZE_T Size)
344 {
345 PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
346 if (ioStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
347 {
348 Irp->IoStatus.Information = Size;
349 return FALSE;
350 }
351 return TRUE;
352 }
353
354 FORCEINLINE
355 BOOLEAN
VerifyIrpInBufferSize(_In_ PIRP Irp,_In_ SIZE_T Size)356 VerifyIrpInBufferSize(
357 _In_ PIRP Irp,
358 _In_ SIZE_T Size)
359 {
360 PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
361 if (ioStack->Parameters.DeviceIoControl.InputBufferLength < Size)
362 {
363 Irp->IoStatus.Information = Size;
364 return FALSE;
365 }
366 return TRUE;
367 }
368
369 // ioctl.c
370
371 NTSTATUS
372 NTAPI
373 ScsiPortDeviceControl(
374 _In_ PDEVICE_OBJECT DeviceObject,
375 _In_ PIRP Irp);
376
377 // fdo.c
378
379 VOID
380 FdoScanAdapter(
381 _In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
382
383 NTSTATUS
384 FdoCallHWInitialize(
385 _In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
386
387 NTSTATUS
388 FdoRemoveAdapter(
389 _In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
390
391 NTSTATUS
392 FdoStartAdapter(
393 _In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
394
395 NTSTATUS
396 FdoDispatchPnp(
397 _In_ PDEVICE_OBJECT DeviceObject,
398 _Inout_ PIRP Irp);
399
400 // pdo.c
401
402 PDEVICE_OBJECT
403 PdoCreateLunDevice(
404 _In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
405
406 PSCSI_PORT_LUN_EXTENSION
407 GetLunByPath(
408 _In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
409 _In_ UCHAR PathId,
410 _In_ UCHAR TargetId,
411 _In_ UCHAR Lun);
412
413 PSCSI_REQUEST_BLOCK_INFO
414 SpiGetSrbData(
415 _In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
416 _In_ PSCSI_PORT_LUN_EXTENSION LunExtension,
417 _In_ UCHAR QueueTag);
418
419 NTSTATUS
420 PdoDispatchPnp(
421 _In_ PDEVICE_OBJECT DeviceObject,
422 _Inout_ PIRP Irp);
423
424 // power.c
425
426 DRIVER_DISPATCH ScsiPortDispatchPower;
427
428 // registry.c
429
430 VOID
431 SpiInitOpenKeys(
432 _Inout_ PCONFIGURATION_INFO ConfigInfo,
433 _In_ PSCSI_PORT_DRIVER_EXTENSION DriverExtension);
434
435 NTSTATUS
436 RegistryInitAdapterKey(
437 _Inout_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
438
439 NTSTATUS
440 RegistryInitLunKey(
441 _Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension);
442
443 // scsi.c
444
445 VOID
446 SpiGetNextRequestFromLun(
447 _In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
448 _Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension,
449 _Inout_opt_ PKIRQL OldIrql);
450
451 IO_DPC_ROUTINE ScsiPortDpcForIsr;
452 DRIVER_DISPATCH ScsiPortDispatchScsi;
453 KSYNCHRONIZE_ROUTINE ScsiPortStartPacket;
454 DRIVER_STARTIO ScsiPortStartIo;
455
456
457 // scsiport.c
458
459 KSERVICE_ROUTINE ScsiPortIsr;
460
461 IO_ALLOCATION_ACTION
462 NTAPI
463 SpiAdapterControl(
464 _In_ PDEVICE_OBJECT DeviceObject,
465 _In_ PIRP Irp,
466 _In_ PVOID MapRegisterBase,
467 _In_ PVOID Context);
468
469 IO_ALLOCATION_ACTION
470 NTAPI
471 ScsiPortAllocateAdapterChannel(
472 _In_ PDEVICE_OBJECT DeviceObject,
473 _In_ PIRP Irp,
474 _In_ PVOID MapRegisterBase,
475 _In_ PVOID Context);
476