4547 lines
		
	
	
		
			113 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			4547 lines
		
	
	
		
			113 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*++
 | ||
| 
 | ||
| Copyright (C) 1990-4  Microsoft Corporation
 | ||
| 
 | ||
| Module Name:
 | ||
| 
 | ||
|     port.h
 | ||
| 
 | ||
| Abstract:
 | ||
| 
 | ||
|     This file defines the necessary structures, defines, and functions for
 | ||
|     the common SCSI port driver.
 | ||
| 
 | ||
| Author:
 | ||
| 
 | ||
|     Jeff Havens  (jhavens) 28-Feb-1991
 | ||
|     Mike Glass
 | ||
| 
 | ||
| Revision History:
 | ||
| 
 | ||
| --*/
 | ||
| 
 | ||
| 
 | ||
| #ifndef _PORT_H_
 | ||
| #define _PORT_H_
 | ||
| 
 | ||
| #include "stdarg.h"
 | ||
| #include "stddef.h"
 | ||
| #include "stdio.h"
 | ||
| #include "string.h"
 | ||
| 
 | ||
| #include "ntddk.h"
 | ||
| #include "scsi.h"
 | ||
| 
 | ||
| #include <ntddscsi.h>
 | ||
| #include <ntdddisk.h>
 | ||
| #include "ntddstor.h"
 | ||
| 
 | ||
| #include "wmistr.h"
 | ||
| 
 | ||
| #include "wdmguid.h"
 | ||
| #include "devguid.h"
 | ||
| 
 | ||
| //
 | ||
| // feature/debugginging #define switches
 | ||
| //
 | ||
| 
 | ||
| #define TEST_LISTS 0
 | ||
| 
 | ||
| //
 | ||
| // ScsiPort global variable declarations.  These should be static data (like
 | ||
| // lookup tables) to avoid synchronization problems.
 | ||
| //
 | ||
| 
 | ||
| extern PDRIVER_DISPATCH AdapterMajorFunctionTable[];
 | ||
| extern PDRIVER_DISPATCH DeviceMajorFunctionTable[];
 | ||
| extern PDRIVER_DISPATCH Scsi1DeviceMajorFunctionTable[];
 | ||
| 
 | ||
| //
 | ||
| // Global list of scsi adapters.  This is used by the srb data allocator routine
 | ||
| // to convert the "tag" provided into a pointer to the device object.
 | ||
| //
 | ||
| 
 | ||
| extern KSPIN_LOCK ScsiGlobalAdapterListSpinLock;
 | ||
| extern PDEVICE_OBJECT *ScsiGlobalAdapterList;
 | ||
| extern ULONG ScsiGlobalAdapterListElements;
 | ||
| 
 | ||
| //
 | ||
| // Count of how many times we've locked down the PAGELOCK section.
 | ||
| //
 | ||
| 
 | ||
| extern LONG SpPAGELOCKLockCount;
 | ||
| 
 | ||
| //
 | ||
| // Whether the system can do 64 bit PA's or not.
 | ||
| //
 | ||
| 
 | ||
| extern ULONG Sp64BitPhysicalAddresses;
 | ||
| 
 | ||
| //
 | ||
| // Handle to pageable verifier code section.  We manually lock the verify
 | ||
| // code into memory iff we need it.
 | ||
| //
 | ||
| 
 | ||
| extern PVOID VerifierCodeSectionHandle;
 | ||
| extern PVOID VerifierApiCodeSectionHandle;
 | ||
| extern ULONG SpVrfyLevel;
 | ||
| 
 | ||
| //
 | ||
| // Constants and macros to enforce good use of Ex[Allocate|Free]PoolWithTag.
 | ||
| // Remeber that all pool tags will display in the debugger in reverse order
 | ||
| //
 | ||
| 
 | ||
| #if USE_EXFREEPOOLWITHTAG_ONLY
 | ||
| #define TAG(x)  (x | 0x80000000)
 | ||
| #else
 | ||
| #define TAG(x)  (x)
 | ||
| #endif
 | ||
| 
 | ||
| #define SCSIPORT_TAG_MINIPORT_PARAM     TAG('aPcS')  // Hold registry data
 | ||
| #define SCSIPORT_TAG_ACCESS_RANGE       TAG('APcS')  // Access Ranges
 | ||
| #define SCSIPORT_TAG_BUS_DATA           TAG('bPcS')  // Get Bus Data holder
 | ||
| #define SCSIPORT_TAG_QUEUE_BITMAP       TAG('BPcS')  // QueueTag BitMap
 | ||
| #define SCSIPORT_TAG_COMMON_BUFFER      TAG('cPcS')  // Fake Common Buffer
 | ||
| #define SCSIPORT_TAG_RESET              TAG('CPcS')  // reset bus code
 | ||
| #define SCSIPORT_TAG_PNP_ID             TAG('dPcS')  // Pnp id strings
 | ||
| #define SCSIPORT_TAG_SRB_DATA           TAG('DPcS')  // SRB_DATA allocations
 | ||
| #define SCSIPORT_TAG_PAE                TAG('ePcS')  // MDLs allocated for PAE requests
 | ||
| #define SCSIPORT_TAG_EMERGENCY_SG_ENTRY TAG('EPcS')  // Scatter gather lists
 | ||
| #define SCSIPORT_TAG_VERIFIER           TAG('fPcS')  // Scsiport verifier entry
 | ||
| #define SCSIPORT_TAG_GLOBAL             TAG('GPcS')  // Global memory
 | ||
| #define SCSIPORT_TAG_DEV_EXT            TAG('hPcS')  // HwDevice Ext
 | ||
| #define SCSIPORT_TAG_LUN_EXT            TAG('HPcS')  // HwLogicalUnit Extension
 | ||
| #define SCSIPORT_TAG_SENSE_BUFFER       TAG('iPcS')  // Sense info
 | ||
| #define SCSIPORT_TAG_INIT_CHAIN         TAG('IPcS')  // Init data chain
 | ||
| #define SCSIPORT_TAG_LOCK_TRACKING      TAG('lPcS')  // remove lock tracking
 | ||
| #define SCSIPORT_TAG_LARGE_SG_ENTRY     TAG('LPcS')  // Scatter gather lists
 | ||
| #define SCSIPORT_TAG_MAPPING_LIST       TAG('mPcS')  // Address mapping lists
 | ||
| #define SCSIPORT_TAG_MEDIUM_SG_ENTRY    TAG('MPcS')  // Scatter gather lists
 | ||
| #define SCSIPORT_TAG_ENABLE             TAG('pPcS')  // device & adapter enable
 | ||
| #define SCSIPORT_TAG_PORT_CONFIG        TAG('PpcS')  // Scsi PortConfig copies
 | ||
| #define SCSIPORT_TAG_INQUIRY            TAG('qPcS')  // inquiry data
 | ||
| #define SCSIPORT_TAG_REQUEST_SENSE      TAG('QPcS')  // request sense
 | ||
| #define SCSIPORT_TAG_RESOURCE_LIST      TAG('rPcS')  // resource list copy
 | ||
| #define SCSIPORT_TAG_REGISTRY           TAG('RPcS')  // registry allocations
 | ||
| #define SCSIPORT_TAG_STOP_DEVICE        TAG('sPcS')  // stop device
 | ||
| #define SCSIPORT_TAG_STOP_ADAPTER       TAG('SPcS')  // stop Adapter
 | ||
| #define SCSIPORT_TAG_REROUTE            TAG('tPcS')  // Legacy request rerouting
 | ||
| #define SCSIPORT_TAG_INTERFACE_MAPPING  TAG('TPcS')  // Interface Mapping
 | ||
| #define SCSIPORT_TAG_DEVICE_RELATIONS   TAG('uPcS')  // device relation structs
 | ||
| #define SCSIPORT_TAG_EVENT              TAG('vPcS')  // KEVENT
 | ||
| #define SCSIPORT_TAG_DEVICE_MAP         TAG('VPcS')  // Device map allocations
 | ||
| 
 | ||
| #define SCSIPORT_TAG_WMI_EVENT          TAG('wPcS')  // WMI Events
 | ||
| #define SCSIPORT_TAG_WMI_REQUEST        TAG('WPcS')  // WMI Requests
 | ||
| 
 | ||
| #define SCSIPORT_TAG_REPORT_LUNS        TAG('xPcS')  // Report Luns
 | ||
| #define SCSIPORT_TAG_REPORT_TARGETS     TAG('XPcS')  // Report Targets
 | ||
| #define SCSIPORT_TAG_TEMP_ID_BUFFER     TAG('yPcS')  // Temporary id buffer
 | ||
| #define SCSIPORT_TAG_ID_BUFFER          TAG('YPcS')  // Id buffer
 | ||
| #define SCSIPORT_TAG_SYMBOLIC_LINK      TAG('zPcS')  // Symbolic link strings
 | ||
| #define SCSIPORT_TAG_DEVICE_NAME        TAG('ZPcS')  // Device name buffer
 | ||
| 
 | ||
| #ifdef POOL_TAGGING
 | ||
| #ifdef ExAllocatePool
 | ||
| #undef ExAllocatePool
 | ||
| #endif
 | ||
| #define ExAllocatePool #assert(0)
 | ||
| #endif
 | ||
| 
 | ||
| #if defined(FORWARD_PROGRESS)
 | ||
| #define SP_RESERVED_PAGES 4
 | ||
| #endif
 | ||
| 
 | ||
| //
 | ||
| // The tag to use for the base remove lock.  This lock is only released when
 | ||
| // the device is finally ready to be destroyed.
 | ||
| //
 | ||
| 
 | ||
| #define SP_BASE_REMOVE_LOCK (UIntToPtr(0xabcdabcd))
 | ||
| 
 | ||
| 
 | ||
| //
 | ||
| // I/O System API routines which should not be called inside scsiport -
 | ||
| // these generally have scsiport versions which perform sanity checks before
 | ||
| // calling the real i/o routine in checked builds.
 | ||
| //
 | ||
| 
 | ||
| #if 0
 | ||
| #ifdef IoCompleteRequest
 | ||
| #ifndef KEEP_COMPLETE_REQUEST
 | ||
| #undef IoCompleteRequest
 | ||
| #endif
 | ||
| #endif
 | ||
| #endif
 | ||
| 
 | ||
| // If Count is not already aligned, then
 | ||
| // round Count up to an even multiple of "Pow2".  "Pow2" must be a power of 2.
 | ||
| //
 | ||
| // DWORD
 | ||
| // ROUND_UP_COUNT(
 | ||
| //     IN DWORD Count,
 | ||
| //     IN DWORD Pow2
 | ||
| //     );
 | ||
| #define ROUND_UP_COUNT(Count,Pow2) \
 | ||
|         ( ((Count)+(Pow2)-1) & (~(((LONG)(Pow2))-1)) )
 | ||
| 
 | ||
| // LPVOID
 | ||
| // ROUND_UP_POINTER(
 | ||
| //     IN LPVOID Ptr,
 | ||
| //     IN DWORD Pow2
 | ||
| //     );
 | ||
| 
 | ||
| // If Ptr is not already aligned, then round it up until it is.
 | ||
| #define ROUND_UP_POINTER(Ptr,Pow2) \
 | ||
|         ( (PVOID) ( (((ULONG_PTR)(Ptr))+(Pow2)-1) & (~(((LONG)(Pow2))-1)) ) )
 | ||
| 
 | ||
| 
 | ||
| //
 | ||
| // Macros, constants and declarations for debug code and debug print
 | ||
| // routines.
 | ||
| //
 | ||
| 
 | ||
| #define DEBUG_BUFFER_LENGTH 256
 | ||
| 
 | ||
| #if SCSIDBG_ENABLED
 | ||
| extern ULONG ScsiDebug;
 | ||
| 
 | ||
| #ifdef DebugPrint
 | ||
| #undef DebugPrint
 | ||
| #endif
 | ||
| 
 | ||
| #if SCSIDBG_ENABLED
 | ||
| 
 | ||
| //
 | ||
| // Forward definition of ScsiDebugPrintInt (internal and not exported)
 | ||
| //
 | ||
| VOID
 | ||
| ScsiDebugPrintInt(
 | ||
|     ULONG DebugPrintLevel,
 | ||
|     PCCHAR DebugMessage,
 | ||
|     ...
 | ||
|     );
 | ||
| 
 | ||
| #define DebugPrint(x) ScsiDebugPrintInt x
 | ||
| #else
 | ||
| #define DebugPrint(x)
 | ||
| #endif
 | ||
| 
 | ||
| #endif
 | ||
| 
 | ||
| #define ASSERT_FDO(x) ASSERT(!(((PCOMMON_EXTENSION) (x)->DeviceExtension)->IsPdo))
 | ||
| #define ASSERT_PDO(x) ASSERT((((PCOMMON_EXTENSION) (x)->DeviceExtension)->IsPdo))
 | ||
| #define ASSERT_SRB_DATA(x) ASSERT(((PSRB_DATA)(x))->Type == SRB_DATA_TYPE)
 | ||
| 
 | ||
| #if DBG
 | ||
| #define SpStartNextPacket(DevObj, Cancelable)                       \
 | ||
|     {                                                               \
 | ||
|         PADAPTER_EXTENSION ext = (DevObj)->DeviceExtension;         \
 | ||
|         ASSERT(!(TEST_FLAG(ext->Flags, PD_PENDING_DEVICE_REQUEST)));\
 | ||
|         IoStartNextPacket((DevObj), (Cancelable));                  \
 | ||
|     }
 | ||
| #else
 | ||
| #define SpStartNextPacket IoStartNextPacket
 | ||
| #endif
 | ||
| 
 | ||
| //
 | ||
| // Some type defines and random macros which don't seem to be in the
 | ||
| // header files i've included (or didn't exist at all)
 | ||
| //
 | ||
| 
 | ||
| #define max(a,b) (((a) > (b)) ? (a) : (b))
 | ||
| #define min(a,b) (((a) < (b)) ? (a) : (b))
 | ||
| 
 | ||
| #if 0   // DBG
 | ||
| #undef INLINE
 | ||
| #define INLINE
 | ||
| #else
 | ||
| #define INLINE __inline
 | ||
| #endif
 | ||
| 
 | ||
| #define INTERLOCKED /* Should only be accessed using InterlockedXxx routines*/
 | ||
| 
 | ||
| #define SET_FLAG(Flags, Bit)    ((Flags) |= (Bit))
 | ||
| #define CLEAR_FLAG(Flags, Bit)  ((Flags) &= ~(Bit))
 | ||
| #define TEST_FLAG(Flags, Bit)   ((Flags) & (Bit))
 | ||
| 
 | ||
| #define TEST(Value)             ((BOOLEAN) ((Value) ? TRUE : FALSE));
 | ||
| 
 | ||
| #define ARRAY_ELEMENTS_FOR_BITMAP(NumberOfBits, ArrayType) \
 | ||
|         ((NumberOfBits) / sizeof(ArrayType))
 | ||
| 
 | ||
| //
 | ||
| // Assorted constant definifitions
 | ||
| //
 | ||
| #define NUMBER_LOGICAL_UNIT_BINS 8
 | ||
| 
 | ||
| #define SP_DEFAULT_PHYSICAL_BREAK_VALUE 17
 | ||
| #define SP_SMALL_PHYSICAL_BREAK_VALUE 4
 | ||
| #define SP_LARGE_PHYSICAL_BREAK_VALUE (SP_DEFAULT_PHYSICAL_BREAK_VALUE + 1)
 | ||
| 
 | ||
| #define SCSIPORT_CONTROL_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\ScsiPort\\"
 | ||
| #define DISK_SERVICE_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Disk"
 | ||
| #define SCSIPORT_SPECIAL_TARGET_KEY L"SpecialTargetList"
 | ||
| #define SCSIPORT_VERIFIER_KEY L"Verifier"
 | ||
| 
 | ||
| //
 | ||
| // WMI constants
 | ||
| //
 | ||
| #define SPMOFRESOURCENAME      L"SCSIPORTWMI"
 | ||
| #define SPMOFREGISTRYPATH      L"SCSIPORT"
 | ||
| 
 | ||
| //
 | ||
| // NT uses a system time measured in 100 nanosecond intervals.  define
 | ||
| // conveninent constants for setting the timer.
 | ||
| //
 | ||
| 
 | ||
| #define MICROSECONDS        10              // 10 nanoseconds
 | ||
| #define MILLISECONDS        (MICROSECONDS * 1000)
 | ||
| #define SECONDS             (MILLISECONDS * 1000)
 | ||
| #define MINUTES             (SECONDS * 60)
 | ||
| 
 | ||
| #define TIMEOUT(x)          ((x) * -1)
 | ||
| 
 | ||
| //
 | ||
| // Possible values for the IsRemoved flag
 | ||
| //
 | ||
| 
 | ||
| #define NO_REMOVE       0
 | ||
| #define REMOVE_PENDING  1
 | ||
| #define REMOVE_COMPLETE 2
 | ||
| 
 | ||
| #define NUMBER_HARDWARE_STRINGS 6
 | ||
| 
 | ||
| #define SRB_DATA_TYPE 'wp'
 | ||
| #define SRB_LIST_DEPTH 20
 | ||
| 
 | ||
| #define NUMBER_BYPASS_SRB_DATA_BLOCKS 4
 | ||
| 
 | ||
| #define WMI_MINIPORT_EVENT_ITEM_MAX_SIZE 128
 | ||
| 
 | ||
| //
 | ||
| // Define the mimimum and maximum number of srb extensions which will be allocated.
 | ||
| //
 | ||
| 
 | ||
| #define MINIMUM_SRB_EXTENSIONS        16
 | ||
| #define MAXIMUM_SRB_EXTENSIONS       255
 | ||
| 
 | ||
| //
 | ||
| // Size of the buffer used for registry operations.
 | ||
| //
 | ||
| 
 | ||
| #define SP_REG_BUFFER_SIZE 512
 | ||
| 
 | ||
| //
 | ||
| // Number of times to retry when a BUSY status is returned.
 | ||
| //
 | ||
| 
 | ||
| #define BUSY_RETRY_COUNT 20
 | ||
| 
 | ||
| //
 | ||
| // Number of times to retry an INQUIRY request.
 | ||
| //
 | ||
| 
 | ||
| #define INQUIRY_RETRY_COUNT 2
 | ||
| 
 | ||
| //
 | ||
| // Number of irp stack locations to allocate for an INQUIRY command.
 | ||
| //
 | ||
| 
 | ||
| #define INQUIRY_STACK_LOCATIONS 1
 | ||
| 
 | ||
| //
 | ||
| // Bitmask used for aligning values.
 | ||
| //
 | ||
| 
 | ||
| #define LONG_ALIGN (sizeof(LONG) - 1)
 | ||
| 
 | ||
| //
 | ||
| // Size of the ADAPTER_EXTENSION
 | ||
| //
 | ||
| 
 | ||
| #define ADAPTER_EXTENSION_SIZE sizeof(ADAPTER_EXTENSION)
 | ||
| 
 | ||
| //
 | ||
| // Size of the buffer used for inquiry operations.  This is one more than the
 | ||
| // max bytes which can be requested from an inquiry operation so that we can
 | ||
| // zero out the buffer and be sure that the last string is null terminated.
 | ||
| //
 | ||
| 
 | ||
| #define SP_INQUIRY_BUFFER_SIZE (VPD_MAX_BUFFER_SIZE + 1)
 | ||
| 
 | ||
| //
 | ||
| // Assorted macros.
 | ||
| //
 | ||
| 
 | ||
| #define NEED_REQUEST_SENSE(Srb) (Srb->ScsiStatus == SCSISTAT_CHECK_CONDITION \
 | ||
|         && !(Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) &&                 \
 | ||
|         Srb->SenseInfoBuffer && Srb->SenseInfoBufferLength )
 | ||
| 
 | ||
| #define GET_FDO_EXTENSION(HwExt) ((CONTAINING_RECORD(HwExt, HW_DEVICE_EXTENSION, HwDeviceExtension))->FdoExtension)
 | ||
| 
 | ||
| #define ADDRESS_TO_HASH(PathId, TargetId, Lun) (((TargetId) + (Lun)) % NUMBER_LOGICAL_UNIT_BINS)
 | ||
| 
 | ||
| #define IS_CLEANUP_REQUEST(irpStack)                                                                    \
 | ||
|         (((irpStack)->MajorFunction == IRP_MJ_CLOSE) ||                                                 \
 | ||
|          ((irpStack)->MajorFunction == IRP_MJ_CLEANUP) ||                                               \
 | ||
|          ((irpStack)->MajorFunction == IRP_MJ_SHUTDOWN) ||                                              \
 | ||
|          (((irpStack)->MajorFunction == IRP_MJ_SCSI) &&                                                 \
 | ||
|           (((irpStack)->Parameters.Scsi.Srb->Function == SRB_FUNCTION_RELEASE_DEVICE) ||                \
 | ||
|            ((irpStack)->Parameters.Scsi.Srb->Function == SRB_FUNCTION_FLUSH_QUEUE) ||                   \
 | ||
|            (TEST_FLAG((irpStack)->Parameters.Scsi.Srb->SrbFlags, SRB_FLAGS_BYPASS_FROZEN_QUEUE |        \
 | ||
|                                                                  SRB_FLAGS_BYPASS_LOCKED_QUEUE)))))
 | ||
| 
 | ||
| 
 | ||
| #define IS_MAPPED_SRB(Srb)                                  \
 | ||
|         ((Srb->Function == SRB_FUNCTION_IO_CONTROL) ||      \
 | ||
|          ((Srb->Function == SRB_FUNCTION_EXECUTE_SCSI) &&   \
 | ||
|           ((Srb->Cdb[0] == SCSIOP_INQUIRY) ||               \
 | ||
|            (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE))))
 | ||
| 
 | ||
| #define LU_OPERATING_IN_DEGRADED_STATE(luFlags)             \
 | ||
|         ((luFlags) | LU_PERF_MAXQDEPTH_REDUCED)
 | ||
| 
 | ||
| //
 | ||
| // SpIsQueuePausedForSrb(lu, srb) -
 | ||
| //  determines if the queue has been paused for this particular type of
 | ||
| //  srb.  This can be used with SpSrbIsBypassRequest to determine whether the
 | ||
| //  srb needs to be handled specially.
 | ||
| //
 | ||
| 
 | ||
| #define SpIsQueuePausedForSrb(luFlags, srbFlags)                                                            \
 | ||
|     ((BOOLEAN) ((((luFlags) & LU_QUEUE_FROZEN) && !(srbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE)) ||           \
 | ||
|                 (((luFlags) & LU_QUEUE_PAUSED) && !(srbFlags & SRB_FLAGS_BYPASS_LOCKED_QUEUE))))
 | ||
| 
 | ||
| #define SpIsQueuePaused(lu) ((lu)->LuFlags & (LU_QUEUE_FROZEN           |   \
 | ||
|                                               LU_QUEUE_LOCKED))
 | ||
| 
 | ||
| #define SpSrbRequiresPower(srb)                                             \
 | ||
