Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4792 lines
120 KiB

  1. /*++
  2. Copyright (C) 1990-4 Microsoft Corporation
  3. Module Name:
  4. port.h
  5. Abstract:
  6. This file defines the necessary structures, defines, and functions for
  7. the common SCSI port driver.
  8. Author:
  9. Jeff Havens (jhavens) 28-Feb-1991
  10. Mike Glass
  11. Revision History:
  12. --*/
  13. #ifndef _PORT_H_
  14. #define _PORT_H_
  15. #include "stdarg.h"
  16. #include "stddef.h"
  17. #include "stdio.h"
  18. #include "string.h"
  19. #include "ntddk.h"
  20. #include "scsi.h"
  21. #include <ntddscsi.h>
  22. #include <ntdddisk.h>
  23. #include "ntddstor.h"
  24. #include "wmistr.h"
  25. #include "wdmguid.h"
  26. #include "devguid.h"
  27. #include "portlib.h"
  28. //
  29. // feature/debugginging #define switches
  30. //
  31. #define TEST_LISTS 0
  32. //
  33. // ScsiPort global variable declarations. These should be static data (like
  34. // lookup tables) to avoid synchronization problems.
  35. //
  36. extern PDRIVER_DISPATCH AdapterMajorFunctionTable[];
  37. extern PDRIVER_DISPATCH DeviceMajorFunctionTable[];
  38. extern PDRIVER_DISPATCH Scsi1DeviceMajorFunctionTable[];
  39. //
  40. // Global list of scsi adapters. This is used by the srb data allocator routine
  41. // to convert the "tag" provided into a pointer to the device object.
  42. //
  43. extern KSPIN_LOCK ScsiGlobalAdapterListSpinLock;
  44. extern PDEVICE_OBJECT *ScsiGlobalAdapterList;
  45. extern ULONG ScsiGlobalAdapterListElements;
  46. //
  47. // Count of how many times we've locked down the PAGELOCK section.
  48. //
  49. extern LONG SpPAGELOCKLockCount;
  50. //
  51. // Whether the system can do 64 bit PA's or not.
  52. //
  53. extern ULONG Sp64BitPhysicalAddresses;
  54. //
  55. // Handle to pageable verifier code section. We manually lock the verify
  56. // code into memory iff we need it.
  57. //
  58. extern PVOID VerifierCodeSectionHandle;
  59. extern PVOID VerifierApiCodeSectionHandle;
  60. extern ULONG SpVrfyLevel;
  61. //
  62. // Constants and macros to enforce good use of Ex[Allocate|Free]PoolWithTag.
  63. // Remeber that all pool tags will display in the debugger in reverse order
  64. //
  65. #if USE_EXFREEPOOLWITHTAG_ONLY
  66. #define TAG(x) (x | 0x80000000)
  67. #else
  68. #define TAG(x) (x)
  69. #endif
  70. #define SCSIPORT_TAG_MINIPORT_PARAM TAG('aPcS') // Hold registry data
  71. #define SCSIPORT_TAG_ACCESS_RANGE TAG('APcS') // Access Ranges
  72. #define SCSIPORT_TAG_BUS_DATA TAG('bPcS') // Get Bus Data holder
  73. #define SCSIPORT_TAG_QUEUE_BITMAP TAG('BPcS') // QueueTag BitMap
  74. #define SCSIPORT_TAG_COMMON_BUFFER TAG('cPcS') // Fake Common Buffer
  75. #define SCSIPORT_TAG_RESET TAG('CPcS') // reset bus code
  76. #define SCSIPORT_TAG_PNP_ID TAG('dPcS') // Pnp id strings
  77. #define SCSIPORT_TAG_SRB_DATA TAG('DPcS') // SRB_DATA allocations
  78. #define SCSIPORT_TAG_PAE TAG('ePcS') // MDLs allocated for PAE requests
  79. #define SCSIPORT_TAG_EMERGENCY_SG_ENTRY TAG('EPcS') // Scatter gather lists
  80. #define SCSIPORT_TAG_VERIFIER TAG('fPcS') // Scsiport verifier entry
  81. #define SCSIPORT_TAG_GLOBAL TAG('GPcS') // Global memory
  82. #define SCSIPORT_TAG_DEV_EXT TAG('hPcS') // HwDevice Ext
  83. #define SCSIPORT_TAG_LUN_EXT TAG('HPcS') // HwLogicalUnit Extension
  84. #define SCSIPORT_TAG_SENSE_BUFFER TAG('iPcS') // Sense info
  85. #define SCSIPORT_TAG_INIT_CHAIN TAG('IPcS') // Init data chain
  86. #define SCSIPORT_TAG_LOCK_TRACKING TAG('lPcS') // remove lock tracking
  87. #define SCSIPORT_TAG_LARGE_SG_ENTRY TAG('LPcS') // Scatter gather lists
  88. #define SCSIPORT_TAG_MAPPING_LIST TAG('mPcS') // Address mapping lists
  89. #define SCSIPORT_TAG_MEDIUM_SG_ENTRY TAG('MPcS') // Scatter gather lists
  90. #define SCSIPORT_TAG_ENABLE TAG('pPcS') // device & adapter enable
  91. #define SCSIPORT_TAG_PORT_CONFIG TAG('PpcS') // Scsi PortConfig copies
  92. #define SCSIPORT_TAG_INQUIRY TAG('qPcS') // inquiry data
  93. #define SCSIPORT_TAG_REQUEST_SENSE TAG('QPcS') // request sense
  94. #define SCSIPORT_TAG_RESOURCE_LIST TAG('rPcS') // resource list copy
  95. #define SCSIPORT_TAG_REGISTRY TAG('RPcS') // registry allocations
  96. #define SCSIPORT_TAG_STOP_DEVICE TAG('sPcS') // stop device
  97. #define SCSIPORT_TAG_STOP_ADAPTER TAG('SPcS') // stop Adapter
  98. #define SCSIPORT_TAG_REROUTE TAG('tPcS') // Legacy request rerouting
  99. #define SCSIPORT_TAG_INTERFACE_MAPPING TAG('TPcS') // Interface Mapping
  100. #define SCSIPORT_TAG_DEVICE_RELATIONS TAG('uPcS') // device relation structs
  101. #define SCSIPORT_TAG_EVENT TAG('vPcS') // KEVENT
  102. #define SCSIPORT_TAG_DEVICE_MAP TAG('VPcS') // Device map allocations
  103. #define SCSIPORT_TAG_WMI_EVENT TAG('wPcS') // WMI Events
  104. #define SCSIPORT_TAG_WMI_REQUEST TAG('WPcS') // WMI Requests
  105. #define SCSIPORT_TAG_REPORT_LUNS TAG('xPcS') // Report Luns
  106. #define SCSIPORT_TAG_REPORT_TARGETS TAG('XPcS') // Report Targets
  107. #define SCSIPORT_TAG_TEMP_ID_BUFFER TAG('yPcS') // Temporary id buffer
  108. #define SCSIPORT_TAG_ID_BUFFER TAG('YPcS') // Id buffer
  109. #define SCSIPORT_TAG_SYMBOLIC_LINK TAG('zPcS') // Symbolic link strings
  110. #define SCSIPORT_TAG_DEVICE_NAME TAG('ZPcS') // Device name buffer
  111. #ifdef POOL_TAGGING
  112. #ifdef ExAllocatePool
  113. #undef ExAllocatePool
  114. #endif
  115. #define ExAllocatePool #assert(0)
  116. #endif
  117. #if defined(FORWARD_PROGRESS)
  118. #define SP_RESERVED_PAGES 4
  119. #endif
  120. //
  121. // The tag to use for the base remove lock. This lock is only released when
  122. // the device is finally ready to be destroyed.
  123. //
  124. #define SP_BASE_REMOVE_LOCK (UIntToPtr(0xabcdabcd))
  125. //
  126. // I/O System API routines which should not be called inside scsiport -
  127. // these generally have scsiport versions which perform sanity checks before
  128. // calling the real i/o routine in checked builds.
  129. //
  130. #if 0
  131. #ifdef IoCompleteRequest
  132. #ifndef KEEP_COMPLETE_REQUEST
  133. #undef IoCompleteRequest
  134. #endif
  135. #endif
  136. #endif
  137. // If Count is not already aligned, then
  138. // round Count up to an even multiple of "Pow2". "Pow2" must be a power of 2.
  139. //
  140. // DWORD
  141. // ROUND_UP_COUNT(
  142. // IN DWORD Count,
  143. // IN DWORD Pow2
  144. // );
  145. #define ROUND_UP_COUNT(Count,Pow2) \
  146. ( ((Count)+(Pow2)-1) & (~(((LONG)(Pow2))-1)) )
  147. // LPVOID
  148. // ROUND_UP_POINTER(
  149. // IN LPVOID Ptr,
  150. // IN DWORD Pow2
  151. // );
  152. // If Ptr is not already aligned, then round it up until it is.
  153. #define ROUND_UP_POINTER(Ptr,Pow2) \
  154. ( (PVOID) ( (((ULONG_PTR)(Ptr))+(Pow2)-1) & (~(((LONG)(Pow2))-1)) ) )
  155. //
  156. // Macros, constants and declarations for debug code and debug print
  157. // routines.
  158. //
  159. #define DEBUG_BUFFER_LENGTH 256
  160. #if SCSIDBG_ENABLED
  161. extern ULONG ScsiDebug;
  162. #ifdef DebugPrint
  163. #undef DebugPrint
  164. #endif
  165. #if SCSIDBG_ENABLED
  166. //
  167. // Forward definition of ScsiDebugPrintInt (internal and not exported)
  168. //
  169. VOID
  170. ScsiDebugPrintInt(
  171. ULONG DebugPrintLevel,
  172. PCCHAR DebugMessage,
  173. ...
  174. );
  175. #define DebugPrint(x) ScsiDebugPrintInt x
  176. #else
  177. #define DebugPrint(x)
  178. #endif
  179. #endif
  180. #define ASSERT_FDO(x) ASSERT(!(((PCOMMON_EXTENSION) (x)->DeviceExtension)->IsPdo))
  181. #define ASSERT_PDO(x) ASSERT((((PCOMMON_EXTENSION) (x)->DeviceExtension)->IsPdo))
  182. #define ASSERT_SRB_DATA(x) ASSERT(((PSRB_DATA)(x))->Type == SRB_DATA_TYPE)
  183. #if DBG
  184. #define SpStartNextPacket(DevObj, Cancelable) \
  185. { \
  186. PADAPTER_EXTENSION ext = (DevObj)->DeviceExtension; \
  187. ASSERT(!(TEST_FLAG(ext->Flags, PD_PENDING_DEVICE_REQUEST)));\
  188. IoStartNextPacket((DevObj), (Cancelable)); \
  189. }
  190. #else
  191. #define SpStartNextPacket IoStartNextPacket
  192. #endif
  193. //
  194. // Some type defines and random macros which don't seem to be in the
  195. // header files i've included (or didn't exist at all)
  196. //
  197. #define max(a,b) (((a) > (b)) ? (a) : (b))
  198. #define min(a,b) (((a) < (b)) ? (a) : (b))
  199. #if 0 // DBG
  200. #undef INLINE
  201. #define INLINE
  202. #else
  203. #define INLINE __inline
  204. #endif
  205. #define INTERLOCKED /* Should only be accessed using InterlockedXxx routines*/
  206. #define SET_FLAG(Flags, Bit) ((Flags) |= (Bit))
  207. #define CLEAR_FLAG(Flags, Bit) ((Flags) &= ~(Bit))
  208. #define TEST_FLAG(Flags, Bit) ((Flags) & (Bit))
  209. #define TEST(Value) ((BOOLEAN) ((Value) ? TRUE : FALSE));
  210. #define ARRAY_ELEMENTS_FOR_BITMAP(NumberOfBits, ArrayType) \
  211. ((NumberOfBits) / sizeof(ArrayType))
  212. //
  213. // Assorted constant definifitions
  214. //
  215. #define NUMBER_LOGICAL_UNIT_BINS 8
  216. #define SP_DEFAULT_PHYSICAL_BREAK_VALUE 17
  217. #define SP_SMALL_PHYSICAL_BREAK_VALUE 17
  218. #define SP_LARGE_PHYSICAL_BREAK_VALUE (SP_DEFAULT_PHYSICAL_BREAK_VALUE + 1)
  219. #define SCSIPORT_CONTROL_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\ScsiPort\\"
  220. #define DISK_SERVICE_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Disk"
  221. #define SCSIPORT_SPECIAL_TARGET_KEY L"SpecialTargetList"
  222. #define SCSIPORT_VERIFIER_KEY L"Verifier"
  223. //
  224. // WMI constants
  225. //
  226. #define SPMOFRESOURCENAME L"SCSIPORTWMI"
  227. #define SPMOFREGISTRYPATH L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\ScsiPort"
  228. //
  229. // NT uses a system time measured in 100 nanosecond intervals. define
  230. // conveninent constants for setting the timer.
  231. //
  232. #define MICROSECONDS 10 // 10 nanoseconds
  233. #define MILLISECONDS (MICROSECONDS * 1000)
  234. #define SECONDS (MILLISECONDS * 1000)
  235. #define MINUTES (SECONDS * 60)
  236. #define TIMEOUT(x) ((x) * -1)
  237. //
  238. // Possible values for the IsRemoved flag
  239. //
  240. #define NO_REMOVE 0
  241. #define REMOVE_PENDING 1
  242. #define REMOVE_COMPLETE 2
  243. #define NUMBER_HARDWARE_STRINGS 6
  244. #define SRB_DATA_TYPE 'wp'
  245. #define SRB_LIST_DEPTH 20
  246. #define NUMBER_BYPASS_SRB_DATA_BLOCKS 4
  247. #define WMI_MINIPORT_EVENT_ITEM_MAX_SIZE 128
  248. //
  249. // Define the mimimum and maximum number of srb extensions which will be allocated.
  250. //
  251. #define MINIMUM_SRB_EXTENSIONS 16
  252. #define MAXIMUM_SRB_EXTENSIONS 255
  253. //
  254. // Size of the buffer used for registry operations.
  255. //
  256. #define SP_REG_BUFFER_SIZE 512
  257. //
  258. // Number of times to retry when a BUSY status is returned.
  259. //
  260. #define BUSY_RETRY_COUNT 20
  261. //
  262. // Number of times to retry an INQUIRY request.
  263. //
  264. #define INQUIRY_RETRY_COUNT 2
  265. //
  266. // Number of irp stack locations to allocate for an INQUIRY command.
  267. //
  268. #define INQUIRY_STACK_LOCATIONS 1
  269. //
  270. // Default Srb Timeout value
  271. //
  272. #define SRB_DEFAULT_TIMEOUT 10
  273. //
  274. // Bitmask used for aligning values.
  275. //
  276. #define LONG_ALIGN (sizeof(LONG) - 1)
  277. //
  278. // Size of the ADAPTER_EXTENSION
  279. //
  280. #define ADAPTER_EXTENSION_SIZE sizeof(ADAPTER_EXTENSION)
  281. //
  282. // Size of the buffer used for inquiry operations. This is one more than the
  283. // max bytes which can be requested from an inquiry operation so that we can
  284. // zero out the buffer and be sure that the last string is null terminated.
  285. //
  286. #define SP_INQUIRY_BUFFER_SIZE (VPD_MAX_BUFFER_SIZE + 1)
  287. //
  288. // Assorted macros.
  289. //
  290. #define NEED_REQUEST_SENSE(Srb) (Srb->ScsiStatus == SCSISTAT_CHECK_CONDITION \
  291. && !(Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) && \
  292. Srb->SenseInfoBuffer && Srb->SenseInfoBufferLength )
  293. #define GET_FDO_EXTENSION(HwExt) ((CONTAINING_RECORD(HwExt, HW_DEVICE_EXTENSION, HwDeviceExtension))->FdoExtension)
  294. #define ADDRESS_TO_HASH(PathId, TargetId, Lun) (((TargetId) + (Lun)) % NUMBER_LOGICAL_UNIT_BINS)
  295. #define IS_CLEANUP_REQUEST(irpStack) \
  296. (((irpStack)->MajorFunction == IRP_MJ_CLOSE) || \
  297. ((irpStack)->MajorFunction == IRP_MJ_CLEANUP) || \
  298. ((irpStack)->MajorFunction == IRP_MJ_SHUTDOWN) || \
  299. (((irpStack)->MajorFunction == IRP_MJ_SCSI) && \
  300. (((irpStack)->Parameters.Scsi.Srb->Function == SRB_FUNCTION_RELEASE_DEVICE) || \
  301. ((irpStack)->Parameters.Scsi.Srb->Function == SRB_FUNCTION_FLUSH_QUEUE) || \
  302. (TEST_FLAG((irpStack)->Parameters.Scsi.Srb->SrbFlags, SRB_FLAGS_BYPASS_FROZEN_QUEUE | \
  303. SRB_FLAGS_BYPASS_LOCKED_QUEUE)))))
  304. #define IS_INQUIRY(Srb) \
  305. ((Srb)->Cdb[0] == SCSIOP_INQUIRY)
  306. #define IS_REQUEST_SENSE(Srb) \
  307. ((Srb)->Cdb[0] == SCSIOP_REQUEST_SENSE)
  308. #define IS_READ_CAPACITY(Srb) \
  309. ((Srb)->Cdb[0] == SCSIOP_READ_CAPACITY)
  310. #define IS_READ(Srb) \
  311. ((Srb)->Cdb[0] == SCSIOP_READ)
  312. #define IS_WRITE(Srb) \
  313. ((Srb)->Cdb[0] == SCSIOP_WRITE)
  314. #define IS_COPY(Srb) \
  315. ((Srb)->Cdb[0] == SCSIOP_COPY)
  316. #define IS_COMPARE(Srb) \
  317. ((Srb)->Cdb[0] == SCSIOP_COMPARE)
  318. #define IS_COPY_COMPARE(Srb) \
  319. ((Srb)->Cdb[0] == SCSIOP_COPY_COMPARE)
  320. #define IS_MAPPED_SRB(Srb) \
  321. (((Srb)->Function == SRB_FUNCTION_IO_CONTROL) || \
  322. (((Srb)->Function == SRB_FUNCTION_EXECUTE_SCSI) && \
  323. ((IS_INQUIRY((Srb))) || \
  324. (IS_REQUEST_SENSE((Srb))) || \
  325. (IS_READ_CAPACITY((Srb))))))
  326. #define IS_ILLEGAL_COMMAND(Srb) \
  327. (IS_COPY((Srb)) || \
  328. IS_COMPARE((Srb)) || \
  329. IS_COPY_COMPARE((Srb)))
  330. #define LU_OPERATING_IN_DEGRADED_STATE(luFlags) \
  331. ((luFlags) & LU_PERF_MAXQDEPTH_REDUCED)
  332. //
  333. // SpIsQueuePausedForSrb(lu, srb) -
  334. // determines if the queue has been paused for this particular type of
  335. // srb. This can be used with SpSrbIsBypassRequest to determine whether the
  336. // srb needs to be handled specially.
  337. //
  338. #define SpIsQueuePausedForSrb(luFlags, srbFlags) \
  339. ((BOOLEAN) ((((luFlags) & LU_QUEUE_FROZEN) && !(srbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE)) || \
  340. (((luFlags) & LU_QUEUE_PAUSED) && !(srbFlags & SRB_FLAGS_BYPASS_LOCKED_QUEUE))))
  341. #define SpIsQueuePaused(lu) ((lu)->LuFlags & (LU_QUEUE_FROZEN | \
  342. LU_QUEUE_LOCKED))
  343. #define SpSrbRequiresPower(srb) \
  344. ((BOOLEAN) ((srb->Function == SRB_FUNCTION_EXECUTE_SCSI) || \
  345. (srb->Function == SRB_FUNCTION_IO_CONTROL) || \
  346. (srb->Function == SRB_FUNCTION_SHUTDOWN) || \
  347. (srb->Function == SRB_FUNCTION_FLUSH) || \
  348. (srb->Function == SRB_FUNCTION_ABORT_COMMAND) || \
  349. (srb->Function == SRB_FUNCTION_RESET_BUS) || \
  350. (srb->Function == SRB_FUNCTION_RESET_DEVICE) || \
  351. (srb->Function == SRB_FUNCTION_TERMINATE_IO) || \
  352. (srb->Function == SRB_FUNCTION_REMOVE_DEVICE) || \
  353. (srb->Function == SRB_FUNCTION_WMI)))
  354. //
  355. // Forward declarations of data structures
  356. //
  357. typedef struct _SRB_DATA SRB_DATA, *PSRB_DATA;
  358. typedef struct _REMOVE_TRACKING_BLOCK
  359. REMOVE_TRACKING_BLOCK,
  360. *PREMOVE_TRACKING_BLOCK;
  361. typedef struct _LOGICAL_UNIT_EXTENSION LOGICAL_UNIT_EXTENSION, *PLOGICAL_UNIT_EXTENSION;
  362. typedef struct _ADAPTER_EXTENSION ADAPTER_EXTENSION, *PADAPTER_EXTENSION;
  363. typedef struct _SP_INIT_CHAIN_ENTRY SP_INIT_CHAIN_ENTRY, *PSP_INIT_CHAIN_ENTRY;
  364. typedef struct _HW_DEVICE_EXTENSION HW_DEVICE_EXTENSION, *PHW_DEVICE_EXTENSION;
  365. //
  366. // Macros for using the DMA functions.
  367. //
  368. #define AllocateCommonBuffer(DmaAdapter, Length, \
  369. LogicalAddress, CacheEnabled) \
  370. ((DmaAdapter)->DmaOperations->AllocateCommonBuffer)( \
  371. (DmaAdapter), \
  372. (Length), \
  373. (LogicalAddress), \
  374. (CacheEnabled))
  375. #define FreeCommonBuffer(DmaAdapter, Length, LogicalAddress, \
  376. VirtualAddress, CacheEnabled) \
  377. ((DmaAdapter)->DmaOperations->FreeCommonBuffer)( \
  378. (DmaAdapter), \
  379. (Length), \
  380. (LogicalAddress), \
  381. (VirtualAddress), \
  382. (CacheEnabled))
  383. #define GetScatterGatherList(DmaAdapter, DeviceObject, Mdl, CurrentVa, \
  384. Length, ExecutionRoutine, Context, \
  385. WriteToDevice) \
  386. ((DmaAdapter)->DmaOperations->GetScatterGatherList)( \
  387. (DmaAdapter), \
  388. (DeviceObject), \
  389. (Mdl), \
  390. (CurrentVa), \
  391. (Length), \
  392. (ExecutionRoutine), \
  393. (Context), \
  394. (WriteToDevice))
  395. #define PutScatterGatherList(DmaAdapter, ScatterGather, WriteToDevice) \
  396. ((DmaAdapter)->DmaOperations->PutScatterGatherList)( \
  397. (DmaAdapter), \
  398. (ScatterGather), \
  399. (WriteToDevice))
  400. #define AllocateAdapterChannel(DmaAdapter, DeviceObject, \
  401. NumberOfMapRegisters, ExecutionRoutine, \
  402. Context) \
  403. ((DmaAdapter)->DmaOperations->AllocateAdapterChannel)( \
  404. (DmaAdapter), \
  405. (DeviceObject), \
  406. (NumberOfMapRegisters), \
  407. (ExecutionRoutine), \
  408. (Context))
  409. #define FlushAdapterBuffers(DmaAdapter, Mdl, MapRegisterBase, CurrentVa, \
  410. Length, WriteToDevice) \
  411. ((DmaAdapter)->DmaOperations->FlushAdapterBuffers)( \
  412. (DmaAdapter), \
  413. (Mdl), \
  414. (MapRegisterBase), \
  415. (CurrentVa), \
  416. (Length), \
  417. (WriteToDevice))
  418. #define MapTransfer(DmaAdapter, Mdl, MapRegisterBase, CurrentVa, Length, \
  419. WriteToDevice) \
  420. ((DmaAdapter)->DmaOperations->MapTransfer)( \
  421. (DmaAdapter), \
  422. (Mdl), \
  423. (MapRegisterBase), \
  424. (CurrentVa), \
  425. (Length), \
  426. (WriteToDevice))
  427. #define FreeAdapterChannel(DmaAdapter) \
  428. ((DmaAdapter)->DmaOperations->FreeAdapterChannel)((DmaAdapter))
  429. #define FreeMapRegisters(DmaAdapter, MapRegisterBase, NumberOfMapRegisters) \
  430. ((DmaAdapter)->DmaOperations->FreeMapRegisters)( \
  431. (DmaAdapter), \
  432. (MapRegisterBase), \
  433. (NumberOfMapRegisters))
  434. #define PutDmaAdapter(DmaAdapter) \
  435. ((DmaAdapter)->DmaOperations->PutDmaAdapter)((DmaAdapter))
  436. #define BuildScatterGatherList(DmaAdapter, DevObj, Mdl, DataBuffer, \
  437. DataTransferLength, ExecutionRoutine, \
  438. Context, Write, Buffer, BufSize) \
  439. ((DmaAdapter)->DmaOperations->BuildScatterGatherList)( \
  440. (DmaAdapter), \
  441. (DevObj), \
  442. (Mdl), \
  443. (DataBuffer), \
  444. (DataTransferLength), \
  445. (ExecutionRoutine), \
  446. (Context), \
  447. (Write), \
  448. (Buffer), \
  449. (BufSize))
  450. #define CalculateScatterGatherList(DmaAdapter, Mdl, CurrentVa, Length, \
  451. SGListSize, NumberOfMapRegs) \
  452. ((DmaAdapter)->DmaOperations->CalculateScatterGatherList)( \
  453. (DmaAdapter), \
  454. (Mdl), \
  455. (CurrentVa), \
  456. (Length), \
  457. (SGListSize), \
  458. (NumberOfMapRegs))
  459. //
  460. // Type Definitions
  461. //
  462. //
  463. // Structure used for tracking remove lock allocations in checked builds
  464. //
  465. struct _REMOVE_TRACKING_BLOCK {
  466. PREMOVE_TRACKING_BLOCK NextBlock;
  467. PVOID Tag;
  468. LARGE_INTEGER TimeLocked;
  469. PCSTR File;
  470. ULONG Line;
  471. };
  472. #if DBG
  473. #define SpAcquireRemoveLock(devobj, tag) \
  474. SpAcquireRemoveLockEx(devobj, tag, __file__, __LINE__)
  475. #endif
  476. typedef struct _RESET_COMPLETION_CONTEXT {
  477. PIRP OriginalIrp;
  478. PDEVICE_OBJECT SafeLogicalUnit;
  479. PDEVICE_OBJECT AdapterDeviceObject;
  480. SCSI_REQUEST_BLOCK Srb;
  481. } RESET_COMPLETION_CONTEXT, *PRESET_COMPLETION_CONTEXT;
  482. //
  483. // Define a pointer to the synchonize execution routine.
  484. //
  485. typedef
  486. BOOLEAN
  487. (*PSYNCHRONIZE_ROUTINE) (
  488. IN PKINTERRUPT Interrupt,
  489. IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine,
  490. IN PVOID SynchronizeContext
  491. );
  492. typedef
  493. VOID
  494. (*PSP_ENABLE_DISABLE_COMPLETION_ROUTINE) (
  495. IN PDEVICE_OBJECT DeviceObject,
  496. IN NTSTATUS Status,
  497. IN PVOID Context
  498. );
  499. typedef
  500. VOID
  501. (*PSP_POWER_COMPLETION_ROUTINE) (
  502. IN PDEVICE_OBJECT DeviceObject,
  503. IN PVOID Context
  504. );
  505. //
  506. // device type table to build id's from
  507. //
  508. typedef const struct _SCSIPORT_DEVICE_TYPE {
  509. const PCSTR DeviceTypeString;
  510. const PCSTR GenericTypeString;
  511. const PCWSTR DeviceMapString;
  512. const BOOLEAN IsStorage;
  513. } SCSIPORT_DEVICE_TYPE, *PSCSIPORT_DEVICE_TYPE;
  514. //
  515. // SCSI Get Configuration Information
  516. //
  517. // LUN Information
  518. //
  519. typedef struct _LOGICAL_UNIT_INFO {
  520. UCHAR PathId;
  521. UCHAR TargetId;
  522. UCHAR Lun;
  523. BOOLEAN DeviceClaimed;
  524. struct _LOGICAL_UNIT_INFO *NextLunInfo;
  525. UCHAR InquiryData[INQUIRYDATABUFFERSIZE];
  526. } LOGICAL_UNIT_INFO, *PLOGICAL_UNIT_INFO;
  527. typedef struct _SCSI_BUS_SCAN_DATA {
  528. USHORT Length;
  529. UCHAR InitiatorBusId;
  530. UCHAR NumberOfLogicalUnits;
  531. PLOGICAL_UNIT_INFO LunInfoList;
  532. } SCSI_BUS_SCAN_DATA, *PSCSI_BUS_SCAN_DATA;
  533. typedef struct _SCSI_CONFIGURATION_INFO {
  534. UCHAR NumberOfBuses;
  535. PSCSI_BUS_SCAN_DATA BusScanData[1];
  536. } SCSI_CONFIGURATION_INFO, *PSCSI_CONFIGURATION_INFO;
  537. //
  538. // Adapter object transfer information.
  539. //
  540. typedef struct _ADAPTER_TRANSFER {
  541. PSRB_DATA SrbData;
  542. ULONG SrbFlags;
  543. PVOID LogicalAddress;
  544. ULONG Length;
  545. }ADAPTER_TRANSFER, *PADAPTER_TRANSFER;
  546. //
  547. // NOTE: When the hal is performing double buffering (e.g. a 32-bit HBA on a
  548. // 64-bit machine) the HalContext (below) is necessary. Otherwise, this is
  549. // wasted space. It would be nice to detect this and only allocate the
  550. // extra memory when necessary.
  551. //
  552. typedef struct _SRB_SCATTER_GATHER_LIST {
  553. ULONG NumberOfElements;
  554. ULONG_PTR Reserved;
  555. SCATTER_GATHER_ELEMENT Elements[SP_SMALL_PHYSICAL_BREAK_VALUE];
  556. UCHAR HalContext[sizeof (INTERNAL_WAIT_CONTEXT_BLOCK)];
  557. } SRB_SCATTER_GATHER_LIST, *PSRB_SCATTER_GATHER_LIST;
  558. typedef SCATTER_GATHER_ELEMENT SRB_SCATTER_GATHER, *PSRB_SCATTER_GATHER;
  559. //
  560. // Port driver error logging
  561. //
  562. typedef struct _ERROR_LOG_ENTRY {
  563. UCHAR MajorFunctionCode;
  564. UCHAR PathId;
  565. UCHAR TargetId;
  566. UCHAR Lun;
  567. ULONG ErrorCode;
  568. ULONG UniqueId;
  569. ULONG ErrorLogRetryCount;
  570. ULONG SequenceNumber;
  571. } ERROR_LOG_ENTRY, *PERROR_LOG_ENTRY;
  572. typedef struct _SP_LUN_IO_LOG {
  573. UCHAR SrbStatus; // +0
  574. UCHAR ScsiStatus; // +1
  575. UCHAR CdbLength; // +2
  576. UCHAR Tag; // +3
  577. UCHAR Cdb[16]; // +4
  578. UCHAR SenseData[18]; // +20
  579. UCHAR SenseDataLength; // +38
  580. union { // +40
  581. ULONG InternalStatus;
  582. ULONG QueueSortKey;
  583. };
  584. ULONG TickCount; // +44
  585. } SP_LUN_IO_LOG, *PSP_LUN_IO_LOG;
  586. //
  587. // Context item for asynchronous enumerators.
  588. //
  589. typedef struct _SP_ENUMERATION_REQUEST SP_ENUMERATION_REQUEST, *PSP_ENUMERATION_REQUEST;
  590. typedef
  591. VOID
  592. (*PSP_ENUMERATION_COMPLETION_ROUTINE) (
  593. IN PADAPTER_EXTENSION Adapter,
  594. IN PSP_ENUMERATION_REQUEST Request,
  595. IN NTSTATUS Status
  596. );
  597. struct _SP_ENUMERATION_REQUEST {
  598. //
  599. // A pointer to the next enumeration request on the list.
  600. //
  601. PSP_ENUMERATION_REQUEST NextRequest;
  602. //
  603. // The completion routine to be run. This routine will be run regardless
  604. // of whether the enumeration actually succeeds. The
  605. // EnumerationDeviceMutex and the EnumerationWorklistMutex will both be
  606. // held when this is called. The completion routine should free the Request
  607. // structure if necessary.
  608. //
  609. PSP_ENUMERATION_COMPLETION_ROUTINE CompletionRoutine;
  610. //
  611. // If this filed contains a pointer to an IO_STATUS_BLOCK then the
  612. // completion routine should write it's status value out. This is so a
  613. // synchronous waiter can return something other than STATUS_PENDING to the
  614. // caller. If this field is NULL then there is no consumer for the status
  615. // value.
  616. //
  617. PNTSTATUS OPTIONAL CompletionStatus;
  618. //
  619. // Arbitrary context value for the completion routine to use. In most cases
  620. // this will be an IRP or an event.
  621. //
  622. PVOID Context;
  623. //
  624. // Indicates whether this request is being handled synchronously.
  625. //
  626. BOOLEAN Synchronous;
  627. };
  628. //
  629. // SCSI request extension for port driver.
  630. //
  631. typedef
  632. VOID
  633. (FASTCALL *PSRB_DATA_FREE_ROUTINE) (
  634. IN PADAPTER_EXTENSION Adapter,
  635. IN PSRB_DATA SrbData
  636. );
  637. struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) _SRB_DATA {
  638. //
  639. // Single list entry. The lookaside list will be maintained in this
  640. // memory.
  641. //
  642. SLIST_ENTRY Reserved;
  643. //
  644. // Header for debugging purposes.
  645. //
  646. CSHORT Type;
  647. USHORT Size;
  648. //
  649. // The free routine for this srb data block.
  650. //
  651. PSRB_DATA_FREE_ROUTINE FreeRoutine;
  652. //
  653. // The list of requests for a particular logical unit.
  654. //
  655. LIST_ENTRY RequestList;
  656. //
  657. // The logical unit this request is intended for.
  658. //
  659. PLOGICAL_UNIT_EXTENSION LogicalUnit;
  660. //
  661. // The irp for the CurrentSrb.
  662. //
  663. PIRP CurrentIrp;
  664. //
  665. // The srb this is block is tracking.
  666. //
  667. PSCSI_REQUEST_BLOCK CurrentSrb;
  668. //
  669. // The chain of requests which have been completed by the miniport and are
  670. // waiting for the CompletionDpc to be run.
  671. //
  672. struct _SRB_DATA *CompletedRequests;
  673. ULONG ErrorLogRetryCount;
  674. ULONG SequenceNumber;
  675. PSCATTER_GATHER_LIST MapRegisterBase;
  676. ULONG NumberOfMapRegisters;
  677. //
  678. // The offset between the data buffer for this request and the data
  679. // buffer described by the MDL in the irp.
  680. //
  681. ULONG_PTR DataOffset;
  682. PVOID RequestSenseSave;
  683. //
  684. // These data values will be restored to the SRB when it is retried within
  685. // the port driver.
  686. //
  687. ULONG OriginalDataTransferLength;
  688. //
  689. // SRB Data flags.
  690. //
  691. ULONG Flags;
  692. //
  693. // Pointer to the adapter this block was allocated from. This is used
  694. // when freeing srbdata blocks from the lookaside list back to pool.
  695. //
  696. PADAPTER_EXTENSION Adapter;
  697. //
  698. // The queue tag which was initially allocated for this srb_data block.
  699. // This tag will be used for any tagged srb's which are associated with
  700. // this block.
  701. //
  702. ULONG QueueTag;
  703. //
  704. // Internal status value - only returned if srb->SrbStatus is set to
  705. // SRBP_STATUS_INTERNAL_ERROR.
  706. //
  707. NTSTATUS InternalStatus;
  708. //
  709. // The tick count when this request was last touched.
  710. //
  711. ULONG TickCount;
  712. //
  713. // The MDL of the remapped buffer (per IoMapTransfer or GET_SCATTER_GATHER)
  714. //
  715. PMDL RemappedMdl;
  716. //
  717. // The original data buffer pointer for this request - this will be
  718. // restored when the request is completed.
  719. //
  720. PVOID OriginalDataBuffer;
  721. //
  722. // Pointer to the scatter gather list for this request
  723. //
  724. PSRB_SCATTER_GATHER ScatterGatherList;
  725. //
  726. // The original length of the sense data buffer supplied by the above
  727. // driver.
  728. //
  729. UCHAR RequestSenseLengthSave;
  730. //
  731. // Pointer to the orignal SRB DataBuffer. We use this to store
  732. // the original when we replace it with our buffer to unmapped
  733. // memory in the case where the MapBuffer is FALSE.
  734. //
  735. PVOID UnmappedDataBuffer;
  736. //
  737. // The "small" scatter gather list for this request. Small
  738. // by the constant SP_SMALL_PHYSICAL_BREAK_VALUE - small lists contain
  739. // this many entries or less.
  740. //
  741. SRB_SCATTER_GATHER_LIST SmallScatterGatherList;
  742. };
  743. typedef struct _LOGICAL_UNIT_BIN {
  744. KSPIN_LOCK Lock;
  745. PLOGICAL_UNIT_EXTENSION List;
  746. } LOGICAL_UNIT_BIN, *PLOGICAL_UNIT_BIN;
  747. //
  748. // WMI request item, queued on a miniport request.
  749. //
  750. typedef struct _WMI_MINIPORT_REQUEST_ITEM {
  751. //
  752. // WnodeEventItem MUST be the first field in WMI_MINIPORT_REQUEST_ITEM, in
  753. // order to accommodate a copy optimization in ScsiPortCompletionDpc().
  754. //
  755. UCHAR WnodeEventItem[WMI_MINIPORT_EVENT_ITEM_MAX_SIZE];
  756. UCHAR TypeOfRequest; // [Event/Reregister]
  757. UCHAR PathId; // [0xFF for adapter]
  758. UCHAR TargetId;
  759. UCHAR Lun;
  760. struct _WMI_MINIPORT_REQUEST_ITEM * NextRequest;
  761. } WMI_MINIPORT_REQUEST_ITEM, *PWMI_MINIPORT_REQUEST_ITEM;
  762. //
  763. // WMI parameters.
  764. //
  765. typedef struct _WMI_PARAMETERS {
  766. ULONG_PTR ProviderId; // ProviderId parameter from IRP
  767. PVOID DataPath; // DataPath parameter from IRP
  768. ULONG BufferSize; // BufferSize parameter from IRP
  769. PVOID Buffer; // Buffer parameter from IRP
  770. } WMI_PARAMETERS, *PWMI_PARAMETERS;
  771. //
  772. // SpInsertFreeWmiMiniPortItem context structure.
  773. //
  774. typedef struct _WMI_INSERT_CONTEXT {
  775. PDEVICE_OBJECT DeviceObject; // [FDO or PDO]
  776. PWMI_MINIPORT_REQUEST_ITEM ItemsToInsert;
  777. } WMI_INSERT_CONTEXT, *PWMI_INSERT_CONTEXT;
  778. //
  779. // SpRemoveFreeWmiMiniPortItem context structure.
  780. //
  781. typedef struct _WMI_REMOVE_CONTEXT {
  782. PDEVICE_OBJECT DeviceObject; // [FDO or PDO]
  783. USHORT NumberToRemove;
  784. } WMI_REMOVE_CONTEXT, *PWMI_REMOVE_CONTEXT;
  785. //
  786. // Define data storage for access at interrupt Irql.
  787. //
  788. typedef struct _INTERRUPT_DATA {
  789. //
  790. // SCSI port interrupt flags
  791. //
  792. ULONG InterruptFlags;
  793. //
  794. // List head for singlely linked list of complete IRPs.
  795. //
  796. PSRB_DATA CompletedRequests;
  797. //
  798. // Adapter object transfer parameters.
  799. //
  800. ADAPTER_TRANSFER MapTransferParameters;
  801. //
  802. // Error log information.
  803. //
  804. ERROR_LOG_ENTRY LogEntry;
  805. //
  806. // Logical unit to start next.
  807. //
  808. PLOGICAL_UNIT_EXTENSION ReadyLogicalUnit;
  809. //
  810. // List of completed abort reqeusts.
  811. //
  812. PLOGICAL_UNIT_EXTENSION CompletedAbort;
  813. //
  814. // Miniport timer request routine.
  815. //
  816. PHW_INTERRUPT HwTimerRequest;
  817. //
  818. // Mini port timer request time in micro seconds.
  819. //
  820. ULONG MiniportTimerValue;
  821. //
  822. // Queued WMI request items.
  823. //
  824. PWMI_MINIPORT_REQUEST_ITEM WmiMiniPortRequests;
  825. //
  826. // A couple of counters used to keep track of when the last interrupt
  827. // occurred on this device.
  828. //
  829. ULONG TickCountAtLastInterruptAck;
  830. ULONG TickCountAtLastInterruptNak;
  831. } INTERRUPT_DATA, *PINTERRUPT_DATA;
  832. #define NON_STANDARD_VPD_SUPPORTS_PAGE80 0x00000001
  833. #define NON_STANDARD_VPD_SUPPORTS_PAGE83 0x00000002
  834. typedef struct {
  835. ULONG SparseLun;
  836. ULONG OneLun;
  837. ULONG LargeLuns;
  838. ULONG SetLunInCdb;
  839. ULONG NonStandardVPD;
  840. ULONG BinarySN;
  841. } SP_SPECIAL_CONTROLLER_FLAGS, *PSP_SPECIAL_CONTROLLER_FLAGS;
  842. typedef struct _CONFIGURATION_CONTEXT {
  843. BOOLEAN DisableTaggedQueueing;
  844. BOOLEAN DisableMultipleLu;
  845. ULONG AdapterNumber;
  846. ULONG BusNumber;
  847. PVOID Parameter;
  848. PACCESS_RANGE AccessRanges;
  849. UNICODE_STRING RegistryPath;
  850. PORT_CONFIGURATION_INFORMATION PortConfig;
  851. }CONFIGURATION_CONTEXT, *PCONFIGURATION_CONTEXT;
  852. typedef struct _DEVICE_MAP_HANDLES {
  853. HANDLE BusKey;
  854. HANDLE InitiatorKey;
  855. } DEVICE_MAP_HANDLES, *PDEVICE_MAP_HANDLES;
  856. typedef struct _COMMON_EXTENSION {
  857. //
  858. // Back pointer to the device object
  859. //
  860. PDEVICE_OBJECT DeviceObject;
  861. struct {
  862. //
  863. // True if this device object is a physical device object
  864. //
  865. BOOLEAN IsPdo : 1;
  866. //
  867. // True if this device object has processed it's first start and
  868. // has been initialized.
  869. //
  870. BOOLEAN IsInitialized : 1;
  871. //
  872. // Has WMI been initialized for this device object?
  873. //
  874. BOOLEAN WmiInitialized : 1;
  875. //
  876. // Has the miniport associated with this FDO or PDO indicated WMI
  877. // support?
  878. //
  879. BOOLEAN WmiMiniPortSupport : 1;
  880. //
  881. // Has the miniport been initialized for WMI.
  882. //
  883. BOOLEAN WmiMiniPortInitialized : 1;
  884. };
  885. //
  886. // Current plug and play state or 0xff if no state operations have been
  887. // sent yet.
  888. //
  889. UCHAR CurrentPnpState;
  890. //
  891. // Previous plug and play state or 0xff if there is no requirement that we
  892. // be able to roll back in the current state (current state is not a query)
  893. //
  894. UCHAR PreviousPnpState;
  895. //
  896. // Interlocked counter indicating that the device has been removed.
  897. //
  898. ULONG IsRemoved;
  899. //
  900. // Pointer to the device object this is on top of
  901. //
  902. PDEVICE_OBJECT LowerDeviceObject;
  903. //
  904. // Srb flags to OR into all SRBs coming through this device object.
  905. //
  906. ULONG SrbFlags;
  907. //
  908. // Pointer to the dispatch table for this object
  909. //
  910. PDRIVER_DISPATCH *MajorFunction;
  911. //
  912. // Current and desired power state for this device and the system.
  913. //
  914. SYSTEM_POWER_STATE CurrentSystemState;
  915. DEVICE_POWER_STATE CurrentDeviceState;
  916. DEVICE_POWER_STATE DesiredDeviceState;
  917. //
  918. // Idle timer for this device
  919. //
  920. PULONG IdleTimer;
  921. //
  922. // Pointer to the SCSIPORT-provided WMIREGINFO structures registered on
  923. // behalf of the miniport for this device object. Size is the size of the
  924. // entire WMIREGINFO buffer in bytes.
  925. //
  926. PWMIREGINFO WmiScsiPortRegInfoBuf;
  927. ULONG WmiScsiPortRegInfoBufSize;
  928. //
  929. // INTERLOCKED counter of the number of consumers of this device object.
  930. // When this count goes to zero the RemoveEvent will be set.
  931. //
  932. //
  933. // This variable is only manipulated by SpAcquireRemoveLock and
  934. // SpReleaseRemoveLock.
  935. //
  936. LONG RemoveLock;
  937. //
  938. // This event will be signalled when it is safe to remove the device object
  939. //
  940. KEVENT RemoveEvent;
  941. //
  942. // The spinlock and the list are only used in checked builds to track who
  943. // has acquired the remove lock. Free systems will leave these initialized
  944. // to 0xff (they are still in the structure to make debugging easier)
  945. //
  946. KSPIN_LOCK RemoveTrackingSpinlock;
  947. PVOID RemoveTrackingList;
  948. LONG RemoveTrackingUntrackedCount;
  949. NPAGED_LOOKASIDE_LIST RemoveTrackingLookasideList;
  950. BOOLEAN RemoveTrackingLookasideListInitialized;
  951. //
  952. // Count of different services this device is being used for (ala
  953. // IRP_MN_DEVICE_USAGE_NOTIFICATION)
  954. //
  955. ULONG PagingPathCount;
  956. ULONG HibernatePathCount;
  957. ULONG DumpPathCount;
  958. } COMMON_EXTENSION, *PCOMMON_EXTENSION;
  959. typedef struct _VERIFIER_EXTENSION {
  960. //
  961. // Miniport routines we verify.
  962. //
  963. PHW_FIND_ADAPTER RealHwFindAdapter;
  964. PHW_INITIALIZE RealHwInitialize;
  965. PHW_STARTIO RealHwStartIo;
  966. PHW_INTERRUPT RealHwInterrupt;
  967. PHW_RESET_BUS RealHwResetBus;
  968. PHW_DMA_STARTED RealHwDmaStarted;
  969. PHW_INTERRUPT RealHwRequestInterrupt;
  970. PHW_INTERRUPT RealHwTimerRequest;
  971. PHW_ADAPTER_CONTROL RealHwAdapterControl;
  972. //
  973. // Indicates the number of common buffer blocks that have been allocated.
  974. //
  975. ULONG CommonBufferBlocks;
  976. //
  977. // Points to an array that holds the VAs of all the common blocks.
  978. //
  979. PVOID* CommonBufferVAs;
  980. //
  981. // Points to an array that holds the PAs of all the common blocks.
  982. //
  983. PHYSICAL_ADDRESS* CommonBufferPAs;
  984. //
  985. // Indicates the size of the non-cached extension.
  986. //
  987. ULONG NonCachedBufferSize;
  988. //
  989. // Controls how aggressively we verify.
  990. //
  991. ULONG VrfyLevel;
  992. //
  993. // Pointer to an invalid page of memory. Used to catch miniports
  994. // that touch memory when they're not supposed to.
  995. //
  996. PVOID InvalidPage;
  997. //
  998. // Indicates whether the common buffer blocks were allocated using
  999. // DMA common buffer allocation routine.
  1000. //
  1001. BOOLEAN IsCommonBuffer;
  1002. } VERIFIER_EXTENSION, *PVERIFIER_EXTENSION;
  1003. struct _ADAPTER_EXTENSION {
  1004. union {
  1005. PDEVICE_OBJECT DeviceObject;
  1006. COMMON_EXTENSION CommonExtension;
  1007. };
  1008. //
  1009. // Pointer to the PDO we attached to - necessary for PnP routines
  1010. //
  1011. PDEVICE_OBJECT LowerPdo;
  1012. #if TEST_LISTS
  1013. //
  1014. // Some simple performance counters to determine how often we use the
  1015. // small vs. medium vs. large scatter gather lists.
  1016. //
  1017. ULONGLONG ScatterGatherAllocationCount;
  1018. //
  1019. // Counters used to calculate the average size of a small medium and
  1020. // large allocation. There are two values for each counter - a total
  1021. // count and an overflow count. The total count will be right-shifted one
  1022. // bit if it overflows on an increment. When this happens the overflow
  1023. // count will also be incremented. This count is used to adjust the
  1024. // allocation count when determining averages.
  1025. //
  1026. ULONGLONG SmallAllocationSize;
  1027. ULONGLONG MediumAllocationSize;
  1028. ULONGLONG LargeAllocationSize;
  1029. ULONG SmallAllocationCount;
  1030. ULONG LargeAllocationCount;
  1031. //
  1032. // Counters to determine how often we can service a request off the
  1033. // srb data list, how often we need to queue a request and how often
  1034. // we can resurrect a free'd srb data to service something off the queue.
  1035. //
  1036. INTERLOCKED ULONGLONG SrbDataAllocationCount;
  1037. INTERLOCKED ULONGLONG SrbDataQueueInsertionCount;
  1038. INTERLOCKED ULONGLONG SrbDataEmergencyFreeCount;
  1039. INTERLOCKED ULONGLONG SrbDataServicedFromTickHandlerCount;
  1040. INTERLOCKED ULONGLONG SrbDataResurrectionCount;
  1041. #endif
  1042. //
  1043. // Device extension for miniport routines.
  1044. //
  1045. PVOID HwDeviceExtension;
  1046. //
  1047. // Miniport noncached device extension
  1048. //
  1049. PVOID NonCachedExtension;
  1050. ULONG NonCachedExtensionSize;
  1051. ULONG PortNumber;
  1052. ULONG AdapterNumber;
  1053. //
  1054. // Active requests count. This count is biased by -1 so a value of -1
  1055. // indicates there are no requests out standing.
  1056. //
  1057. LONG ActiveRequestCount;
  1058. //
  1059. // Binary Flags
  1060. //
  1061. typedef struct {
  1062. //
  1063. // Did pnp or the port driver detect this device and provide resources
  1064. // to the miniport, or did the miniport detect the device for us. This
  1065. // flag also indicates whether the AllocatedResources list is non-null
  1066. // going into the find adapter routine.
  1067. //
  1068. BOOLEAN IsMiniportDetected : 1;
  1069. //
  1070. // Do we need to virtualize this adapter and make it look like the only
  1071. // adapter on it's own bus?
  1072. //
  1073. BOOLEAN IsInVirtualSlot : 1;
  1074. //
  1075. // Is this a pnp adapter?
  1076. //
  1077. BOOLEAN IsPnp : 1;
  1078. //
  1079. // Was an interrupt assigned to this device by the system?
  1080. //
  1081. BOOLEAN HasInterrupt : 1;
  1082. //
  1083. // Can this device be powered off?
  1084. //
  1085. BOOLEAN DisablePower : 1;
  1086. //
  1087. // Can this device be stopped?
  1088. //
  1089. BOOLEAN DisableStop : 1;
  1090. //
  1091. // Does this device need power notification on shutdown?
  1092. //
  1093. BOOLEAN NeedsShutdown : 1;
  1094. };
  1095. //
  1096. // For most virtual slot devices this will be zero. However for some
  1097. // the real slot/function number is needed by the miniport to access
  1098. // hardware shared by multiple slots/functions.
  1099. //
  1100. PCI_SLOT_NUMBER VirtualSlotNumber;
  1101. //
  1102. // The bus and slot number of this device as returned by the PCI driver.
  1103. // This is used when building the ConfigInfo block for crashdump so that
  1104. // the dump drivers can talk directly with the hal. These are only
  1105. // valid if IsInVirtualSlot is TRUE above.
  1106. //
  1107. ULONG RealBusNumber;
  1108. ULONG RealSlotNumber;
  1109. //
  1110. // Number of SCSI buses
  1111. //
  1112. UCHAR NumberOfBuses;
  1113. UCHAR MaximumTargetIds;
  1114. UCHAR MaxLuCount;
  1115. //
  1116. // SCSI port driver flags
  1117. //
  1118. ULONG Flags;
  1119. INTERLOCKED ULONG DpcFlags;
  1120. //
  1121. // The number of times this adapter has been disabled.
  1122. //
  1123. ULONG DisableCount;
  1124. LONG PortTimeoutCounter;
  1125. //
  1126. // A pointer to the interrupt object to be used with
  1127. // the SynchronizeExecution routine. If the miniport is
  1128. // using SpSynchronizeExecution then this will actually point
  1129. // back to the adapter extension.
  1130. //
  1131. PKINTERRUPT InterruptObject;
  1132. //
  1133. // Second Interrupt object (PCI IDE work-around)
  1134. //
  1135. PKINTERRUPT InterruptObject2;
  1136. //
  1137. // Routine to call to synchronize execution for the miniport.
  1138. //
  1139. PSYNCHRONIZE_ROUTINE SynchronizeExecution;
  1140. //
  1141. // Global device sequence number.
  1142. //
  1143. ULONG SequenceNumber;
  1144. KSPIN_LOCK SpinLock;
  1145. //
  1146. // Second spin lock (PCI IDE work-around). This is only initalized
  1147. // if the miniport has requested multiple interrupts.
  1148. //
  1149. KSPIN_LOCK MultipleIrqSpinLock;
  1150. //
  1151. // Dummy interrupt spin lock.
  1152. //
  1153. KSPIN_LOCK InterruptSpinLock;
  1154. //
  1155. // Dma Adapter information.
  1156. //
  1157. PVOID MapRegisterBase;
  1158. PDMA_ADAPTER DmaAdapterObject;
  1159. ADAPTER_TRANSFER FlushAdapterParameters;
  1160. //
  1161. // miniport's copy of the configuraiton informaiton.
  1162. // Used only during initialization.
  1163. //
  1164. PPORT_CONFIGURATION_INFORMATION PortConfig;
  1165. //
  1166. // Resources allocated and translated for this particular adapter.
  1167. //
  1168. PCM_RESOURCE_LIST AllocatedResources;
  1169. PCM_RESOURCE_LIST TranslatedResources;
  1170. //
  1171. // Common buffer size. Used for HalFreeCommonBuffer.
  1172. //
  1173. ULONG CommonBufferSize;
  1174. ULONG SrbExtensionSize;
  1175. //
  1176. // Indicates whether the common buffer was allocated using
  1177. // ALLOCATE_COMMON_BUFFER or MmAllocateContiguousMemorySpecifyCache.
  1178. //
  1179. BOOLEAN UncachedExtensionIsCommonBuffer;
  1180. //
  1181. // The number of srb extensions which were allocated.
  1182. //
  1183. ULONG SrbExtensionCount;
  1184. //
  1185. // Placeholder for the minimum number of requests to allocate for.
  1186. // This can be a registry parameter.
  1187. //
  1188. ULONG NumberOfRequests;
  1189. //
  1190. // SrbExtension and non-cached common buffer
  1191. //
  1192. PVOID SrbExtensionBuffer;
  1193. //
  1194. // List head of free SRB extentions.
  1195. //
  1196. PVOID SrbExtensionListHeader;
  1197. //
  1198. // A bitmap for keeping track of which queue tags are in use.
  1199. //
  1200. KSPIN_LOCK QueueTagSpinLock;
  1201. PRTL_BITMAP QueueTagBitMap;
  1202. UCHAR MaxQueueTag;
  1203. //
  1204. // Hint for allocating queue tags. Value will be the last queue
  1205. // tag allocated + 1.
  1206. //
  1207. ULONG QueueTagHint;
  1208. //
  1209. // Logical Unit Extensions
  1210. //
  1211. ULONG HwLogicalUnitExtensionSize;
  1212. //
  1213. // List of mapped address entries for use when powering up the adapter
  1214. // or cleaning up its mappings.
  1215. //
  1216. PMAPPED_ADDRESS MappedAddressList;
  1217. //
  1218. // List of free mapped address blocks preallocated by scsiport before
  1219. // calling HwFindAdapter. One is allocated for each memory range in the
  1220. // miniport's resource list. As ranges are unmapped their blocks will
  1221. // be placed here for potential reuse by the miniport's HwFindAdapter
  1222. // routine.
  1223. //
  1224. PMAPPED_ADDRESS FreeMappedAddressList;
  1225. //
  1226. // Miniport service routine pointers.
  1227. //
  1228. PHW_FIND_ADAPTER HwFindAdapter;
  1229. PHW_INITIALIZE HwInitialize;
  1230. PHW_STARTIO HwStartIo;
  1231. PHW_INTERRUPT HwInterrupt;
  1232. PHW_RESET_BUS HwResetBus;
  1233. PHW_DMA_STARTED HwDmaStarted;
  1234. PHW_INTERRUPT HwRequestInterrupt;
  1235. PHW_INTERRUPT HwTimerRequest;
  1236. PHW_ADAPTER_CONTROL HwAdapterControl;
  1237. ULONG InterruptLevel;
  1238. ULONG IoAddress;
  1239. //
  1240. // BitMap containing the list of supported adapter control types for this
  1241. // adapter/miniport.
  1242. //
  1243. RTL_BITMAP SupportedControlBitMap;
  1244. ULONG SupportedControlBits[ARRAY_ELEMENTS_FOR_BITMAP(
  1245. (ScsiAdapterControlMax),
  1246. ULONG)];
  1247. //
  1248. // Array of logical unit extensions.
  1249. //
  1250. LOGICAL_UNIT_BIN LogicalUnitList[NUMBER_LOGICAL_UNIT_BINS];
  1251. //
  1252. // The last logical unit for which the miniport completed a request. This
  1253. // will give us a chance to stay out of the LogicalUnitList for the common
  1254. // completion type.
  1255. //
  1256. // This value is set by ScsiPortNotification and will be cleared by
  1257. // SpRemoveLogicalUnitFromBin.
  1258. //
  1259. PLOGICAL_UNIT_EXTENSION CachedLogicalUnit;
  1260. //
  1261. // Interrupt level data storage.
  1262. //
  1263. INTERRUPT_DATA InterruptData;
  1264. //
  1265. // Whether or not an interrupt has occured since the last timeout.
  1266. // Used to determine if interrupts may not be getting delivered.
  1267. // This value must be set within KeSynchronizeExecution
  1268. //
  1269. ULONG WatchdogInterruptCount;
  1270. //
  1271. // SCSI Capabilities structure
  1272. //
  1273. IO_SCSI_CAPABILITIES Capabilities;
  1274. //
  1275. // Miniport timer object.
  1276. //
  1277. KTIMER MiniPortTimer;
  1278. //
  1279. // Miniport DPC for timer object.
  1280. //
  1281. KDPC MiniPortTimerDpc;
  1282. //
  1283. // Physical address of common buffer
  1284. //
  1285. PHYSICAL_ADDRESS PhysicalCommonBuffer;
  1286. //
  1287. // Buffers must be mapped into system space.
  1288. //
  1289. BOOLEAN MapBuffers;
  1290. //
  1291. // Buffers must be remapped into system space after IoMapTransfer has been
  1292. // called.
  1293. //
  1294. BOOLEAN RemapBuffers;
  1295. //
  1296. // Is this device a bus master and does it require map registers.
  1297. //
  1298. BOOLEAN MasterWithAdapter;
  1299. //
  1300. // Supports tagged queuing
  1301. //
  1302. BOOLEAN TaggedQueuing;
  1303. //
  1304. // Supports auto request sense.
  1305. //
  1306. BOOLEAN AutoRequestSense;
  1307. //
  1308. // Supports multiple requests per logical unit.
  1309. //
  1310. BOOLEAN MultipleRequestPerLu;
  1311. //
  1312. // Support receive event function.
  1313. //
  1314. BOOLEAN ReceiveEvent;
  1315. //
  1316. // Indicates an srb extension needs to be allocated.
  1317. //
  1318. BOOLEAN AllocateSrbExtension;
  1319. //
  1320. // Indicates the contorller caches data.
  1321. //
  1322. BOOLEAN CachesData;
  1323. //
  1324. // Indicates that the adapter can handle 64-bit DMA.
  1325. //
  1326. BOOLEAN Dma64BitAddresses;
  1327. //
  1328. // Indicates that the adapter can handle 32-bit DMA.
  1329. //
  1330. BOOLEAN Dma32BitAddresses;
  1331. //
  1332. // Queued WMI request items that are not in use.
  1333. //
  1334. INTERLOCKED SLIST_HEADER WmiFreeMiniPortRequestList;
  1335. KSPIN_LOCK WmiFreeMiniPortRequestLock;
  1336. INTERLOCKED ULONG WmiFreeMiniPortRequestWatermark;
  1337. INTERLOCKED ULONG WmiFreeMiniPortRequestCount;
  1338. BOOLEAN WmiFreeMiniPortRequestInitialized;
  1339. //
  1340. // Free WMI request items were exhausted at least once in the lifetime
  1341. // of this adapter (used to log error only once).
  1342. //
  1343. BOOLEAN WmiFreeMiniPortRequestsExhausted;
  1344. //
  1345. // This mutex is used to synchronize access & modification of the list
  1346. // of devices during enumeration & reporting.
  1347. //
  1348. KMUTEX EnumerationDeviceMutex;
  1349. //
  1350. // This fast-mutex is used to protect the enumeration work-item and
  1351. // the list of completion routines to be run once an enumeration is
  1352. // finished.
  1353. //
  1354. FAST_MUTEX EnumerationWorklistMutex;
  1355. //
  1356. // System time of the last bus scan. This is protected by the
  1357. // EnumerationWorkListMutex.
  1358. //
  1359. LARGE_INTEGER LastBusScanTime;
  1360. //
  1361. // Indicates that the next rescan which comes in should be "forced", ie.
  1362. // it should rescan no matter how recent the last one was.
  1363. //
  1364. INTERLOCKED LONG ForceNextBusScan;
  1365. //
  1366. // A work item to use in enumerating the bus.
  1367. //
  1368. WORK_QUEUE_ITEM EnumerationWorkItem;
  1369. //
  1370. // A pointer to the thread the workitem is running on. This is for
  1371. // debugging purposes.
  1372. //
  1373. PKTHREAD EnumerationWorkThread;
  1374. //
  1375. // If this is TRUE then there is already an enumeration worker thread
  1376. // running. If FALSE then the work item must be requeued. This flag is
  1377. // protected by the EnumerationWorklistMutex
  1378. //
  1379. BOOLEAN EnumerationRunning;
  1380. //
  1381. // A list of enumeration requests. When an bus scan is completed the
  1382. // scanner should run through the list of enumeration requests and complete
  1383. // each one. This list is protected by the EnumerationWorklistMutex.
  1384. //
  1385. PSP_ENUMERATION_REQUEST EnumerationWorkList;
  1386. //
  1387. // A pointer to the PNP enumeration request object. This is used so
  1388. // so we can use interlocked exchange to determine if the block is
  1389. // in use.
  1390. //
  1391. PSP_ENUMERATION_REQUEST PnpEnumRequestPtr;
  1392. //
  1393. // An enumeration request to use for PNP enumeration requests. Since there
  1394. // will only be one of these outstanding at any time we can statically
  1395. // allocate one for that case.
  1396. //
  1397. SP_ENUMERATION_REQUEST PnpEnumerationRequest;
  1398. //
  1399. // A lookaside list to pull SRB_DATA blocks off of.
  1400. //
  1401. NPAGED_LOOKASIDE_LIST SrbDataLookasideList;
  1402. //
  1403. // The following members are used to keep an SRB_DATA structure allocated
  1404. // for emergency use and to queue requests which need to use it. The
  1405. // structures are synchronized with the EmergencySrbDataSpinLock.
  1406. // The routines Sp[Allocate|Free]SrbData & ScsiPortTickHandler will
  1407. // handle queueing and eventual restarting of these requests.
  1408. //
  1409. //
  1410. // This spinlock protects the blocked request list.
  1411. //
  1412. KSPIN_LOCK EmergencySrbDataSpinLock;
  1413. //
  1414. // Contains a queue of irps which could not be dispatched because of
  1415. // low memory conditions and because the EmergencySrbData block is already
  1416. // allocated.
  1417. //
  1418. LIST_ENTRY SrbDataBlockedRequests;
  1419. //
  1420. // The SRB_DATA reserved for "emergency" use. This pointer should be set
  1421. // to NULL if the SRB_DATA is in use. Any SRB_DATA block may be used
  1422. // for the emergency request.
  1423. //
  1424. INTERLOCKED PSRB_DATA EmergencySrbData;
  1425. //
  1426. // Flags to indicate whether the srbdata and scatter gather lookaside
  1427. // lists have been allocated already.
  1428. //
  1429. BOOLEAN SrbDataListInitialized;
  1430. //
  1431. // Bus standard interface. Retrieved from the lower driver immediately
  1432. // after it completes the start irp.
  1433. //
  1434. BOOLEAN LowerBusInterfaceStandardRetrieved;
  1435. BUS_INTERFACE_STANDARD LowerBusInterfaceStandard;
  1436. //
  1437. // Handles into the device map for the various entries this adapter will
  1438. // have created.
  1439. //
  1440. //
  1441. // An array of handles for each
  1442. HANDLE PortDeviceMapKey;
  1443. PDEVICE_MAP_HANDLES BusDeviceMapKeys;
  1444. //
  1445. // Unicode string containing the device name of this object
  1446. //
  1447. PWSTR DeviceName;
  1448. //
  1449. // The guid for the underlying bus. Saved here so we don't have to
  1450. // retrieve it so often.
  1451. //
  1452. GUID BusTypeGuid;
  1453. //
  1454. // The pnp interface name for this device.
  1455. //
  1456. UNICODE_STRING InterfaceName;
  1457. //
  1458. // The device state for this adapter.
  1459. //
  1460. PNP_DEVICE_STATE DeviceState;
  1461. //
  1462. // The number of calls to ScsiPortTickHandler for this adapter since
  1463. // the machine was booted.
  1464. //
  1465. INTERLOCKED ULONG TickCount;
  1466. //
  1467. // Preallocated memory to use for IssueInquiry. The InquiryBuffer is used
  1468. // to retreive the inquiry data and the serial number for the device.
  1469. //
  1470. PVOID InquiryBuffer;
  1471. PSENSE_DATA InquirySenseBuffer;
  1472. PIRP InquiryIrp;
  1473. PMDL InquiryMdl;
  1474. //
  1475. // Mutex used to synchronize multiple threads all synchronously waiting for
  1476. // a power up to occur.
  1477. //
  1478. FAST_MUTEX PowerMutex;
  1479. //
  1480. // A pointer to a logical unit which is used to scan empty locations on the
  1481. // bus.
  1482. //
  1483. PLOGICAL_UNIT_EXTENSION RescanLun;
  1484. //
  1485. // The number of additional sense bytes supported by this adapter.
  1486. //
  1487. UCHAR AdditionalSenseBytes;
  1488. //
  1489. // Indicates whether the SenseData WMI event is enabled.
  1490. //
  1491. BOOLEAN EnableSenseDataEvent;
  1492. //
  1493. // Identifies the event class used to generate sense data wmi events.
  1494. //
  1495. GUID SenseDataEventClass;
  1496. //
  1497. // Pointer to verifier state that gets allocated and initialized when
  1498. // scsiport's verifier is enabled.
  1499. //
  1500. PVERIFIER_EXTENSION VerifierExtension;
  1501. //
  1502. // The minimum & maximum addresses for common buffer. These are loaded
  1503. // from [Minimum|Maximum]UCXAddress in the registry.
  1504. //
  1505. PHYSICAL_ADDRESS MinimumCommonBufferBase;
  1506. PHYSICAL_ADDRESS MaximumCommonBufferBase;
  1507. #if defined(FORWARD_PROGRESS)
  1508. //
  1509. // Pointer to a block of reserved pages we use to make forward progress
  1510. // in low memory conditons.
  1511. //
  1512. PVOID ReservedPages;
  1513. //
  1514. // Pointer to an emergency MDL we can use if we cannot allocate one
  1515. //
  1516. PMDL ReservedMdl;
  1517. #endif
  1518. //
  1519. // Identified how many successfully completed requests are required to
  1520. // restore a LUN on this adapter from a degraded performation state
  1521. // with respect to MaxQueueDepth.
  1522. //
  1523. ULONG RemainInReducedMaxQueueState;
  1524. //
  1525. // This value dictates on what type of boundary an adapter's uncached extension
  1526. // must be aligned.
  1527. //
  1528. ULONG UncachedExtAlignment;
  1529. //
  1530. // This value is used to keep track of the number of instances of the
  1531. // SRB_DATA free routine is running. This helps us avoid a nasty recursion
  1532. // brought on by synchronously completing requests and starting blocked
  1533. // requests waiting for SRB_DATA objects.
  1534. //
  1535. LONG SrbDataFreeRunning;
  1536. //
  1537. // This is the timeout value we put into INQUIRY SRBs. Some devices are
  1538. // known to take longer than the default 4 seconds to respond.
  1539. //
  1540. ULONG SrbTimeout;
  1541. //
  1542. // This boolean indicates whether the adapter supports multiple concurrent
  1543. // requests. This means it either supports tagged queuing or multiple
  1544. // requests per logical unit.
  1545. //
  1546. BOOLEAN SupportsMultipleRequests;
  1547. //
  1548. // This is the size of the preallocated SG buffer contained in each
  1549. // SRB_DATA structure allocated for this adapter. We pass this value to
  1550. // the HAL when we supply our own SG buffer.
  1551. //
  1552. ULONG SgBufferLen;
  1553. //
  1554. // This is the number of seconds we hold requests for following a bus
  1555. // reset.
  1556. //
  1557. ULONG ResetHoldTime;
  1558. //
  1559. // Array of LU extensions representing the initiator for each bus.
  1560. //
  1561. PLOGICAL_UNIT_EXTENSION InitiatorLU[8];
  1562. //
  1563. // Inidicates whether the adapter is configured to have a logical unit
  1564. // created for the initiator on each supported bus.
  1565. //
  1566. BOOLEAN CreateInitiatorLU;
  1567. //
  1568. // Used to chain Logical units having blocked requests.
  1569. //
  1570. PLOGICAL_UNIT_EXTENSION BlockedLogicalUnit;
  1571. };
  1572. struct _LOGICAL_UNIT_EXTENSION {
  1573. union {
  1574. PDEVICE_OBJECT DeviceObject;
  1575. COMMON_EXTENSION CommonExtension;
  1576. };
  1577. //
  1578. // Logical Unit flags
  1579. //
  1580. ULONG LuFlags;
  1581. //
  1582. // The adapter number this device is attached to
  1583. //
  1584. ULONG PortNumber;
  1585. //
  1586. // Has this device been claimed by a driver (legacy or pnp)
  1587. //
  1588. BOOLEAN IsClaimed;
  1589. BOOLEAN IsLegacyClaim;
  1590. //
  1591. // Has this device been enumerated yet? If so then we cannot actually
  1592. // delete it until we've explicitly told the PNP system that it's gone
  1593. // (by not enumerating it)
  1594. //
  1595. BOOLEAN IsEnumerated;
  1596. //
  1597. // Has this device gone missing?
  1598. //
  1599. BOOLEAN IsMissing;
  1600. //
  1601. // Is this device visible - should it be exposed to PNP?
  1602. //
  1603. BOOLEAN IsVisible;
  1604. //
  1605. // Was this device marked missing because we found something different at
  1606. // it's bus location? If so then the removal of this device from the
  1607. // logical unit bins will trigger a new bus scan.
  1608. //
  1609. BOOLEAN IsMismatched;
  1610. //
  1611. // Is this lun temporary? Temporary luns are used to scan bus locations
  1612. // which are believed to be empty. They are the only luns which can be
  1613. // swapped out of the logical unit list.
  1614. //
  1615. BOOLEAN IsTemporary;
  1616. //
  1617. // Indicates that this device needs to have an inquiry sent to it to
  1618. // determine if it's still present. This flag is cleared if the inquiry
  1619. // succeeds and the inquiry data matches what was previously read at that
  1620. // address. If this flag is set when SpPurgeTarget is called then the
  1621. // lun will be marked as missing.
  1622. //
  1623. ULONG NeedsVerification;
  1624. //
  1625. // The bus address of this device.
  1626. //
  1627. UCHAR PathId;
  1628. UCHAR TargetId;
  1629. UCHAR Lun;
  1630. //
  1631. // The number of times the current busy request has been retried
  1632. //
  1633. UCHAR RetryCount;
  1634. //
  1635. // The current queue sort key
  1636. //
  1637. ULONG CurrentKey;
  1638. //
  1639. // A pointer to the miniport's logical unit extension.
  1640. //
  1641. PVOID HwLogicalUnitExtension;
  1642. //
  1643. // A pointer to the device extension for the adapter.
  1644. //
  1645. PADAPTER_EXTENSION AdapterExtension;
  1646. //
  1647. // The number of unreleased queue locks on this device
  1648. //
  1649. ULONG QueueLockCount;
  1650. //
  1651. // Reference counts for pausing & unpausing the queue (see LU_QUEUE_PAUSED)
  1652. //
  1653. ULONG QueuePauseCount;
  1654. //
  1655. // List of lock & unlock requests which are waiting to be dispatched.
  1656. //
  1657. KDEVICE_QUEUE LockRequestQueue;
  1658. //
  1659. // The currently operating lock request.
  1660. //
  1661. PSRB_DATA CurrentLockRequest;
  1662. //
  1663. // A pointer to the next logical unit extension in the logical unit bin.
  1664. //
  1665. PLOGICAL_UNIT_EXTENSION NextLogicalUnit;
  1666. //
  1667. // Used to chain logical units in the interrupt data block.
  1668. //
  1669. PLOGICAL_UNIT_EXTENSION ReadyLogicalUnit;
  1670. //
  1671. // Used to chain completed abort requests in the interrupt data block.
  1672. //
  1673. PLOGICAL_UNIT_EXTENSION CompletedAbort;
  1674. //
  1675. // The current abort request for this logical unit
  1676. //
  1677. PSCSI_REQUEST_BLOCK AbortSrb;
  1678. //
  1679. // Timeout counter for this logical unit
  1680. //
  1681. LONG RequestTimeoutCounter;
  1682. //
  1683. // The list of requests for this logical unit.
  1684. //
  1685. LIST_ENTRY RequestList;
  1686. //
  1687. // The next request to be executed.
  1688. //
  1689. PSRB_DATA PendingRequest;
  1690. //
  1691. // This irp could not be executed before because the
  1692. // device returned BUSY.
  1693. //
  1694. PSRB_DATA BusyRequest;
  1695. //
  1696. // The current untagged request for this logical unit.
  1697. //
  1698. PSRB_DATA CurrentUntaggedRequest;
  1699. //
  1700. // The maximum number of request which we will issue to the device
  1701. //
  1702. UCHAR MaxQueueDepth;
  1703. //
  1704. // The current number of outstanding requests.
  1705. //
  1706. UCHAR QueueCount;
  1707. //
  1708. // The inquiry data for this logical unit.
  1709. //
  1710. INQUIRYDATA InquiryData;
  1711. //
  1712. // The handles for the target & logical unit keys in the device map.
  1713. //
  1714. HANDLE TargetDeviceMapKey;
  1715. HANDLE LunDeviceMapKey;
  1716. //
  1717. // Our fixed set of SRB_DATA blocks for use when processing bypass requests.
  1718. // If this set is exhausted then scsiport will bugcheck - this should be
  1719. // okay since bypass requests are only sent in certain extreme conditions
  1720. // and should never be overlapped (we should only see one bypass request
  1721. // at a time).
  1722. //
  1723. SRB_DATA BypassSrbDataBlocks[NUMBER_BYPASS_SRB_DATA_BLOCKS];
  1724. //
  1725. // A list of the free bypass SRB_DATA blocks.
  1726. //
  1727. KSPIN_LOCK BypassSrbDataSpinLock;
  1728. SLIST_HEADER BypassSrbDataList;
  1729. //
  1730. // A pointer to the request for which we have issued a request-sense irp
  1731. // (if any). This field is protected by the port spinlock.
  1732. //
  1733. PSRB_DATA ActiveFailedRequest;
  1734. //
  1735. // A pointer to the request for which we need to issue a request-sense irp
  1736. // (if any). RequestSenseCompletion will promote this to the active
  1737. // failed request and issue a new RS operation when it runs.
  1738. // This field is protected by the port spinlock.
  1739. //
  1740. PSRB_DATA BlockedFailedRequest;
  1741. //
  1742. // Resources for issuing request-sense commands.
  1743. //
  1744. PIRP RequestSenseIrp;
  1745. SCSI_REQUEST_BLOCK RequestSenseSrb;
  1746. struct {
  1747. MDL RequestSenseMdl;
  1748. PFN_NUMBER RequestSenseMdlPfn1;
  1749. PFN_NUMBER RequestSenseMdlPfn2;
  1750. };
  1751. //
  1752. // The "lun-list" associated with this target. SpIssueReportLuns will
  1753. // store this value in the logical unit extension for LUN 0 of each target
  1754. // for use in the event that we are unable to retrieve it from the LUN.
  1755. //
  1756. PLUN_LIST TargetLunList;
  1757. //
  1758. // The special controller flags for this target. These flags are valid
  1759. // for LUN 0 only.
  1760. //
  1761. SP_SPECIAL_CONTROLLER_FLAGS SpecialFlags;
  1762. //
  1763. // Flags to keep track of what EVPD pages this device supports.
  1764. //
  1765. BOOLEAN DeviceIdentifierPageSupported : 1;
  1766. BOOLEAN SerialNumberPageSupported : 1;
  1767. //
  1768. // The vital product data for this device - this buffer contains the
  1769. // device serial number. The other fields contain the length of the
  1770. // data in the buffer and the page code used to retrieve this buffer.
  1771. //
  1772. ANSI_STRING SerialNumber;
  1773. //
  1774. // The device identifier page retreived from the device's vital product
  1775. // data.
  1776. //
  1777. PVPD_IDENTIFICATION_PAGE DeviceIdentifierPage;
  1778. ULONG DeviceIdentifierPageLength;
  1779. //
  1780. // If we reduce the MaxQueueDepth, track how long we remain in the degraded
  1781. // state. If we reach a configurable number of ticks we restore ourselves
  1782. // to full power.
  1783. //
  1784. ULONG TicksInReducedMaxQueueDepthState;
  1785. #if defined(NEWQUEUE)
  1786. //
  1787. // Capacity of this LU in sectors.
  1788. //
  1789. ULONG Capacity;
  1790. //
  1791. // The number of zones we divide the LU into.
  1792. //
  1793. ULONG Zones;
  1794. //
  1795. // The number of sectors per zone.
  1796. //
  1797. ULONG ZoneLength;
  1798. //
  1799. // This array holds each zone's first sector.
  1800. //
  1801. ULONG FirstSector[4];
  1802. //
  1803. // This array holds each zone's last sector.
  1804. //
  1805. ULONG LastSector[4];
  1806. //
  1807. // Tracks the number of requests per zone.
  1808. //
  1809. ULONG64 RequestCount[4];
  1810. //
  1811. // The media is divided into a number of zones. This value identifies
  1812. // which zone the port driver is currently servicing.
  1813. //
  1814. ULONG CurrentZone;
  1815. //
  1816. // The value tracks the number of requests we perform in each zone.
  1817. //
  1818. ULONG ZoneCount;
  1819. //
  1820. // Tracks the current location in each zone.
  1821. //
  1822. ULONG ZonePointer[4];
  1823. //
  1824. // Tracks the number of consecutive requests for the same sector.
  1825. //
  1826. UCHAR RedundantRequests[4];
  1827. //
  1828. // Table mapping current zone to next zone.
  1829. //
  1830. ULONG NextSequentialZone[4];
  1831. #endif // NEWQUEUE
  1832. //
  1833. // Maintain a circular buffer of the last 10 IO requests.
  1834. //
  1835. ULONG IoLogIndex;
  1836. ULONG IoLogEntries;
  1837. SP_LUN_IO_LOG IoLog[10];
  1838. //
  1839. // Used to chain Logical units having blocked requests.
  1840. //
  1841. PLOGICAL_UNIT_EXTENSION BlockedLogicalUnit;
  1842. //
  1843. // Contains a queue of irps which could not be dispatched because of
  1844. // low memory conditions and because the EmergencySrbData block is already
  1845. // allocated.
  1846. //
  1847. LIST_ENTRY SrbDataBlockedRequests;
  1848. };
  1849. #if defined(NEWQUEUE)
  1850. ULONG
  1851. INLINE
  1852. GetZone(
  1853. IN PLOGICAL_UNIT_EXTENSION Lun,
  1854. IN ULONG Sector
  1855. )
  1856. {
  1857. ULONG i;
  1858. for (i = 0; i < Lun->Zones; i++) {
  1859. if (Sector <= Lun->LastSector[i]) {
  1860. return i;
  1861. }
  1862. }
  1863. ASSERT(FALSE);
  1864. return (Lun->Zones - 1);
  1865. }
  1866. #endif // NEWQUEUE
  1867. //
  1868. // Miniport specific device extension wrapper
  1869. //
  1870. struct _HW_DEVICE_EXTENSION {
  1871. PADAPTER_EXTENSION FdoExtension;
  1872. UCHAR HwDeviceExtension[0];
  1873. };
  1874. typedef struct _INTERRUPT_CONTEXT {
  1875. PADAPTER_EXTENSION DeviceExtension;
  1876. PINTERRUPT_DATA SavedInterruptData;
  1877. }INTERRUPT_CONTEXT, *PINTERRUPT_CONTEXT;
  1878. typedef struct _RESET_CONTEXT {
  1879. PADAPTER_EXTENSION DeviceExtension;
  1880. UCHAR PathId;
  1881. }RESET_CONTEXT, *PRESET_CONTEXT;
  1882. //
  1883. // Used in LUN rescan determination.
  1884. //
  1885. typedef struct _UNICODE_LUN_LIST {
  1886. UCHAR TargetId;
  1887. struct _UNICODE_LUN_LIST *Next;
  1888. UNICODE_STRING UnicodeInquiryData;
  1889. } UNICODE_LUN_LIST, *PUNICODE_LUN_LIST;
  1890. typedef struct _POWER_CHANGE_CONTEXT {
  1891. PDEVICE_OBJECT DeviceObject;
  1892. POWER_STATE_TYPE Type;
  1893. POWER_STATE State;
  1894. PIRP OriginalIrp;
  1895. PSCSI_REQUEST_BLOCK Srb;
  1896. } POWER_CHANGE_CONTEXT, *PPOWER_CHANGE_CONTEXT;
  1897. //
  1898. // Driver extension
  1899. //
  1900. struct _SP_INIT_CHAIN_ENTRY {
  1901. HW_INITIALIZATION_DATA InitData;
  1902. PSP_INIT_CHAIN_ENTRY NextEntry;
  1903. };
  1904. typedef struct _SCSIPORT_INTERFACE_TYPE_DATA {
  1905. INTERFACE_TYPE InterfaceType;
  1906. ULONG Flags;
  1907. } SCSIPORT_INTERFACE_TYPE_DATA, *PSCSIPORT_INTERFACE_TYPE_DATA;
  1908. typedef struct _SCSIPORT_DRIVER_EXTENSION {
  1909. //
  1910. // Pointer back to the driver object
  1911. //
  1912. PDRIVER_OBJECT DriverObject;
  1913. //
  1914. // Unicode string containing the registry path information
  1915. // for this driver
  1916. //
  1917. UNICODE_STRING RegistryPath;
  1918. UNICODE_STRING MPIOSupportedDeviceList;
  1919. //
  1920. // the chain of HwInitializationData structures that were passed in during
  1921. // the miniport's initialization
  1922. //
  1923. PSP_INIT_CHAIN_ENTRY InitChain;
  1924. //
  1925. // A count of the number of adapter which are using scsiport. This is
  1926. // used for generating unique Id's
  1927. //
  1928. ULONG AdapterCount;
  1929. //
  1930. // The bus type for this driver.
  1931. //
  1932. STORAGE_BUS_TYPE BusType;
  1933. //
  1934. // Flag indicating whether this miniport is set to do device detection.
  1935. // This flag will be initialized out of the registry when the driver
  1936. // extension is setup.
  1937. //
  1938. BOOLEAN LegacyAdapterDetection;
  1939. //
  1940. // The list of pnp interface values we read out of the registry for this
  1941. // device. The number of entries here can vary.
  1942. //
  1943. ULONG PnpInterfaceCount;
  1944. //
  1945. // The number of interfaces which are safe for pnp.
  1946. //
  1947. ULONG SafeInterfaceCount;
  1948. //
  1949. // A pointer to a reserve error log entry for the driver. This entry will
  1950. // be used to log an allocation failure if the logging routine cannot
  1951. // allocate the necessary memory for an error log entry.
  1952. //
  1953. PVOID ReserveAllocFailureLogEntry;
  1954. //
  1955. // Indicates whether the driver is being verified.
  1956. //
  1957. ULONG Verifying;
  1958. //
  1959. // When verifying, we occasionally set pointers so they point to a page
  1960. // of invalid memory so the system will bugcheck if a miniport attempts
  1961. // to access the memory. The following 3 variables are used to maintain
  1962. // this invalid page.
  1963. //
  1964. PVOID UnusedPage;
  1965. PMDL UnusedPageMdl;
  1966. PVOID InvalidPage;
  1967. SCSIPORT_INTERFACE_TYPE_DATA PnpInterface[0];
  1968. //
  1969. // The remaining pnp interface flags trail the defined structure
  1970. //
  1971. } SCSIPORT_DRIVER_EXTENSION, *PSCSIPORT_DRIVER_EXTENSION;
  1972. //
  1973. // Port driver extension flags.
  1974. // These flags are protected by the adapter spinlock.
  1975. //
  1976. //
  1977. // This flag indicates that a request has been passed to the miniport and the
  1978. // miniport has not indicated it is ready for another request. It is set by
  1979. // SpStartIoSynchronized. It is cleared by ScsiPortCompletionDpc when the
  1980. // miniport asks for another request. Note the port driver will defer giving
  1981. // the miniport driver a new request if the current request disabled disconnects.
  1982. //
  1983. #define PD_DEVICE_IS_BUSY 0X00001
  1984. //
  1985. // Indicates there is a pending request for which resources
  1986. // could not be allocated. This flag is set by SpAllocateRequestStructures
  1987. // which is called from ScsiPortStartIo. It is cleared by
  1988. // SpProcessCompletedRequest when a request completes which then calls
  1989. // ScsiPortStartIo to try the request again.
  1990. //
  1991. #define PD_PENDING_DEVICE_REQUEST 0X00800
  1992. //
  1993. // This flag indicates that there are currently no requests executing with
  1994. // disconnects disabled. This flag is normally on. It is cleared by
  1995. // SpStartIoSynchronized when a request with disconnect disabled is started
  1996. // and is set when that request completes. SpProcessCompletedRequest will
  1997. // start the next request for the miniport if PD_DEVICE_IS_BUSY is clear.
  1998. //
  1999. #define PD_DISCONNECT_RUNNING 0X01000
  2000. //
  2001. // Indicates the miniport wants the system interrupts disabled. Set by
  2002. // ScsiPortNofitication and cleared by ScsiPortCompletionDpc. This flag is
  2003. // NOT stored in the interrupt data structure. The parameters are stored in
  2004. // the device extension.
  2005. //
  2006. #define PD_DISABLE_CALL_REQUEST 0X02000
  2007. //
  2008. // Indicates that the miniport is being reinitialized. This is set and
  2009. // cleared by SpReinitializeAdapter is is tested by some of the ScsiPort APIs.
  2010. //
  2011. #define PD_MINIPORT_REINITIALIZING 0x40000
  2012. #define PD_UNCACHED_EXTENSION_RETURNED 0x80000
  2013. //
  2014. // Interrupt Data Flags
  2015. // These flags are protected by the interrupt spinlock.
  2016. //
  2017. //
  2018. // Indicates that ScsiPortCompletionDpc needs to be run. This is set when
  2019. // A miniport makes a request which must be done at DPC and is cleared when
  2020. // when the request information is gotten by SpGetInterruptState.
  2021. //
  2022. #define PD_NOTIFICATION_REQUIRED 0X00004
  2023. //
  2024. // Indicates the miniport is ready for another request. Set by
  2025. // ScsiPortNotification and cleared by SpGetInterruptState. This flag is
  2026. // stored in the interrupt data structure.
  2027. //
  2028. #define PD_READY_FOR_NEXT_REQUEST 0X00008
  2029. //
  2030. // Indicates the miniport wants the adapter channel flushed. Set by
  2031. // ScsiPortFlushDma and cleared by SpGetInterruptState. This flag is
  2032. // stored in the data interrupt structure. The flush adapter parameters
  2033. // are saved in the device object.
  2034. //
  2035. #define PD_FLUSH_ADAPTER_BUFFERS 0X00010
  2036. //
  2037. // Indicates the miniport wants the adapter channel programmed. Set by
  2038. // ScsiPortIoMapTransfer and cleared by SpGetInterruptState or
  2039. // ScsiPortFlushDma. This flag is stored in the interrupt data structure.
  2040. // The I/O map transfer parameters are saved in the interrupt data structure.
  2041. //
  2042. #define PD_MAP_TRANSFER 0X00020
  2043. //
  2044. // Indicates the miniport wants to log an error. Set by
  2045. // ScsiPortLogError and cleared by SpGetInterruptState. This flag is
  2046. // stored in the interrupt data structure. The error log parameters
  2047. // are saved in the interrupt data structure. Note at most one error per DPC
  2048. // can be logged.
  2049. //
  2050. #define PD_LOG_ERROR 0X00040
  2051. //
  2052. // Indicates that no request should be sent to the miniport after
  2053. // a bus reset. Set when the miniport reports a reset or the port driver
  2054. // resets the bus. It is cleared by SpTimeoutSynchronized. The
  2055. // PortTimeoutCounter is used to time the length of the reset hold. This flag
  2056. // is stored in the interrupt data structure.
  2057. //
  2058. #define PD_RESET_HOLD 0X00080
  2059. //
  2060. // Indicates a request was stopped due to a reset hold. The held request is
  2061. // stored in the current request of the device object. This flag is set by
  2062. // SpStartIoSynchronized and cleared by SpTimeoutSynchronized which also
  2063. // starts the held request when the reset hold has ended. This flag is stored
  2064. // in the interrupt data structure.
  2065. //
  2066. #define PD_HELD_REQUEST 0X00100
  2067. //
  2068. // Indicates the miniport has reported a bus reset. Set by
  2069. // ScsiPortNotification and cleared by SpGetInterruptState. This flag is
  2070. // stored in the interrupt data structure.
  2071. //
  2072. #define PD_RESET_REPORTED 0X00200
  2073. //
  2074. // Indicates that system interrupts have been enabled and that the miniport
  2075. // has disabled its adapter from interruptint. The miniport's interrupt
  2076. // routine is not called while this flag is set. This flag is set by
  2077. // ScsiPortNotification when a CallEnableInterrupts request is made and
  2078. // cleared by SpEnableInterruptSynchronized when the miniport requests that
  2079. // system interrupts be disabled. This flag is stored in the interrupt data
  2080. // structure.
  2081. //
  2082. #define PD_DISABLE_INTERRUPTS 0X04000
  2083. //
  2084. // Indicates the miniport wants the system interrupt enabled. Set by
  2085. // ScsiPortNotification and cleared by SpGetInterruptState. This flag is
  2086. // stored in the interrupt data structure. The call enable interrupts
  2087. // parameters are saved in the device extension.
  2088. //
  2089. #define PD_ENABLE_CALL_REQUEST 0X08000
  2090. //
  2091. // Indicates the miniport is wants a timer request. Set by
  2092. // ScsiPortNotification and cleared by SpGetInterruptState. This flag is
  2093. // stored in the interrupt data structure. The timer request parameters are
  2094. // stored in the interrupt data structure.
  2095. //
  2096. #define PD_TIMER_CALL_REQUEST 0X10000
  2097. //
  2098. // Indicates the miniport has a WMI request. Set by ScsiPortNotification
  2099. // and cleared by SpGetInterruptState. This flag is stored in the interrupt
  2100. // data structure. The WMI request parameters are stored in the interrupt
  2101. // data structure.
  2102. //
  2103. #define PD_WMI_REQUEST 0X20000
  2104. //
  2105. // Indicates that the miniport has detected some sort of change on the bus -
  2106. // usually device arrival or removal - and wishes the port driver to rescan
  2107. // the bus.
  2108. //
  2109. #define PD_BUS_CHANGE_DETECTED 0x40000
  2110. //
  2111. // Indicates that the adapter has disappeared. If this flag is set then no
  2112. // calls should be made into the miniport.
  2113. //
  2114. #define PD_ADAPTER_REMOVED 0x80000
  2115. //
  2116. // Indicates that interrupts from the miniport do not appear to be getting
  2117. // delivered to scsiport. This flag is set by SpTimeoutSynchronized and
  2118. // will cause the DPC routine to log an error to this effect.
  2119. //
  2120. #define PD_INTERRUPT_FAILURE 0x100000
  2121. #if defined(FORWARD_PROGRESS)
  2122. //
  2123. // Indicates that the adapter's reserved pages are currently in use. The
  2124. // reserved pages is a special VA range set aside by MM in order for devices
  2125. // to make forward progress in low memory conditions.
  2126. //
  2127. #define PD_RESERVED_PAGES_IN_USE 0x200000
  2128. //
  2129. // Indicates that the adapter's reserved MDL is currently in use.
  2130. //
  2131. #define PD_RESERVED_MDL_IN_USE 0x400000
  2132. #endif
  2133. //
  2134. // Indicates that the adapter is in the process of shutting down. Certain
  2135. // operations must not be started when this is the case.
  2136. //
  2137. #define PD_SHUTDOWN_IN_PROGRESS 0x800000
  2138. //
  2139. // The following flags should not be cleared from the interrupt data structure
  2140. // by SpGetInterruptState.
  2141. //
  2142. #define PD_INTERRUPT_FLAG_MASK (PD_RESET_HOLD | PD_HELD_REQUEST | PD_DISABLE_INTERRUPTS | PD_ADAPTER_REMOVED)
  2143. //
  2144. // Adapter extension flags for DPC routine.
  2145. //
  2146. //
  2147. // Indicates that the completion DPC is either already running or has been
  2148. // queued to service completed requests. This flag is checked when the
  2149. // completion DPC needs to be run - the DPC should only be started if this
  2150. // flag is already clear. It will be cleared when the DPC has completed
  2151. // processing any work items.
  2152. //
  2153. #define PD_DPC_RUNNING 0x20000
  2154. //
  2155. // Logical unit extension flags.
  2156. //
  2157. //
  2158. // Indicates the logical unit queue is frozen. Set by
  2159. // SpProcessCompletedRequest when an error occurs and is cleared by the class
  2160. // driver.
  2161. //
  2162. #define LU_QUEUE_FROZEN 0X0001
  2163. //
  2164. // Indicates that the miniport has an active request for this logical unit.
  2165. // Set by SpStartIoSynchronized when the request is started and cleared by
  2166. // GetNextLuRequest. This flag is used to track when it is ok to start another
  2167. // request from the logical unit queue for this device.
  2168. //
  2169. #define LU_LOGICAL_UNIT_IS_ACTIVE 0X0002
  2170. //
  2171. // Indicates that a request for this logical unit has failed and a REQUEST
  2172. // SENSE command needs to be done. This flag prevents other requests from
  2173. // being started until an untagged, by-pass queue command is started. This
  2174. // flag is cleared in SpStartIoSynchronized. It is set by
  2175. // SpGetInterruptState.
  2176. //
  2177. #define LU_NEED_REQUEST_SENSE 0X0004
  2178. //
  2179. // Indicates that a request for this logical unit has completed with a status
  2180. // of BUSY or QUEUE FULL. This flag is set by SpProcessCompletedRequest and
  2181. // the busy request is saved in the logical unit structure. This flag is
  2182. // cleared by ScsiPortTickHandler which also restarts the request. Busy
  2183. // request may also be requeued to the logical unit queue if an error occurs
  2184. // on the device (This will only occur with command queueing.). Not busy
  2185. // requests are nasty because they are restarted asynchronously by
  2186. // ScsiPortTickHandler rather than GetNextLuRequest. This makes error recovery
  2187. // more complex.
  2188. //
  2189. #define LU_LOGICAL_UNIT_IS_BUSY 0X0008
  2190. //
  2191. // This flag indicates a queue full has been returned by the device. It is
  2192. // similar to PD_LOGICAL_UNIT_IS_BUSY but is set in SpGetInterruptState when
  2193. // a QUEUE FULL status is returned. This flag is used to prevent other
  2194. // requests from being started for the logical unit before
  2195. // SpProcessCompletedRequest has a chance to set the busy flag.
  2196. //
  2197. #define LU_QUEUE_IS_FULL 0X0010
  2198. //
  2199. // Indicates that there is a request for this logical unit which cannot be
  2200. // executed for now. This flag is set by SpAllocateRequestStructures. It is
  2201. // cleared by GetNextLuRequest when it detects that the pending request
  2202. // can now be executed. The pending request is stored in the logical unit
  2203. // structure. A new single non-queued reqeust cannot be executed on a logical
  2204. // that is currently executing queued requests. Non-queued requests must wait
  2205. // unit for all queued requests to complete. A non-queued requests is one
  2206. // which is not tagged and does not have SRB_FLAGS_NO_QUEUE_FREEZE set.
  2207. // Normally only read and write commands can be queued.
  2208. //
  2209. #define LU_PENDING_LU_REQUEST 0x0020
  2210. //
  2211. // Indicates that the logical unit queue has been paused due to an error. Set
  2212. // by SpProcessCompletedRequest when an error occurs and is cleared by the
  2213. // class driver either by unfreezing or flushing the queue. This flag is used
  2214. // with the following one to determine why the logical unit queue is paused.
  2215. //
  2216. #define LU_QUEUE_LOCKED 0x0040
  2217. //
  2218. // Indicates that this LUN has been "paused". This flag is set and cleared by
  2219. // the power management code while changing the power state. It causes
  2220. // GetNextLuRequest to return without starting another request and is used
  2221. // by SpSrbIsBypassRequest to determine that a bypass request should get
  2222. // shoved to the front of the line.
  2223. //
  2224. #define LU_QUEUE_PAUSED 0x0080
  2225. //
  2226. // Indicates that the LUN is operating in a degraded state. The maximum queue
  2227. // depth has been reduced because the LUN has returned QUEUE FULL status. We
  2228. // track this because in the event that the QUEUE FULL was transient, we want
  2229. // to restore the queue depth to it's original maximum.
  2230. #define LU_PERF_MAXQDEPTH_REDUCED 0x0100
  2231. //
  2232. // SRB_DATA flags.
  2233. //
  2234. //
  2235. // Indicates that the srb_data block was for a bypass request
  2236. //
  2237. #define SRB_DATA_BYPASS_REQUEST 0x10000000
  2238. #if defined(FORWARD_PROGRESS)
  2239. //
  2240. // Indicates that the request is using reserved pages that enable
  2241. // forward progress in low-memory condition.
  2242. //
  2243. #define SRB_DATA_RESERVED_PAGES 0x20000000
  2244. //
  2245. // Indicates that the request is using a reserved MDL that enables
  2246. // forward progress in low-memory conditions.
  2247. //
  2248. #define SRB_DATA_RESERVED_MDL 0x40000000
  2249. #endif
  2250. //
  2251. // Port Timeout Counter values.
  2252. //
  2253. #define PD_TIMER_STOPPED -1
  2254. //
  2255. // Possible registry flags for pnp interface key
  2256. //
  2257. //
  2258. // The absence of any information about a particular interface in the
  2259. // PnpInterface key in the registry indicates that pnp is not safe for this
  2260. // particular card.
  2261. //
  2262. #define SP_PNP_NOT_SAFE 0x00000000
  2263. //
  2264. // Indicates that pnp is a safe operation for this device. If this flag is
  2265. // set then the miniport will not be allowed to do detection and will always
  2266. // be handed resources provided by the pnp system. This flag may or may not
  2267. // be set in the registry - the fact that a value for a particular interface
  2268. // exists is enough to indicate that pnp is safe and this flag will always
  2269. // be set.
  2270. //
  2271. #define SP_PNP_IS_SAFE 0x00000001
  2272. //
  2273. // Indicates that we should take advantage of a chance to enumerate a particular
  2274. // bus type using the miniport. This flag is set for all non-enumerable legacy
  2275. // buses (ISA, EISA, etc...) and is cleared for the non-legacy ones and for the
  2276. // PnpBus type.
  2277. //
  2278. #define SP_PNP_NON_ENUMERABLE 0x00000002
  2279. //
  2280. // Indicates that we need to include some sort of location information in the
  2281. // config data to discern this adapter from any others.
  2282. //
  2283. #define SP_PNP_NEEDS_LOCATION 0x00000004
  2284. //
  2285. // Indicates that this type of adapter must have an interrupt for us to try
  2286. // and start it. If PNP doesn't provide an interrupt then scsiport will
  2287. // log an error and fail the start operation. If this flag is set then
  2288. // SP_PNP_IS_SAFE must also be set.
  2289. //
  2290. #define SP_PNP_INTERRUPT_REQUIRED 0x00000008
  2291. //
  2292. // Indicates that legacy detection should not be done.
  2293. //
  2294. #define SP_PNP_NO_LEGACY_DETECTION 0x00000010
  2295. //
  2296. // Internal scsiport srb status codes.
  2297. // these must be between 0x38 and 0x3f (inclusive) and should never get
  2298. // returned to a class driver.
  2299. //
  2300. // These values are used after the srb has been put on the adapter's
  2301. // startio queue and thus cannot be completed without running it through the
  2302. // completion DPC.
  2303. //
  2304. #ifndef KDBG_EXT
  2305. //
  2306. // Function declarations
  2307. //
  2308. NTSTATUS
  2309. ScsiPortGlobalDispatch(
  2310. IN PDEVICE_OBJECT DeviceObject,
  2311. IN PIRP Irp
  2312. );
  2313. NTSTATUS
  2314. ScsiPortFdoCreateClose (
  2315. IN PDEVICE_OBJECT DeviceObject,
  2316. IN PIRP Irp
  2317. );
  2318. NTSTATUS
  2319. ScsiPortFdoDispatch(
  2320. IN PDEVICE_OBJECT DeviceObject,
  2321. IN PIRP Irp
  2322. );
  2323. NTSTATUS
  2324. ScsiPortPdoScsi(
  2325. IN PDEVICE_OBJECT DeviceObject,
  2326. IN PIRP Irp
  2327. );
  2328. NTSTATUS
  2329. ScsiPortScsi1PdoScsi(
  2330. IN PDEVICE_OBJECT DeviceObject,
  2331. IN PIRP Irp
  2332. );
  2333. VOID
  2334. ScsiPortStartIo(
  2335. IN PDEVICE_OBJECT DeviceObject,
  2336. IN PIRP Irp
  2337. );
  2338. BOOLEAN
  2339. ScsiPortInterrupt(
  2340. IN PKINTERRUPT InterruptObject,
  2341. IN PDEVICE_OBJECT DeviceObject
  2342. );
  2343. NTSTATUS
  2344. ScsiPortFdoDeviceControl(
  2345. IN PDEVICE_OBJECT DeviceObject,
  2346. IN PIRP Irp
  2347. );
  2348. NTSTATUS
  2349. ScsiPortPdoDeviceControl(
  2350. IN PDEVICE_OBJECT DeviceObject,
  2351. IN PIRP Irp
  2352. );
  2353. NTSTATUS
  2354. ScsiPortPdoCreateClose(
  2355. IN PDEVICE_OBJECT DeviceObject,
  2356. IN PIRP Irp
  2357. );
  2358. NTSTATUS
  2359. ScsiPortPdoPnp(
  2360. IN PDEVICE_OBJECT DeviceObject,
  2361. IN PIRP Irp
  2362. );
  2363. VOID
  2364. ScsiPortTickHandler(
  2365. IN PDEVICE_OBJECT DeviceObject,
  2366. IN PVOID Context
  2367. );
  2368. VOID
  2369. IssueRequestSense(
  2370. IN PADAPTER_EXTENSION deviceExtension,
  2371. IN PSCSI_REQUEST_BLOCK FailingSrb
  2372. );
  2373. BOOLEAN
  2374. SpStartIoSynchronized (
  2375. PVOID ServiceContext
  2376. );
  2377. BOOLEAN
  2378. SpResetBusSynchronized (
  2379. PVOID ServiceContext
  2380. );
  2381. BOOLEAN
  2382. SpTimeoutSynchronized (
  2383. PVOID ServiceContext
  2384. );
  2385. BOOLEAN
  2386. SpEnableInterruptSynchronized (
  2387. PVOID ServiceContext
  2388. );
  2389. VOID
  2390. IssueAbortRequest(
  2391. IN PADAPTER_EXTENSION DeviceExtension,
  2392. IN PLOGICAL_UNIT_EXTENSION LogicalUnit
  2393. );
  2394. BOOLEAN
  2395. SpGetInterruptState(
  2396. IN PVOID ServiceContext
  2397. );
  2398. #if DBG
  2399. #define GetLogicalUnitExtension(fdo, path, target, lun, lock, getlock) \
  2400. GetLogicalUnitExtensionEx(fdo, path, target, lun, lock, getlock, __file__, __LINE__)
  2401. PLOGICAL_UNIT_EXTENSION
  2402. GetLogicalUnitExtensionEx(
  2403. PADAPTER_EXTENSION DeviceExtension,
  2404. UCHAR PathId,
  2405. UCHAR TargetId,
  2406. UCHAR Lun,
  2407. PVOID LockTag,
  2408. BOOLEAN AcquireBinLock,
  2409. PCSTR File,
  2410. ULONG Line
  2411. );
  2412. #else
  2413. PLOGICAL_UNIT_EXTENSION
  2414. GetLogicalUnitExtension(
  2415. PADAPTER_EXTENSION DeviceExtension,
  2416. UCHAR PathId,
  2417. UCHAR TargetId,
  2418. UCHAR Lun,
  2419. PVOID LockTag,
  2420. BOOLEAN AcquireBinLock
  2421. );
  2422. #endif
  2423. IO_ALLOCATION_ACTION
  2424. ScsiPortAllocationRoutine (
  2425. IN PDEVICE_OBJECT DeviceObject,
  2426. IN PIRP Irp,
  2427. IN PVOID MapRegisterBase,
  2428. IN PVOID Context
  2429. );
  2430. VOID
  2431. LogErrorEntry(
  2432. IN PADAPTER_EXTENSION DeviceExtension,
  2433. IN PERROR_LOG_ENTRY LogEntry
  2434. );
  2435. VOID
  2436. FASTCALL
  2437. GetNextLuRequest(
  2438. IN PLOGICAL_UNIT_EXTENSION LogicalUnit
  2439. );
  2440. VOID
  2441. GetNextLuRequestWithoutLock(
  2442. IN PLOGICAL_UNIT_EXTENSION LogicalUnit
  2443. );
  2444. VOID
  2445. SpLogPortTimeoutError(
  2446. IN PADAPTER_EXTENSION DeviceExtension,
  2447. IN ULONG UniqueId
  2448. );
  2449. VOID
  2450. SpProcessCompletedRequest(
  2451. IN PADAPTER_EXTENSION DeviceExtension,
  2452. IN PSRB_DATA SrbData,
  2453. OUT PBOOLEAN CallStartIo
  2454. );
  2455. PSRB_DATA
  2456. SpGetSrbData(
  2457. IN PADAPTER_EXTENSION DeviceExtension,
  2458. UCHAR PathId,
  2459. UCHAR TargetId,
  2460. UCHAR Lun,
  2461. UCHAR QueueTag,
  2462. BOOLEAN AcquireBinLock
  2463. );
  2464. VOID
  2465. SpCompleteSrb(
  2466. IN PADAPTER_EXTENSION DeviceExtension,
  2467. IN PSRB_DATA SrbData,
  2468. IN UCHAR SrbStatus
  2469. );
  2470. BOOLEAN
  2471. SpAllocateSrbExtension(
  2472. IN PADAPTER_EXTENSION DeviceExtension,
  2473. IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
  2474. IN PSCSI_REQUEST_BLOCK Srb,
  2475. OUT BOOLEAN *StartNextRequest,
  2476. OUT BOOLEAN *Tagged
  2477. );
  2478. NTSTATUS
  2479. SpSendMiniPortIoctl(
  2480. IN PADAPTER_EXTENSION DeviceExtension,
  2481. IN PIRP RequestIrp
  2482. );
  2483. NTSTATUS
  2484. SpGetInquiryData(
  2485. IN PADAPTER_EXTENSION DeviceExtension,
  2486. IN PIRP Irp
  2487. );
  2488. NTSTATUS
  2489. SpClaimLogicalUnit(
  2490. IN PADAPTER_EXTENSION AdapterExtension,
  2491. IN PLOGICAL_UNIT_EXTENSION LogicalUnitExtension,
  2492. IN PIRP Irp,
  2493. IN BOOLEAN StartDevice
  2494. );
  2495. VOID
  2496. SpMiniPortTimerDpc(
  2497. IN struct _KDPC *Dpc,
  2498. IN PVOID DeviceObject,
  2499. IN PVOID SystemArgument1,
  2500. IN PVOID SystemArgument2
  2501. );
  2502. BOOLEAN
  2503. SpSynchronizeExecution (
  2504. IN PKINTERRUPT Interrupt,
  2505. IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine,
  2506. IN PVOID SynchronizeContext
  2507. );
  2508. NTSTATUS
  2509. SpGetCommonBuffer(
  2510. IN PADAPTER_EXTENSION DeviceExtension,
  2511. IN ULONG NonCachedExtensionSize
  2512. );
  2513. VOID
  2514. SpDestroyAdapter(
  2515. IN PADAPTER_EXTENSION Adapter,
  2516. IN BOOLEAN Surprise
  2517. );
  2518. VOID
  2519. SpReleaseAdapterResources(
  2520. IN PADAPTER_EXTENSION Adapter,
  2521. IN BOOLEAN Stop,
  2522. IN BOOLEAN Surprise
  2523. );
  2524. NTSTATUS
  2525. SpInitializeConfiguration(
  2526. IN PADAPTER_EXTENSION DeviceExtension,
  2527. IN PUNICODE_STRING RegistryPath,
  2528. IN PHW_INITIALIZATION_DATA HwInitData,
  2529. IN PCONFIGURATION_CONTEXT Context
  2530. );
  2531. VOID
  2532. SpParseDevice(
  2533. IN PADAPTER_EXTENSION DeviceExtension,
  2534. IN HANDLE Key,
  2535. IN PCONFIGURATION_CONTEXT Context,
  2536. IN PUCHAR Buffer
  2537. );
  2538. NTSTATUS
  2539. SpConfigurationCallout(
  2540. IN PVOID Context,
  2541. IN PUNICODE_STRING PathName,
  2542. IN INTERFACE_TYPE BusType,
  2543. IN ULONG BusNumber,
  2544. IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
  2545. IN CONFIGURATION_TYPE ControllerType,
  2546. IN ULONG ControllerNumber,
  2547. IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
  2548. IN CONFIGURATION_TYPE PeripheralType,
  2549. IN ULONG PeripheralNumber,
  2550. IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
  2551. );
  2552. PCM_RESOURCE_LIST
  2553. SpBuildResourceList(
  2554. PADAPTER_EXTENSION DeviceExtension,
  2555. PPORT_CONFIGURATION_INFORMATION MiniportConfigInfo
  2556. );
  2557. BOOLEAN
  2558. GetPciConfiguration(
  2559. IN PDRIVER_OBJECT DriverObject,
  2560. IN OUT PDEVICE_OBJECT DeviceObject,
  2561. IN PHW_INITIALIZATION_DATA HwInitializationData,
  2562. IN PVOID RegistryPath,
  2563. IN ULONG BusNumber,
  2564. IN OUT PPCI_SLOT_NUMBER SlotNumber
  2565. );
  2566. NTSTATUS
  2567. ScsiPortAddDevice(
  2568. IN PDRIVER_OBJECT DriverObject,
  2569. IN PDEVICE_OBJECT PhysicalDeviceObject
  2570. );
  2571. VOID
  2572. ScsiPortUnload(
  2573. IN PDRIVER_OBJECT DriverObject
  2574. );
  2575. NTSTATUS
  2576. ScsiPortFdoPnp(
  2577. IN PDEVICE_OBJECT DeviceObject,
  2578. IN PIRP Irp
  2579. );
  2580. NTSTATUS
  2581. ScsiPortStartAdapter(
  2582. IN PDEVICE_OBJECT Fdo
  2583. );
  2584. NTSTATUS
  2585. ScsiPortStopAdapter(
  2586. IN PDEVICE_OBJECT Adapter,
  2587. IN PIRP StopRequest
  2588. );
  2589. NTSTATUS
  2590. ScsiPortStartLogicalUnit(
  2591. IN PLOGICAL_UNIT_EXTENSION LogicalUnit
  2592. );
  2593. NTSTATUS
  2594. ScsiPortInitLogicalUnit(
  2595. IN PLOGICAL_UNIT_EXTENSION LogicalUnit
  2596. );
  2597. NTSTATUS
  2598. ScsiPortStopLogicalUnit(
  2599. IN PLOGICAL_UNIT_EXTENSION LogicalUnit
  2600. );
  2601. NTSTATUS
  2602. SpEnumerateAdapterSynchronous(
  2603. IN PADAPTER_EXTENSION Adapter,
  2604. IN BOOLEAN Force
  2605. );
  2606. VOID
  2607. SpEnumerateAdapterAsynchronous(
  2608. IN PADAPTER_EXTENSION Adapter,
  2609. IN PSP_ENUMERATION_REQUEST EnumerationRequest,
  2610. IN BOOLEAN Force
  2611. );
  2612. VOID
  2613. SpEnumerationWorker(
  2614. IN PADAPTER_EXTENSION Adapter
  2615. );
  2616. NTSTATUS
  2617. SpExtractDeviceRelations(
  2618. IN PADAPTER_EXTENSION Adapter,
  2619. IN DEVICE_RELATION_TYPE RelationType,
  2620. OUT PDEVICE_RELATIONS *DeviceRelations
  2621. );
  2622. VOID
  2623. ScsiPortInitializeDispatchTables(
  2624. VOID
  2625. );
  2626. NTSTATUS
  2627. ScsiPortStringArrayToMultiString(
  2628. IN PDRIVER_OBJECT DriverObject,
  2629. PUNICODE_STRING MultiString,
  2630. PCSTR StringArray[]
  2631. );
  2632. NTSTATUS
  2633. ScsiPortGetDeviceId(
  2634. IN PDEVICE_OBJECT Pdo,
  2635. OUT PUNICODE_STRING UnicodeString
  2636. );
  2637. NTSTATUS
  2638. ScsiPortGetInstanceId(
  2639. IN PDEVICE_OBJECT Pdo,
  2640. OUT PUNICODE_STRING UnicodeString
  2641. );
  2642. NTSTATUS
  2643. ScsiPortGetCompatibleIds(
  2644. IN PDRIVER_OBJECT DriverObject,
  2645. IN PINQUIRYDATA InquiryData,
  2646. OUT PUNICODE_STRING UnicodeString
  2647. );
  2648. NTSTATUS
  2649. ScsiPortGetHardwareIds(
  2650. IN PDRIVER_OBJECT DriverObject,
  2651. IN PINQUIRYDATA InquiryData,
  2652. OUT PUNICODE_STRING UnicodeString
  2653. );
  2654. NTSTATUS
  2655. ScsiPortStartAdapterCompletion(
  2656. IN PDEVICE_OBJECT DeviceObject,
  2657. IN PIRP Irp,
  2658. IN PVOID Context
  2659. );
  2660. NTSTATUS
  2661. SpReportNewAdapter(
  2662. IN PDEVICE_OBJECT DeviceObject
  2663. );
  2664. NTSTATUS
  2665. ScsiPortQueryPropertyPdo(
  2666. IN PDEVICE_OBJECT DeviceObject,
  2667. IN PIRP QueryIrp
  2668. );
  2669. NTSTATUS
  2670. ScsiPortQueryProperty(
  2671. IN PDEVICE_OBJECT DeviceObject,
  2672. IN PIRP QueryIrp
  2673. );
  2674. NTSTATUS
  2675. ScsiPortInitLegacyAdapter(
  2676. IN PSCSIPORT_DRIVER_EXTENSION DriverExtension,
  2677. IN PHW_INITIALIZATION_DATA HwInitializationData,
  2678. IN PVOID HwContext
  2679. );
  2680. NTSTATUS
  2681. SpCreateAdapter(
  2682. IN PDRIVER_OBJECT DriverObject,
  2683. OUT PDEVICE_OBJECT *Fdo
  2684. );
  2685. VOID
  2686. SpInitializeAdapterExtension(
  2687. IN PADAPTER_EXTENSION FdoExtension,
  2688. IN PHW_INITIALIZATION_DATA HwInitializationData,
  2689. IN OUT PHW_DEVICE_EXTENSION HwDeviceExtension OPTIONAL
  2690. );
  2691. PHW_INITIALIZATION_DATA
  2692. SpFindInitData(
  2693. IN PSCSIPORT_DRIVER_EXTENSION DriverExtension,
  2694. IN INTERFACE_TYPE InterfaceType
  2695. );
  2696. VOID
  2697. SpBuildConfiguration(
  2698. IN PADAPTER_EXTENSION AdapterExtension,
  2699. IN PHW_INITIALIZATION_DATA HwInitializationData,
  2700. IN PPORT_CONFIGURATION_INFORMATION ConfigInformation
  2701. );
  2702. NTSTATUS
  2703. SpCallHwFindAdapter(
  2704. IN PDEVICE_OBJECT Fdo,
  2705. IN PHW_INITIALIZATION_DATA HwInitData,
  2706. IN PVOID HwContext OPTIONAL,
  2707. IN OUT PCONFIGURATION_CONTEXT ConfigurationContext,
  2708. IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
  2709. OUT PBOOLEAN CallAgain
  2710. );
  2711. NTSTATUS
  2712. SpCallHwInitialize(
  2713. IN PDEVICE_OBJECT Fdo
  2714. );
  2715. HANDLE
  2716. SpOpenParametersKey(
  2717. IN PUNICODE_STRING RegistryPath
  2718. );
  2719. HANDLE
  2720. SpOpenDeviceKey(
  2721. IN PUNICODE_STRING RegistryPath,
  2722. IN ULONG DeviceNumber
  2723. );
  2724. ULONG
  2725. SpQueryPnpInterfaceFlags(
  2726. IN PSCSIPORT_DRIVER_EXTENSION DriverExtension,
  2727. IN INTERFACE_TYPE InterfaceType
  2728. );
  2729. NTSTATUS
  2730. SpGetRegistryValue(
  2731. IN PDRIVER_OBJECT DriverObject,
  2732. IN HANDLE Handle,
  2733. IN PWSTR KeyString,
  2734. OUT PKEY_VALUE_FULL_INFORMATION *KeyInformation
  2735. );
  2736. NTSTATUS
  2737. SpInitDeviceMap(
  2738. VOID
  2739. );
  2740. NTSTATUS
  2741. SpBuildDeviceMapEntry(
  2742. IN PCOMMON_EXTENSION CommonExtension
  2743. );
  2744. VOID
  2745. SpDeleteDeviceMapEntry(
  2746. IN PCOMMON_EXTENSION CommonExtension
  2747. );
  2748. NTSTATUS
  2749. SpUpdateLogicalUnitDeviceMapEntry(
  2750. IN PLOGICAL_UNIT_EXTENSION LogicalUnit
  2751. );
  2752. VOID
  2753. SpLogResetMsg(
  2754. IN PADAPTER_EXTENSION DeviceExtension,
  2755. IN PSCSI_REQUEST_BLOCK Srb,
  2756. IN ULONG UniqueId
  2757. );
  2758. VOID
  2759. SpLogResetError(
  2760. IN PADAPTER_EXTENSION DeviceExtension,
  2761. IN PLOGICAL_UNIT_EXTENSION Lun,
  2762. IN ULONG UniqueId
  2763. );
  2764. VOID
  2765. SpRemoveLogicalUnitFromBin (
  2766. IN PADAPTER_EXTENSION AdapterExtension,
  2767. IN PLOGICAL_UNIT_EXTENSION LogicalUnitExtension
  2768. );
  2769. VOID
  2770. SpAddLogicalUnitToBin (
  2771. IN PADAPTER_EXTENSION AdapterExtension,
  2772. IN PLOGICAL_UNIT_EXTENSION LogicalUnitExtension
  2773. );
  2774. PSCSIPORT_DEVICE_TYPE
  2775. SpGetDeviceTypeInfo(
  2776. IN UCHAR DeviceType
  2777. );
  2778. BOOLEAN
  2779. SpRemoveLogicalUnit(
  2780. IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
  2781. IN UCHAR RemoveType
  2782. );
  2783. VOID
  2784. SpDeleteLogicalUnit(
  2785. IN PLOGICAL_UNIT_EXTENSION LogicalUnit
  2786. );
  2787. PLOGICAL_UNIT_EXTENSION
  2788. SpFindSafeLogicalUnit(
  2789. IN PDEVICE_OBJECT DeviceObject,
  2790. IN UCHAR PathId,
  2791. IN PVOID LockTag
  2792. );
  2793. NTSTATUS
  2794. ScsiPortSystemControlIrp(
  2795. IN PDEVICE_OBJECT DeviceObject,
  2796. IN OUT PIRP Irp);
  2797. NTSTATUS
  2798. SpWmiIrpNormalRequest(
  2799. IN PDEVICE_OBJECT DeviceObject,
  2800. IN UCHAR WmiMinorCode,
  2801. IN OUT PWMI_PARAMETERS WmiParameters);
  2802. NTSTATUS
  2803. SpWmiIrpRegisterRequest(
  2804. IN PDEVICE_OBJECT DeviceObject,
  2805. IN OUT PWMI_PARAMETERS WmiParameters);
  2806. NTSTATUS
  2807. SpWmiHandleOnMiniPortBehalf(
  2808. IN PDEVICE_OBJECT DeviceObject,
  2809. IN UCHAR WmiMinorCode,
  2810. IN OUT PWMI_PARAMETERS WmiParameters);
  2811. NTSTATUS
  2812. SpWmiPassToMiniPort(
  2813. IN PDEVICE_OBJECT DeviceObject,
  2814. IN UCHAR WmiMinorCode,
  2815. IN OUT PWMI_PARAMETERS WmiParameters);
  2816. VOID
  2817. SpWmiInitializeSpRegInfo(
  2818. IN PDEVICE_OBJECT DeviceObject);
  2819. VOID
  2820. SpWmiGetSpRegInfo(
  2821. IN PDEVICE_OBJECT DeviceObject,
  2822. OUT PWMIREGINFO * SpRegInfoBuf,
  2823. OUT ULONG * SpRegInfoBufSize);
  2824. VOID
  2825. SpWmiDestroySpRegInfo(
  2826. IN PDEVICE_OBJECT DeviceObject);
  2827. NTSTATUS
  2828. SpWmiInitializeFreeRequestList(
  2829. IN PDEVICE_OBJECT DeviceObject,
  2830. IN ULONG NumberOfItems
  2831. );
  2832. VOID
  2833. SpWmiPushExistingFreeRequestItem(
  2834. IN PADAPTER_EXTENSION Adapter,
  2835. IN PWMI_MINIPORT_REQUEST_ITEM WmiRequestItem
  2836. );
  2837. NTSTATUS
  2838. SpWmiPushFreeRequestItem(
  2839. IN PADAPTER_EXTENSION Adapter
  2840. );
  2841. PWMI_MINIPORT_REQUEST_ITEM
  2842. SpWmiPopFreeRequestItem(
  2843. IN PADAPTER_EXTENSION Adapter
  2844. );
  2845. BOOLEAN
  2846. SpWmiRemoveFreeMiniPortRequestItems(
  2847. IN PADAPTER_EXTENSION fdoExtension
  2848. );
  2849. #if DBG
  2850. ULONG
  2851. FASTCALL
  2852. FASTCALL
  2853. SpAcquireRemoveLockEx(
  2854. IN PDEVICE_OBJECT DeviceObject,
  2855. IN OPTIONAL PVOID Tag,
  2856. IN PCSTR File,
  2857. IN ULONG Line
  2858. );
  2859. #else
  2860. ULONG
  2861. INLINE
  2862. SpAcquireRemoveLock(
  2863. IN PDEVICE_OBJECT DeviceObject,
  2864. IN OPTIONAL PVOID Tag
  2865. )
  2866. {
  2867. PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
  2868. InterlockedIncrement(&commonExtension->RemoveLock);
  2869. return (commonExtension->IsRemoved);
  2870. }
  2871. #endif
  2872. VOID
  2873. FASTCALL
  2874. SpReleaseRemoveLock(
  2875. IN PDEVICE_OBJECT DeviceObject,
  2876. IN OPTIONAL PVOID Tag
  2877. );
  2878. VOID
  2879. FASTCALL
  2880. FASTCALL
  2881. SpCompleteRequest(
  2882. IN PDEVICE_OBJECT DeviceObject,
  2883. IN PIRP Irp,
  2884. IN OPTIONAL PSRB_DATA SrbData,
  2885. IN CCHAR PriorityBoost
  2886. );
  2887. NTSTATUS
  2888. ScsiPortDispatchPower(
  2889. IN PDEVICE_OBJECT DeviceObject,
  2890. IN PIRP Irp
  2891. );
  2892. VOID
  2893. SpDefaultPowerCompletion(
  2894. IN PDEVICE_OBJECT DeviceObject,
  2895. IN UCHAR MinorFunction,
  2896. IN POWER_STATE PowerState,
  2897. IN PIRP OriginalIrp,
  2898. IN PIO_STATUS_BLOCK IoStatus
  2899. );
  2900. PCM_RESOURCE_LIST
  2901. RtlDuplicateCmResourceList(
  2902. IN PDRIVER_OBJECT DriverObject,
  2903. POOL_TYPE PoolType,
  2904. PCM_RESOURCE_LIST ResourceList,
  2905. ULONG Tag
  2906. );
  2907. ULONG
  2908. RtlSizeOfCmResourceList(
  2909. IN PCM_RESOURCE_LIST ResourceList
  2910. );
  2911. BOOLEAN
  2912. SpTranslateResources(
  2913. IN PDRIVER_OBJECT DriverObject,
  2914. IN PCM_RESOURCE_LIST AllocatedResources,
  2915. OUT PCM_RESOURCE_LIST *TranslatedResources
  2916. );
  2917. BOOLEAN
  2918. SpFindAddressTranslation(
  2919. IN PADAPTER_EXTENSION AdapterExtension,
  2920. IN INTERFACE_TYPE BusType,
  2921. IN ULONG BusNumber,
  2922. IN PHYSICAL_ADDRESS RangeStart,
  2923. IN ULONG RangeLength,
  2924. IN BOOLEAN InIoSpace,
  2925. IN OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Translation
  2926. );
  2927. NTSTATUS
  2928. SpAllocateAdapterResources(
  2929. IN PDEVICE_OBJECT Fdo
  2930. );
  2931. NTSTATUS
  2932. SpLockUnlockQueue(
  2933. IN PDEVICE_OBJECT LogicalUnit,
  2934. IN BOOLEAN LockQueue,
  2935. IN BOOLEAN BypassLockedQueue
  2936. );
  2937. VOID
  2938. ScsiPortRemoveAdapter(
  2939. IN PDEVICE_OBJECT Adapter,
  2940. IN BOOLEAN Surprise
  2941. );
  2942. VOID
  2943. SpTerminateAdapter(
  2944. IN PADAPTER_EXTENSION Adapter
  2945. );
  2946. NTSTATUS
  2947. SpQueryDeviceText(
  2948. IN PDEVICE_OBJECT LogicalUnit,
  2949. IN DEVICE_TEXT_TYPE TextType,
  2950. IN LCID LocaleId,
  2951. IN OUT PWSTR *DeviceText
  2952. );
  2953. NTSTATUS
  2954. SpCheckSpecialDeviceFlags(
  2955. IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
  2956. IN PINQUIRYDATA InquiryData
  2957. );
  2958. PSRB_DATA
  2959. FASTCALL
  2960. SpAllocateSrbData(
  2961. IN PADAPTER_EXTENSION Adapter,
  2962. IN OPTIONAL PIRP Request,
  2963. IN OPTIONAL PLOGICAL_UNIT_EXTENSION LogicalUnit
  2964. );
  2965. PSRB_DATA
  2966. FASTCALL
  2967. SpAllocateBypassSrbData(
  2968. IN PLOGICAL_UNIT_EXTENSION LogicalUnit
  2969. );
  2970. VOID
  2971. SpCheckSrbLists(
  2972. IN PADAPTER_EXTENSION Adapter,
  2973. IN PUCHAR FailureString
  2974. );
  2975. VOID
  2976. ScsiPortCompletionDpc(
  2977. IN PKDPC Dpc,
  2978. IN PDEVICE_OBJECT DeviceObject,
  2979. IN PIRP Irp,
  2980. IN PVOID Context
  2981. );
  2982. NTSTATUS
  2983. SpAllocateTagBitMap(
  2984. IN PADAPTER_EXTENSION Adapter
  2985. );
  2986. NTSTATUS
  2987. SpRequestValidPowerState(
  2988. IN PADAPTER_EXTENSION Adapter,
  2989. IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
  2990. IN PSCSI_REQUEST_BLOCK Srb
  2991. );
  2992. NTSTATUS
  2993. SpRequestValidAdapterPowerStateSynchronous(
  2994. IN PADAPTER_EXTENSION Adapter
  2995. );
  2996. NTSTATUS
  2997. SpEnableDisableAdapter(
  2998. IN PADAPTER_EXTENSION Adapter,
  2999. IN BOOLEAN Enable
  3000. );
  3001. NTSTATUS
  3002. SpEnableDisableLogicalUnit(
  3003. IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
  3004. IN BOOLEAN Enable,
  3005. IN PSP_ENABLE_DISABLE_COMPLETION_ROUTINE CompletionRoutine,
  3006. IN PVOID Context
  3007. );
  3008. VOID
  3009. ScsiPortProcessAdapterPower(
  3010. IN PDEVICE_OBJECT DeviceObject,
  3011. IN PIRP Irp
  3012. );
  3013. INTERFACE_TYPE
  3014. SpGetPdoInterfaceType(
  3015. IN PDEVICE_OBJECT Pdo
  3016. );
  3017. NTSTATUS
  3018. SpReadNumericInstanceValue(
  3019. IN PDEVICE_OBJECT Pdo,
  3020. IN PWSTR ValueName,
  3021. OUT PULONG Value
  3022. );
  3023. NTSTATUS
  3024. SpWriteNumericInstanceValue(
  3025. IN PDEVICE_OBJECT Pdo,
  3026. IN PWSTR ValueName,
  3027. IN ULONG Value
  3028. );
  3029. VOID
  3030. SpGetSupportedAdapterControlFunctions(
  3031. IN PADAPTER_EXTENSION Adapter
  3032. );
  3033. VOID
  3034. SpReleaseMappedAddresses(
  3035. IN PADAPTER_EXTENSION Adapter
  3036. );
  3037. VOID
  3038. SpGetSupportedAdapterControlFunctions(
  3039. PADAPTER_EXTENSION Adapter
  3040. );
  3041. BOOLEAN
  3042. SpIsAdapterControlTypeSupported(
  3043. IN PADAPTER_EXTENSION AdapterExtension,
  3044. IN SCSI_ADAPTER_CONTROL_TYPE ControlType
  3045. );
  3046. SCSI_ADAPTER_CONTROL_STATUS
  3047. SpCallAdapterControl(
  3048. IN PADAPTER_EXTENSION AdapterExtension,
  3049. IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
  3050. IN PVOID Parameters
  3051. );
  3052. PVOID
  3053. SpAllocateSrbDataBackend(
  3054. IN POOL_TYPE PoolType,
  3055. IN ULONG NumberOfBytes,
  3056. IN ULONG AdapterIndex
  3057. );
  3058. VOID
  3059. SpFreeSrbDataBackend(
  3060. IN PSRB_DATA SrbData
  3061. );
  3062. ULONG
  3063. SpAllocateQueueTag(
  3064. IN PADAPTER_EXTENSION Adapter
  3065. );
  3066. VOID
  3067. SpReleaseQueueTag(
  3068. IN PADAPTER_EXTENSION Adapter,
  3069. IN ULONG QueueTag
  3070. );
  3071. NTSTATUS
  3072. SpInitializeGuidInterfaceMapping(
  3073. IN PDRIVER_OBJECT DriverObject
  3074. );
  3075. NTSTATUS
  3076. SpSignalCompletion(
  3077. IN PDEVICE_OBJECT DeviceObject,
  3078. IN PIRP Irp,
  3079. IN PKEVENT Event
  3080. );
  3081. NTSTATUS
  3082. SpSendIrpSynchronous(
  3083. IN PDEVICE_OBJECT DeviceObject,
  3084. IN PIRP Irp
  3085. );
  3086. NTSTATUS
  3087. SpGetBusTypeGuid(
  3088. IN PADAPTER_EXTENSION Adapter
  3089. );
  3090. BOOLEAN
  3091. SpDetermine64BitSupport(
  3092. VOID
  3093. );
  3094. VOID
  3095. SpAdjustDisabledBit(
  3096. IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
  3097. IN BOOLEAN Enable
  3098. );
  3099. NTSTATUS
  3100. SpReadNumericValue(
  3101. IN OPTIONAL HANDLE Root,
  3102. IN OPTIONAL PUNICODE_STRING KeyName,
  3103. IN PUNICODE_STRING ValueName,
  3104. OUT PULONG Value
  3105. );
  3106. VOID
  3107. SpWaitForRemoveLock(
  3108. IN PDEVICE_OBJECT DeviceObject,
  3109. IN PVOID LockTag
  3110. );
  3111. VOID
  3112. SpStartLockRequest(
  3113. IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
  3114. IN PIRP Irp OPTIONAL
  3115. );
  3116. BOOLEAN
  3117. SpAdapterConfiguredForSenseDataEvents(
  3118. IN PDEVICE_OBJECT DeviceObject,
  3119. OUT GUID *SenseDataClass
  3120. );
  3121. NTSTATUS
  3122. SpInitAdapterWmiRegInfo(
  3123. IN PDEVICE_OBJECT DeviceObject
  3124. );
  3125. PMAPPED_ADDRESS
  3126. SpAllocateAddressMapping(
  3127. PADAPTER_EXTENSION Adapter
  3128. );
  3129. BOOLEAN
  3130. SpPreallocateAddressMapping(
  3131. PADAPTER_EXTENSION Adapter,
  3132. IN UCHAR NumberOfBlocks
  3133. );
  3134. VOID
  3135. SpPurgeFreeMappedAddressList(
  3136. IN PADAPTER_EXTENSION Adapter
  3137. );
  3138. BOOLEAN
  3139. SpFreeMappedAddress(
  3140. IN PADAPTER_EXTENSION Adapter,
  3141. IN PVOID MappedAddress
  3142. );
  3143. PMAPPED_ADDRESS
  3144. SpFindMappedAddress(
  3145. IN PADAPTER_EXTENSION Adapter,
  3146. IN LARGE_INTEGER IoAddress,
  3147. IN ULONG NumberOfBytes,
  3148. IN ULONG SystemIoBusNumber
  3149. );
  3150. BOOLEAN
  3151. SpTransferBlockedRequestsToAdapter(
  3152. PADAPTER_EXTENSION Adapter
  3153. );
  3154. //
  3155. // SCSIPORT specified verifier error codes.
  3156. //
  3157. #define SCSIPORT_VERIFIER_BAD_INIT_PARAMS 0x1000
  3158. #define SCSIPORT_VERIFIER_STALL_TOO_LONG 0x1001
  3159. #define SCSIPORT_VERIFIER_MINIPORT_ROUTINE_TIMEOUT 0x1002
  3160. #define SCSIPORT_VERIFIER_REQUEST_COMPLETED_TWICE 0x1003
  3161. #define SCSIPORT_VERIFIER_BAD_SRBSTATUS 0x1004
  3162. #define SCSIPORT_VERIFIER_UNTAGGED_REQUEST_ACTIVE 0x1005
  3163. #define SCSIPORT_VERIFIER_BAD_VA 0x1006
  3164. #define SCSIPORT_VERIFIER_RQSTS_NOT_COMPLETE 0x1007
  3165. #define SCSIPORT_VERIFIER_BAD_BUSDATATYPE 0x1008
  3166. #define SP_VRFY_NONE (ULONG)-1
  3167. #define SP_VRFY_COMMON_BUFFERS 0x00000001
  3168. typedef struct _SP_VA_MAPPING_INFO {
  3169. PVOID OriginalSrbExtVa;
  3170. ULONG SrbExtLen;
  3171. PMDL SrbExtMdl;
  3172. PVOID RemappedSrbExtVa;
  3173. PVOID OriginalSenseVa;
  3174. ULONG SenseLen;
  3175. PMDL SenseMdl;
  3176. PVOID RemappedSenseVa;
  3177. } SP_VA_MAPPING_INFO, *PSP_VA_MAPPING_INFO;
  3178. #define GET_VA_MAPPING_INFO(adapter, block)\
  3179. (PSP_VA_MAPPING_INFO)((PUCHAR)(block) + ((adapter)->CommonBufferSize - PAGE_SIZE))
  3180. BOOLEAN
  3181. SpVerifierInitialization(
  3182. VOID
  3183. );
  3184. VOID
  3185. SpVerifySrbStatus(
  3186. PVOID HwDeviceExtension,
  3187. PSCSI_REQUEST_BLOCK srb
  3188. );
  3189. ULONG
  3190. SpHwFindAdapterVrfy (
  3191. IN PVOID DeviceExtension,
  3192. IN PVOID HwContext,
  3193. IN PVOID BusInformation,
  3194. IN PCHAR ArgumentString,
  3195. IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
  3196. OUT PBOOLEAN Again
  3197. );
  3198. BOOLEAN
  3199. SpHwInitializeVrfy (
  3200. IN PVOID DeviceExtension
  3201. );
  3202. BOOLEAN
  3203. SpHwStartIoVrfy (
  3204. IN PVOID DeviceExtension,
  3205. IN PSCSI_REQUEST_BLOCK Srb
  3206. );
  3207. BOOLEAN
  3208. SpHwInterruptVrfy (
  3209. IN PVOID DeviceExtension
  3210. );
  3211. BOOLEAN
  3212. SpHwResetBusVrfy (
  3213. IN PVOID DeviceExtension,
  3214. IN ULONG PathId
  3215. );
  3216. VOID
  3217. SpHwDmaStartedVrfy (
  3218. IN PVOID DeviceExtension
  3219. );
  3220. BOOLEAN
  3221. SpHwRequestInterruptVrfy (
  3222. IN PVOID DeviceExtension
  3223. );
  3224. BOOLEAN
  3225. SpHwTimerRequestVrfy (
  3226. IN PVOID DeviceExtension
  3227. );
  3228. SCSI_ADAPTER_CONTROL_STATUS
  3229. SpHwAdapterControlVrfy (
  3230. IN PVOID DeviceExtension,
  3231. IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
  3232. IN PVOID Parameters
  3233. );
  3234. NTSTATUS
  3235. SpGetCommonBufferVrfy(
  3236. PADAPTER_EXTENSION DeviceExtension,
  3237. ULONG NonCachedExtensionSize
  3238. );
  3239. VOID
  3240. SpFreeCommonBufferVrfy(
  3241. PADAPTER_EXTENSION Adapter
  3242. );
  3243. PVOID
  3244. SpGetOriginalSrbExtVa(
  3245. PADAPTER_EXTENSION Adapter,
  3246. PVOID Va
  3247. );
  3248. VOID
  3249. SpInsertSrbExtension(
  3250. PADAPTER_EXTENSION Adapter,
  3251. PCCHAR SrbExtension
  3252. );
  3253. PVOID
  3254. SpPrepareSrbExtensionForUse(
  3255. PADAPTER_EXTENSION Adapter,
  3256. PCCHAR *SrbExtension
  3257. );
  3258. PCCHAR
  3259. SpPrepareSenseBufferForUse(
  3260. PADAPTER_EXTENSION Adapter,
  3261. PCCHAR SrbExtension
  3262. );
  3263. PVOID
  3264. SpGetInaccessiblePage(
  3265. PADAPTER_EXTENSION Adapter
  3266. );
  3267. VOID
  3268. SpEnsureAllRequestsAreComplete(
  3269. PADAPTER_EXTENSION Adapter
  3270. );
  3271. VOID
  3272. SpDoVerifierCleanup(
  3273. IN PADAPTER_EXTENSION Adapter
  3274. );
  3275. VOID
  3276. SpDoVerifierInit(
  3277. IN PADAPTER_EXTENSION Adapter,
  3278. IN PHW_INITIALIZATION_DATA HwInitializationData
  3279. );
  3280. VOID
  3281. ScsiPortInitPdoWmi(
  3282. IN PLOGICAL_UNIT_EXTENSION LogicalUnit
  3283. );
  3284. PMDL
  3285. INLINE
  3286. SpGetRemappedSrbExt(
  3287. PADAPTER_EXTENSION Adapter,
  3288. PVOID Block
  3289. )
  3290. {
  3291. PSP_VA_MAPPING_INFO MappingInfo = GET_VA_MAPPING_INFO(Adapter, Block);
  3292. return MappingInfo->SrbExtMdl;
  3293. }
  3294. PMDL
  3295. INLINE
  3296. SpGetRemappedSenseBuffer(
  3297. PADAPTER_EXTENSION Adapter,
  3298. PVOID Block
  3299. )
  3300. {
  3301. PSP_VA_MAPPING_INFO MappingInfo = GET_VA_MAPPING_INFO(Adapter, Block);
  3302. return MappingInfo->SenseMdl;
  3303. }
  3304. BOOLEAN
  3305. INLINE
  3306. SpVerifierActive(
  3307. IN PADAPTER_EXTENSION Adapter
  3308. )
  3309. {
  3310. return (Adapter->VerifierExtension != NULL) ? TRUE : FALSE;
  3311. }
  3312. BOOLEAN
  3313. INLINE
  3314. SpVerifyingCommonBuffer(
  3315. IN PADAPTER_EXTENSION Adapter
  3316. )
  3317. {
  3318. return (Adapter->VerifierExtension == NULL) ? FALSE :
  3319. (Adapter->VerifierExtension->VrfyLevel & SP_VRFY_COMMON_BUFFERS) ? TRUE :
  3320. FALSE;
  3321. }
  3322. //
  3323. // Definitions and declarations used for logging allocation failures. When
  3324. // enabled, all allocation failures are logged to the system event log
  3325. // as warnings.
  3326. //
  3327. PVOID
  3328. SpAllocateErrorLogEntry(
  3329. IN PDRIVER_OBJECT DriverObject
  3330. );
  3331. VOID
  3332. FASTCALL
  3333. SpLogAllocationFailureFn(
  3334. IN PDRIVER_OBJECT DriverObject,
  3335. IN POOL_TYPE PoolType,
  3336. IN SIZE_T Size,
  3337. IN ULONG Tag,
  3338. IN ULONG FileId,
  3339. IN ULONG LineNumber
  3340. );
  3341. PVOID
  3342. SpAllocatePoolEx(
  3343. IN POOL_TYPE PoolType,
  3344. IN SIZE_T NumberOfBytes,
  3345. IN ULONG Tag,
  3346. IN PDRIVER_OBJECT DriverObject,
  3347. IN ULONG FileId,
  3348. IN ULONG LineNumber
  3349. );
  3350. PMDL
  3351. SpAllocateMdlEx(
  3352. IN PVOID VirtualAddress,
  3353. IN ULONG Length,
  3354. IN BOOLEAN SecondaryBuffer,
  3355. IN BOOLEAN ChargeQuota,
  3356. IN OUT PIRP Irp,
  3357. IN PDRIVER_OBJECT DriverObject,
  3358. IN ULONG FileId,
  3359. IN ULONG LineNumber
  3360. );
  3361. PIRP
  3362. SpAllocateIrpEx(
  3363. IN CCHAR StackSize,
  3364. IN BOOLEAN ChargeQuota,
  3365. IN PDRIVER_OBJECT DriverObject,
  3366. IN ULONG FileId,
  3367. IN ULONG LineNumber
  3368. );
  3369. #define SCSIPORT_TAG_ALLOCMDL TAG('LDMs')
  3370. #define SCSIPORT_TAG_ALLOCIRP TAG('PRIs')
  3371. #define SCSIPORT_TAG_LOOKASIDE TAG('LALs')
  3372. #define SpAllocatePool(type, size, tag, drvObj) \
  3373. SpAllocatePoolEx((type), (size), (tag), (drvObj), __FILE_ID__, __LINE__)
  3374. #define SpAllocateMdl(va, len, secbuf, cq, irp, drvobj) \
  3375. SpAllocateMdlEx((va), (len), (secbuf), (cq), (irp), (drvobj), __FILE_ID__, __LINE__)
  3376. #define SpAllocateIrp(ss, cq, drvobj) \
  3377. SpAllocateIrpEx((ss), (cq), (drvobj), __FILE_ID__, __LINE__)
  3378. //
  3379. // This structure makes it easy to allocate a contiguous chunk of memory
  3380. // for an event log entry with room for the insertion strings.
  3381. //
  3382. typedef struct _SCSIPORT_ALLOCFAILURE_DATA {
  3383. ULONG Size;
  3384. ULONG FileId;
  3385. ULONG LineNumber;
  3386. } SCSIPORT_ALLOCFAILURE_DATA;
  3387. //
  3388. // Inline functions
  3389. //
  3390. ULONG
  3391. INLINE
  3392. SpGetCommonBufferSize(
  3393. IN PADAPTER_EXTENSION DeviceExtension,
  3394. IN ULONG NonCachedExtensionSize,
  3395. OUT OPTIONAL PULONG BlockSize
  3396. )
  3397. {
  3398. ULONG length;
  3399. ULONG blockSize;
  3400. //
  3401. // To ensure that we never transfer normal request data to the SrbExtension
  3402. // (ie. the case of Srb->SenseInfoBuffer == VirtualAddress in
  3403. // ScsiPortGetPhysicalAddress) on some platforms where an inconsistency in
  3404. // MM can result in the same Virtual address supplied for 2 different
  3405. // physical addresses, bump the SrbExtensionSize if it's zero.
  3406. //
  3407. if (DeviceExtension->SrbExtensionSize == 0) {
  3408. DeviceExtension->SrbExtensionSize = 16;
  3409. }
  3410. //
  3411. // Calculate the block size for the list elements based on the Srb
  3412. // Extension.
  3413. //
  3414. blockSize = DeviceExtension->SrbExtensionSize;
  3415. //
  3416. // If auto request sense is supported then add in space for the request
  3417. // sense data.
  3418. //
  3419. if (DeviceExtension->AutoRequestSense) {
  3420. blockSize += sizeof(SENSE_DATA) +
  3421. DeviceExtension->AdditionalSenseBytes;
  3422. }
  3423. //
  3424. // Round blocksize up to the size of a PVOID.
  3425. //
  3426. blockSize = (blockSize + sizeof(LONGLONG) - 1) & ~(sizeof(LONGLONG) - 1);
  3427. //
  3428. // The length of the common buffer should be equal to the size of the
  3429. // noncached extension and a minimum number of srb extension
  3430. //
  3431. length = NonCachedExtensionSize +
  3432. (blockSize * DeviceExtension->NumberOfRequests);
  3433. //
  3434. // Round the length up to a page size, since HalAllocateCommonBuffer
  3435. // allocates in pages anyway.
  3436. //
  3437. length = (ULONG)ROUND_TO_PAGES(length);
  3438. //
  3439. // If the user is interested in the block size, copy it into the provided
  3440. // buffer.
  3441. //
  3442. if (BlockSize != NULL) {
  3443. *BlockSize = blockSize;
  3444. }
  3445. return length;
  3446. }
  3447. NTSTATUS
  3448. INLINE
  3449. SpDispatchRequest(
  3450. IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
  3451. IN PIRP Irp
  3452. )
  3453. {
  3454. PCOMMON_EXTENSION commonExtension = &(LogicalUnit->CommonExtension);
  3455. PCOMMON_EXTENSION lowerCommonExtension =
  3456. commonExtension->LowerDeviceObject->DeviceExtension;
  3457. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  3458. PSCSI_REQUEST_BLOCK srb = irpStack->Parameters.Scsi.Srb;
  3459. ASSERT_PDO(LogicalUnit->CommonExtension.DeviceObject);
  3460. ASSERT_SRB_DATA(srb->OriginalRequest);
  3461. if((LogicalUnit->CommonExtension.IdleTimer != NULL) &&
  3462. (SpSrbRequiresPower(srb)) &&
  3463. !(srb->SrbFlags & SRB_FLAGS_BYPASS_LOCKED_QUEUE) &&
  3464. !(srb->SrbFlags & SRB_FLAGS_NO_KEEP_AWAKE)) {
  3465. PoSetDeviceBusy(LogicalUnit->CommonExtension.IdleTimer);
  3466. }
  3467. ASSERT(irpStack->MajorFunction == IRP_MJ_SCSI);
  3468. return (lowerCommonExtension->MajorFunction[IRP_MJ_SCSI])(
  3469. commonExtension->LowerDeviceObject,
  3470. Irp);
  3471. }
  3472. BOOLEAN
  3473. INLINE
  3474. SpSrbIsBypassRequest(
  3475. PSCSI_REQUEST_BLOCK Srb,
  3476. ULONG LuFlags
  3477. )
  3478. /*++
  3479. Routine Description:
  3480. This routine determines whether a request is a "bypass" request - one which
  3481. should skip the lun queueing and be injected straight into the startio
  3482. queue.
  3483. Bypass requests do not start the next LU request when they complete. This
  3484. ensures that no new i/o is run until the condition being bypassed is
  3485. cleared.
  3486. Note: LOCK & UNLOCK requests are not bypass requests unless the queue
  3487. is already locked. This ensures that the first LOCK request will
  3488. get run after previously queued requests, but that additional LOCK
  3489. requests will not get stuck in the lun queue.
  3490. Likewise any UNLOCK request sent when the queue is locked will be
  3491. run immediately. However since SpStartIoSynchronized checks to
  3492. see if the request is a bypass request AFTER ScsiPortStartIo has
  3493. cleared the QUEUE_LOCKED flag this will force the completion dpc
  3494. to call GetNextLuRequest which will take the next operation out of
  3495. the lun queue. This is how i/o is restarted after a lock sequence
  3496. has been completed.
  3497. Arguments:
  3498. Srb - the srb in question
  3499. LuFlags - the flags for the lun.
  3500. Return Value:
  3501. TRUE if the request should bypass the lun queue, be injected into the
  3502. StartIo queue and if GetNextLuRequest should not be called after this
  3503. request has completed.
  3504. FALSE otherwise
  3505. --*/
  3506. {
  3507. ULONG flags = Srb->SrbFlags & (SRB_FLAGS_BYPASS_FROZEN_QUEUE |
  3508. SRB_FLAGS_BYPASS_LOCKED_QUEUE);
  3509. ASSERT(TEST_FLAG(LuFlags, LU_QUEUE_FROZEN | LU_QUEUE_LOCKED) !=
  3510. (LU_QUEUE_FROZEN | LU_QUEUE_LOCKED));
  3511. if(flags == 0) {
  3512. return FALSE;
  3513. }
  3514. if(flags & SRB_FLAGS_BYPASS_LOCKED_QUEUE) {
  3515. DebugPrint((2, "SpSrbIsBypassRequest: Srb %#08lx is marked to bypass "
  3516. "locked queue\n", Srb));
  3517. if(TEST_FLAG(LuFlags, LU_QUEUE_LOCKED | LU_QUEUE_PAUSED)) {
  3518. DebugPrint((1, "SpSrbIsBypassRequest: Queue is locked - %#08lx is "
  3519. "a bypass srb\n", Srb));
  3520. return TRUE;
  3521. } else {
  3522. DebugPrint((3, "SpSrbIsBypassRequest: Queue is not locked - not a "
  3523. "bypass request\n"));
  3524. return FALSE;
  3525. }
  3526. }
  3527. return TRUE;
  3528. }
  3529. VOID
  3530. INLINE
  3531. SpRequestCompletionDpc(
  3532. IN PDEVICE_OBJECT Adapter
  3533. )
  3534. /*++
  3535. Routine Description:
  3536. This routine will request that the Completion DPC be queued if there isn't
  3537. already one queued or in progress. It will set the DpcFlags
  3538. PD_DPC_NOTIFICATION_REQUIRED and PD_DPC_RUNNING. If the DPC_RUNNING flag
  3539. was not already set then it will request a DPC from the system as well.
  3540. Arguments:
  3541. Adapter - the Adapter to request the DPC for
  3542. Return Value:
  3543. none
  3544. --*/
  3545. {
  3546. PADAPTER_EXTENSION adapterExtension = Adapter->DeviceExtension;
  3547. ULONG oldDpcFlags;
  3548. //
  3549. // Set the DPC flags to indicate that there is work to be processed
  3550. // (otherwise we wouldn't queue the DPC) and that the DPC is queued.
  3551. //
  3552. oldDpcFlags = InterlockedExchange(
  3553. &(adapterExtension->DpcFlags),
  3554. (PD_NOTIFICATION_REQUIRED | PD_DPC_RUNNING));
  3555. //
  3556. // If the DPC was already queued or running then don't bother requesting
  3557. // a new one - the current one will pickup the work itself.
  3558. //
  3559. if(TEST_FLAG(oldDpcFlags, PD_DPC_RUNNING) == FALSE) {
  3560. IoRequestDpc(Adapter, NULL, NULL);
  3561. }
  3562. return;
  3563. }
  3564. NTSTATUS
  3565. INLINE
  3566. SpTranslateScsiStatus(
  3567. IN PSCSI_REQUEST_BLOCK Srb
  3568. )
  3569. /*++
  3570. Routine Description:
  3571. This routine translates an srb status into an ntstatus.
  3572. Arguments:
  3573. Srb - Supplies a pointer to the failing Srb.
  3574. Return Value:
  3575. An nt status approprate for the error.
  3576. --*/
  3577. {
  3578. switch (SRB_STATUS(Srb->SrbStatus)) {
  3579. case SRB_STATUS_INVALID_LUN:
  3580. case SRB_STATUS_INVALID_TARGET_ID:
  3581. case SRB_STATUS_NO_DEVICE:
  3582. case SRB_STATUS_NO_HBA:
  3583. return(STATUS_DEVICE_DOES_NOT_EXIST);
  3584. case SRB_STATUS_COMMAND_TIMEOUT:
  3585. case SRB_STATUS_TIMEOUT:
  3586. return(STATUS_IO_TIMEOUT);
  3587. case SRB_STATUS_SELECTION_TIMEOUT:
  3588. return(STATUS_DEVICE_NOT_CONNECTED);
  3589. case SRB_STATUS_BAD_FUNCTION:
  3590. case SRB_STATUS_BAD_SRB_BLOCK_LENGTH:
  3591. return(STATUS_INVALID_DEVICE_REQUEST);
  3592. case SRB_STATUS_DATA_OVERRUN:
  3593. return(STATUS_BUFFER_OVERFLOW);
  3594. default:
  3595. return(STATUS_IO_DEVICE_ERROR);
  3596. }
  3597. return(STATUS_IO_DEVICE_ERROR);
  3598. }
  3599. PVOID
  3600. INLINE
  3601. SpGetSrbExtensionBuffer(
  3602. IN PADAPTER_EXTENSION Adapter
  3603. )
  3604. /*++
  3605. Routine Description:
  3606. This routine returns a pointer to the adapter's SrbExtensionBuffer.
  3607. Arguments:
  3608. Adapter - Supplies a pointer to the adapter's ADAPTER_EXTNENSION.
  3609. Return Value:
  3610. A pointer to the adapter's SrbExtensionBuffer.
  3611. --*/
  3612. {
  3613. return (SpVerifyingCommonBuffer(Adapter)) ?
  3614. Adapter->VerifierExtension->CommonBufferVAs :
  3615. Adapter->SrbExtensionBuffer;
  3616. }
  3617. VOID
  3618. INLINE
  3619. SpForceRequestIntoLuQueue(
  3620. IN PKDEVICE_QUEUE DeviceQueue,
  3621. IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry,
  3622. IN ULONG SortKey,
  3623. IN PVOID BusyRequest
  3624. )
  3625. {
  3626. if (!KeInsertByKeyDeviceQueue(
  3627. DeviceQueue,
  3628. DeviceQueueEntry,
  3629. SortKey)) {
  3630. //
  3631. // The LU says it is busy, so there should be a busy request.
  3632. //
  3633. ASSERT(BusyRequest != NULL);
  3634. //
  3635. // We can arrive here if the LU's device queue was drained by
  3636. // the DCP routine prior to calling us, transitioning the queue
  3637. // from busy to not busy. It is safe for us to force the
  3638. // request into the queue because we know we have a busy
  3639. // request that will get restarted by our TickHandler routine.
  3640. //
  3641. KeInsertByKeyDeviceQueue(
  3642. DeviceQueue,
  3643. DeviceQueueEntry,
  3644. SortKey);
  3645. }
  3646. }
  3647. PMDL
  3648. SpBuildMdlForMappedTransfer(
  3649. IN PDEVICE_OBJECT DeviceObject,
  3650. IN PDMA_ADAPTER AdapterObject,
  3651. IN PMDL OriginalMdl,
  3652. IN PVOID StartVa,
  3653. IN ULONG ByteCount,
  3654. IN PSRB_SCATTER_GATHER ScatterGatherList,
  3655. IN ULONG ScatterGatherEntries
  3656. );
  3657. NTSTATUS
  3658. SpFlushReleaseQueue(
  3659. IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
  3660. IN BOOLEAN Flush,
  3661. IN BOOLEAN SurpriseRemove
  3662. );
  3663. #if defined(FORWARD_PROGRESS)
  3664. VOID
  3665. SpPrepareMdlForMappedTransfer(
  3666. IN PMDL mdl,
  3667. IN PDEVICE_OBJECT DeviceObject,
  3668. IN PDMA_ADAPTER AdapterObject,
  3669. IN PMDL OriginalMdl,
  3670. IN PVOID StartVa,
  3671. IN ULONG ByteCount,
  3672. IN PSRB_SCATTER_GATHER ScatterGatherList,
  3673. IN ULONG ScatterGatherEntries
  3674. );
  3675. VOID
  3676. INLINE
  3677. SpFreeSrbExtension(
  3678. IN PADAPTER_EXTENSION Adapter,
  3679. IN PVOID SrbExtension
  3680. )
  3681. {
  3682. if (SpVerifyingCommonBuffer(Adapter)) {
  3683. SpInsertSrbExtension(Adapter, SrbExtension);
  3684. } else {
  3685. *((PVOID *) SrbExtension) = Adapter->SrbExtensionListHeader;
  3686. Adapter->SrbExtensionListHeader = SrbExtension;
  3687. }
  3688. }
  3689. #endif // FORWARD_PROGRESS
  3690. #endif
  3691. #if defined(NEWQUEUE)
  3692. #define SP_DEFAULT_MAX_CAPACITY 0xffffffff
  3693. #define SP_DEFAULT_ZONES 4
  3694. extern ULONG SpPerZoneLimit;
  3695. extern ULONG SpPerBlockLimit;
  3696. #endif // NEWQUEUE
  3697. #endif // _PORT_H_