reactos/drivers/storage/port/scsiport/scsiport.h
Victor Perevertkin 66cf1d20f4
[SCSIPORT] Use pointer alignment for MiniPortDeviceExtension
This seems logical and some miniport drivers (uniata) actually rely on
that.

CORE-17424
2021-01-17 01:46:35 +03:00

476 lines
11 KiB
C

/*
* SCSI_PORT_TIMER_STATES
*
* DESCRIPTION
* An enumeration containing the states in the timer DFA
*/
#pragma once
#include <ntifs.h>
#include <stdio.h>
#include <scsi.h>
#include <ntddscsi.h>
#include <ntdddisk.h>
#include <mountdev.h>
#ifdef DBG
#include <debug/driverdbg.h>
#endif
#define TAG_SCSIPORT 'ISCS'
/* Defines how many logical unit arrays will be in a device extension */
#define LUS_NUMBER 8
#define MAX_SG_LIST 17
/* Flags */
#define SCSI_PORT_DEVICE_BUSY 0x00001
#define SCSI_PORT_LU_ACTIVE 0x00002
#define SCSI_PORT_NOTIFICATION_NEEDED 0x00004
#define SCSI_PORT_NEXT_REQUEST_READY 0x00008
#define SCSI_PORT_FLUSH_ADAPTERS 0x00010
#define SCSI_PORT_MAP_TRANSFER 0x00020
#define SCSI_PORT_RESET 0x00080
#define SCSI_PORT_RESET_REQUEST 0x00100
#define SCSI_PORT_RESET_REPORTED 0x00200
#define SCSI_PORT_REQUEST_PENDING 0x00800
#define SCSI_PORT_DISCONNECT_ALLOWED 0x01000
#define SCSI_PORT_DISABLE_INT_REQUESET 0x02000
#define SCSI_PORT_DISABLE_INTERRUPTS 0x04000
#define SCSI_PORT_ENABLE_INT_REQUEST 0x08000
#define SCSI_PORT_TIMER_NEEDED 0x10000
/* LUN Extension flags*/
#define LUNEX_FROZEN_QUEUE 0x0001
#define LUNEX_NEED_REQUEST_SENSE 0x0004
#define LUNEX_BUSY 0x0008
#define LUNEX_FULL_QUEUE 0x0010
#define LUNEX_REQUEST_PENDING 0x0020
#define SCSI_PORT_SCAN_IN_PROGRESS 0x8000
// we need this to be compatible with ReactOS' classpnp (which is compiled with NTDDI_WIN8)
typedef struct _STORAGE_ADAPTER_DESCRIPTOR_WIN8 {
ULONG Version;
ULONG Size;
ULONG MaximumTransferLength;
ULONG MaximumPhysicalPages;
ULONG AlignmentMask;
BOOLEAN AdapterUsesPio;
BOOLEAN AdapterScansDown;
BOOLEAN CommandQueueing;
BOOLEAN AcceleratedTransfer;
UCHAR BusType;
USHORT BusMajorVersion;
USHORT BusMinorVersion;
UCHAR SrbType;
UCHAR AddressType;
} STORAGE_ADAPTER_DESCRIPTOR_WIN8, *PSTORAGE_ADAPTER_DESCRIPTOR_WIN8;
typedef enum _SCSI_PORT_TIMER_STATES
{
IDETimerIdle,
IDETimerCmdWait,
IDETimerResetWaitForBusyNegate,
IDETimerResetWaitForDrdyAssert
} SCSI_PORT_TIMER_STATES;
typedef struct _CONFIGURATION_INFO
{
/* Identify info */
ULONG AdapterNumber;
ULONG LastAdapterNumber;
ULONG BusNumber;
/* Registry related */
HANDLE BusKey;
HANDLE ServiceKey;
HANDLE DeviceKey;
/* Features */
BOOLEAN DisableTaggedQueueing;
BOOLEAN DisableMultipleLun;
/* Parameters */
PVOID Parameter;
PACCESS_RANGE AccessRanges;
} CONFIGURATION_INFO, *PCONFIGURATION_INFO;
typedef struct _SCSI_PORT_DEVICE_BASE
{
LIST_ENTRY List;
PVOID MappedAddress;
ULONG NumberOfBytes;
SCSI_PHYSICAL_ADDRESS IoAddress;
ULONG SystemIoBusNumber;
} SCSI_PORT_DEVICE_BASE, *PSCSI_PORT_DEVICE_BASE;
typedef struct _SCSI_SG_ADDRESS
{
PHYSICAL_ADDRESS PhysicalAddress;
ULONG Length;
} SCSI_SG_ADDRESS, *PSCSI_SG_ADDRESS;
typedef struct _SCSI_REQUEST_BLOCK_INFO
{
LIST_ENTRY Requests;
PSCSI_REQUEST_BLOCK Srb;
PCHAR DataOffset;
PVOID SaveSenseRequest;
ULONG SequenceNumber;
/* DMA stuff */
PVOID BaseOfMapRegister;
ULONG NumberOfMapRegisters;
struct _SCSI_REQUEST_BLOCK_INFO *CompletedRequests;
/* Scatter-gather list */
PSCSI_SG_ADDRESS ScatterGather;
SCSI_SG_ADDRESS ScatterGatherList[MAX_SG_LIST];
} SCSI_REQUEST_BLOCK_INFO, *PSCSI_REQUEST_BLOCK_INFO;
typedef struct _SCSI_PORT_COMMON_EXTENSION
{
PDEVICE_OBJECT DeviceObject;
PDEVICE_OBJECT LowerDevice;
BOOLEAN IsFDO;
} SCSI_PORT_COMMON_EXTENSION, *PSCSI_PORT_COMMON_EXTENSION;
// PDO device
typedef struct _SCSI_PORT_LUN_EXTENSION
{
SCSI_PORT_COMMON_EXTENSION Common;
UCHAR PathId;
UCHAR TargetId;
UCHAR Lun;
ULONG Flags;
LIST_ENTRY LunEntry;
BOOLEAN DeviceClaimed;
INQUIRYDATA InquiryData;
KDEVICE_QUEUE DeviceQueue;
ULONG SortKey;
ULONG QueueCount;
ULONG MaxQueueCount;
ULONG AttemptCount;
LONG RequestTimeout;
PIRP BusyRequest;
PIRP PendingRequest;
struct _SCSI_PORT_LUN_EXTENSION *ReadyLun;
struct _SCSI_PORT_LUN_EXTENSION *CompletedAbortRequests;
SCSI_REQUEST_BLOCK_INFO SrbInfo;
HANDLE RegistryMapKey;
/* More data? */
UCHAR MiniportLunExtension[1]; /* must be the last entry */
} SCSI_PORT_LUN_EXTENSION, *PSCSI_PORT_LUN_EXTENSION;
/* Structures for inquiries support */
typedef struct _SCSI_BUS_INFO
{
LIST_ENTRY LunsListHead;
UCHAR LogicalUnitsCount;
UCHAR TargetsCount;
UCHAR BusIdentifier;
HANDLE RegistryMapKey;
} SCSI_BUS_INFO, *PSCSI_BUS_INFO;
typedef struct _SCSI_PORT_INTERRUPT_DATA
{
ULONG Flags; /* Interrupt-time flags */
PSCSI_REQUEST_BLOCK_INFO CompletedRequests; /* Linked list of Srb info data */
PSCSI_PORT_LUN_EXTENSION CompletedAbort;
PSCSI_PORT_LUN_EXTENSION ReadyLun;
PHW_TIMER HwScsiTimer;
ULONG MiniportTimerValue;
} SCSI_PORT_INTERRUPT_DATA, *PSCSI_PORT_INTERRUPT_DATA;
/* Only for interrupt data saving function */
typedef struct _SCSI_PORT_SAVE_INTERRUPT
{
PSCSI_PORT_INTERRUPT_DATA InterruptData;
struct _SCSI_PORT_DEVICE_EXTENSION *DeviceExtension;
} SCSI_PORT_SAVE_INTERRUPT, *PSCSI_PORT_SAVE_INTERRUPT;
/*
* SCSI_PORT_DEVICE_EXTENSION
*
* DESCRIPTION
* First part of the port objects device extension. The second
* part is the miniport-specific device extension.
*/
#ifdef _WIN64
#define ALIGNAS_PTR DECLSPEC_ALIGN(8)
#else
#define ALIGNAS_PTR DECLSPEC_ALIGN(4)
#endif
// FDO
typedef struct _SCSI_PORT_DEVICE_EXTENSION
{
SCSI_PORT_COMMON_EXTENSION Common;
ULONG Length;
ULONG MiniPortExtensionSize;
PPORT_CONFIGURATION_INFORMATION PortConfig;
PSCSI_BUS_INFO Buses; // children LUNs are stored here
PVOID NonCachedExtension;
ULONG PortNumber;
LONG ActiveRequestCounter;
ULONG SrbFlags;
ULONG Flags;
UCHAR NumberOfBuses;
ULONG MaxTargedIds;
ULONG MaxLunCount;
KSPIN_LOCK IrqLock; /* Used when there are 2 irqs */
ULONG SequenceNumber; /* Global sequence number for packets */
KSPIN_LOCK SpinLock;
PKINTERRUPT Interrupt[2];
PIRP CurrentIrp;
ULONG IrpFlags;
SCSI_PORT_TIMER_STATES TimerState;
LONG TimerCount;
KTIMER MiniportTimer;
KDPC MiniportTimerDpc;
PMAPPED_ADDRESS MappedAddressList;
ULONG LunExtensionSize;
SCSI_PORT_INTERRUPT_DATA InterruptData;
/* SRB extension stuff*/
ULONG SrbExtensionSize;
PVOID SrbExtensionBuffer;
PVOID FreeSrbExtensions;
/* SRB information */
PSCSI_REQUEST_BLOCK_INFO SrbInfo;
PSCSI_REQUEST_BLOCK_INFO FreeSrbInfo;
ULONG SrbDataCount;
IO_SCSI_CAPABILITIES PortCapabilities;
PCONTROLLER_OBJECT ControllerObject;
PHW_INITIALIZE HwInitialize;
PHW_STARTIO HwStartIo;
PHW_INTERRUPT HwInterrupt;
PHW_RESET_BUS HwResetBus;
PHW_DMA_STARTED HwDmaStarted;
PHW_TIMER HwScsiTimer;
PSCSI_REQUEST_BLOCK OriginalSrb;
SCSI_REQUEST_BLOCK InternalSrb;
SENSE_DATA InternalSenseData;
/* DMA related stuff */
PADAPTER_OBJECT AdapterObject;
ULONG MapRegisterCount;
BOOLEAN MapBuffers;
BOOLEAN MapRegisters;
PVOID MapRegisterBase;
/* Features */
BOOLEAN CachesData;
BOOLEAN SupportsTaggedQueuing;
BOOLEAN SupportsAutoSense;
BOOLEAN MultipleReqsPerLun;
BOOLEAN ReceiveEvent;
PHYSICAL_ADDRESS PhysicalAddress;
ULONG CommonBufferLength;
ULONG InterruptLevel[2];
ULONG IoAddress;
BOOLEAN NeedSrbExtensionAlloc;
BOOLEAN NeedSrbDataAlloc;
ULONG RequestsNumber;
ULONG InterruptCount;
UNICODE_STRING DeviceName;
UNICODE_STRING InterfaceName;
BOOLEAN DeviceStarted;
UINT8 TotalLUCount;
// use the pointer alignment here, some miniport drivers rely on this
// moreover, it has to be the last member
ALIGNAS_PTR UCHAR MiniPortDeviceExtension[];
} SCSI_PORT_DEVICE_EXTENSION, *PSCSI_PORT_DEVICE_EXTENSION;
typedef struct _RESETBUS_PARAMS
{
ULONG PathId;
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
} RESETBUS_PARAMS, *PRESETBUS_PARAMS;
typedef struct _SCSIPORT_DRIVER_EXTENSION
{
PDRIVER_OBJECT DriverObject;
UNICODE_STRING RegistryPath;
BOOLEAN IsLegacyDriver;
} SCSI_PORT_DRIVER_EXTENSION, *PSCSI_PORT_DRIVER_EXTENSION;
FORCEINLINE
BOOLEAN
VerifyIrpOutBufferSize(
_In_ PIRP Irp,
_In_ SIZE_T Size)
{
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
if (ioStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
{
Irp->IoStatus.Information = Size;
return FALSE;
}
return TRUE;
}
FORCEINLINE
BOOLEAN
VerifyIrpInBufferSize(
_In_ PIRP Irp,
_In_ SIZE_T Size)
{
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
if (ioStack->Parameters.DeviceIoControl.InputBufferLength < Size)
{
Irp->IoStatus.Information = Size;
return FALSE;
}
return TRUE;
}
// ioctl.c
NTSTATUS
NTAPI
ScsiPortDeviceControl(
_In_ PDEVICE_OBJECT DeviceObject,
_In_ PIRP Irp);
// fdo.c
VOID
FdoScanAdapter(
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
NTSTATUS
FdoCallHWInitialize(
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
NTSTATUS
FdoRemoveAdapter(
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
NTSTATUS
FdoStartAdapter(
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
NTSTATUS
FdoDispatchPnp(
_In_ PDEVICE_OBJECT DeviceObject,
_Inout_ PIRP Irp);
// pdo.c
PDEVICE_OBJECT
PdoCreateLunDevice(
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
PSCSI_PORT_LUN_EXTENSION
GetLunByPath(
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
_In_ UCHAR PathId,
_In_ UCHAR TargetId,
_In_ UCHAR Lun);
PSCSI_REQUEST_BLOCK_INFO
SpiGetSrbData(
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
_In_ PSCSI_PORT_LUN_EXTENSION LunExtension,
_In_ UCHAR QueueTag);
NTSTATUS
PdoDispatchPnp(
_In_ PDEVICE_OBJECT DeviceObject,
_Inout_ PIRP Irp);
// power.c
DRIVER_DISPATCH ScsiPortDispatchPower;
// registry.c
VOID
SpiInitOpenKeys(
_Inout_ PCONFIGURATION_INFO ConfigInfo,
_In_ PSCSI_PORT_DRIVER_EXTENSION DriverExtension);
NTSTATUS
RegistryInitAdapterKey(
_Inout_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
NTSTATUS
RegistryInitLunKey(
_Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension);
// scsi.c
VOID
SpiGetNextRequestFromLun(
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
_Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension,
_Inout_opt_ PKIRQL OldIrql);
IO_DPC_ROUTINE ScsiPortDpcForIsr;
DRIVER_DISPATCH ScsiPortDispatchScsi;
KSYNCHRONIZE_ROUTINE ScsiPortStartPacket;
DRIVER_STARTIO ScsiPortStartIo;
// scsiport.c
KSERVICE_ROUTINE ScsiPortIsr;
IO_ALLOCATION_ACTION
NTAPI
SpiAdapterControl(
_In_ PDEVICE_OBJECT DeviceObject,
_In_ PIRP Irp,
_In_ PVOID MapRegisterBase,
_In_ PVOID Context);
IO_ALLOCATION_ACTION
NTAPI
ScsiPortAllocateAdapterChannel(
_In_ PDEVICE_OBJECT DeviceObject,
_In_ PIRP Irp,
_In_ PVOID MapRegisterBase,
_In_ PVOID Context);