|     ((BOOLEAN) ((srb->Function == SRB_FUNCTION_EXECUTE_SCSI) ||             \
 | ||
|                  (srb->Function == SRB_FUNCTION_IO_CONTROL) ||              \
 | ||
|                  (srb->Function == SRB_FUNCTION_SHUTDOWN) ||                \
 | ||
|                  (srb->Function == SRB_FUNCTION_FLUSH) ||                   \
 | ||
|                  (srb->Function == SRB_FUNCTION_ABORT_COMMAND) ||           \
 | ||
|                  (srb->Function == SRB_FUNCTION_RESET_BUS) ||               \
 | ||
|                  (srb->Function == SRB_FUNCTION_RESET_DEVICE) ||            \
 | ||
|                  (srb->Function == SRB_FUNCTION_TERMINATE_IO) ||            \
 | ||
|                  (srb->Function == SRB_FUNCTION_REMOVE_DEVICE) ||           \
 | ||
|                  (srb->Function == SRB_FUNCTION_WMI)))
 | ||
| 
 | ||
| //
 | ||
| // Forward declarations of data structures
 | ||
| //
 | ||
| 
 | ||
| typedef struct _SRB_DATA SRB_DATA, *PSRB_DATA;
 | ||
| 
 | ||
| typedef struct _REMOVE_TRACKING_BLOCK
 | ||
|                REMOVE_TRACKING_BLOCK,
 | ||
|                *PREMOVE_TRACKING_BLOCK;
 | ||
| 
 | ||
| typedef struct _LOGICAL_UNIT_EXTENSION LOGICAL_UNIT_EXTENSION, *PLOGICAL_UNIT_EXTENSION;
 | ||
| typedef struct _ADAPTER_EXTENSION ADAPTER_EXTENSION, *PADAPTER_EXTENSION;
 | ||
| 
 | ||
| typedef struct _SP_INIT_CHAIN_ENTRY SP_INIT_CHAIN_ENTRY, *PSP_INIT_CHAIN_ENTRY;
 | ||
| 
 | ||
| typedef struct _HW_DEVICE_EXTENSION HW_DEVICE_EXTENSION, *PHW_DEVICE_EXTENSION;
 | ||
| //
 | ||
| // Macros for using the DMA functions.
 | ||
| //
 | ||
| 
 | ||
| #define AllocateCommonBuffer(DmaAdapter, Length,                        \
 | ||
|                                LogicalAddress, CacheEnabled)            \
 | ||
|             ((DmaAdapter)->DmaOperations->AllocateCommonBuffer)(        \
 | ||
|                 (DmaAdapter),                                           \
 | ||
|                 (Length),                                               \
 | ||
|                 (LogicalAddress),                                       \
 | ||
|                 (CacheEnabled))
 | ||
| #define FreeCommonBuffer(DmaAdapter, Length, LogicalAddress,            \
 | ||
|                          VirtualAddress, CacheEnabled)                  \
 | ||
|             ((DmaAdapter)->DmaOperations->FreeCommonBuffer)(            \
 | ||
|                 (DmaAdapter),                                           \
 | ||
|                 (Length),                                               \
 | ||
|                 (LogicalAddress),                                       \
 | ||
|                 (VirtualAddress),                                       \
 | ||
|                 (CacheEnabled))
 | ||
| 
 | ||
| #define GetScatterGatherList(DmaAdapter, DeviceObject, Mdl, CurrentVa,      \
 | ||
|                              Length, ExecutionRoutine, Context,             \
 | ||
|                              WriteToDevice)                                 \
 | ||
|             ((DmaAdapter)->DmaOperations->GetScatterGatherList)(            \
 | ||
|                 (DmaAdapter),                                               \
 | ||
|                 (DeviceObject),                                             \
 | ||
|                 (Mdl),                                                      \
 | ||
|                 (CurrentVa),                                                \
 | ||
|                 (Length),                                                   \
 | ||
|                 (ExecutionRoutine),                                         \
 | ||
|                 (Context),                                                  \
 | ||
|                 (WriteToDevice))
 | ||
| 
 | ||
| #define PutScatterGatherList(DmaAdapter, ScatterGather, WriteToDevice)      \
 | ||
|             ((DmaAdapter)->DmaOperations->PutScatterGatherList)(            \
 | ||
|                 (DmaAdapter),                                               \
 | ||
|                 (ScatterGather),                                            \
 | ||
|                 (WriteToDevice))
 | ||
| 
 | ||
| #define AllocateAdapterChannel(DmaAdapter, DeviceObject,                    \
 | ||
|                                NumberOfMapRegisters, ExecutionRoutine,      \
 | ||
|                                Context)                                     \
 | ||
|             ((DmaAdapter)->DmaOperations->AllocateAdapterChannel)(          \
 | ||
|                 (DmaAdapter),                                               \
 | ||
|                 (DeviceObject),                                             \
 | ||
|                 (NumberOfMapRegisters),                                     \
 | ||
|                 (ExecutionRoutine),                                         \
 | ||
|                 (Context))
 | ||
| 
 | ||
| #define FlushAdapterBuffers(DmaAdapter, Mdl, MapRegisterBase, CurrentVa,    \
 | ||
|                             Length, WriteToDevice)                          \
 | ||
|             ((DmaAdapter)->DmaOperations->FlushAdapterBuffers)(             \
 | ||
|                 (DmaAdapter),                                               \
 | ||
|                 (Mdl),                                                      \
 | ||
|                 (MapRegisterBase),                                          \
 | ||
|                 (CurrentVa),                                                \
 | ||
|                 (Length),                                                   \
 | ||
|                 (WriteToDevice))
 | ||
| 
 | ||
| #define MapTransfer(DmaAdapter, Mdl, MapRegisterBase, CurrentVa, Length,    \
 | ||
|                     WriteToDevice)                                          \
 | ||
|             ((DmaAdapter)->DmaOperations->MapTransfer)(                     \
 | ||
|                 (DmaAdapter),                                               \
 | ||
|                 (Mdl),                                                      \
 | ||
|                 (MapRegisterBase),                                          \
 | ||
|                 (CurrentVa),                                                \
 | ||
|                 (Length),                                                   \
 | ||
|                 (WriteToDevice))
 | ||
| 
 | ||
| #define FreeAdapterChannel(DmaAdapter)                                      \
 | ||
|             ((DmaAdapter)->DmaOperations->FreeAdapterChannel)((DmaAdapter))
 | ||
| 
 | ||
| #define FreeMapRegisters(DmaAdapter, MapRegisterBase, NumberOfMapRegisters) \
 | ||
|             ((DmaAdapter)->DmaOperations->FreeMapRegisters)(                \
 | ||
|                 (DmaAdapter),                                               \
 | ||
|                 (MapRegisterBase),                                          \
 | ||
|                 (NumberOfMapRegisters))
 | ||
| 
 | ||
| #define PutDmaAdapter(DmaAdapter)                                           \
 | ||
|             ((DmaAdapter)->DmaOperations->PutDmaAdapter)((DmaAdapter))
 | ||
| 
 | ||
| //
 | ||
| // Type Definitions
 | ||
| //
 | ||
| 
 | ||
| //
 | ||
| // Structure used for tracking remove lock allocations in checked builds
 | ||
| //
 | ||
| 
 | ||
| struct _REMOVE_TRACKING_BLOCK {
 | ||
|     PREMOVE_TRACKING_BLOCK NextBlock;
 | ||
|     PVOID Tag;
 | ||
|     LARGE_INTEGER TimeLocked;
 | ||
|     PCSTR File;
 | ||
|     ULONG Line;
 | ||
| };
 | ||
| 
 | ||
| #if DBG
 | ||
| #define SpAcquireRemoveLock(devobj, tag) \
 | ||
|     SpAcquireRemoveLockEx(devobj, tag, __file__, __LINE__)
 | ||
| #endif
 | ||
| 
 | ||
| typedef struct _RESET_COMPLETION_CONTEXT {
 | ||
|     PIRP           OriginalIrp;
 | ||
|     PDEVICE_OBJECT SafeLogicalUnit;
 | ||
|     PDEVICE_OBJECT AdapterDeviceObject;
 | ||
| 
 | ||
|     SCSI_REQUEST_BLOCK Srb;
 | ||
| } RESET_COMPLETION_CONTEXT, *PRESET_COMPLETION_CONTEXT;
 | ||
| 
 | ||
| //
 | ||
| // Define a pointer to the synchonize execution routine.
 | ||
| //
 | ||
| 
 | ||
| typedef
 | ||
| BOOLEAN
 | ||
| (*PSYNCHRONIZE_ROUTINE) (
 | ||
|     IN PKINTERRUPT Interrupt,
 | ||
|     IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine,
 | ||
|     IN PVOID SynchronizeContext
 | ||
|     );
 | ||
| 
 | ||
| typedef
 | ||
| VOID
 | ||
| (*PSP_ENABLE_DISABLE_COMPLETION_ROUTINE) (
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN NTSTATUS Status,
 | ||
|     IN PVOID Context
 | ||
|     );
 | ||
| 
 | ||
| typedef
 | ||
| VOID
 | ||
| (*PSP_POWER_COMPLETION_ROUTINE) (
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PVOID Context
 | ||
|     );
 | ||
| 
 | ||
| //
 | ||
| // device type table to build id's from
 | ||
| //
 | ||
| 
 | ||
| typedef const struct _SCSIPORT_DEVICE_TYPE {
 | ||
| 
 | ||
|     const PCSTR DeviceTypeString;
 | ||
| 
 | ||
|     const PCSTR GenericTypeString;
 | ||
| 
 | ||
|     const PCWSTR DeviceMapString;
 | ||
| 
 | ||
|     const BOOLEAN IsStorage;
 | ||
| 
 | ||
| } SCSIPORT_DEVICE_TYPE, *PSCSIPORT_DEVICE_TYPE;
 | ||
| 
 | ||
| //
 | ||
| // SCSI Get Configuration Information
 | ||
| //
 | ||
| // LUN Information
 | ||
| //
 | ||
| 
 | ||
| typedef struct _LOGICAL_UNIT_INFO {
 | ||
|     UCHAR PathId;
 | ||
|     UCHAR TargetId;
 | ||
|     UCHAR Lun;
 | ||
|     BOOLEAN DeviceClaimed;
 | ||
|     struct _LOGICAL_UNIT_INFO *NextLunInfo;
 | ||
|     UCHAR InquiryData[INQUIRYDATABUFFERSIZE];
 | ||
| } LOGICAL_UNIT_INFO, *PLOGICAL_UNIT_INFO;
 | ||
| 
 | ||
| typedef struct _SCSI_BUS_SCAN_DATA {
 | ||
|     USHORT Length;
 | ||
|     UCHAR InitiatorBusId;
 | ||
|     UCHAR NumberOfLogicalUnits;
 | ||
|     PLOGICAL_UNIT_INFO LunInfoList;
 | ||
| } SCSI_BUS_SCAN_DATA, *PSCSI_BUS_SCAN_DATA;
 | ||
| 
 | ||
| typedef struct _SCSI_CONFIGURATION_INFO {
 | ||
|     UCHAR NumberOfBuses;
 | ||
|     PSCSI_BUS_SCAN_DATA BusScanData[1];
 | ||
| } SCSI_CONFIGURATION_INFO, *PSCSI_CONFIGURATION_INFO;
 | ||
| 
 | ||
| //
 | ||
| // Adapter object transfer information.
 | ||
| //
 | ||
| 
 | ||
| typedef struct _ADAPTER_TRANSFER {
 | ||
|     PSRB_DATA SrbData;
 | ||
|     ULONG SrbFlags;
 | ||
|     PVOID LogicalAddress;
 | ||
|     ULONG Length;
 | ||
| }ADAPTER_TRANSFER, *PADAPTER_TRANSFER;
 | ||
| 
 | ||
| #ifdef USE_DMA_MACROS
 | ||
| 
 | ||
| typedef SCATTER_GATHER_ELEMENT SRB_SCATTER_GATHER, *PSRB_SCATTER_GATHER;
 | ||
| 
 | ||
| #else 
 | ||
| 
 | ||
| typedef struct _SRB_SCATTER_GATHER {
 | ||
|     SCSI_PHYSICAL_ADDRESS Address;
 | ||
|     ULONG Length;
 | ||
| }SRB_SCATTER_GATHER, *PSRB_SCATTER_GATHER;
 | ||
| 
 | ||
| #endif
 | ||
| 
 | ||
| //
 | ||
| // Port driver error logging
 | ||
| //
 | ||
| 
 | ||
| typedef struct _ERROR_LOG_ENTRY {
 | ||
|     UCHAR MajorFunctionCode;
 | ||
|     UCHAR PathId;
 | ||
|     UCHAR TargetId;
 | ||
|     UCHAR Lun;
 | ||
|     ULONG ErrorCode;
 | ||
|     ULONG UniqueId;
 | ||
|     ULONG ErrorLogRetryCount;
 | ||
|     ULONG SequenceNumber;
 | ||
| } ERROR_LOG_ENTRY, *PERROR_LOG_ENTRY;
 | ||
| 
 | ||
| //
 | ||
| // Context item for asynchronous enumerators.
 | ||
| //
 | ||
| 
 | ||
| typedef struct _SP_ENUMERATION_REQUEST SP_ENUMERATION_REQUEST, *PSP_ENUMERATION_REQUEST;
 | ||
| 
 | ||
| typedef
 | ||
| VOID
 | ||
| (*PSP_ENUMERATION_COMPLETION_ROUTINE) (
 | ||
|     IN PADAPTER_EXTENSION Adapter,
 | ||
|     IN PSP_ENUMERATION_REQUEST Request,
 | ||
|     IN NTSTATUS Status
 | ||
|     );
 | ||
| 
 | ||
| struct _SP_ENUMERATION_REQUEST {
 | ||
| 
 | ||
|     //
 | ||
|     // A pointer to the next enumeration request on the list.
 | ||
|     //
 | ||
| 
 | ||
|     PSP_ENUMERATION_REQUEST NextRequest;
 | ||
| 
 | ||
|     //
 | ||
|     // The completion routine to be run.  This routine will be run regardless
 | ||
|     // of whether the enumeration actually succeeds.  The
 | ||
|     // EnumerationDeviceMutex and the EnumerationWorklistMutex will both be
 | ||
|     // held when this is called.  The completion routine should free the Request
 | ||
|     // structure if necessary.
 | ||
|     //
 | ||
| 
 | ||
|     PSP_ENUMERATION_COMPLETION_ROUTINE CompletionRoutine;
 | ||
| 
 | ||
|     //
 | ||
|     // If this filed contains a pointer to an IO_STATUS_BLOCK then the
 | ||
|     // completion routine should write it's status value out.  This is so a
 | ||
|     // synchronous waiter can return something other than STATUS_PENDING to the
 | ||
|     // caller.  If this field is NULL then there is no consumer for the status
 | ||
|     // value.
 | ||
|     //
 | ||
| 
 | ||
|     PNTSTATUS OPTIONAL CompletionStatus;
 | ||
| 
 | ||
|     //
 | ||
|     // Arbitrary context value for the completion routine to use.  In most cases
 | ||
|     // this will be an IRP or an event.
 | ||
|     //
 | ||
| 
 | ||
|     PVOID Context;
 | ||
| 
 | ||
|     //
 | ||
|     // Indicates whether this request is being handled synchronously.
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN Synchronous;
 | ||
| };
 | ||
| 
 | ||
| //
 | ||
| // SCSI request extension for port driver.
 | ||
| //
 | ||
| 
 | ||
| typedef
 | ||
| VOID
 | ||
| (FASTCALL *PSRB_DATA_FREE_ROUTINE) (
 | ||
|     IN PADAPTER_EXTENSION Adapter,
 | ||
|     IN PSRB_DATA SrbData
 | ||
|     );
 | ||
| 
 | ||
| struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) _SRB_DATA {
 | ||
| 
 | ||
|     //
 | ||
|     // Single list entry.  The lookaside list will be maintained in this
 | ||
|     // memory.
 | ||
|     //
 | ||
| 
 | ||
|     SINGLE_LIST_ENTRY Reserved;
 | ||
| 
 | ||
|     //
 | ||
|     // Header for debugging purposes.
 | ||
|     //
 | ||
| 
 | ||
|     CSHORT Type;
 | ||
|     USHORT Size;
 | ||
| 
 | ||
|     //
 | ||
|     // The free routine for this srb data block.
 | ||
|     //
 | ||
| 
 | ||
|     PSRB_DATA_FREE_ROUTINE FreeRoutine;
 | ||
| 
 | ||
|     //
 | ||
|     // The list of requests for a particular logical unit.
 | ||
|     //
 | ||
| 
 | ||
|     LIST_ENTRY RequestList;
 | ||
| 
 | ||
|     //
 | ||
|     // The logical unit this request is intended for.
 | ||
|     //
 | ||
| 
 | ||
|     PLOGICAL_UNIT_EXTENSION LogicalUnit;
 | ||
| 
 | ||
|     //
 | ||
|     // The irp for the CurrentSrb.
 | ||
|     //
 | ||
| 
 | ||
|     PIRP CurrentIrp;
 | ||
| 
 | ||
|     //
 | ||
|     // The srb this is block is tracking.
 | ||
|     //
 | ||
| 
 | ||
|     PSCSI_REQUEST_BLOCK CurrentSrb;
 | ||
| 
 | ||
|     //
 | ||
|     // The chain of requests which have been completed by the miniport and are
 | ||
|     // waiting for the CompletionDpc to be run.
 | ||
|     //
 | ||
| 
 | ||
|     struct _SRB_DATA *CompletedRequests;
 | ||
|     ULONG ErrorLogRetryCount;
 | ||
|     ULONG SequenceNumber;
 | ||
| 
 | ||
| #ifdef USE_DMA_MACROS
 | ||
|     PSCATTER_GATHER_LIST MapRegisterBase;
 | ||
| #else 
 | ||
|     PVOID MapRegisterBase;
 | ||
| #endif
 | ||
| 
 | ||
|     ULONG NumberOfMapRegisters;
 | ||
| 
 | ||
|     //
 | ||
|     // The offset between the  data buffer for this request and the data
 | ||
|     // buffer described by the MDL in the irp.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG_PTR DataOffset;
 | ||
| 
 | ||
|     PVOID RequestSenseSave;
 | ||
| 
 | ||
|     //
 | ||
|     // These data values will be restored to the SRB when it is retried within
 | ||
|     // the port driver.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG OriginalDataTransferLength;
 | ||
| 
 | ||
|     //
 | ||
|     // SRB Data flags.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG Flags;
 | ||
| 
 | ||
|     //
 | ||
|     // Pointer to the adapter this block was allocated from.  This is used
 | ||
|     // when freeing srbdata blocks from the lookaside list back to pool.
 | ||
|     //
 | ||
| 
 | ||
|     PADAPTER_EXTENSION Adapter;
 | ||
| 
 | ||
|     //
 | ||
|     // The queue tag which was initially allocated for this srb_data block.
 | ||
|     // This tag will be used for any tagged srb's which are associated with
 | ||
|     // this block.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG QueueTag;
 | ||
| 
 | ||
|     //
 | ||
|     // Internal status value - only returned if srb->SrbStatus is set to
 | ||
|     // SRBP_STATUS_INTERNAL_ERROR.
 | ||
|     //
 | ||
| 
 | ||
|     NTSTATUS InternalStatus;
 | ||
| 
 | ||
|     //
 | ||
|     // The tick count when this request was last touched.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG TickCount;
 | ||
| 
 | ||
|     //
 | ||
|     // The MDL of the remapped buffer (per IoMapTransfer or GET_SCATTER_GATHER)
 | ||
|     //
 | ||
| 
 | ||
|     PMDL RemappedMdl;
 | ||
| 
 | ||
|     //
 | ||
|     // The original data buffer pointer for this request - this will be
 | ||
|     // restored when the request is completed.
 | ||
|     //
 | ||
| 
 | ||
|     PVOID OriginalDataBuffer;
 | ||
| 
 | ||
|     //
 | ||
|     // Pointer to the scatter gather list for this request
 | ||
|     //
 | ||
| 
 | ||
|     PSRB_SCATTER_GATHER ScatterGatherList;
 | ||
| 
 | ||
|     //
 | ||
|     // The original length of the sense data buffer supplied by the above
 | ||
|     // driver.
 | ||
|     //
 | ||
| 
 | ||
|     UCHAR RequestSenseLengthSave;
 | ||
| 
 | ||
|     //
 | ||
|     // Pointer to the orignal SRB DataBuffer.  We use this to store
 | ||
|     // the original when we replace it with our buffer to unmapped
 | ||
|     // memory in the case where the MapBuffer is FALSE.
 | ||
|     //
 | ||
| 
 | ||
|     PVOID UnmappedDataBuffer;
 | ||
| 
 | ||
| #ifndef USE_DMA_MACROS
 | ||
|     //
 | ||
|     // The "small" scatter gather list for this request.  Small
 | ||
|     // by the constant SP_SMALL_PHYSICAL_BREAK_VALUE - small lists contain
 | ||
|     // this many entries or less.
 | ||
|     //
 | ||
| 
 | ||
|     SRB_SCATTER_GATHER SmallScatterGatherList[SP_SMALL_PHYSICAL_BREAK_VALUE];
 | ||
| #endif
 | ||
| 
 | ||
| };
 | ||
| 
 | ||
| typedef struct _LOGICAL_UNIT_BIN {
 | ||
|     KSPIN_LOCK Lock;
 | ||
|     PLOGICAL_UNIT_EXTENSION List;
 | ||
| } LOGICAL_UNIT_BIN, *PLOGICAL_UNIT_BIN;
 | ||
| 
 | ||
| //
 | ||
| // WMI request item, queued on a miniport request.
 | ||
| //
 | ||
| 
 | ||
| typedef struct _WMI_MINIPORT_REQUEST_ITEM {
 | ||
|    //
 | ||
|    // WnodeEventItem MUST be the first field in WMI_MINIPORT_REQUEST_ITEM, in
 | ||
|    // order to accommodate a copy optimization in ScsiPortCompletionDpc().
 | ||
|    //
 | ||
|    UCHAR  WnodeEventItem[WMI_MINIPORT_EVENT_ITEM_MAX_SIZE];
 | ||
|    UCHAR  TypeOfRequest;                                  // [Event/Reregister]
 | ||
|    UCHAR  PathId;                                         // [0xFF for adapter]
 | ||
|    UCHAR  TargetId;
 | ||
|    UCHAR  Lun;
 | ||
|    struct _WMI_MINIPORT_REQUEST_ITEM * NextRequest;
 | ||
| } WMI_MINIPORT_REQUEST_ITEM, *PWMI_MINIPORT_REQUEST_ITEM;
 | ||
| 
 | ||
| //
 | ||
| // WMI parameters.
 | ||
| //
 | ||
| 
 | ||
