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