| typedef struct _WMI_PARAMETERS {
 | ||
|    ULONG_PTR ProviderId; // ProviderId parameter from IRP
 | ||
|    PVOID DataPath;      // DataPath parameter from IRP
 | ||
|    ULONG BufferSize;    // BufferSize parameter from IRP
 | ||
|    PVOID Buffer;        // Buffer parameter from IRP
 | ||
| } WMI_PARAMETERS, *PWMI_PARAMETERS;
 | ||
| 
 | ||
| //
 | ||
| // SpInsertFreeWmiMiniPortItem context structure.
 | ||
| //
 | ||
| 
 | ||
| typedef struct _WMI_INSERT_CONTEXT {
 | ||
|    PDEVICE_OBJECT             DeviceObject;                     // [FDO or PDO]
 | ||
|    PWMI_MINIPORT_REQUEST_ITEM ItemsToInsert;
 | ||
| } WMI_INSERT_CONTEXT, *PWMI_INSERT_CONTEXT;
 | ||
| 
 | ||
| //
 | ||
| // SpRemoveFreeWmiMiniPortItem context structure.
 | ||
| //
 | ||
| 
 | ||
| typedef struct _WMI_REMOVE_CONTEXT {
 | ||
|    PDEVICE_OBJECT             DeviceObject;                     // [FDO or PDO]
 | ||
|    USHORT                     NumberToRemove;
 | ||
| } WMI_REMOVE_CONTEXT, *PWMI_REMOVE_CONTEXT;
 | ||
| 
 | ||
| //
 | ||
| // Define data storage for access at interrupt Irql.
 | ||
| //
 | ||
| 
 | ||
| typedef struct _INTERRUPT_DATA {
 | ||
| 
 | ||
|     //
 | ||
|     // SCSI port interrupt flags
 | ||
|     //
 | ||
| 
 | ||
|     ULONG InterruptFlags;
 | ||
| 
 | ||
|     //
 | ||
|     // List head for singlely linked list of complete IRPs.
 | ||
|     //
 | ||
| 
 | ||
|     PSRB_DATA CompletedRequests;
 | ||
| 
 | ||
|     //
 | ||
|     // Adapter object transfer parameters.
 | ||
|     //
 | ||
| 
 | ||
|     ADAPTER_TRANSFER MapTransferParameters;
 | ||
| 
 | ||
|     //
 | ||
|     // Error log information.
 | ||
|     //
 | ||
| 
 | ||
|     ERROR_LOG_ENTRY  LogEntry;
 | ||
| 
 | ||
|     //
 | ||
|     // Logical unit to start next.
 | ||
|     //
 | ||
| 
 | ||
|     PLOGICAL_UNIT_EXTENSION ReadyLogicalUnit;
 | ||
| 
 | ||
|     //
 | ||
|     // List of completed abort reqeusts.
 | ||
|     //
 | ||
| 
 | ||
|     PLOGICAL_UNIT_EXTENSION CompletedAbort;
 | ||
| 
 | ||
|     //
 | ||
|     // Miniport timer request routine.
 | ||
|     //
 | ||
| 
 | ||
|     PHW_INTERRUPT HwTimerRequest;
 | ||
| 
 | ||
|     //
 | ||
|     // Mini port timer request time in micro seconds.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG MiniportTimerValue;
 | ||
| 
 | ||
|     //
 | ||
|     // Queued WMI request items.
 | ||
|     //
 | ||
| 
 | ||
|     PWMI_MINIPORT_REQUEST_ITEM WmiMiniPortRequests;
 | ||
| 
 | ||
| } INTERRUPT_DATA, *PINTERRUPT_DATA;
 | ||
| 
 | ||
| #define NON_STANDARD_VPD_SUPPORTS_PAGE80 0x00000001
 | ||
| #define NON_STANDARD_VPD_SUPPORTS_PAGE83 0x00000002
 | ||
| 
 | ||
| typedef struct {
 | ||
|     ULONG SparseLun;
 | ||
|     ULONG OneLun;
 | ||
|     ULONG LargeLuns;
 | ||
|     ULONG SetLunInCdb;
 | ||
|     ULONG NonStandardVPD;
 | ||
|     ULONG BinarySN;
 | ||
| } SP_SPECIAL_CONTROLLER_FLAGS, *PSP_SPECIAL_CONTROLLER_FLAGS;
 | ||
| 
 | ||
| typedef struct _CONFIGURATION_CONTEXT {
 | ||
|     BOOLEAN DisableTaggedQueueing;
 | ||
|     BOOLEAN DisableMultipleLu;
 | ||
|     ULONG AdapterNumber;
 | ||
|     ULONG BusNumber;
 | ||
|     PVOID Parameter;
 | ||
|     PACCESS_RANGE AccessRanges;
 | ||
|     UNICODE_STRING RegistryPath;
 | ||
|     PORT_CONFIGURATION_INFORMATION PortConfig;
 | ||
| }CONFIGURATION_CONTEXT, *PCONFIGURATION_CONTEXT;
 | ||
| 
 | ||
| typedef struct _DEVICE_MAP_HANDLES {
 | ||
|     HANDLE BusKey;
 | ||
|     HANDLE InitiatorKey;
 | ||
| } DEVICE_MAP_HANDLES, *PDEVICE_MAP_HANDLES;
 | ||
| 
 | ||
| typedef struct _COMMON_EXTENSION {
 | ||
| 
 | ||
|     //
 | ||
|     // Back pointer to the device object
 | ||
|     //
 | ||
| 
 | ||
|     PDEVICE_OBJECT DeviceObject;
 | ||
| 
 | ||
|     struct {
 | ||
| 
 | ||
|         //
 | ||
|         // True if this device object is a physical device object
 | ||
|         //
 | ||
| 
 | ||
|         BOOLEAN IsPdo : 1;
 | ||
| 
 | ||
|         //
 | ||
|         // True if this device object has processed it's first start and
 | ||
|         // has been initialized.
 | ||
|         //
 | ||
| 
 | ||
|         BOOLEAN IsInitialized : 1;
 | ||
| 
 | ||
|         //
 | ||
|         // Has WMI been initialized for this device object?
 | ||
|         //
 | ||
| 
 | ||
|         BOOLEAN WmiInitialized : 1;
 | ||
| 
 | ||
|         //
 | ||
|         // Has the miniport associated with this FDO or PDO indicated WMI
 | ||
|         // support?
 | ||
|         //
 | ||
| 
 | ||
|         BOOLEAN WmiMiniPortSupport : 1;
 | ||
| 
 | ||
|         //
 | ||
|         // Has the miniport been initialized for WMI.
 | ||
|         //
 | ||
| 
 | ||
|         BOOLEAN WmiMiniPortInitialized : 1;
 | ||
| 
 | ||
|     };
 | ||
| 
 | ||
|     //
 | ||
|     // Current plug and play state or 0xff if no state operations have been
 | ||
|     // sent yet.
 | ||
|     //
 | ||
| 
 | ||
|     UCHAR CurrentPnpState;
 | ||
| 
 | ||
|     //
 | ||
|     // Previous plug and play state or 0xff if there is no requirement that we
 | ||
|     // be able to roll back in the current state (current state is not a query)
 | ||
|     //
 | ||
| 
 | ||
|     UCHAR PreviousPnpState;
 | ||
| 
 | ||
|     //
 | ||
|     // Interlocked counter indicating that the device has been removed.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG IsRemoved;
 | ||
| 
 | ||
| 
 | ||
|     //
 | ||
|     // Pointer to the device object this is on top of
 | ||
|     //
 | ||
| 
 | ||
|     PDEVICE_OBJECT LowerDeviceObject;
 | ||
| 
 | ||
|     //
 | ||
|     // Srb flags to OR into all SRBs coming through this device object.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG SrbFlags;
 | ||
| 
 | ||
|     //
 | ||
|     // Pointer to the dispatch table for this object
 | ||
|     //
 | ||
| 
 | ||
|     PDRIVER_DISPATCH *MajorFunction;
 | ||
| 
 | ||
| 
 | ||
|     //
 | ||
|     // Current and desired power state for this device and the system.
 | ||
|     //
 | ||
| 
 | ||
|     SYSTEM_POWER_STATE CurrentSystemState;
 | ||
| 
 | ||
|     DEVICE_POWER_STATE CurrentDeviceState;
 | ||
| 
 | ||
|     DEVICE_POWER_STATE DesiredDeviceState;
 | ||
| 
 | ||
|     //
 | ||
|     // Idle timer for this device
 | ||
|     //
 | ||
| 
 | ||
|     PULONG IdleTimer;
 | ||
| 
 | ||
|     //
 | ||
|     // Pointer to the SCSIPORT-provided WMIREGINFO structures registered on
 | ||
|     // behalf of the miniport for this device object.  Size is the size of the
 | ||
|     // entire WMIREGINFO buffer in bytes.
 | ||
|     //
 | ||
| 
 | ||
|     PWMIREGINFO WmiScsiPortRegInfoBuf;
 | ||
|     ULONG       WmiScsiPortRegInfoBufSize;
 | ||
| 
 | ||
|     //
 | ||
|     // INTERLOCKED counter of the number of consumers of this device object.
 | ||
|     // When this count goes to zero the RemoveEvent will be set.
 | ||
|     //
 | ||
| 
 | ||
|     //
 | ||
|     // This variable is only manipulated by SpAcquireRemoveLock and
 | ||
|     // SpReleaseRemoveLock.
 | ||
|     //
 | ||
| 
 | ||
|     LONG RemoveLock;
 | ||
| 
 | ||
|     //
 | ||
|     // This event will be signalled when it is safe to remove the device object
 | ||
|     //
 | ||
| 
 | ||
|     KEVENT RemoveEvent;
 | ||
| 
 | ||
|     //
 | ||
|     // The spinlock and the list are only used in checked builds to track who
 | ||
|     // has acquired the remove lock.  Free systems will leave these initialized
 | ||
|     // to 0xff (they are still in the structure to make debugging easier)
 | ||
|     //
 | ||
| 
 | ||
|     KSPIN_LOCK RemoveTrackingSpinlock;
 | ||
| 
 | ||
|     PVOID RemoveTrackingList;
 | ||
| 
 | ||
|     LONG RemoveTrackingUntrackedCount;
 | ||
| 
 | ||
|     NPAGED_LOOKASIDE_LIST RemoveTrackingLookasideList;
 | ||
| 
 | ||
|     BOOLEAN RemoveTrackingLookasideListInitialized;
 | ||
| 
 | ||
|     //
 | ||
|     // Count of different services this device is being used for (ala
 | ||
|     // IRP_MN_DEVICE_USAGE_NOTIFICATION)
 | ||
|     //
 | ||
| 
 | ||
|     ULONG PagingPathCount;
 | ||
|     ULONG HibernatePathCount;
 | ||
|     ULONG DumpPathCount;
 | ||
| 
 | ||
| } COMMON_EXTENSION, *PCOMMON_EXTENSION;
 | ||
| 
 | ||
| typedef struct _VERIFIER_EXTENSION {
 | ||
| 
 | ||
|     //
 | ||
|     // Miniport routines we verify.
 | ||
|     //
 | ||
| 
 | ||
|     PHW_FIND_ADAPTER    RealHwFindAdapter;
 | ||
|     PHW_INITIALIZE      RealHwInitialize;
 | ||
|     PHW_STARTIO         RealHwStartIo;
 | ||
|     PHW_INTERRUPT       RealHwInterrupt;
 | ||
|     PHW_RESET_BUS       RealHwResetBus;
 | ||
|     PHW_DMA_STARTED     RealHwDmaStarted;
 | ||
|     PHW_INTERRUPT       RealHwRequestInterrupt;
 | ||
|     PHW_INTERRUPT       RealHwTimerRequest;
 | ||
|     PHW_ADAPTER_CONTROL RealHwAdapterControl;
 | ||
| 
 | ||
|     //
 | ||
|     // Indicates the number of common buffer blocks that have been allocated.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG CommonBufferBlocks;
 | ||
| 
 | ||
|     //
 | ||
|     // Points to an array that holds the VAs of all the common blocks.
 | ||
|     //
 | ||
| 
 | ||
|     PVOID* CommonBufferVAs;
 | ||
| 
 | ||
|     //
 | ||
|     // Points to an array that holds the PAs of all the common blocks.
 | ||
|     //
 | ||
| 
 | ||
|     PHYSICAL_ADDRESS* CommonBufferPAs;
 | ||
| 
 | ||
|     //
 | ||
|     // Indicates the size of the non-cached extension.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG NonCachedBufferSize;
 | ||
| 
 | ||
|     //
 | ||
|     // Controls how aggressively we verify.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG VrfyLevel;
 | ||
| 
 | ||
|     //
 | ||
|     // Pointer to an invalid page of memory.  Used to catch miniports
 | ||
|     // that touch memory when they're not supposed to.
 | ||
|     //
 | ||
| 
 | ||
|     PVOID InvalidPage;
 | ||
| 
 | ||
|     //
 | ||
|     // Indicates whether the common buffer blocks were allocated using
 | ||
|     // DMA common buffer allocation routine.
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN IsCommonBuffer;
 | ||
| 
 | ||
| } VERIFIER_EXTENSION, *PVERIFIER_EXTENSION;
 | ||
| 
 | ||
| 
 | ||
| struct _ADAPTER_EXTENSION {
 | ||
| 
 | ||
|     union {
 | ||
|         PDEVICE_OBJECT DeviceObject;
 | ||
|         COMMON_EXTENSION CommonExtension;
 | ||
|     };
 | ||
| 
 | ||
|     //
 | ||
|     // Pointer to the PDO we attached to - necessary for PnP routines
 | ||
|     //
 | ||
| 
 | ||
|     PDEVICE_OBJECT LowerPdo;
 | ||
| 
 | ||
| #if TEST_LISTS
 | ||
| 
 | ||
|     //
 | ||
|     // Some simple performance counters to determine how often we use the
 | ||
|     // small vs. medium vs. large scatter gather lists.
 | ||
|     //
 | ||
| 
 | ||
|     ULONGLONG ScatterGatherAllocationCount;
 | ||
| 
 | ||
|     //
 | ||
|     // Counters used to calculate the average size of a small medium and
 | ||
|     // large allocation.  There are two values for each counter - a total
 | ||
|     // count and an overflow count.  The total count will be right-shifted one
 | ||
|     // bit if it overflows on an increment.  When this happens the overflow
 | ||
|     // count will also be incremented.  This count is used to adjust the
 | ||
|     // allocation count when determining averages.
 | ||
|     //
 | ||
| 
 | ||
|     ULONGLONG SmallAllocationSize;
 | ||
|     ULONGLONG MediumAllocationSize;
 | ||
|     ULONGLONG LargeAllocationSize;
 | ||
| 
 | ||
|     ULONG SmallAllocationCount;
 | ||
|     ULONG LargeAllocationCount;
 | ||
| 
 | ||
|     //
 | ||
|     // Counters to determine how often we can service a request off the
 | ||
|     // srb data list, how often we need to queue a request and how often
 | ||
|     // we can resurrect a free'd srb data to service something off the queue.
 | ||
|     //
 | ||
| 
 | ||
|     INTERLOCKED ULONGLONG SrbDataAllocationCount;
 | ||
|     INTERLOCKED ULONGLONG SrbDataQueueInsertionCount;
 | ||
|     INTERLOCKED ULONGLONG SrbDataEmergencyFreeCount;
 | ||
|     INTERLOCKED ULONGLONG SrbDataServicedFromTickHandlerCount;
 | ||
|     INTERLOCKED ULONGLONG SrbDataResurrectionCount;
 | ||
| 
 | ||
| #endif
 | ||
| 
 | ||
|     //
 | ||
|     // Device extension for miniport routines.
 | ||
|     //
 | ||
| 
 | ||
|     PVOID HwDeviceExtension;
 | ||
| 
 | ||
|     //
 | ||
|     // Miniport noncached device extension
 | ||
|     //
 | ||
| 
 | ||
|     PVOID NonCachedExtension;
 | ||
|     ULONG NonCachedExtensionSize;
 | ||
| 
 | ||
|     ULONG PortNumber;
 | ||
| 
 | ||
|     ULONG AdapterNumber;
 | ||
| 
 | ||
|     //
 | ||
|     // Active requests count.  This count is biased by -1 so a value of -1
 | ||
|     // indicates there are no requests out standing.
 | ||
|     //
 | ||
| 
 | ||
|     LONG ActiveRequestCount;
 | ||
| 
 | ||
|     //
 | ||
|     // Binary Flags
 | ||
|     //
 | ||
| 
 | ||
|     typedef struct {
 | ||
| 
 | ||
|         //
 | ||
|         // Did pnp or the port driver detect this device and provide resources
 | ||
|         // to the miniport, or did the miniport detect the device for us.  This
 | ||
|         // flag also indicates whether the AllocatedResources list is non-null
 | ||
|         // going into the find adapter routine.
 | ||
|         //
 | ||
| 
 | ||
|         BOOLEAN IsMiniportDetected : 1;
 | ||
| 
 | ||
|         //
 | ||
|         // Do we need to virtualize this adapter and make it look like the only
 | ||
|         // adapter on it's own bus?
 | ||
|         //
 | ||
| 
 | ||
|         BOOLEAN IsInVirtualSlot : 1;
 | ||
| 
 | ||
|         //
 | ||
|         // Is this a pnp adapter?
 | ||
|         //
 | ||
| 
 | ||
|         BOOLEAN IsPnp : 1;
 | ||
| 
 | ||
|         //
 | ||
|         // Was an interrupt assigned to this device by the system?
 | ||
|         //
 | ||
| 
 | ||
|         BOOLEAN HasInterrupt : 1;
 | ||
| 
 | ||
|         //
 | ||
|         // Can this device be powered off?
 | ||
|         //
 | ||
| 
 | ||
|         BOOLEAN DisablePower : 1;
 | ||
| 
 | ||
|         //
 | ||
|         // Can this device be stopped?
 | ||
|         //
 | ||
| 
 | ||
|         BOOLEAN DisableStop : 1;
 | ||
| 
 | ||
|         //
 | ||
|         // Does this device need power notification on shutdown?
 | ||
|         //
 | ||
| 
 | ||
|         BOOLEAN NeedsShutdown : 1;
 | ||
| 
 | ||
|     };
 | ||
| 
 | ||
|     //
 | ||
|     // For most virtual slot devices this will be zero.  However for some
 | ||
|     // the real slot/function number is needed by the miniport to access
 | ||
|     // hardware shared by multiple slots/functions.
 | ||
|     //
 | ||
| 
 | ||
|     PCI_SLOT_NUMBER VirtualSlotNumber;
 | ||
| 
 | ||
|     //
 | ||
|     // The bus and slot number of this device as returned by the PCI driver.
 | ||
|     // This is used when building the ConfigInfo block for crashdump so that
 | ||
|     // the dump drivers can talk directly with the hal.  These are only
 | ||
|     // valid if IsInVirtualSlot is TRUE above.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG RealBusNumber;
 | ||
| 
 | ||
|     ULONG RealSlotNumber;
 | ||
| 
 | ||
|     //
 | ||
|     // Number of SCSI buses
 | ||
|     //
 | ||
| 
 | ||
|     UCHAR NumberOfBuses;
 | ||
|     UCHAR MaximumTargetIds;
 | ||
|     UCHAR MaxLuCount;
 | ||
| 
 | ||
|     //
 | ||
|     // SCSI port driver flags
 | ||
|     //
 | ||
| 
 | ||
|     ULONG Flags;
 | ||
| 
 | ||
|     INTERLOCKED ULONG DpcFlags;
 | ||
| 
 | ||
|     //
 | ||
|     // The number of times this adapter has been disabled.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG DisableCount;
 | ||
| 
 | ||
|     LONG PortTimeoutCounter;
 | ||
| 
 | ||
|     //
 | ||
|     // A pointer to the interrupt object to be used with
 | ||
|     // the SynchronizeExecution routine.  If the miniport is
 | ||
|     // using SpSynchronizeExecution then this will actually point
 | ||
|     // back to the adapter extension.
 | ||
|     //
 | ||
| 
 | ||
|     PKINTERRUPT InterruptObject;
 | ||
| 
 | ||
|     //
 | ||
|     // Second Interrupt object (PCI IDE work-around)
 | ||
|     //
 | ||
| 
 | ||
|     PKINTERRUPT InterruptObject2;
 | ||
| 
 | ||
|     //
 | ||
|     // Routine to call to synchronize execution for the miniport.
 | ||
|     //
 | ||
| 
 | ||
|     PSYNCHRONIZE_ROUTINE  SynchronizeExecution;
 | ||
| 
 | ||
|     //
 | ||
|     // Global device sequence number.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG SequenceNumber;
 | ||
|     KSPIN_LOCK SpinLock;
 | ||
| 
 | ||
|     //
 | ||
|     // Second spin lock (PCI IDE work-around).  This is only initalized
 | ||
|     // if the miniport has requested multiple interrupts.
 | ||
|     //
 | ||
| 
 | ||
|     KSPIN_LOCK MultipleIrqSpinLock;
 | ||
| 
 | ||
|     //
 | ||
|     // Dummy interrupt spin lock.
 | ||
|     //
 | ||
| 
 | ||
|     KSPIN_LOCK InterruptSpinLock;
 | ||
| 
 | ||
|     //
 | ||
|     // Dma Adapter information.
 | ||
|     //
 | ||
| 
 | ||
|     PVOID MapRegisterBase;
 | ||
|     PDMA_ADAPTER DmaAdapterObject;
 | ||
|     ADAPTER_TRANSFER FlushAdapterParameters;
 | ||
| 
 | ||
|     //
 | ||
|     // miniport's copy of the configuraiton informaiton.
 | ||
|     // Used only during initialization.
 | ||
|     //
 | ||
| 
 | ||
|     PPORT_CONFIGURATION_INFORMATION PortConfig;
 | ||
| 
 | ||
|     //
 | ||
|     // Resources allocated and translated for this particular adapter.
 | ||
|     //
 | ||
| 
 | ||
|     PCM_RESOURCE_LIST AllocatedResources;
 | ||
| 
 | ||
|     PCM_RESOURCE_LIST TranslatedResources;
 | ||
| 
 | ||
|     //
 | ||
|     // Common buffer size.  Used for HalFreeCommonBuffer.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG CommonBufferSize;
 | ||
|     ULONG SrbExtensionSize;
 | ||
| 
 | ||
|     //
 | ||
|     // Indicates whether the common buffer was allocated using
 | ||
|     // ALLOCATE_COMMON_BUFFER or MmAllocateContiguousMemorySpecifyCache.
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN UncachedExtensionIsCommonBuffer;
 | ||
| 
 | ||
|     //
 | ||
|     // The number of srb extensions which were allocated.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG SrbExtensionCount;
 | ||
| 
 | ||
|     //
 | ||
|     // Placeholder for the minimum number of requests to allocate for.
 | ||
|     // This can be a registry parameter.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG NumberOfRequests;
 | ||
| 
 | ||
|     //
 | ||
|     // SrbExtension and non-cached common buffer
 | ||
|     //
 | ||
| 
 | ||
|     PVOID SrbExtensionBuffer;
 | ||
| 
 | ||
|     //
 | ||
|     // List head of free SRB extentions.
 | ||
|     //
 | ||
| 
 | ||
|     PVOID SrbExtensionListHeader;
 | ||
| 
 | ||
|     //
 | ||
|     // A bitmap for keeping track of which queue tags are in use.
 | ||
|     //
 | ||
| 
 | ||
|     KSPIN_LOCK QueueTagSpinLock;
 | ||
|     PRTL_BITMAP QueueTagBitMap;
 | ||
| 
 | ||
|     UCHAR MaxQueueTag;
 | ||
| 
 | ||
|     //
 | ||
|     // Hint for allocating queue tags.  Value will be the last queue
 | ||
|     // tag allocated + 1.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG QueueTagHint;
 | ||
| 
 | ||
|     //
 | ||
|     // Logical Unit Extensions
 | ||
|     //
 | ||
| 
 | ||
|     ULONG HwLogicalUnitExtensionSize;
 | ||
| 
 | ||
|     //
 | ||
|     // List of mapped address entries for use when powering up the adapter
 | ||
|     // or cleaning up its mappings.
 | ||
|     //
 | ||
| 
 | ||
|     PMAPPED_ADDRESS MappedAddressList;
 | ||
| 
 | ||
|     //
 | ||
|     // List of free mapped address blocks preallocated by scsiport before 
 | ||
|     // calling HwFindAdapter.  One is allocated for each memory range in the 
 | ||
|     // miniport's resource list.  As ranges are unmapped their blocks will 
 | ||
|     // be placed here for potential reuse by the miniport's HwFindAdapter 
 | ||
|     // routine.
 | ||
|     //
 | ||
| 
 | ||
|     PMAPPED_ADDRESS FreeMappedAddressList;
 | ||
| 
 | ||
|     //
 | ||
|     // Miniport service routine pointers.
 | ||
|     //
 | ||
| 
 | ||
|     PHW_FIND_ADAPTER HwFindAdapter;
 | ||
|     PHW_INITIALIZE HwInitialize;
 | ||
|     PHW_STARTIO HwStartIo;
 | ||
|     PHW_INTERRUPT HwInterrupt;
 | ||
|     PHW_RESET_BUS HwResetBus;
 | ||
|     PHW_DMA_STARTED HwDmaStarted;
 | ||
|     PHW_INTERRUPT HwRequestInterrupt;
 | ||
|     PHW_INTERRUPT HwTimerRequest;
 | ||
|     PHW_ADAPTER_CONTROL HwAdapterControl;
 | ||
| 
 | ||
|     ULONG InterruptLevel;
 | ||
|     ULONG IoAddress;
 | ||
| 
 | ||
|     //
 | ||
|     // BitMap containing the list of supported adapter control types for this
 | ||
|     // adapter/miniport.
 | ||
|     //
 | ||
| 
 | ||
|     RTL_BITMAP SupportedControlBitMap;
 | ||
|     ULONG SupportedControlBits[ARRAY_ELEMENTS_FOR_BITMAP(
 | ||
|                                     (ScsiAdapterControlMax),
 | ||
|                                     ULONG)];
 | ||
| 
 | ||
|     //
 | ||
|     // Array of logical unit extensions.
 | ||
|     //
 | ||
| 
 | ||
|     LOGICAL_UNIT_BIN LogicalUnitList[NUMBER_LOGICAL_UNIT_BINS];
 | ||
| 
 | ||
|     //
 | ||
|     // The last logical unit for which the miniport completed a request.  This
 | ||
|     // will give us a chance to stay out of the LogicalUnitList for the common
 | ||
|     // completion type.
 | ||
|     //
 | ||
|     // This value is set by ScsiPortNotification and will be cleared by
 | ||
|     // SpRemoveLogicalUnitFromBin.
 | ||
|     //
 | ||
| 
 | ||
|     PLOGICAL_UNIT_EXTENSION CachedLogicalUnit;
 | ||
| 
 | ||
|     //
 | ||
|     // Interrupt level data storage.
 | ||
|     //
 | ||
| 
 | ||
|     INTERRUPT_DATA InterruptData;
 | ||
| 
 | ||
|     //
 | ||
|     // Whether or not an interrupt has occured since the last timeout.
 | ||
|     // Used to determine if interrupts may not be getting delivered.
 | ||
|     // This value must be set within KeSynchronizeExecution
 | ||
|     //
 | ||
| 
 | ||
|     ULONG WatchdogInterruptCount;
 | ||
| 
 | ||
|     //
 | ||
|     // SCSI Capabilities structure
 | ||
|     //
 | ||
| 
 | ||
|     IO_SCSI_CAPABILITIES Capabilities;
 | ||
| 
 | ||
|     //
 | ||
|     // Miniport timer object.
 | ||
|     //
 | ||
| 
 | ||
|     KTIMER MiniPortTimer;
 | ||
| 
 | ||
|     //
 | ||
|     // Miniport DPC for timer object.
 | ||
|     //
 | ||
| 
 | ||
|     KDPC MiniPortTimerDpc;
 | ||
| 
 | ||
|     //
 | ||
|     // Physical address of common buffer
 | ||
|     //
 | ||
| 
 | ||
|     PHYSICAL_ADDRESS PhysicalCommonBuffer;
 | ||
| 
 | ||
|     //
 | ||
|     // Buffers must be mapped into system space.
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN MapBuffers;
 | ||
| 
 | ||
|     //
 | ||
|     // Buffers must be remapped into system space after IoMapTransfer has been
 | ||
|     // called.
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN RemapBuffers;
 | ||
| 
 | ||
|     //
 | ||
|     // Is this device a bus master and does it require map registers.
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN MasterWithAdapter;
 | ||
| 
 | ||
|     //
 | ||
|     // Supports tagged queuing
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN TaggedQueuing;
 | ||
| 
 | ||
|     //
 | ||
|     // Supports auto request sense.
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN AutoRequestSense;
 | ||
| 
 | ||
|     //
 | ||
|     // Supports multiple requests per logical unit.
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN MultipleRequestPerLu;
 | ||
| 
 | ||
|     //
 | ||
|     // Support receive event function.
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN ReceiveEvent;
 | ||
| 
 | ||
|     //
 | ||
|     // Indicates an srb extension needs to be allocated.
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN AllocateSrbExtension;
 | ||
| 
 | ||
|     //
 | ||
|     // Indicates the contorller caches data.
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN CachesData;
 | ||
| 
 | ||
|     //
 | ||
|     // Indicates that the adapter can handle 64-bit DMA.
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN Dma64BitAddresses;
 | ||
| 
 | ||
|     //
 | ||
|     // Indicates that the adapter can handle 32-bit DMA.
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN Dma32BitAddresses;
 | ||
| 
 | ||
|     //
 | ||
|     // Queued WMI request items that are not in use.
 | ||
|     //
 | ||
|     INTERLOCKED SLIST_HEADER    WmiFreeMiniPortRequestList;
 | ||
|     KSPIN_LOCK                  WmiFreeMiniPortRequestLock;
 | ||
|     INTERLOCKED ULONG           WmiFreeMiniPortRequestWatermark;
 | ||
|     INTERLOCKED ULONG           WmiFreeMiniPortRequestCount;
 | ||
|     BOOLEAN                     WmiFreeMiniPortRequestInitialized;
 | ||
| 
 | ||
|     //
 | ||
|     // Free WMI request items were exhausted at least once in the lifetime
 | ||
|     // of this adapter (used to log error only once).
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN                    WmiFreeMiniPortRequestsExhausted;
 | ||
| 
 | ||
|     //
 | ||
|     // This mutex is used to synchronize access & modification of the list
 | ||
|     // of devices during enumeration & reporting.
 | ||
|     //
 | ||
| 
 | ||
|     KMUTEX EnumerationDeviceMutex;
 | ||
| 
 | ||
|     //
 | ||
|     // This fast-mutex is used to protect the enumeration work-item and
 | ||
|     // the list of completion routines to be run once an enumeration is
 | ||
|     // finished.
 | ||
|     //
 | ||
| 
 | ||
|     FAST_MUTEX EnumerationWorklistMutex;
 | ||
| 
 | ||
|     //
 | ||
|     // System time of the last bus scan.  This is protected by the
 | ||
|     // EnumerationWorkListMutex.
 | ||
|     //
 | ||
| 
 | ||
|     LARGE_INTEGER LastBusScanTime;
 | ||
| 
 | ||
|     //
 | ||
|     // Indicates that the next rescan which comes in should be "forced", ie.
 | ||
|     // it should rescan no matter how recent the last one was.
 | ||
|     //
 | ||
| 
 | ||
|     INTERLOCKED LONG ForceNextBusScan;
 | ||
| 
 | ||
|     //
 | ||
|     // A work item to use in enumerating the bus.
 | ||
|     //
 | ||
| 
 | ||
|     WORK_QUEUE_ITEM EnumerationWorkItem;
 | ||
| 
 | ||
|     //
 | ||
|     // A pointer to the thread the workitem is running on.  This is for
 | ||
|     // debugging purposes.
 | ||
|     //
 | ||
| 
 | ||
|     PKTHREAD EnumerationWorkThread;
 | ||
| 
 | ||
|     //
 | ||
|     // If this is TRUE then there is already an enumeration worker thread
 | ||
|     // running.  If FALSE then the work item must be requeued.  This flag is
 | ||
|     // protected by the EnumerationWorklistMutex
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN EnumerationRunning;
 | ||
| 
 | ||
|     //
 | ||
|     // A list of enumeration requests.  When an bus scan is completed the
 | ||
|     // scanner should run through the list of enumeration requests and complete
 | ||
|     // each one.  This list is protected by the EnumerationWorklistMutex.
 | ||
|     //
 | ||
| 
 | ||
|     PSP_ENUMERATION_REQUEST EnumerationWorkList;
 | ||
| 
 | ||
|     //
 | ||
|     // A pointer to the PNP enumeration request object.  This is used so
 | ||
|     // so we can use interlocked exchange to determine if the block is
 | ||
|     // in use.
 | ||
|     //
 | ||
| 
 | ||
|     PSP_ENUMERATION_REQUEST PnpEnumRequestPtr;
 | ||
| 
 | ||
|     //
 | ||
|     // An enumeration request to use for PNP enumeration requests.  Since there
 | ||
|     // will only be one of these outstanding at any time we can statically
 | ||
|     // allocate one for that case.
 | ||
|     //
 | ||
| 
 | ||
|     SP_ENUMERATION_REQUEST PnpEnumerationRequest;
 | ||
| 
 | ||
|     //
 | ||
|     // A lookaside list to pull SRB_DATA blocks off of.
 | ||
|     //
 | ||
| 
 | ||
|     NPAGED_LOOKASIDE_LIST SrbDataLookasideList;
 | ||
| 
 | ||
|     //
 | ||
|     // The following members are used to keep an SRB_DATA structure allocated
 | ||
|     // for emergency use and to queue requests which need to use it.  The
 | ||
|     // structures are synchronized with the EmergencySrbDataSpinLock.
 | ||
|     // The routines Sp[Allocate|Free]SrbData & ScsiPortTickHandler will
 | ||
|     // handle queueing and eventual restarting of these requests.
 | ||
|     //
 | ||
| 
 | ||
|     //
 | ||
|     // This spinlock protects the blocked request list.
 | ||
|     //
 | ||
| 
 | ||
|     KSPIN_LOCK EmergencySrbDataSpinLock;
 | ||
| 
 | ||
|     //
 | ||
|     // Contains a queue of irps which could not be dispatched because of
 | ||
|     // low memory conditions and because the EmergencySrbData block is already
 | ||
|     // allocated.
 | ||
|     //
 | ||
| 
 | ||
|     LIST_ENTRY SrbDataBlockedRequests;
 | ||
| 
 | ||
|     //
 | ||
|     // The SRB_DATA reserved for "emergency" use.  This pointer should be set
 | ||
|     // to NULL if the SRB_DATA is in use.  Any SRB_DATA block may be used
 | ||
|     // for the emergency request.
 | ||
|     //
 | ||
| 
 | ||
|     INTERLOCKED PSRB_DATA EmergencySrbData;
 | ||
| 
 | ||
|     //
 | ||
|     // Flags to indicate whether the srbdata and scatter gather lookaside
 | ||
|     // lists have been allocated already.
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN SrbDataListInitialized;
 | ||
| 
 | ||
| #ifndef USE_DMA_MACROS
 | ||
|     BOOLEAN MediumScatterGatherListInitialized;
 | ||
| 
 | ||
|     //
 | ||
|     // Sizes for small, medium and large scatter gather lists.  This is the
 | ||
|     // number of entries in the list, not the number of bytes.
 | ||
|     //
 | ||
| 
 | ||
|     UCHAR LargeScatterGatherListSize;
 | ||
| 
 | ||
|     //
 | ||
|     // Lookaside list for medium scatter gather lists.  Medium lists are used
 | ||
|     // to service anything between a small and large number of physical
 | ||
|     // breaks.
 | ||
|     //
 | ||
| 
 | ||
|     NPAGED_LOOKASIDE_LIST MediumScatterGatherLookasideList;
 | ||
| #endif
 | ||
| 
 | ||
|     //
 | ||
|     // Bus standard interface.  Retrieved from the lower driver immediately
 | ||
|     // after it completes the start irp.
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN LowerBusInterfaceStandardRetrieved;
 | ||
|     BUS_INTERFACE_STANDARD LowerBusInterfaceStandard;
 | ||
| 
 | ||
|     //
 | ||
|     // Handles into the device map for the various entries this adapter will
 | ||
|     // have created.
 | ||
|     //
 | ||
| 
 | ||
|     //
 | ||
|     // An array of handles for each
 | ||
| 
 | ||
|     HANDLE PortDeviceMapKey;
 | ||
| 
 | ||
|     PDEVICE_MAP_HANDLES BusDeviceMapKeys;
 | ||
| 
 | ||
|     //
 | ||
|     // Unicode string containing the device name of this object
 | ||
|     //
 | ||
| 
 | ||
|     PWSTR DeviceName;
 | ||
| 
 | ||
|     //
 | ||
|     // The guid for the underlying bus.  Saved here so we don't have to
 | ||
|     // retrieve it so often.
 | ||
|     //
 | ||
| 
 | ||
|     GUID BusTypeGuid;
 | ||
| 
 | ||
|     //
 | ||
|     // The pnp interface name for this device.
 | ||
|     //
 | ||
| 
 | ||
|     UNICODE_STRING InterfaceName;
 | ||
| 
 | ||
|     //
 | ||
|     // The device state for this adapter.
 | ||
|     //
 | ||
| 
 | ||
|     PNP_DEVICE_STATE DeviceState;
 | ||
| 
 | ||
|     //
 | ||
|     // The number of calls to ScsiPortTickHandler for this adapter since
 | ||
|     // the machine was booted.
 | ||
|     //
 | ||
| 
 | ||
|     INTERLOCKED ULONG TickCount;
 | ||
| 
 | ||
|     //
 | ||
|     // Preallocated memory to use for IssueInquiry.  The InquiryBuffer is used
 | ||
|     // to retreive the inquiry data and the serial number for the device.
 | ||
|     //
 | ||
| 
 | ||
|     PVOID InquiryBuffer;
 | ||
|     PSENSE_DATA InquirySenseBuffer;
 | ||
|     PIRP InquiryIrp;
 | ||
|     PMDL InquiryMdl;
 | ||
| 
 | ||
|     //
 | ||
|     // Mutex used to synchronize multiple threads all synchronously waiting for
 | ||
|     // a power up to occur.
 | ||
|     //
 | ||
| 
 | ||
|     FAST_MUTEX PowerMutex;
 | ||
| 
 | ||
|     //
 | ||
|     // A pointer to a logical unit which is used to scan empty locations on the
 | ||
|     // bus.
 | ||
|     //
 | ||
| 
 | ||
|     PLOGICAL_UNIT_EXTENSION RescanLun;
 | ||
| 
 | ||
|     //
 | ||
|     // The number of additional sense bytes supported by this adapter.
 | ||
|     //
 | ||
| 
 | ||
|     UCHAR AdditionalSenseBytes;
 | ||
| 
 | ||
|     //
 | ||
|     // Configurable timeout value for request sense commands.
 | ||
|     //
 | ||
| 
 | ||
|     UCHAR RequestSenseTimeout;
 | ||
| 
 | ||
|     //
 | ||
|     // Indicates whether the SenseData WMI event is enabled.
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN EnableSenseDataEvent;
 | ||
| 
 | ||
|     //
 | ||
|     // Identifies the event class used to generate sense data wmi events.
 | ||
|     //
 | ||
| 
 | ||
|     GUID SenseDataEventClass;
 | ||
| 
 | ||
|     //
 | ||
|     // Pointer to verifier state that gets allocated and initialized when
 | ||
|     // scsiport's verifier is enabled.
 | ||
|     //
 | ||
| 
 | ||
|     PVERIFIER_EXTENSION VerifierExtension;
 | ||
| 
 | ||
|     //
 | ||
|     // The minimum & maximum addresses for common buffer.  These are loaded 
 | ||
|     // from [Minimum|Maximum]UCXAddress in the registry.
 | ||
|     //
 | ||
| 
 | ||
|     PHYSICAL_ADDRESS MinimumCommonBufferBase;
 | ||
|     PHYSICAL_ADDRESS MaximumCommonBufferBase;
 | ||
| 
 | ||
| #if defined(FORWARD_PROGRESS)
 | ||
|     //
 | ||
|     // Pointer to a block of reserved pages we use to make forward progress
 | ||
|     // in low memory conditons.
 | ||
|     //
 | ||
| 
 | ||
|     PVOID ReservedPages;
 | ||
| 
 | ||
|     //
 | ||
|     // Pointer to an emergency MDL we can use if we cannot allocate one
 | ||
|     //
 | ||
| 
 | ||
|     PMDL ReservedMdl;
 | ||
| #endif
 | ||
| 
 | ||
|     //
 | ||
|     // Identified how many successfully completed requests are required to
 | ||
|     // restore a LUN on this adapter from a degraded performation state
 | ||
|     // with respect to MaxQueueDepth.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG RemainInReducedMaxQueueState;
 | ||
| 
 | ||
|     //
 | ||
|     // This value dictates on what type of boundary an adapter's uncached extension
 | ||
|     // must be aligned.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG UncachedExtAlignment;
 | ||
| 
 | ||
|     //
 | ||
|     // This value is used to keep track of the number of instances of the
 | ||
|     // SRB_DATA free routine is running.  This helps us avoid a nasty recursion
 | ||
|     // brought on by synchronously completing requests and starting blocked
 | ||
|     // requests waiting for SRB_DATA objects.
 | ||
|     //
 | ||
| 
 | ||
|     LONG SrbDataFreeRunning;
 | ||
| 
 | ||
|     //
 | ||
|     // This boolean indicates whether the adapter supports multiconcurrent
 | ||
|     // requests.  This means it either supports tagged queuing or multiple
 | ||
|     // requests per logical unit.
 | ||
|     //
 | ||
|     
 | ||
|     BOOLEAN SupportsMultipleRequests;
 | ||
| };
 | ||
| 
 | ||
| struct _LOGICAL_UNIT_EXTENSION {
 | ||
| 
 | ||
|     union {
 | ||
|         PDEVICE_OBJECT DeviceObject;
 | ||
|         COMMON_EXTENSION CommonExtension;
 | ||
|     };
 | ||
| 
 | ||
|     //
 | ||
|     // Logical Unit flags
 | ||
|     //
 | ||
| 
 | ||
|     ULONG LuFlags;
 | ||
| 
 | ||
|     //
 | ||
|     // The adapter number this device is attached to
 | ||
|     //
 | ||
| 
 | ||
|     ULONG PortNumber;
 | ||
| 
 | ||
|     //
 | ||
|     // Has this device been claimed by a driver (legacy or pnp)
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN IsClaimed;
 | ||
| 
 | ||
|     BOOLEAN IsLegacyClaim;
 | ||
| 
 | ||
|     //
 | ||
|     // Has this device been enumerated yet?  If so then we cannot actually
 | ||
|     // delete it until we've explicitly told the PNP system that it's gone
 | ||
|     // (by not enumerating it)
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN IsEnumerated;
 | ||
| 
 | ||
|     //
 | ||
|     // Has this device gone missing?
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN IsMissing;
 | ||
| 
 | ||
|     //
 | ||
|     // Is this device visible - should it be exposed to PNP?
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN IsVisible;
 | ||
| 
 | ||
|     //
 | ||
|     // Was this device marked missing because we found something different at
 | ||
|     // it's bus location?  If so then the removal of this device from the
 | ||
|     // logical unit bins will trigger a new bus scan.
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN IsMismatched;
 | ||
| 
 | ||
|     //
 | ||
|     // Is this lun temporary?  Temporary luns are used to scan bus locations
 | ||
|     // which are believed to be empty.  They are the only luns which can be
 | ||
|     // swapped out of the logical unit list.
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN IsTemporary;
 | ||
| 
 | ||
|     //
 | ||
|     // Indicates that this device needs to have an inquiry sent to it to
 | ||
|     // determine if it's still present.  This flag is cleared if the inquiry
 | ||
|     // succeeds and the inquiry data matches what was previously read at that
 | ||
|     // address.  If this flag is set when SpPurgeTarget is called then the
 | ||
|     // lun will be marked as missing.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG NeedsVerification;
 | ||
| 
 | ||
|     //
 | ||
|     // The bus address of this device.
 | ||
|     //
 | ||
| 
 | ||
|     UCHAR PathId;
 | ||
|     UCHAR TargetId;
 | ||
|     UCHAR Lun;
 | ||
| 
 | ||
|     //
 | ||
|     // The number of times the current busy request has been retried
 | ||
|     //
 | ||
| 
 | ||
|     UCHAR RetryCount;
 | ||
| 
 | ||
|     //
 | ||
|     // The current queue sort key
 | ||
|     //
 | ||
| 
 | ||
|     ULONG CurrentKey;
 | ||
| 
 | ||
|     //
 | ||
|     // A pointer to the miniport's logical unit extension.
 | ||
|     //
 | ||
| 
 | ||
|     PVOID HwLogicalUnitExtension;
 | ||
| 
 | ||
|     //
 | ||
|     // A pointer to the device extension for the adapter.
 | ||
|     //
 | ||
| 
 | ||
|     PADAPTER_EXTENSION AdapterExtension;
 | ||
| 
 | ||
|     //
 | ||
|     // The number of unreleased queue locks on this device
 | ||
|     //
 | ||
| 
 | ||
|     ULONG QueueLockCount;
 | ||
| 
 | ||
|     //
 | ||
|     // Reference counts for pausing & unpausing the queue (see LU_QUEUE_PAUSED)
 | ||
|     //
 | ||
| 
 | ||
|     ULONG QueuePauseCount;
 | ||
| 
 | ||
|     //
 | ||
|     // List of lock & unlock requests which are waiting to be dispatched.
 | ||
|     //
 | ||
| 
 | ||
|     KDEVICE_QUEUE LockRequestQueue;
 | ||
| 
 | ||
|     //
 | ||
|     // The currently operating lock request.
 | ||
|     //
 | ||
| 
 | ||
|     PSRB_DATA CurrentLockRequest;
 | ||
| 
 | ||
|     //
 | ||
|     // A pointer to the next logical unit extension in the logical unit bin.
 | ||
|     //
 | ||
| 
 | ||
|     PLOGICAL_UNIT_EXTENSION NextLogicalUnit;
 | ||
| 
 | ||
|     //
 | ||
|     // Used to chain logical units in the interrupt data block.
 | ||
|     //
 | ||
| 
 | ||
|     PLOGICAL_UNIT_EXTENSION ReadyLogicalUnit;
 | ||
| 
 | ||
|     //
 | ||
|     // Used to chain completed abort requests in the interrupt data block.
 | ||
|     //
 | ||
| 
 | ||
|     PLOGICAL_UNIT_EXTENSION CompletedAbort;
 | ||
| 
 | ||
|     //
 | ||
|     // The current abort request for this logical unit
 | ||
|     //
 | ||
| 
 | ||
|     PSCSI_REQUEST_BLOCK AbortSrb;
 | ||
| 
 | ||
|     //
 | ||
|     // Timeout counter for this logical unit
 | ||
|     //
 | ||
| 
 | ||
|     LONG RequestTimeoutCounter;
 | ||
| 
 | ||
|     //
 | ||
|     // The list of requests for this logical unit.
 | ||
|     //
 | ||
| 
 | ||
|     LIST_ENTRY RequestList;
 | ||
| 
 | ||
|     //
 | ||
|     // The next request to be executed.
 | ||
|     //
 | ||
| 
 | ||
|     PSRB_DATA PendingRequest;
 | ||
| 
 | ||
|     //
 | ||
|     // This irp could not be executed before because the
 | ||
|     // device returned BUSY.
 | ||
|     //
 | ||
| 
 | ||
|     PSRB_DATA BusyRequest;
 | ||
| 
 | ||
|     //
 | ||
|     // The current untagged request for this logical unit.
 | ||
|     //
 | ||
| 
 | ||
|     PSRB_DATA CurrentUntaggedRequest;
 | ||
| 
 | ||
|     //
 | ||
|     // The maximum number of request which we will issue to the device
 | ||
|     //
 | ||
| 
 | ||
|     UCHAR MaxQueueDepth;
 | ||
| 
 | ||
|     //
 | ||
|     // The current number of outstanding requests.
 | ||
|     //
 | ||
| 
 | ||
|     UCHAR QueueCount;
 | ||
| 
 | ||
|     //
 | ||
|     // The inquiry data for this logical unit.
 | ||
|     //
 | ||
| 
 | ||
|     INQUIRYDATA InquiryData;
 | ||
| 
 | ||
|     //
 | ||
|     // The handles for the target & logical unit keys in the device map.
 | ||
|     //
 | ||
| 
 | ||
|     HANDLE TargetDeviceMapKey;
 | ||
|     HANDLE LunDeviceMapKey;
 | ||
| 
 | ||
|     //
 | ||
|     // Our fixed set of SRB_DATA blocks for use when processing bypass requests.
 | ||
|     // If this set is exhausted then scsiport will bugcheck - this should be
 | ||
|     // okay since bypass requests are only sent in certain extreme conditions
 | ||
|     // and should never be overlapped (we should only see one bypass request
 | ||
|     // at a time).
 | ||
|     //
 | ||
| 
 | ||
|     SRB_DATA BypassSrbDataBlocks[NUMBER_BYPASS_SRB_DATA_BLOCKS];
 | ||
| 
 | ||
|     //
 | ||
|     // A list of the free bypass SRB_DATA blocks.
 | ||
|     //
 | ||
| 
 | ||
|     KSPIN_LOCK BypassSrbDataSpinLock;
 | ||
|     SLIST_HEADER BypassSrbDataList;
 | ||
| 
 | ||
|     //
 | ||
|     // A pointer to the request for which we have issued a request-sense irp
 | ||
|     // (if any).  This field is protected by the port spinlock.
 | ||
|     //
 | ||
| 
 | ||
|     PSRB_DATA ActiveFailedRequest;
 | ||
| 
 | ||
|     //
 | ||
|     // A pointer to the request for which we need to issue a request-sense irp
 | ||
|     // (if any).  RequestSenseCompletion will promote this to the active
 | ||
|     // failed request and issue a new RS operation when it runs.
 | ||
|     // This field is protected by the port spinlock.
 | ||
|     //
 | ||
| 
 | ||
|     PSRB_DATA BlockedFailedRequest;
 | ||
| 
 | ||
|     //
 | ||
|     // Resources for issuing request-sense commands.
 | ||
|     //
 | ||
| 
 | ||
|     PIRP RequestSenseIrp;
 | ||
|     SCSI_REQUEST_BLOCK RequestSenseSrb;
 | ||
| 
 | ||
|     struct {
 | ||
|         MDL RequestSenseMdl;
 | ||
|         PFN_NUMBER RequestSenseMdlPfn1;
 | ||
|         PFN_NUMBER RequestSenseMdlPfn2;
 | ||
|     };
 | ||
| 
 | ||
|     //
 | ||
|     // The "lun-list" associated with this target.  SpIssueReportLuns will
 | ||
|     // store this value in the logical unit extension for LUN 0 of each target
 | ||
|     // for use in the event that we are unable to retrieve it from the LUN.
 | ||
|     //
 | ||
| 
 | ||
|     PLUN_LIST TargetLunList;
 | ||
| 
 | ||
|     //
 | ||
|     // The special controller flags for this target.  These flags are valid
 | ||
|     // for LUN 0 only.
 | ||
|     //
 | ||
| 
 | ||
|     SP_SPECIAL_CONTROLLER_FLAGS SpecialFlags;
 | ||
| 
 | ||
|     //
 | ||
|     // Flags to keep track of what EVPD pages this device supports.
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN DeviceIdentifierPageSupported : 1;
 | ||
|     BOOLEAN SerialNumberPageSupported : 1;
 | ||
| 
 | ||
|     //
 | ||
|     // The vital product data for this device - this buffer contains the
 | ||
|     // device serial number.  The other fields contain the length of the
 | ||
|     // data in the buffer and the page code used to retrieve this buffer.
 | ||
|     //
 | ||
| 
 | ||
|     ANSI_STRING SerialNumber;
 | ||
| 
 | ||
|     //
 | ||
|     // The device identifier page retreived from the device's vital product
 | ||
|     // data.
 | ||
|     //
 | ||
| 
 | ||
|     PVPD_IDENTIFICATION_PAGE DeviceIdentifierPage;
 | ||
|     ULONG DeviceIdentifierPageLength;
 | ||
| 
 | ||
|     //
 | ||
|     // If we reduce the MaxQueueDepth, track how long we remain in the degraded
 | ||
|     // state.  If we reach a configurable number of ticks we restore ourselves
 | ||
|     // to full power.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG TicksInReducedMaxQueueDepthState;
 | ||
| 
 | ||
| };
 | ||
| 
 | ||
| //
 | ||
| // Miniport specific device extension wrapper
 | ||
| //
 | ||
| 
 | ||
| struct _HW_DEVICE_EXTENSION {
 | ||
|     PADAPTER_EXTENSION FdoExtension;
 | ||
|     UCHAR HwDeviceExtension[0];
 | ||
| };
 | ||
| 
 | ||
| typedef struct _INTERRUPT_CONTEXT {
 | ||
|     PADAPTER_EXTENSION DeviceExtension;
 | ||
|     PINTERRUPT_DATA SavedInterruptData;
 | ||
| }INTERRUPT_CONTEXT, *PINTERRUPT_CONTEXT;
 | ||
| 
 | ||
| typedef struct _RESET_CONTEXT {
 | ||
|     PADAPTER_EXTENSION DeviceExtension;
 | ||
|     UCHAR PathId;
 | ||
| }RESET_CONTEXT, *PRESET_CONTEXT;
 | ||
| 
 | ||
| //
 | ||
| // Used in LUN rescan determination.
 | ||
| //
 | ||
| 
 | ||
| typedef struct _UNICODE_LUN_LIST {
 | ||
|     UCHAR TargetId;
 | ||
|     struct _UNICODE_LUN_LIST *Next;
 | ||
|     UNICODE_STRING UnicodeInquiryData;
 | ||
| } UNICODE_LUN_LIST, *PUNICODE_LUN_LIST;
 | ||
| 
 | ||
| typedef struct _POWER_CHANGE_CONTEXT {
 | ||
|     PDEVICE_OBJECT DeviceObject;
 | ||
|     POWER_STATE_TYPE Type;
 | ||
|     POWER_STATE State;
 | ||
|     PIRP OriginalIrp;
 | ||
|     PSCSI_REQUEST_BLOCK Srb;
 | ||
| } POWER_CHANGE_CONTEXT, *PPOWER_CHANGE_CONTEXT;
 | ||
| 
 | ||
| //
 | ||
| // Driver extension
 | ||
| //
 | ||
| 
 | ||
| struct _SP_INIT_CHAIN_ENTRY {
 | ||
|     HW_INITIALIZATION_DATA InitData;
 | ||
|     PSP_INIT_CHAIN_ENTRY NextEntry;
 | ||
| };
 | ||
| 
 | ||
| typedef struct _SCSIPORT_INTERFACE_TYPE_DATA {
 | ||
|     INTERFACE_TYPE InterfaceType;
 | ||
|     ULONG Flags;
 | ||
| } SCSIPORT_INTERFACE_TYPE_DATA, *PSCSIPORT_INTERFACE_TYPE_DATA;
 | ||
| 
 | ||
| typedef struct _SCSIPORT_DRIVER_EXTENSION {
 | ||
| 
 | ||
|     //
 | ||
|     // Pointer back to the driver object
 | ||
|     //
 | ||
| 
 | ||
|     PDRIVER_OBJECT DriverObject;
 | ||
| 
 | ||
|     //
 | ||
|     // Unicode string containing the registry path information
 | ||
|     // for this driver
 | ||
|     //
 | ||
| 
 | ||
|     UNICODE_STRING RegistryPath;
 | ||
| 
 | ||
|     //
 | ||
|     // the chain of HwInitializationData structures that were passed in during
 | ||
|     // the miniport's initialization
 | ||
|     //
 | ||
| 
 | ||
|     PSP_INIT_CHAIN_ENTRY InitChain;
 | ||
| 
 | ||
|     //
 | ||
|     // A count of the number of adapter which are using scsiport.  This is
 | ||
|     // used for generating unique Id's
 | ||
|     //
 | ||
| 
 | ||
|     ULONG AdapterCount;
 | ||
| 
 | ||
|     //
 | ||
|     // The bus type for this driver.
 | ||
|     //
 | ||
| 
 | ||
|     STORAGE_BUS_TYPE BusType;
 | ||
| 
 | ||
|     //
 | ||
|     // Flag indicating whether this miniport is set to do device detection.
 | ||
|     // This flag will be initialized out of the registry when the driver
 | ||
|     // extension is setup.
 | ||
|     //
 | ||
| 
 | ||
|     BOOLEAN LegacyAdapterDetection;
 | ||
| 
 | ||
|     //
 | ||
|     // The list of pnp interface values we read out of the registry for this
 | ||
|     // device.  The number of entries here can vary.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG PnpInterfaceCount;
 | ||
| 
 | ||
|     //
 | ||
|     // The number of interfaces which are safe for pnp.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG SafeInterfaceCount;
 | ||
| 
 | ||
|     //
 | ||
|     // A pointer to a reserve error log entry for the driver.  This entry will
 | ||
|     // be used to log an allocation failure if the logging routine cannot
 | ||
|     // allocate the necessary memory for an error log entry.
 | ||
|     //
 | ||
| 
 | ||
|     PVOID ReserveAllocFailureLogEntry;
 | ||
| 
 | ||
|     //
 | ||
|     // Indicates whether the driver is being verified.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG Verifying;
 | ||
| 
 | ||
|     //
 | ||
|     // When verifying, we occasionally set pointers so they point to a page
 | ||
|     // of invalid memory so the system will bugcheck if a miniport attempts
 | ||
|     // to access the memory.  The following 3 variables are used to maintain
 | ||
|     // this invalid page.
 | ||
|     //
 | ||
| 
 | ||
|     PVOID UnusedPage;
 | ||
|     PMDL UnusedPageMdl;
 | ||
|     PVOID InvalidPage;
 | ||
| 
 | ||
|     SCSIPORT_INTERFACE_TYPE_DATA PnpInterface[0];
 | ||
| 
 | ||
|     //
 | ||
|     // The remaining pnp interface flags trail the defined structure
 | ||
|     //
 | ||
| 
 | ||
| } SCSIPORT_DRIVER_EXTENSION, *PSCSIPORT_DRIVER_EXTENSION;
 | ||
| 
 | ||
| 
 | ||
| //
 | ||
| // Port driver extension flags.
 | ||
| // These flags are protected by the adapter spinlock.
 | ||
| //
 | ||
| 
 | ||
| //
 | ||
| // This flag indicates that a request has been passed to the miniport and the
 | ||
| // miniport has not indicated it is ready for another request.  It is set by
 | ||
| // SpStartIoSynchronized. It is cleared by ScsiPortCompletionDpc when the
 | ||
| // miniport asks for another request.  Note the port driver will defer giving
 | ||
| // the miniport driver a new request if the current request disabled disconnects.
 | ||
| //
 | ||
| 
 | ||
| #define PD_DEVICE_IS_BUSY            0X00001
 | ||
| 
 | ||
| //
 | ||
| // Indicates there is a pending request for which resources
 | ||
| // could not be allocated.  This flag is set by SpAllocateRequestStructures
 | ||
| // which is called from ScsiPortStartIo.  It is cleared by
 | ||
| // SpProcessCompletedRequest when a request completes which then calls
 | ||
| // ScsiPortStartIo to try the request again.
 | ||
| //
 | ||
| 
 | ||
| #define PD_PENDING_DEVICE_REQUEST    0X00800
 | ||
| 
 | ||
| //
 | ||
| // This flag indicates that there are currently no requests executing with
 | ||
| // disconnects disabled.  This flag is normally on.  It is cleared by
 | ||
| // SpStartIoSynchronized when a request with disconnect disabled is started
 | ||
| // and is set when that request completes.  SpProcessCompletedRequest will
 | ||
| // start the next request for the miniport if PD_DEVICE_IS_BUSY is clear.
 | ||
| //
 | ||
| 
 | ||
| #define PD_DISCONNECT_RUNNING        0X01000
 | ||
| 
 | ||
| //
 | ||
| // Indicates the miniport wants the system interrupts disabled.  Set by
 | ||
| // ScsiPortNofitication and cleared by ScsiPortCompletionDpc.  This flag is
 | ||
| // NOT stored in the interrupt data structure.  The parameters are stored in
 | ||
| // the device extension.
 | ||
| //
 | ||
| 
 | ||
| #define PD_DISABLE_CALL_REQUEST      0X02000
 | ||
| 
 | ||
| //
 | ||
| // Indicates that the miniport is being reinitialized.  This is set and
 | ||
| // cleared by SpReinitializeAdapter is is tested by some of the ScsiPort APIs.
 | ||
| //
 | ||
| 
 | ||
| #define PD_MINIPORT_REINITIALIZING          0x40000
 | ||
| #define PD_UNCACHED_EXTENSION_RETURNED      0x80000
 | ||
| 
 | ||
| //
 | ||
| // Interrupt Data Flags
 | ||
| // These flags are protected by the interrupt spinlock.
 | ||
| //
 | ||
| 
 | ||
| //
 | ||
| // Indicates that ScsiPortCompletionDpc needs to be run.  This is set when
 | ||
| // A miniport makes a request which must be done at DPC and is cleared when
 | ||
| // when the request information is gotten by SpGetInterruptState.
 | ||
| //
 | ||
| 
 | ||
| #define PD_NOTIFICATION_REQUIRED     0X00004
 | ||
| 
 | ||
| //
 | ||
| // Indicates the miniport is ready for another request.  Set by
 | ||
| // ScsiPortNotification and cleared by SpGetInterruptState.  This flag is
 | ||
| // stored in the interrupt data structure.
 | ||
| //
 | ||
| 
 | ||
| #define PD_READY_FOR_NEXT_REQUEST    0X00008
 | ||
| 
 | ||
| //
 | ||
| // Indicates the miniport wants the adapter channel flushed.  Set by
 | ||
| // ScsiPortFlushDma and cleared by SpGetInterruptState.  This flag is
 | ||
| // stored in the data interrupt structure.  The flush adapter parameters
 | ||
| // are saved in the device object.
 | ||
| //
 | ||
| 
 | ||
| #define PD_FLUSH_ADAPTER_BUFFERS     0X00010
 | ||
| 
 | ||
| //
 | ||
| // Indicates the miniport wants the adapter channel programmed.  Set by
 | ||
| // ScsiPortIoMapTransfer and cleared by SpGetInterruptState or
 | ||
| // ScsiPortFlushDma.  This flag is stored in the interrupt data structure.
 | ||
| // The I/O map transfer parameters are saved in the interrupt data structure.
 | ||
| //
 | ||
| 
 | ||
| #define PD_MAP_TRANSFER              0X00020
 | ||
| 
 | ||
| //
 | ||
| // Indicates the miniport wants to log an error.  Set by
 | ||
| // ScsiPortLogError and cleared by SpGetInterruptState.  This flag is
 | ||
| // stored in the interrupt data structure.  The error log parameters
 | ||
| // are saved in the interrupt data structure.  Note at most one error per DPC
 | ||
| // can be logged.
 | ||
| //
 | ||
| 
 | ||
| #define PD_LOG_ERROR                 0X00040
 | ||
| 
 | ||
| //
 | ||
| // Indicates that no request should be sent to the miniport after
 | ||
| // a bus reset. Set when the miniport reports a reset or the port driver
 | ||
| // resets the bus. It is cleared by SpTimeoutSynchronized.  The
 | ||
| // PortTimeoutCounter is used to time the length of the reset hold.  This flag
 | ||
| // is stored in the interrupt data structure.
 | ||
| //
 | ||
| 
 | ||
| #define PD_RESET_HOLD                0X00080
 | ||
| 
 | ||
| //
 | ||
| // Indicates a request was stopped due to a reset hold.  The held request is
 | ||
| // stored in the current request of the device object.  This flag is set by
 | ||
| // SpStartIoSynchronized and cleared by SpTimeoutSynchronized which also
 | ||
| // starts the held request when the reset hold has ended.  This flag is stored
 | ||
| // in the interrupt data structure.
 | ||
| //
 | ||
| 
 | ||
| #define PD_HELD_REQUEST              0X00100
 | ||
| 
 | ||
| //
 | ||
| // Indicates the miniport has reported a bus reset.  Set by
 | ||
| // ScsiPortNotification and cleared by SpGetInterruptState.  This flag is
 | ||
| // stored in the interrupt data structure.
 | ||
| //
 | ||
| 
 | ||
| #define PD_RESET_REPORTED            0X00200
 | ||
| 
 | ||
| //
 | ||
| // Indicates that system interrupts have been enabled and that the miniport
 | ||
| // has disabled its adapter from interruptint.  The miniport's interrupt
 | ||
| // routine is not called while this flag is set.  This flag is set by
 | ||
| // ScsiPortNotification when a CallEnableInterrupts request is made and
 | ||
| // cleared by SpEnableInterruptSynchronized when the miniport requests that
 | ||
| // system interrupts be disabled.  This flag is stored in the interrupt data
 | ||
| // structure.
 | ||
| //
 | ||
| 
 | ||
| #define PD_DISABLE_INTERRUPTS        0X04000
 | ||
| 
 | ||
| //
 | ||
| // Indicates the miniport wants the system interrupt enabled.  Set by
 | ||
| // ScsiPortNotification and cleared by SpGetInterruptState.  This flag is
 | ||
| // stored in the interrupt data structure.  The call enable interrupts
 | ||
| // parameters are saved in the device extension.
 | ||
| //
 | ||
| 
 | ||
| #define PD_ENABLE_CALL_REQUEST       0X08000
 | ||
| 
 | ||
| //
 | ||
| // Indicates the miniport is wants a timer request.  Set by
 | ||
| // ScsiPortNotification and cleared by SpGetInterruptState.  This flag is
 | ||
| // stored in the interrupt data structure. The timer request parameters are
 | ||
| // stored in the interrupt data structure.
 | ||
| //
 | ||
| 
 | ||
| #define PD_TIMER_CALL_REQUEST        0X10000
 | ||
| 
 | ||
| //
 | ||
| // Indicates the miniport has a WMI request.  Set by ScsiPortNotification
 | ||
| // and cleared by SpGetInterruptState.  This flag is stored in the interrupt
 | ||
| // data structure.    The WMI request parameters are stored in the interrupt
 | ||
| // data structure.
 | ||
| //
 | ||
| 
 | ||
| #define PD_WMI_REQUEST               0X20000
 | ||
| 
 | ||
| //
 | ||
| // Indicates that the miniport has detected some sort of change on the bus -
 | ||
| // usually device arrival or removal - and wishes the port driver to rescan
 | ||
| // the bus.
 | ||
| //
 | ||
| 
 | ||
| #define PD_BUS_CHANGE_DETECTED       0x40000
 | ||
| 
 | ||
| //
 | ||
| // Indicates that the adapter has disappeared.  If this flag is set then no
 | ||
| // calls should be made into the miniport.
 | ||
| //
 | ||
| 
 | ||
| #define PD_ADAPTER_REMOVED           0x80000
 | ||
| 
 | ||
| //
 | ||
| // Indicates that interrupts from the miniport do not appear to be getting
 | ||
| // delivered to scsiport.  This flag is set by SpTimeoutSynchronized and
 | ||
| // will cause the DPC routine to log an error to this effect.
 | ||
| //
 | ||
| 
 | ||
| #define PD_INTERRUPT_FAILURE         0x100000
 | ||
| 
 | ||
| #if defined(FORWARD_PROGRESS)
 | ||
| //
 | ||
| // Indicates that the adapter's reserved pages are currently in use.  The 
 | ||
| // reserved pages is a special VA range set aside by MM in order for devices
 | ||
| // to make forward progress in low memory conditions.
 | ||
| //
 | ||
| 
 | ||
| #define PD_RESERVED_PAGES_IN_USE     0x200000
 | ||
| 
 | ||
| //
 | ||
| // Indicates that the adapter's reserved MDL is currently in use.
 | ||
| //
 | ||
| #define PD_RESERVED_MDL_IN_USE       0x400000
 | ||
| #endif
 | ||
| 
 | ||
| //
 | ||
| // Indicates that the adapter is in the process of shutting down.  Certain
 | ||
| // operations must not be started when this is the case.
 | ||
| //
 | ||
| #define PD_SHUTDOWN_IN_PROGRESS      0x800000
 | ||
| 
 | ||
| //
 | ||
| // The following flags should not be cleared from the interrupt data structure
 | ||
| // by SpGetInterruptState.
 | ||
| //
 | ||
| 
 | ||
| #define PD_INTERRUPT_FLAG_MASK (PD_RESET_HOLD | PD_HELD_REQUEST | PD_DISABLE_INTERRUPTS | PD_ADAPTER_REMOVED)
 | ||
| 
 | ||
| //
 | ||
| // Adapter extension flags for DPC routine.
 | ||
| //
 | ||
| 
 | ||
| //
 | ||
| // Indicates that the completion DPC is either already running or has been
 | ||
| // queued to service completed requests.  This flag is checked when the
 | ||
| // completion DPC needs to be run - the DPC should only be started if this
 | ||
| // flag is already clear.  It will be cleared when the DPC has completed
 | ||
| // processing any work items.
 | ||
| //
 | ||
| 
 | ||
| #define PD_DPC_RUNNING              0x20000
 | ||
| 
 | ||
| //
 | ||
| // Logical unit extension flags.
 | ||
| //
 | ||
| 
 | ||
| //
 | ||
| // Indicates the logical unit queue is frozen.  Set by
 | ||
| // SpProcessCompletedRequest when an error occurs and is cleared by the class
 | ||
| // driver.
 | ||
| //
 | ||
| 
 | ||
| #define LU_QUEUE_FROZEN              0X0001
 | ||
| 
 | ||
| //
 | ||
| // Indicates that the miniport has an active request for this logical unit.
 | ||
| // Set by SpStartIoSynchronized when the request is started and cleared by
 | ||
| // GetNextLuRequest.  This flag is used to track when it is ok to start another
 | ||
| // request from the logical unit queue for this device.
 | ||
| //
 | ||
| 
 | ||
| #define LU_LOGICAL_UNIT_IS_ACTIVE    0X0002
 | ||
| 
 | ||
| //
 | ||
| // Indicates that a request for this logical unit has failed and a REQUEST
 | ||
| // SENSE command needs to be done. This flag prevents other requests from
 | ||
| // being started until an untagged, by-pass queue command is started.  This
 | ||
| // flag is cleared in SpStartIoSynchronized.  It is set by
 | ||
| // SpGetInterruptState.
 | ||
| //
 | ||
| 
 | ||
| #define LU_NEED_REQUEST_SENSE  0X0004
 | ||
| 
 | ||
| //
 | ||
| // Indicates that a request for this logical unit has completed with a status
 | ||
| // of BUSY or QUEUE FULL.  This flag is set by SpProcessCompletedRequest and
 | ||
| // the busy request is saved in the logical unit structure.  This flag is
 | ||
| // cleared by ScsiPortTickHandler which also restarts the request.  Busy
 | ||
| // request may also be requeued to the logical unit queue if an error occurs
 | ||
| // on the device (This will only occur with command queueing.).  Not busy
 | ||
| // requests are nasty because they are restarted asynchronously by
 | ||
| // ScsiPortTickHandler rather than GetNextLuRequest. This makes error recovery
 | ||
| // more complex.
 | ||
| //
 | ||
| 
 | ||
| #define LU_LOGICAL_UNIT_IS_BUSY      0X0008
 | ||
| 
 | ||
| //
 | ||
| // This flag indicates a queue full has been returned by the device.  It is
 | ||
| // similar to PD_LOGICAL_UNIT_IS_BUSY but is set in SpGetInterruptState when
 | ||
| // a QUEUE FULL status is returned.  This flag is used to prevent other
 | ||
| // requests from being started for the logical unit before
 | ||
| // SpProcessCompletedRequest has a chance to set the busy flag.
 | ||
| //
 | ||
| 
 | ||
| #define LU_QUEUE_IS_FULL             0X0010
 | ||
| 
 | ||
| //
 | ||
| // Indicates that there is a request for this logical unit which cannot be
 | ||
| // executed for now.  This flag is set by SpAllocateRequestStructures.  It is
 | ||
| // cleared by GetNextLuRequest when it detects that the pending request
 | ||
| // can now be executed. The pending request is stored in the logical unit
 | ||
| // structure.  A new single non-queued reqeust cannot be executed on a logical
 | ||
| // that is currently executing queued requests.  Non-queued requests must wait
 | ||
| // unit for all queued requests to complete.  A non-queued requests is one
 | ||
| // which is not tagged and does not have SRB_FLAGS_NO_QUEUE_FREEZE set.
 | ||
| // Normally only read and write commands can be queued.
 | ||
| //
 | ||
| 
 | ||
| #define LU_PENDING_LU_REQUEST        0x0020
 | ||
| 
 | ||
| //
 | ||
| // Indicates that the logical unit queue has been paused due to an error.  Set
 | ||
| // by SpProcessCompletedRequest when an error occurs and is cleared by the
 | ||
| // class driver either by unfreezing or flushing the queue.  This flag is used
 | ||
| // with the following one to determine why the logical unit queue is paused.
 | ||
| //
 | ||
| 
 | ||
| #define LU_QUEUE_LOCKED             0x0040
 | ||
| 
 | ||
| //
 | ||
| // Indicates that this LUN has been "paused".  This flag is set and cleared by
 | ||
| // the power management code while changing the power state.  It causes
 | ||
| // GetNextLuRequest to return without starting another request and is used
 | ||
| // by SpSrbIsBypassRequest to determine that a bypass request should get
 | ||
| // shoved to the front of the line.
 | ||
| //
 | ||
| 
 | ||
| #define LU_QUEUE_PAUSED             0x0080
 | ||
| 
 | ||
| //
 | ||
| // Indicates that the LUN is operating in a degraded state.  The maximum queue
 | ||
| // depth has been reduced because the LUN has returned QUEUE FULL status.  We
 | ||
| // track this because in the event that the QUEUE FULL was transient, we want
 | ||
| // to restore the queue depth to it's original maximum.
 | ||
| 
 | ||
| #define LU_PERF_MAXQDEPTH_REDUCED   0x0100
 | ||
| 
 | ||
| //
 | ||
| // SRB_DATA flags.
 | ||
| //
 | ||
| 
 | ||
| //
 | ||
| // These three flags indicate the size of scatter gather list necessary to
 | ||
| // service the request and are used to determine how the scatter gather list
 | ||
| // should be freed.  Small requests require <= SP_SMALL_PHYSICAL_BREAK_VALUE
 | ||
| // breaks and the scatter gather list is preallocated in the SRB_DATA structure.
 | ||
| // Large requests are >= SP_LARGE_PHYSICAL_BREAK_VALUE and have scatter gather
 | ||
| // lists allocated from non-paged pool.  Medium requests are between small
 | ||
| // and large - they use scatter gather lists from a lookaside list which contain
 | ||
| // one less entry than a large list would.
 | ||
| //
 | ||
| 
 | ||
| #ifndef USE_DMA_MACROS
 | ||
| 
 | ||
| #define SRB_DATA_SMALL_SG_LIST      0x00000001
 | ||
| #define SRB_DATA_MEDIUM_SG_LIST     0x00000002
 | ||
| #define SRB_DATA_LARGE_SG_LIST      0x00000004
 | ||
| 
 | ||
| #endif
 | ||
| 
 | ||
| //
 | ||
| // Indicates that the srb_data block was for a bypass request
 | ||
| //
 | ||
| 
 | ||
| #define SRB_DATA_BYPASS_REQUEST     0x10000000
 | ||
| 
 | ||
| #if defined(FORWARD_PROGRESS)
 | ||
| //
 | ||
| // Indicates that the request is using reserved pages that enable
 | ||
| // forward progress in low-memory condition.
 | ||
| //
 | ||
| 
 | ||
| #define SRB_DATA_RESERVED_PAGES     0x20000000
 | ||
| 
 | ||
| //
 | ||
| // Indicates that the request is using a reserved MDL that enables
 | ||
| // forward progress in low-memory conditions.
 | ||
| //
 | ||
| #define SRB_DATA_RESERVED_MDL       0x40000000
 | ||
| #endif
 | ||
| 
 | ||
| //
 | ||
| // Port Timeout Counter values.
 | ||
| //
 | ||
| 
 | ||
| #define PD_TIMER_STOPPED             -1
 | ||
| #define PD_TIMER_RESET_HOLD_TIME     4
 | ||
| 
 | ||
| //
 | ||
| // Possible registry flags for pnp interface key
 | ||
| //
 | ||
| 
 | ||
| //
 | ||
| // The absence of any information about a particular interface in the
 | ||
| // PnpInterface key in the registry indicates that pnp is not safe for this
 | ||
| // particular card.
 | ||
| //
 | ||
| 
 | ||
| #define SP_PNP_NOT_SAFE             0x00000000
 | ||
| 
 | ||
| //
 | ||
| // Indicates that pnp is a safe operation for this device.  If this flag is
 | ||
| // set then the miniport will not be allowed to do detection and will always
 | ||
| // be handed resources provided by the pnp system.  This flag may or may not
 | ||
| // be set in the registry - the fact that a value for a particular interface
 | ||
| // exists is enough to indicate that pnp is safe and this flag will always
 | ||
| // be set.
 | ||
| //
 | ||
| 
 | ||
| #define SP_PNP_IS_SAFE              0x00000001
 | ||
| 
 | ||
| //
 | ||
| // Indicates that we should take advantage of a chance to enumerate a particular
 | ||
| // bus type using the miniport.  This flag is set for all non-enumerable legacy
 | ||
| // buses (ISA, EISA, etc...) and is cleared for the non-legacy ones and for the
 | ||
| // PnpBus type.
 | ||
| //
 | ||
| 
 | ||
| #define SP_PNP_NON_ENUMERABLE       0x00000002
 | ||
| 
 | ||
| //
 | ||
| // Indicates that we need to include some sort of location information in the
 | ||
| // config data to discern this adapter from any others.
 | ||
| //
 | ||
| 
 | ||
| #define SP_PNP_NEEDS_LOCATION       0x00000004
 | ||
| 
 | ||
| //
 | ||
| // Indicates that this type of adapter must have an interrupt for us to try
 | ||
| // and start it.  If PNP doesn't provide an interrupt then scsiport will
 | ||
| // log an error and fail the start operation.  If this flag is set then
 | ||
| // SP_PNP_IS_SAFE must also be set.
 | ||
| //
 | ||
| 
 | ||
| #define SP_PNP_INTERRUPT_REQUIRED   0x00000008
 | ||
| 
 | ||
| //
 | ||
| // Indicates that legacy detection should not be done.
 | ||
| //
 | ||
| 
 | ||
| #define SP_PNP_NO_LEGACY_DETECTION  0x00000010
 | ||
| 
 | ||
| //
 | ||
| // Internal scsiport srb status codes.
 | ||
| // these must be between 0x38 and 0x3f (inclusive) and should never get
 | ||
| // returned to a class driver.
 | ||
| //
 | ||
| // These values are used after the srb has been put on the adapter's
 | ||
| // startio queue and thus cannot be completed without running it through the
 | ||
| // completion DPC.
 | ||
| //
 | ||
| 
 | ||
| #ifndef KDBG_EXT
 | ||
| //
 | ||
| // Function declarations
 | ||
| //
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortGlobalDispatch(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PIRP Irp
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortFdoCreateClose (
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PIRP Irp
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortFdoDispatch(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PIRP Irp
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortPdoScsi(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PIRP Irp
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortScsi1PdoScsi(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PIRP Irp
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| ScsiPortStartIo(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PIRP Irp
 | ||
|     );
 | ||
| 
 | ||
| BOOLEAN
 | ||
| ScsiPortInterrupt(
 | ||
|     IN PKINTERRUPT InterruptObject,
 | ||
|     IN PDEVICE_OBJECT DeviceObject
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortFdoDeviceControl(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PIRP Irp
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortPdoDeviceControl(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PIRP Irp
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortPdoCreateClose(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PIRP Irp
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortPdoPnp(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PIRP Irp
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| ScsiPortTickHandler(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PVOID Context
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| IssueRequestSense(
 | ||
|     IN PADAPTER_EXTENSION deviceExtension,
 | ||
|     IN PSCSI_REQUEST_BLOCK FailingSrb
 | ||
|     );
 | ||
| 
 | ||
| BOOLEAN
 | ||
| SpStartIoSynchronized (
 | ||
|     PVOID ServiceContext
 | ||
|     );
 | ||
| 
 | ||
| BOOLEAN
 | ||
| SpResetBusSynchronized (
 | ||
|     PVOID ServiceContext
 | ||
|     );
 | ||
| 
 | ||
| BOOLEAN
 | ||
| SpTimeoutSynchronized (
 | ||
|     PVOID ServiceContext
 | ||
|     );
 | ||
| 
 | ||
| BOOLEAN
 | ||
| SpEnableInterruptSynchronized (
 | ||
|     PVOID ServiceContext
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| IssueAbortRequest(
 | ||
|     IN PADAPTER_EXTENSION DeviceExtension,
 | ||
|     IN PLOGICAL_UNIT_EXTENSION LogicalUnit
 | ||
|     );
 | ||
| 
 | ||
| BOOLEAN
 | ||
| SpGetInterruptState(
 | ||
|     IN PVOID ServiceContext
 | ||
|     );
 | ||
| 
 | ||
| #if DBG
 | ||
| 
 | ||
| #define GetLogicalUnitExtension(fdo, path, target, lun, lock, getlock) \
 | ||
|     GetLogicalUnitExtensionEx(fdo, path, target, lun, lock, getlock, __file__, __LINE__)
 | ||
| 
 | ||
| PLOGICAL_UNIT_EXTENSION
 | ||
| GetLogicalUnitExtensionEx(
 | ||
|     PADAPTER_EXTENSION DeviceExtension,
 | ||
|     UCHAR PathId,
 | ||
|     UCHAR TargetId,
 | ||
|     UCHAR Lun,
 | ||
|     PVOID LockTag,
 | ||
|     BOOLEAN AcquireBinLock,
 | ||
|     PCSTR File,
 | ||
|     ULONG Line
 | ||
|     );
 | ||
| 
 | ||
| #else
 | ||
| 
 | ||
| PLOGICAL_UNIT_EXTENSION
 | ||
| GetLogicalUnitExtension(
 | ||
|     PADAPTER_EXTENSION DeviceExtension,
 | ||
|     UCHAR PathId,
 | ||
|     UCHAR TargetId,
 | ||
|     UCHAR Lun,
 | ||
|     PVOID LockTag,
 | ||
|     BOOLEAN AcquireBinLock
 | ||
|     );
 | ||
| 
 | ||
| #endif
 | ||
| 
 | ||
| IO_ALLOCATION_ACTION
 | ||
| ScsiPortAllocationRoutine (
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PIRP Irp,
 | ||
|     IN PVOID MapRegisterBase,
 | ||
|     IN PVOID Context
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| LogErrorEntry(
 | ||
|     IN PADAPTER_EXTENSION DeviceExtension,
 | ||
|     IN PERROR_LOG_ENTRY LogEntry
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| FASTCALL
 | ||
| GetNextLuRequest(
 | ||
|     IN PLOGICAL_UNIT_EXTENSION LogicalUnit
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| GetNextLuRequestWithoutLock(
 | ||
|     IN PLOGICAL_UNIT_EXTENSION LogicalUnit
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpLogTimeoutError(
 | ||
|     IN PADAPTER_EXTENSION DeviceExtension,
 | ||
|     IN PIRP Irp,
 | ||
|     IN ULONG UniqueId
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpProcessCompletedRequest(
 | ||
|     IN PADAPTER_EXTENSION DeviceExtension,
 | ||
|     IN PSRB_DATA SrbData,
 | ||
|     OUT PBOOLEAN CallStartIo
 | ||
|     );
 | ||
| 
 | ||
| PSRB_DATA
 | ||
| SpGetSrbData(
 | ||
|     IN PADAPTER_EXTENSION DeviceExtension,
 | ||
|     UCHAR PathId,
 | ||
|     UCHAR TargetId,
 | ||
|     UCHAR Lun,
 | ||
|     UCHAR QueueTag,
 | ||
|     BOOLEAN AcquireBinLock
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpCompleteSrb(
 | ||
|     IN PADAPTER_EXTENSION DeviceExtension,
 | ||
|     IN PSRB_DATA SrbData,
 | ||
|     IN UCHAR SrbStatus
 | ||
|     );
 | ||
| 
 | ||
| BOOLEAN
 | ||
| SpAllocateSrbExtension(
 | ||
|     IN PADAPTER_EXTENSION DeviceExtension,
 | ||
|     IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
 | ||
|     IN PSCSI_REQUEST_BLOCK Srb,
 | ||
|     OUT BOOLEAN *StartNextRequest,
 | ||
|     OUT BOOLEAN *Tagged
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpSendMiniPortIoctl(
 | ||
|     IN PADAPTER_EXTENSION DeviceExtension,
 | ||
|     IN PIRP RequestIrp
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpGetInquiryData(
 | ||
|     IN PADAPTER_EXTENSION DeviceExtension,
 | ||
|     IN PIRP Irp
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpSendPassThrough(
 | ||
|     IN PADAPTER_EXTENSION DeviceExtension,
 | ||
|     IN PIRP Irp
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpClaimLogicalUnit(
 | ||
|     IN PADAPTER_EXTENSION AdapterExtension,
 | ||
|     IN PLOGICAL_UNIT_EXTENSION LogicalUnitExtension,
 | ||
|     IN PIRP Irp,
 | ||
|     IN BOOLEAN StartDevice
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpMiniPortTimerDpc(
 | ||
|     IN struct _KDPC *Dpc,
 | ||
|     IN PVOID DeviceObject,
 | ||
|     IN PVOID SystemArgument1,
 | ||
|     IN PVOID SystemArgument2
 | ||
|     );
 | ||
| 
 | ||
| BOOLEAN
 | ||
| SpSynchronizeExecution (
 | ||
|     IN PKINTERRUPT Interrupt,
 | ||
|     IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine,
 | ||
|     IN PVOID SynchronizeContext
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpGetCommonBuffer(
 | ||
|     IN PADAPTER_EXTENSION DeviceExtension,
 | ||
|     IN ULONG NonCachedExtensionSize
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpDestroyAdapter(
 | ||
|     IN PADAPTER_EXTENSION Adapter,
 | ||
|     IN BOOLEAN Surprise
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpReleaseAdapterResources(
 | ||
|     IN PADAPTER_EXTENSION Adapter,
 | ||
|     IN BOOLEAN Surprise
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpInitializeConfiguration(
 | ||
|     IN PADAPTER_EXTENSION DeviceExtension,
 | ||
|     IN PUNICODE_STRING RegistryPath,
 | ||
|     IN PHW_INITIALIZATION_DATA HwInitData,
 | ||
|     IN PCONFIGURATION_CONTEXT Context
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpParseDevice(
 | ||
|     IN PADAPTER_EXTENSION DeviceExtension,
 | ||
|     IN HANDLE Key,
 | ||
|     IN PCONFIGURATION_CONTEXT Context,
 | ||
|     IN PUCHAR Buffer
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpConfigurationCallout(
 | ||
|     IN PVOID Context,
 | ||
|     IN PUNICODE_STRING PathName,
 | ||
|     IN INTERFACE_TYPE BusType,
 | ||
|     IN ULONG BusNumber,
 | ||
|     IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
 | ||
|     IN CONFIGURATION_TYPE ControllerType,
 | ||
|     IN ULONG ControllerNumber,
 | ||
|     IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
 | ||
|     IN CONFIGURATION_TYPE PeripheralType,
 | ||
|     IN ULONG PeripheralNumber,
 | ||
|     IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
 | ||
|     );
 | ||
| 
 | ||
| PCM_RESOURCE_LIST
 | ||
| SpBuildResourceList(
 | ||
|     PADAPTER_EXTENSION DeviceExtension,
 | ||
|     PPORT_CONFIGURATION_INFORMATION MiniportConfigInfo
 | ||
|     );
 | ||
| 
 | ||
| BOOLEAN
 | ||
| GetPciConfiguration(
 | ||
|     IN PDRIVER_OBJECT          DriverObject,
 | ||
|     IN OUT PDEVICE_OBJECT      DeviceObject,
 | ||
|     IN PHW_INITIALIZATION_DATA HwInitializationData,
 | ||
|     IN PVOID                   RegistryPath,
 | ||
|     IN ULONG                   BusNumber,
 | ||
|     IN OUT PPCI_SLOT_NUMBER    SlotNumber
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortAddDevice(
 | ||
|     IN PDRIVER_OBJECT DriverObject,
 | ||
|     IN PDEVICE_OBJECT PhysicalDeviceObject
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| ScsiPortUnload(
 | ||
|     IN PDRIVER_OBJECT DriverObject
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortFdoPnp(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PIRP Irp
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortStartAdapter(
 | ||
|     IN PDEVICE_OBJECT Fdo
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortStopAdapter(
 | ||
|     IN PDEVICE_OBJECT Adapter,
 | ||
|     IN PIRP StopRequest
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortStartLogicalUnit(
 | ||
|     IN PLOGICAL_UNIT_EXTENSION LogicalUnit
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortInitLogicalUnit(
 | ||
|     IN PLOGICAL_UNIT_EXTENSION LogicalUnit
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortStopLogicalUnit(
 | ||
|     IN PLOGICAL_UNIT_EXTENSION LogicalUnit
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpEnumerateAdapterSynchronous(
 | ||
|     IN PADAPTER_EXTENSION Adapter,
 | ||
|     IN BOOLEAN Force
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpEnumerateAdapterAsynchronous(
 | ||
|     IN PADAPTER_EXTENSION Adapter,
 | ||
|     IN PSP_ENUMERATION_REQUEST EnumerationRequest,
 | ||
|     IN BOOLEAN Force
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpEnumerationWorker(
 | ||
|     IN PADAPTER_EXTENSION Adapter
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpExtractDeviceRelations(
 | ||
|     IN PADAPTER_EXTENSION Adapter,
 | ||
|     IN DEVICE_RELATION_TYPE RelationType,
 | ||
|     OUT PDEVICE_RELATIONS *DeviceRelations
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| ScsiPortInitializeDispatchTables(
 | ||
|     VOID
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortStringArrayToMultiString(
 | ||
|     IN PDRIVER_OBJECT DriverObject,
 | ||
|     PUNICODE_STRING MultiString,
 | ||
|     PCSTR StringArray[]
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortGetDeviceId(
 | ||
|     IN PDEVICE_OBJECT Pdo,
 | ||
|     OUT PUNICODE_STRING UnicodeString
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortGetInstanceId(
 | ||
|     IN PDEVICE_OBJECT Pdo,
 | ||
|     OUT PUNICODE_STRING UnicodeString
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortGetCompatibleIds(
 | ||
|     IN PDRIVER_OBJECT DriverObject,
 | ||
|     IN PINQUIRYDATA InquiryData,
 | ||
|     OUT PUNICODE_STRING UnicodeString
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortGetHardwareIds(
 | ||
|     IN PDRIVER_OBJECT DriverObject,
 | ||
|     IN PINQUIRYDATA InquiryData,
 | ||
|     OUT PUNICODE_STRING UnicodeString
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortStartAdapterCompletion(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PIRP Irp,
 | ||
|     IN PVOID Context
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpReportNewAdapter(
 | ||
|     IN PDEVICE_OBJECT DeviceObject
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortQueryProperty(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PIRP QueryIrp
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortInitLegacyAdapter(
 | ||
|     IN PSCSIPORT_DRIVER_EXTENSION DriverExtension,
 | ||
|     IN PHW_INITIALIZATION_DATA HwInitializationData,
 | ||
|     IN PVOID HwContext
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpCreateAdapter(
 | ||
|     IN PDRIVER_OBJECT DriverObject,
 | ||
|     OUT PDEVICE_OBJECT *Fdo
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpInitializeAdapterExtension(
 | ||
|     IN PADAPTER_EXTENSION FdoExtension,
 | ||
|     IN PHW_INITIALIZATION_DATA HwInitializationData,
 | ||
|     IN OUT PHW_DEVICE_EXTENSION HwDeviceExtension OPTIONAL
 | ||
|     );
 | ||
| 
 | ||
| PHW_INITIALIZATION_DATA
 | ||
| SpFindInitData(
 | ||
|     IN PSCSIPORT_DRIVER_EXTENSION DriverExtension,
 | ||
|     IN INTERFACE_TYPE InterfaceType
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpBuildConfiguration(
 | ||
|     IN PADAPTER_EXTENSION    AdapterExtension,
 | ||
|     IN PHW_INITIALIZATION_DATA         HwInitializationData,
 | ||
|     IN PPORT_CONFIGURATION_INFORMATION ConfigInformation
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpCallHwFindAdapter(
 | ||
|     IN PDEVICE_OBJECT Fdo,
 | ||
|     IN PHW_INITIALIZATION_DATA HwInitData,
 | ||
|     IN PVOID HwContext OPTIONAL,
 | ||
|     IN OUT PCONFIGURATION_CONTEXT ConfigurationContext,
 | ||
|     IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
 | ||
|     OUT PBOOLEAN CallAgain
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpCallHwInitialize(
 | ||
|     IN PDEVICE_OBJECT Fdo
 | ||
|     );
 | ||
| 
 | ||
| HANDLE
 | ||
| SpOpenParametersKey(
 | ||
|     IN PUNICODE_STRING RegistryPath
 | ||
|     );
 | ||
| 
 | ||
| HANDLE
 | ||
| SpOpenDeviceKey(
 | ||
|     IN PUNICODE_STRING RegistryPath,
 | ||
|     IN ULONG DeviceNumber
 | ||
|     );
 | ||
| 
 | ||
| ULONG
 | ||
| SpQueryPnpInterfaceFlags(
 | ||
|     IN PSCSIPORT_DRIVER_EXTENSION DriverExtension,
 | ||
|     IN INTERFACE_TYPE InterfaceType
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpGetRegistryValue(
 | ||
|     IN PDRIVER_OBJECT DriverObject,
 | ||
|     IN HANDLE Handle,
 | ||
|     IN PWSTR KeyString,
 | ||
|     OUT PKEY_VALUE_FULL_INFORMATION *KeyInformation
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpInitDeviceMap(
 | ||
|     VOID
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpBuildDeviceMapEntry(
 | ||
|     IN PCOMMON_EXTENSION CommonExtension
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpDeleteDeviceMapEntry(
 | ||
|     IN PCOMMON_EXTENSION CommonExtension
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpUpdateLogicalUnitDeviceMapEntry(
 | ||
|     IN PLOGICAL_UNIT_EXTENSION LogicalUnit
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpLogResetError(
 | ||
|     IN PADAPTER_EXTENSION DeviceExtension,
 | ||
|     IN PSCSI_REQUEST_BLOCK  Srb,
 | ||
|     IN ULONG UniqueId
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpRemoveLogicalUnitFromBin (
 | ||
|     IN PADAPTER_EXTENSION AdapterExtension,
 | ||
|     IN PLOGICAL_UNIT_EXTENSION LogicalUnitExtension
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpAddLogicalUnitToBin (
 | ||
|     IN PADAPTER_EXTENSION AdapterExtension,
 | ||
|     IN PLOGICAL_UNIT_EXTENSION LogicalUnitExtension
 | ||
|     );
 | ||
| 
 | ||
| PSCSIPORT_DEVICE_TYPE
 | ||
| SpGetDeviceTypeInfo(
 | ||
|     IN UCHAR DeviceType
 | ||
|     );
 | ||
| 
 | ||
| BOOLEAN
 | ||
| SpRemoveLogicalUnit(
 | ||
|     IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
 | ||
|     IN UCHAR RemoveType
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpDeleteLogicalUnit(
 | ||
|     IN PLOGICAL_UNIT_EXTENSION LogicalUnit
 | ||
|     );
 | ||
| 
 | ||
| PLOGICAL_UNIT_EXTENSION
 | ||
| SpFindSafeLogicalUnit(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN UCHAR PathId,
 | ||
|     IN PVOID LockTag
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortSystemControlIrp(
 | ||
|     IN     PDEVICE_OBJECT DeviceObject,
 | ||
|     IN OUT PIRP           Irp);
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpWmiIrpNormalRequest(
 | ||
|     IN     PDEVICE_OBJECT  DeviceObject,
 | ||
|     IN     UCHAR           WmiMinorCode,
 | ||
|     IN OUT PWMI_PARAMETERS WmiParameters);
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpWmiIrpRegisterRequest(
 | ||
|     IN     PDEVICE_OBJECT  DeviceObject,
 | ||
|     IN OUT PWMI_PARAMETERS WmiParameters);
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpWmiHandleOnMiniPortBehalf(
 | ||
|     IN     PDEVICE_OBJECT  DeviceObject,
 | ||
|     IN     UCHAR           WmiMinorCode,
 | ||
|     IN OUT PWMI_PARAMETERS WmiParameters);
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpWmiPassToMiniPort(
 | ||
|     IN     PDEVICE_OBJECT  DeviceObject,
 | ||
|     IN     UCHAR           WmiMinorCode,
 | ||
|     IN OUT PWMI_PARAMETERS WmiParameters);
 | ||
| 
 | ||
| VOID
 | ||
| SpWmiInitializeSpRegInfo(
 | ||
|     IN  PDEVICE_OBJECT  DeviceObject);
 | ||
| 
 | ||
| VOID
 | ||
| SpWmiGetSpRegInfo(
 | ||
|     IN  PDEVICE_OBJECT DeviceObject,
 | ||
|     OUT PWMIREGINFO  * SpRegInfoBuf,
 | ||
|     OUT ULONG        * SpRegInfoBufSize);
 | ||
| 
 | ||
| VOID
 | ||
| SpWmiDestroySpRegInfo(
 | ||
|     IN  PDEVICE_OBJECT DeviceObject);
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpWmiInitializeFreeRequestList(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN ULONG          NumberOfItems
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpWmiPushExistingFreeRequestItem(
 | ||
|     IN PADAPTER_EXTENSION Adapter,
 | ||
|     IN PWMI_MINIPORT_REQUEST_ITEM WmiRequestItem
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpWmiPushFreeRequestItem(
 | ||
|     IN PADAPTER_EXTENSION           Adapter
 | ||
|     );
 | ||
| 
 | ||
| PWMI_MINIPORT_REQUEST_ITEM
 | ||
| SpWmiPopFreeRequestItem(
 | ||
|     IN PADAPTER_EXTENSION           Adapter
 | ||
|     );
 | ||
| 
 | ||
| BOOLEAN
 | ||
| SpWmiRemoveFreeMiniPortRequestItems(
 | ||
|     IN PADAPTER_EXTENSION   fdoExtension
 | ||
|     );
 | ||
| 
 | ||
| #if DBG
 | ||
| ULONG
 | ||
| FASTCALL
 | ||
| FASTCALL
 | ||
| SpAcquireRemoveLockEx(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN OPTIONAL PVOID Tag,
 | ||
|     IN PCSTR File,
 | ||
|     IN ULONG Line
 | ||
|     );
 | ||
| #else
 | ||
| ULONG
 | ||
| INLINE
 | ||
| SpAcquireRemoveLock(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN OPTIONAL PVOID Tag
 | ||
|     )
 | ||
| {
 | ||
|     PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
 | ||
|     InterlockedIncrement(&commonExtension->RemoveLock);
 | ||
|     return (commonExtension->IsRemoved);
 | ||
| }
 | ||
| #endif
 | ||
| 
 | ||
| VOID
 | ||
| FASTCALL
 | ||
| SpReleaseRemoveLock(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN OPTIONAL PVOID Tag
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| FASTCALL
 | ||
| FASTCALL
 | ||
| SpCompleteRequest(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PIRP Irp,
 | ||
|     IN OPTIONAL PSRB_DATA SrbData,
 | ||
|     IN CCHAR PriorityBoost
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| ScsiPortDispatchPower(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PIRP Irp
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpDefaultPowerCompletion(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN UCHAR MinorFunction,
 | ||
|     IN POWER_STATE PowerState,
 | ||
|     IN PIRP OriginalIrp,
 | ||
|     IN PIO_STATUS_BLOCK IoStatus
 | ||
|     );
 | ||
| 
 | ||
| PCM_RESOURCE_LIST
 | ||
| RtlDuplicateCmResourceList(
 | ||
|     IN PDRIVER_OBJECT DriverObject,
 | ||
|     POOL_TYPE PoolType,
 | ||
|     PCM_RESOURCE_LIST ResourceList,
 | ||
|     ULONG Tag
 | ||
|     );
 | ||
| 
 | ||
| ULONG
 | ||
| RtlSizeOfCmResourceList(
 | ||
|     IN PCM_RESOURCE_LIST ResourceList
 | ||
|     );
 | ||
| 
 | ||
| BOOLEAN
 | ||
| SpTranslateResources(
 | ||
|     IN PDRIVER_OBJECT DriverObject,
 | ||
|     IN PCM_RESOURCE_LIST AllocatedResources,
 | ||
|     OUT PCM_RESOURCE_LIST *TranslatedResources
 | ||
|     );
 | ||
| 
 | ||
| BOOLEAN
 | ||
| SpFindAddressTranslation(
 | ||
|     IN PADAPTER_EXTENSION AdapterExtension,
 | ||
|     IN INTERFACE_TYPE BusType,
 | ||
|     IN ULONG BusNumber,
 | ||
|     IN PHYSICAL_ADDRESS RangeStart,
 | ||
|     IN ULONG RangeLength,
 | ||
|     IN BOOLEAN InIoSpace,
 | ||
|     IN OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Translation
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpAllocateAdapterResources(
 | ||
|     IN PDEVICE_OBJECT Fdo
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpLockUnlockQueue(
 | ||
|     IN PDEVICE_OBJECT LogicalUnit,
 | ||
|     IN BOOLEAN LockQueue,
 | ||
|     IN BOOLEAN BypassLockedQueue
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| ScsiPortRemoveAdapter(
 | ||
|     IN PDEVICE_OBJECT Adapter,
 | ||
|     IN BOOLEAN Surprise
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpTerminateAdapter(
 | ||
|     IN PADAPTER_EXTENSION Adapter
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpQueryDeviceText(
 | ||
|     IN PDEVICE_OBJECT LogicalUnit,
 | ||
|     IN DEVICE_TEXT_TYPE TextType,
 | ||
|     IN LCID LocaleId,
 | ||
|     IN OUT PWSTR *DeviceText
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpCheckSpecialDeviceFlags(
 | ||
|     IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
 | ||
|     IN PINQUIRYDATA InquiryData
 | ||
|     );
 | ||
| 
 | ||
| PSRB_DATA
 | ||
| FASTCALL
 | ||
| SpAllocateSrbData(
 | ||
|     IN PADAPTER_EXTENSION Adapter,
 | ||
|     IN OPTIONAL PIRP Request
 | ||
|     );
 | ||
| 
 | ||
| PSRB_DATA
 | ||
| FASTCALL
 | ||
| SpAllocateBypassSrbData(
 | ||
|     IN PLOGICAL_UNIT_EXTENSION LogicalUnit
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpCheckSrbLists(
 | ||
|     IN PADAPTER_EXTENSION Adapter,
 | ||
|     IN PUCHAR FailureString
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| ScsiPortCompletionDpc(
 | ||
|     IN PKDPC Dpc,
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PIRP Irp,
 | ||
|     IN PVOID Context
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpAllocateTagBitMap(
 | ||
|     IN PADAPTER_EXTENSION Adapter
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpRequestValidPowerState(
 | ||
|     IN PADAPTER_EXTENSION Adapter,
 | ||
|     IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
 | ||
|     IN PSCSI_REQUEST_BLOCK Srb
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpRequestValidAdapterPowerStateSynchronous(
 | ||
|     IN PADAPTER_EXTENSION Adapter
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpEnableDisableAdapter(
 | ||
|     IN PADAPTER_EXTENSION Adapter,
 | ||
|     IN BOOLEAN Enable
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpEnableDisableLogicalUnit(
 | ||
|     IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
 | ||
|     IN BOOLEAN Enable,
 | ||
|     IN PSP_ENABLE_DISABLE_COMPLETION_ROUTINE CompletionRoutine,
 | ||
|     IN PVOID Context
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| ScsiPortProcessAdapterPower(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PIRP Irp
 | ||
|     );
 | ||
| 
 | ||
| INTERFACE_TYPE
 | ||
| SpGetPdoInterfaceType(
 | ||
|     IN PDEVICE_OBJECT Pdo
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpReadNumericInstanceValue(
 | ||
|     IN PDEVICE_OBJECT Pdo,
 | ||
|     IN PWSTR ValueName,
 | ||
|     OUT PULONG Value
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpWriteNumericInstanceValue(
 | ||
|     IN PDEVICE_OBJECT Pdo,
 | ||
|     IN PWSTR ValueName,
 | ||
|     IN ULONG Value
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpGetSupportedAdapterControlFunctions(
 | ||
|     IN PADAPTER_EXTENSION Adapter
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpReleaseMappedAddresses(
 | ||
|     IN PADAPTER_EXTENSION Adapter
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpGetSupportedAdapterControlFunctions(
 | ||
|     PADAPTER_EXTENSION Adapter
 | ||
|     );
 | ||
| 
 | ||
| BOOLEAN
 | ||
| SpIsAdapterControlTypeSupported(
 | ||
|     IN PADAPTER_EXTENSION AdapterExtension,
 | ||
|     IN SCSI_ADAPTER_CONTROL_TYPE ControlType
 | ||
|     );
 | ||
| 
 | ||
| SCSI_ADAPTER_CONTROL_STATUS
 | ||
| SpCallAdapterControl(
 | ||
|     IN PADAPTER_EXTENSION AdapterExtension,
 | ||
|     IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
 | ||
|     IN PVOID Parameters
 | ||
|     );
 | ||
| 
 | ||
| PVOID
 | ||
| SpAllocateSrbDataBackend(
 | ||
|     IN POOL_TYPE PoolType,
 | ||
|     IN ULONG NumberOfBytes,
 | ||
|     IN ULONG AdapterIndex
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpFreeSrbDataBackend(
 | ||
|     IN PSRB_DATA SrbData
 | ||
|     );
 | ||
| 
 | ||
| ULONG
 | ||
| SpAllocateQueueTag(
 | ||
|     IN PADAPTER_EXTENSION Adapter
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpReleaseQueueTag(
 | ||
|     IN PADAPTER_EXTENSION Adapter,
 | ||
|     IN ULONG QueueTag
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpInitializeGuidInterfaceMapping(
 | ||
|     IN PDRIVER_OBJECT DriverObject
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpSignalCompletion(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PIRP Irp,
 | ||
|     IN PKEVENT Event
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpSendIrpSynchronous(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PIRP Irp
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpGetBusTypeGuid(
 | ||
|     IN PADAPTER_EXTENSION Adapter
 | ||
|     );
 | ||
| 
 | ||
| BOOLEAN
 | ||
| SpDetermine64BitSupport(
 | ||
|     VOID
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpAdjustDisabledBit(
 | ||
|     IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
 | ||
|     IN BOOLEAN Enable
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpReadNumericValue(
 | ||
|     IN OPTIONAL HANDLE Root,
 | ||
|     IN OPTIONAL PUNICODE_STRING KeyName,
 | ||
|     IN PUNICODE_STRING ValueName,
 | ||
|     OUT PULONG Value
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpWaitForRemoveLock(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PVOID LockTag
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpStartLockRequest(
 | ||
|     IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
 | ||
|     IN PIRP Irp OPTIONAL
 | ||
|     );
 | ||
| 
 | ||
| BOOLEAN
 | ||
| SpAdapterConfiguredForSenseDataEvents(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     OUT GUID *SenseDataClass
 | ||
|     );
 | ||
|         
 | ||
| NTSTATUS
 | ||
| SpInitAdapterWmiRegInfo(
 | ||
|     IN PDEVICE_OBJECT DeviceObject
 | ||
|     );
 | ||
| 
 | ||
| PMAPPED_ADDRESS
 | ||
| SpAllocateAddressMapping(
 | ||
|     PADAPTER_EXTENSION Adapter
 | ||
|     );
 | ||
| 
 | ||
| BOOLEAN
 | ||
| SpPreallocateAddressMapping(
 | ||
|     PADAPTER_EXTENSION Adapter,
 | ||
|     IN UCHAR NumberOfBlocks
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpPurgeFreeMappedAddressList(
 | ||
|     IN PADAPTER_EXTENSION Adapter
 | ||
|     );
 | ||
| 
 | ||
| BOOLEAN
 | ||
| SpFreeMappedAddress(
 | ||
|     IN PADAPTER_EXTENSION Adapter,
 | ||
|     IN PVOID MappedAddress
 | ||
|     );
 | ||
| 
 | ||
| PMAPPED_ADDRESS
 | ||
| SpFindMappedAddress(
 | ||
|     IN PADAPTER_EXTENSION Adapter,
 | ||
|     IN LARGE_INTEGER IoAddress,
 | ||
|     IN ULONG NumberOfBytes,
 | ||
|     IN ULONG SystemIoBusNumber
 | ||
|     );
 | ||
| 
 | ||
| //
 | ||
| // SCSIPORT specified verifier error codes.
 | ||
| // 
 | ||
| #define SCSIPORT_VERIFIER_BAD_INIT_PARAMS          0x1000
 | ||
| #define SCSIPORT_VERIFIER_STALL_TOO_LONG           0x1001
 | ||
| #define SCSIPORT_VERIFIER_MINIPORT_ROUTINE_TIMEOUT 0x1002
 | ||
| #define SCSIPORT_VERIFIER_REQUEST_COMPLETED_TWICE  0x1003
 | ||
| #define SCSIPORT_VERIFIER_BAD_SRBSTATUS            0x1004
 | ||
| #define SCSIPORT_VERIFIER_UNTAGGED_REQUEST_ACTIVE  0x1005
 | ||
| #define SCSIPORT_VERIFIER_BAD_VA                   0x1006
 | ||
| #define SCSIPORT_VERIFIER_RQSTS_NOT_COMPLETE       0x1007
 | ||
| 
 | ||
| #define SP_VRFY_NONE                               (ULONG)-1
 | ||
| #define SP_VRFY_COMMON_BUFFERS                     0x00000001
 | ||
| 
 | ||
| typedef struct _SP_VA_MAPPING_INFO {
 | ||
|       PVOID OriginalSrbExtVa;
 | ||
|       ULONG SrbExtLen;
 | ||
|       PMDL SrbExtMdl;
 | ||
|       PVOID RemappedSrbExtVa;
 | ||
|       PVOID OriginalSenseVa;
 | ||
|       ULONG SenseLen;
 | ||
|       PMDL SenseMdl;
 | ||
|       PVOID RemappedSenseVa;
 | ||
| } SP_VA_MAPPING_INFO, *PSP_VA_MAPPING_INFO;
 | ||
| 
 | ||
| #define GET_VA_MAPPING_INFO(adapter, block)\
 | ||
|     (PSP_VA_MAPPING_INFO)((PUCHAR)(block) + ((adapter)->CommonBufferSize - PAGE_SIZE))
 | ||
| 
 | ||
| BOOLEAN
 | ||
| SpVerifierInitialization(
 | ||
|     VOID
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpVerifySrbStatus(
 | ||
|     PVOID HwDeviceExtension,
 | ||
|     PSCSI_REQUEST_BLOCK srb
 | ||
|     );
 | ||
| 
 | ||
| ULONG
 | ||
| SpHwFindAdapterVrfy (
 | ||
|     IN PVOID DeviceExtension,
 | ||
|     IN PVOID HwContext,
 | ||
|     IN PVOID BusInformation,
 | ||
|     IN PCHAR ArgumentString,
 | ||
|     IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
 | ||
|     OUT PBOOLEAN Again
 | ||
|     );
 | ||
| 
 | ||
| BOOLEAN
 | ||
| SpHwInitializeVrfy (
 | ||
|     IN PVOID DeviceExtension
 | ||
|     );
 | ||
| 
 | ||
| BOOLEAN
 | ||
| SpHwStartIoVrfy (
 | ||
|     IN PVOID DeviceExtension,
 | ||
|     IN PSCSI_REQUEST_BLOCK Srb
 | ||
|     );
 | ||
| 
 | ||
| BOOLEAN
 | ||
| SpHwInterruptVrfy (
 | ||
|     IN PVOID DeviceExtension
 | ||
|     );
 | ||
| 
 | ||
| BOOLEAN
 | ||
| SpHwResetBusVrfy (
 | ||
|     IN PVOID DeviceExtension,
 | ||
|     IN ULONG PathId
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpHwDmaStartedVrfy (
 | ||
|     IN PVOID DeviceExtension
 | ||
|     );
 | ||
| 
 | ||
| BOOLEAN
 | ||
| SpHwRequestInterruptVrfy (
 | ||
|     IN PVOID DeviceExtension
 | ||
|     );
 | ||
| 
 | ||
| BOOLEAN
 | ||
| SpHwTimerRequestVrfy (
 | ||
|     IN PVOID DeviceExtension
 | ||
|     );
 | ||
| 
 | ||
| SCSI_ADAPTER_CONTROL_STATUS
 | ||
| SpHwAdapterControlVrfy (
 | ||
|     IN PVOID DeviceExtension,
 | ||
|     IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
 | ||
|     IN PVOID Parameters
 | ||
|     );
 | ||
| 
 | ||
| NTSTATUS
 | ||
| SpGetCommonBufferVrfy(
 | ||
|     PADAPTER_EXTENSION DeviceExtension,
 | ||
|     ULONG NonCachedExtensionSize
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpFreeCommonBufferVrfy(
 | ||
|     PADAPTER_EXTENSION Adapter
 | ||
|     );
 | ||
| 
 | ||
| PVOID
 | ||
| SpGetOriginalSrbExtVa(
 | ||
|     PADAPTER_EXTENSION Adapter,
 | ||
|     PVOID Va
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpInsertSrbExtension(
 | ||
|     PADAPTER_EXTENSION Adapter,
 | ||
|     PCCHAR SrbExtension
 | ||
|     );
 | ||
| 
 | ||
| PVOID
 | ||
| SpPrepareSrbExtensionForUse(
 | ||
|     PADAPTER_EXTENSION Adapter,
 | ||
|     PCCHAR SrbExtension
 | ||
|     );
 | ||
| 
 | ||
| PCCHAR
 | ||
| SpPrepareSenseBufferForUse(
 | ||
|     PADAPTER_EXTENSION Adapter,
 | ||
|     PCCHAR SrbExtension
 | ||
|     );
 | ||
| 
 | ||
| PVOID
 | ||
| SpGetInaccessiblePage(
 | ||
|     PADAPTER_EXTENSION Adapter
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpEnsureAllRequestsAreComplete(
 | ||
|     PADAPTER_EXTENSION Adapter
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpDoVerifierCleanup(
 | ||
|     IN PADAPTER_EXTENSION Adapter
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| SpDoVerifierInit(
 | ||
|     IN PADAPTER_EXTENSION Adapter,
 | ||
|     IN PHW_INITIALIZATION_DATA HwInitializationData
 | ||
|     );
 | ||
| 
 | ||
| PMDL
 | ||
| INLINE
 | ||
| SpGetRemappedSrbExt(
 | ||
|     PADAPTER_EXTENSION Adapter,
 | ||
|     PVOID Block
 | ||
|     )
 | ||
| {
 | ||
|     PSP_VA_MAPPING_INFO MappingInfo = GET_VA_MAPPING_INFO(Adapter, Block);
 | ||
|     return MappingInfo->SrbExtMdl;
 | ||
| }
 | ||
| 
 | ||
| PMDL
 | ||
| INLINE
 | ||
| SpGetRemappedSenseBuffer(
 | ||
|     PADAPTER_EXTENSION Adapter,
 | ||
|     PVOID Block
 | ||
|     )
 | ||
| {
 | ||
|     PSP_VA_MAPPING_INFO MappingInfo = GET_VA_MAPPING_INFO(Adapter, Block);
 | ||
|     return MappingInfo->SenseMdl;
 | ||
| }
 | ||
| 
 | ||
| BOOLEAN
 | ||
| INLINE
 | ||
| SpVerifierActive(
 | ||
|     IN PADAPTER_EXTENSION Adapter
 | ||
|     )
 | ||
| {
 | ||
|     return (Adapter->VerifierExtension != NULL) ? TRUE : FALSE;
 | ||
| }
 | ||
| 
 | ||
| BOOLEAN
 | ||
| INLINE
 | ||
| SpVerifyingCommonBuffer(
 | ||
|     IN PADAPTER_EXTENSION Adapter
 | ||
|     )
 | ||
| {
 | ||
|     return (Adapter->VerifierExtension == NULL) ? FALSE :
 | ||
|        (Adapter->VerifierExtension->VrfyLevel & SP_VRFY_COMMON_BUFFERS) ? TRUE :
 | ||
|        FALSE;
 | ||
| }
 | ||
| 
 | ||
| //
 | ||
| // Definitions and declarations used for logging allocation failures.  When
 | ||
| // enabled, all allocation failures are logged to the system event log
 | ||
| // as warnings.
 | ||
| //
 | ||
| 
 | ||
| PVOID
 | ||
| SpAllocateErrorLogEntry(
 | ||
|     IN PDRIVER_OBJECT DriverObject
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| FASTCALL
 | ||
| SpLogAllocationFailureFn(
 | ||
|     IN PDRIVER_OBJECT DriverObject,
 | ||
|     IN POOL_TYPE PoolType,
 | ||
|     IN SIZE_T Size,
 | ||
|     IN ULONG Tag,
 | ||
|     IN ULONG FileId,
 | ||
|     IN ULONG LineNumber
 | ||
|     );
 | ||
| 
 | ||
| PVOID
 | ||
| SpAllocatePoolEx(
 | ||
|     IN POOL_TYPE PoolType,
 | ||
|     IN SIZE_T NumberOfBytes,
 | ||
|     IN ULONG Tag,
 | ||
|     IN PDRIVER_OBJECT DriverObject,
 | ||
|     IN ULONG FileId,
 | ||
|     IN ULONG LineNumber
 | ||
|     );
 | ||
| 
 | ||
| PMDL
 | ||
| SpAllocateMdlEx(
 | ||
|     IN PVOID VirtualAddress,
 | ||
|     IN ULONG Length,
 | ||
|     IN BOOLEAN SecondaryBuffer,
 | ||
|     IN BOOLEAN ChargeQuota,
 | ||
|     IN OUT PIRP Irp,
 | ||
|     IN PDRIVER_OBJECT DriverObject,
 | ||
|     IN ULONG FileId,
 | ||
|     IN ULONG LineNumber
 | ||
|     );
 | ||
| 
 | ||
| PIRP
 | ||
| SpAllocateIrpEx(
 | ||
|     IN CCHAR StackSize,
 | ||
|     IN BOOLEAN ChargeQuota,
 | ||
|     IN PDRIVER_OBJECT DriverObject,
 | ||
|     IN ULONG FileId,
 | ||
|     IN ULONG LineNumber
 | ||
|     );
 | ||
| 
 | ||
| #define SCSIPORT_TAG_ALLOCMDL  TAG('LDMs')
 | ||
| #define SCSIPORT_TAG_ALLOCIRP  TAG('PRIs')
 | ||
| #define SCSIPORT_TAG_LOOKASIDE TAG('LALs')
 | ||
| 
 | ||
| #define SpAllocatePool(type, size, tag, drvObj) \
 | ||
|     SpAllocatePoolEx((type), (size), (tag), (drvObj), __FILE_ID__, __LINE__)
 | ||
| 
 | ||
| #define SpAllocateMdl(va, len, secbuf, cq, irp, drvobj) \
 | ||
|     SpAllocateMdlEx((va), (len), (secbuf), (cq), (irp), (drvobj), __FILE_ID__, __LINE__)
 | ||
| 
 | ||
| #define SpAllocateIrp(ss, cq, drvobj) \
 | ||
|     SpAllocateIrpEx((ss), (cq), (drvobj), __FILE_ID__, __LINE__)
 | ||
| 
 | ||
| //
 | ||
| // This structure makes it easy to allocate a contiguous chunk of memory
 | ||
| // for an event log entry with room for the insertion strings.
 | ||
| //
 | ||
| typedef struct _SCSIPORT_ALLOCFAILURE_DATA {
 | ||
|     ULONG Size;
 | ||
|     ULONG FileId;
 | ||
|     ULONG LineNumber;
 | ||
| } SCSIPORT_ALLOCFAILURE_DATA;
 | ||
| 
 | ||
| //
 | ||
| // Inline functions
 | ||
| //
 | ||
| 
 | ||
| ULONG
 | ||
| INLINE
 | ||
| SpGetCommonBufferSize(
 | ||
|     IN PADAPTER_EXTENSION DeviceExtension,
 | ||
|     IN ULONG NonCachedExtensionSize,
 | ||
|     OUT OPTIONAL PULONG BlockSize
 | ||
|     )
 | ||
| {
 | ||
|     ULONG length;
 | ||
|     ULONG blockSize;
 | ||
| 
 | ||
|     //
 | ||
|     // To ensure that we never transfer normal request data to the SrbExtension
 | ||
|     // (ie. the case of Srb->SenseInfoBuffer == VirtualAddress in
 | ||
|     // ScsiPortGetPhysicalAddress) on some platforms where an inconsistency in
 | ||
|     // MM can result in the same Virtual address supplied for 2 different
 | ||
|     // physical addresses, bump the SrbExtensionSize if it's zero.
 | ||
|     //
 | ||
| 
 | ||
|     if (DeviceExtension->SrbExtensionSize == 0) {
 | ||
|         DeviceExtension->SrbExtensionSize = 16;
 | ||
|     }
 | ||
| 
 | ||
|     //
 | ||
|     // Calculate the block size for the list elements based on the Srb
 | ||
|     // Extension.
 | ||
|     //
 | ||
| 
 | ||
|     blockSize = DeviceExtension->SrbExtensionSize;
 | ||
| 
 | ||
|     //
 | ||
|     // If auto request sense is supported then add in space for the request
 | ||
|     // sense data.
 | ||
|     //
 | ||
| 
 | ||
|     if (DeviceExtension->AutoRequestSense) {        
 | ||
|         blockSize += sizeof(SENSE_DATA) + 
 | ||
|                      DeviceExtension->AdditionalSenseBytes;
 | ||
|     }
 | ||
| 
 | ||
|     //
 | ||
|     // Round blocksize up to the size of a PVOID.
 | ||
|     //
 | ||
| 
 | ||
|     blockSize = (blockSize + sizeof(LONGLONG) - 1) & ~(sizeof(LONGLONG) - 1);
 | ||
| 
 | ||
|     //
 | ||
|     // The length of the common buffer should be equal to the size of the
 | ||
|     // noncached extension and a minimum number of srb extension
 | ||
|     //
 | ||
| 
 | ||
|     length = NonCachedExtensionSize + 
 | ||
|              (blockSize * DeviceExtension->NumberOfRequests);
 | ||
| 
 | ||
|     //
 | ||
|     // Round the length up to a page size, since HalAllocateCommonBuffer
 | ||
|     // allocates in pages anyway.
 | ||
|     //
 | ||
| 
 | ||
|     length = (ULONG)ROUND_TO_PAGES(length);
 | ||
| 
 | ||
|     //
 | ||
|     // If the user is interested in the block size, copy it into the provided
 | ||
|     // buffer.
 | ||
|     //
 | ||
| 
 | ||
|     if (BlockSize != NULL) {
 | ||
|         *BlockSize = blockSize;
 | ||
|     }
 | ||
| 
 | ||
|     return length;
 | ||
| }
 | ||
| 
 | ||
| NTSTATUS
 | ||
| INLINE
 | ||
| SpDispatchRequest(
 | ||
|     IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
 | ||
|     IN PIRP Irp
 | ||
|     )
 | ||
| {
 | ||
|     PCOMMON_EXTENSION commonExtension = &(LogicalUnit->CommonExtension);
 | ||
|     PCOMMON_EXTENSION lowerCommonExtension =
 | ||
|         commonExtension->LowerDeviceObject->DeviceExtension;
 | ||
| 
 | ||
|     PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
 | ||
|     PSCSI_REQUEST_BLOCK srb = irpStack->Parameters.Scsi.Srb;
 | ||
| 
 | ||
|     ASSERT_PDO(LogicalUnit->CommonExtension.DeviceObject);
 | ||
|     ASSERT_SRB_DATA(srb->OriginalRequest);
 | ||
| 
 | ||
|     if((LogicalUnit->CommonExtension.IdleTimer != NULL) &&
 | ||
|        (SpSrbRequiresPower(srb)) &&
 | ||
|        !(srb->SrbFlags & SRB_FLAGS_BYPASS_LOCKED_QUEUE) &&
 | ||
|        !(srb->SrbFlags & SRB_FLAGS_NO_KEEP_AWAKE)) {
 | ||
|        PoSetDeviceBusy(LogicalUnit->CommonExtension.IdleTimer);
 | ||
|     }
 | ||
| 
 | ||
|     ASSERT(irpStack->MajorFunction == IRP_MJ_SCSI);
 | ||
|     return (lowerCommonExtension->MajorFunction[IRP_MJ_SCSI])(
 | ||
|                 commonExtension->LowerDeviceObject,
 | ||
|                 Irp);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| BOOLEAN
 | ||
| INLINE
 | ||
| SpSrbIsBypassRequest(
 | ||
|     PSCSI_REQUEST_BLOCK Srb,
 | ||
|     ULONG LuFlags
 | ||
|     )
 | ||
| /*++
 | ||
| 
 | ||
| Routine Description:
 | ||
| 
 | ||
|     This routine determines whether a request is a "bypass" request - one which
 | ||
|     should skip the lun queueing and be injected straight into the startio
 | ||
|     queue.
 | ||
| 
 | ||
|     Bypass requests do not start the next LU request when they complete.  This
 | ||
|     ensures that no new i/o is run until the condition being bypassed is
 | ||
|     cleared.
 | ||
| 
 | ||
|     Note: LOCK & UNLOCK requests are not bypass requests unless the queue
 | ||
|           is already locked.  This ensures that the first LOCK request will
 | ||
|           get run after previously queued requests, but that additional LOCK
 | ||
|           requests will not get stuck in the lun queue.
 | ||
| 
 | ||
|           Likewise any UNLOCK request sent when the queue is locked will be
 | ||
|           run immediately.  However since SpStartIoSynchronized checks to
 | ||
|           see if the request is a bypass request AFTER ScsiPortStartIo has
 | ||
|           cleared the QUEUE_LOCKED flag this will force the completion dpc
 | ||
|           to call GetNextLuRequest which will take the next operation out of
 | ||
|           the lun queue.  This is how i/o is restarted after a lock sequence
 | ||
|           has been completed.
 | ||
| 
 | ||
| Arguments:
 | ||
| 
 | ||
|     Srb - the srb in question
 | ||
| 
 | ||
|     LuFlags - the flags for the lun.
 | ||
| 
 | ||
| Return Value:
 | ||
| 
 | ||
|     TRUE if the request should bypass the lun queue, be injected into the
 | ||
|          StartIo queue and if GetNextLuRequest should not be called after this
 | ||
|          request has completed.
 | ||
| 
 | ||
|     FALSE otherwise
 | ||
| 
 | ||
| --*/
 | ||
| 
 | ||
| {
 | ||
|     ULONG flags = Srb->SrbFlags & (SRB_FLAGS_BYPASS_FROZEN_QUEUE |
 | ||
|                                    SRB_FLAGS_BYPASS_LOCKED_QUEUE);
 | ||
| 
 | ||
|     ASSERT(TEST_FLAG(LuFlags, LU_QUEUE_FROZEN | LU_QUEUE_LOCKED) !=
 | ||
|            (LU_QUEUE_FROZEN | LU_QUEUE_LOCKED));
 | ||
| 
 | ||
|     if(flags == 0) {
 | ||
|         return FALSE;
 | ||
|     }
 | ||
| 
 | ||
|     if(flags & SRB_FLAGS_BYPASS_LOCKED_QUEUE) {
 | ||
| 
 | ||
|         DebugPrint((2, "SpSrbIsBypassRequest: Srb %#08lx is marked to bypass "
 | ||
|                        "locked queue\n", Srb));
 | ||
| 
 | ||
|         if(TEST_FLAG(LuFlags, LU_QUEUE_LOCKED | LU_QUEUE_PAUSED)) {
 | ||
| 
 | ||
|             DebugPrint((1, "SpSrbIsBypassRequest: Queue is locked - %#08lx is "
 | ||
|                            "a bypass srb\n", Srb));
 | ||
|             return TRUE;
 | ||
|         } else {
 | ||
|             DebugPrint((3, "SpSrbIsBypassRequest: Queue is not locked - not a "
 | ||
|                            "bypass request\n"));
 | ||
|             return FALSE;
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     return TRUE;
 | ||
| }
 | ||
| 
 | ||
| VOID
 | ||
| INLINE
 | ||
| SpRequestCompletionDpc(
 | ||
|     IN PDEVICE_OBJECT Adapter
 | ||
|     )
 | ||
| 
 | ||
| /*++
 | ||
| 
 | ||
| Routine Description:
 | ||
| 
 | ||
|     This routine will request that the Completion DPC be queued if there isn't
 | ||
|     already one queued or in progress.  It will set the DpcFlags
 | ||
|     PD_DPC_NOTIFICATION_REQUIRED and PD_DPC_RUNNING.  If the DPC_RUNNING flag
 | ||
|     was not already set then it will request a DPC from the system as well.
 | ||
| 
 | ||
| Arguments:
 | ||
| 
 | ||
|     Adapter - the Adapter to request the DPC for
 | ||
| 
 | ||
| Return Value:
 | ||
| 
 | ||
|     none
 | ||
| 
 | ||
| --*/
 | ||
| 
 | ||
| {
 | ||
|     PADAPTER_EXTENSION adapterExtension = Adapter->DeviceExtension;
 | ||
|     ULONG oldDpcFlags;
 | ||
| 
 | ||
|     //
 | ||
|     // Set the DPC flags to indicate that there is work to be processed
 | ||
|     // (otherwise we wouldn't queue the DPC) and that the DPC is queued.
 | ||
|     //
 | ||
| 
 | ||
|     oldDpcFlags = InterlockedExchange(
 | ||
|                     &(adapterExtension->DpcFlags),
 | ||
|                     (PD_NOTIFICATION_REQUIRED | PD_DPC_RUNNING));
 | ||
| 
 | ||
|     //
 | ||
|     // If the DPC was already queued or running then don't bother requesting
 | ||
|     // a new one - the current one will pickup the work itself.
 | ||
|     //
 | ||
| 
 | ||
|     if(TEST_FLAG(oldDpcFlags, PD_DPC_RUNNING) == FALSE) {
 | ||
|         IoRequestDpc(Adapter, NULL, NULL);
 | ||
|     }
 | ||
| 
 | ||
|     return;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| NTSTATUS
 | ||
| INLINE
 | ||
| SpTranslateScsiStatus(
 | ||
|     IN PSCSI_REQUEST_BLOCK Srb
 | ||
|     )
 | ||
| /*++
 | ||
| 
 | ||
| Routine Description:
 | ||
| 
 | ||
|     This routine translates an srb status into an ntstatus.
 | ||
| 
 | ||
| Arguments:
 | ||
| 
 | ||
|     Srb - Supplies a pointer to the failing Srb.
 | ||
| 
 | ||
| Return Value:
 | ||
| 
 | ||
|     An nt status approprate for the error.
 | ||
| 
 | ||
| --*/
 | ||
| 
 | ||
| {
 | ||
|     switch (SRB_STATUS(Srb->SrbStatus)) {
 | ||
|     case SRB_STATUS_INVALID_LUN:
 | ||
|     case SRB_STATUS_INVALID_TARGET_ID:
 | ||
|     case SRB_STATUS_NO_DEVICE:
 | ||
|     case SRB_STATUS_NO_HBA:
 | ||
|         return(STATUS_DEVICE_DOES_NOT_EXIST);
 | ||
|     case SRB_STATUS_COMMAND_TIMEOUT:
 | ||
|     case SRB_STATUS_TIMEOUT:
 | ||
|         return(STATUS_IO_TIMEOUT);
 | ||
|     case SRB_STATUS_SELECTION_TIMEOUT:
 | ||
|         return(STATUS_DEVICE_NOT_CONNECTED);
 | ||
|     case SRB_STATUS_BAD_FUNCTION:
 | ||
|     case SRB_STATUS_BAD_SRB_BLOCK_LENGTH:
 | ||
|         return(STATUS_INVALID_DEVICE_REQUEST);
 | ||
|     case SRB_STATUS_DATA_OVERRUN:
 | ||
|         return(STATUS_BUFFER_OVERFLOW);
 | ||
|     default:
 | ||
|         return(STATUS_IO_DEVICE_ERROR);
 | ||
|     }
 | ||
| 
 | ||
|     return(STATUS_IO_DEVICE_ERROR);
 | ||
| }
 | ||
| 
 | ||
| PVOID
 | ||
| INLINE
 | ||
| SpGetSrbExtensionBuffer(
 | ||
|     IN PADAPTER_EXTENSION Adapter
 | ||
|     )
 | ||
| 
 | ||
| /*++
 | ||
| 
 | ||
| Routine Description:
 | ||
| 
 | ||
|     This routine returns a pointer to the adapter's SrbExtensionBuffer.
 | ||
| 
 | ||
| Arguments:
 | ||
| 
 | ||
|     Adapter - Supplies a pointer to the adapter's ADAPTER_EXTNENSION.
 | ||
| 
 | ||
| Return Value:
 | ||
| 
 | ||
|     A pointer to the adapter's SrbExtensionBuffer.
 | ||
| 
 | ||
| --*/
 | ||
| 
 | ||
| {
 | ||
|     return (SpVerifyingCommonBuffer(Adapter)) ?
 | ||
|        Adapter->VerifierExtension->CommonBufferVAs :
 | ||
|        Adapter->SrbExtensionBuffer;
 | ||
| }
 | ||
| 
 | ||
| PMDL
 | ||
| SpBuildMdlForMappedTransfer(
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PDMA_ADAPTER AdapterObject,
 | ||
|     IN PMDL OriginalMdl,
 | ||
|     IN PVOID StartVa,
 | ||
|     IN ULONG ByteCount,
 | ||
|     IN PSRB_SCATTER_GATHER ScatterGatherList,
 | ||
|     IN ULONG ScatterGatherEntries
 | ||
|     );
 | ||
| 
 | ||
| #if defined(FORWARD_PROGRESS)
 | ||
| VOID
 | ||
| SpPrepareMdlForMappedTransfer(
 | ||
|     IN PMDL mdl,
 | ||
|     IN PDEVICE_OBJECT DeviceObject,
 | ||
|     IN PDMA_ADAPTER AdapterObject,
 | ||
|     IN PMDL OriginalMdl,
 | ||
|     IN PVOID StartVa,
 | ||
|     IN ULONG ByteCount,
 | ||
|     IN PSRB_SCATTER_GATHER ScatterGatherList,
 | ||
|     IN ULONG ScatterGatherEntries
 | ||
|     );
 | ||
| 
 | ||
| VOID
 | ||
| INLINE
 | ||
| SpFreeSrbExtension(
 | ||
|     IN PADAPTER_EXTENSION Adapter, 
 | ||
|     IN PVOID SrbExtension
 | ||
|     )
 | ||
| {
 | ||
|     if (SpVerifyingCommonBuffer(Adapter)) {
 | ||
|         
 | ||
|         SpInsertSrbExtension(Adapter, SrbExtension);
 | ||
|         
 | ||
|     } else {
 | ||
|         
 | ||
|         *((PVOID *) SrbExtension) = Adapter->SrbExtensionListHeader;
 | ||
|         Adapter->SrbExtensionListHeader = SrbExtension;
 | ||
|         
 | ||
|     }    
 | ||
| }
 | ||
| #ifndef USE_DMA_MACROS
 | ||
| VOID
 | ||
| SpFreeSGList(
 | ||
|     IN PADAPTER_EXTENSION Adapter,
 | ||
|     IN PSRB_DATA SrbData
 | ||
|     );
 | ||
| #endif
 | ||
| #endif // FORWARD_PROGRESS
 | ||
| 
 | ||
| #endif
 | ||
| 
 | ||
| #endif // _PORT_H_
 | ||
| 
 |