Source code of Windows XP (NT5)
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.

3049 lines
87 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1990 - 2000
  3. Module Name:
  4. verify.c
  5. Abstract:
  6. This module implements a driver verifier extension for the SCSI port
  7. driver. Scsiport adds some of its exports to the list of apis that get
  8. thunked by the system driver verifier, thus enabling scsiport-specific
  9. verification of miniport drivers.
  10. Authors:
  11. John Strange (JohnStra)
  12. Environment:
  13. kernel mode only
  14. Revision History:
  15. --*/
  16. #include "port.h"
  17. #if DBG
  18. static const char *__file__ = __FILE__;
  19. #endif
  20. #define __FILE_ID__ 'vfry'
  21. SCSIPORT_API
  22. ULONG
  23. ScsiPortInitializeVrfy(
  24. IN PVOID Argument1,
  25. IN PVOID Argument2,
  26. IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
  27. IN PVOID HwContext
  28. );
  29. SCSIPORT_API
  30. VOID
  31. ScsiPortCompleteRequestVrfy(
  32. IN PVOID HwDeviceExtension,
  33. IN UCHAR PathId,
  34. IN UCHAR TargetId,
  35. IN UCHAR Lun,
  36. IN UCHAR SrbStatus
  37. );
  38. SCSIPORT_API
  39. PSCSI_REQUEST_BLOCK
  40. ScsiPortGetSrbVrfy(
  41. IN PVOID DeviceExtension,
  42. IN UCHAR PathId,
  43. IN UCHAR TargetId,
  44. IN UCHAR Lun,
  45. IN LONG QueueTag
  46. );
  47. SCSIPORT_API
  48. PVOID
  49. ScsiPortGetDeviceBaseVrfy(
  50. IN PVOID HwDeviceExtension,
  51. IN INTERFACE_TYPE BusType,
  52. IN ULONG SystemIoBusNumber,
  53. IN SCSI_PHYSICAL_ADDRESS IoAddress,
  54. IN ULONG NumberOfBytes,
  55. IN BOOLEAN InIoSpace
  56. );
  57. SCSIPORT_API
  58. VOID
  59. ScsiPortNotificationVrfy(
  60. IN SCSI_NOTIFICATION_TYPE NotificationType,
  61. IN PVOID HwDeviceExtension,
  62. ...
  63. );
  64. SCSIPORT_API
  65. VOID
  66. ScsiPortFlushDmaVrfy(
  67. IN PVOID DeviceExtension
  68. );
  69. SCSIPORT_API
  70. VOID
  71. ScsiPortFreeDeviceBaseVrfy(
  72. IN PVOID HwDeviceExtension,
  73. IN PVOID MappedAddress
  74. );
  75. SCSIPORT_API
  76. ULONG
  77. ScsiPortGetBusDataVrfy(
  78. IN PVOID DeviceExtension,
  79. IN ULONG BusDataType,
  80. IN ULONG SystemIoBusNumber,
  81. IN ULONG SlotNumber,
  82. IN PVOID Buffer,
  83. IN ULONG Length
  84. );
  85. SCSIPORT_API
  86. PVOID
  87. ScsiPortGetLogicalUnitVrfy(
  88. IN PVOID HwDeviceExtension,
  89. IN UCHAR PathId,
  90. IN UCHAR TargetId,
  91. IN UCHAR Lun
  92. );
  93. SCSIPORT_API
  94. SCSI_PHYSICAL_ADDRESS
  95. ScsiPortGetPhysicalAddressVrfy(
  96. IN PVOID HwDeviceExtension,
  97. IN PSCSI_REQUEST_BLOCK Srb,
  98. IN PVOID VirtualAddress,
  99. OUT ULONG *Length
  100. );
  101. SCSIPORT_API
  102. PVOID
  103. ScsiPortGetUncachedExtensionVrfy(
  104. IN PVOID HwDeviceExtension,
  105. IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
  106. IN ULONG NumberOfBytes
  107. );
  108. SCSIPORT_API
  109. PVOID
  110. ScsiPortGetVirtualAddressVrfy(
  111. IN PVOID HwDeviceExtension,
  112. IN SCSI_PHYSICAL_ADDRESS PhysicalAddress
  113. );
  114. SCSIPORT_API
  115. VOID
  116. ScsiPortIoMapTransferVrfy(
  117. IN PVOID HwDeviceExtension,
  118. IN PSCSI_REQUEST_BLOCK Srb,
  119. IN PVOID LogicalAddress,
  120. IN ULONG Length
  121. );
  122. SCSIPORT_API
  123. VOID
  124. ScsiPortMoveMemoryVrfy(
  125. IN PVOID WriteBuffer,
  126. IN PVOID ReadBuffer,
  127. IN ULONG Length
  128. );
  129. SCSIPORT_API
  130. ULONG
  131. ScsiPortSetBusDataByOffsetVrfy(
  132. IN PVOID DeviceExtension,
  133. IN ULONG BusDataType,
  134. IN ULONG SystemIoBusNumber,
  135. IN ULONG SlotNumber,
  136. IN PVOID Buffer,
  137. IN ULONG Offset,
  138. IN ULONG Length
  139. );
  140. SCSIPORT_API
  141. BOOLEAN
  142. ScsiPortValidateRangeVrfy(
  143. IN PVOID HwDeviceExtension,
  144. IN INTERFACE_TYPE BusType,
  145. IN ULONG SystemIoBusNumber,
  146. IN SCSI_PHYSICAL_ADDRESS IoAddress,
  147. IN ULONG NumberOfBytes,
  148. IN BOOLEAN InIoSpace
  149. );
  150. SCSIPORT_API
  151. VOID
  152. ScsiPortStallExecutionVrfy(
  153. IN ULONG Delay
  154. );
  155. PVOID
  156. SpAllocateContiguousChunk(
  157. IN PDRIVER_OBJECT DriverObject,
  158. IN PDMA_ADAPTER DmaAdapterObject,
  159. IN BOOLEAN Dma64BitAddresses,
  160. IN ULONG Length,
  161. IN ULONG Align,
  162. OUT PHYSICAL_ADDRESS *PhysicalCommonBuffer,
  163. OUT BOOLEAN *CommonBuffer
  164. );
  165. PVOID
  166. SpRemapBlock(
  167. IN PVOID BlockVa,
  168. IN ULONG BlockSize,
  169. OUT PMDL* Mdl
  170. );
  171. BOOLEAN
  172. SpCheckForActiveRequests(
  173. IN PADAPTER_EXTENSION
  174. );
  175. ULONG
  176. SpGetAdapterVerifyLevel(
  177. IN PADAPTER_EXTENSION Adapter
  178. );
  179. #ifdef ALLOC_PRAGMA
  180. #pragma alloc_text(PAGE, SpVerifierInitialization)
  181. #pragma alloc_text(PAGE, ScsiPortInitializeVrfy)
  182. #pragma alloc_text(PAGE, SpGetAdapterVerifyLevel)
  183. #pragma alloc_text(PAGE, SpDoVerifierInit)
  184. #pragma alloc_text(PAGEVRFY1, ScsiPortGetSrbVrfy)
  185. #pragma alloc_text(PAGEVRFY1, ScsiPortCompleteRequestVrfy)
  186. #pragma alloc_text(PAGEVRFY1, ScsiPortGetDeviceBaseVrfy)
  187. #pragma alloc_text(PAGEVRFY1, ScsiPortNotificationVrfy)
  188. #pragma alloc_text(PAGEVRFY1, ScsiPortFlushDmaVrfy)
  189. #pragma alloc_text(PAGEVRFY1, ScsiPortFreeDeviceBaseVrfy)
  190. #pragma alloc_text(PAGEVRFY1, ScsiPortGetBusDataVrfy)
  191. #pragma alloc_text(PAGEVRFY1, ScsiPortGetLogicalUnitVrfy)
  192. #pragma alloc_text(PAGEVRFY1, ScsiPortGetPhysicalAddressVrfy)
  193. #pragma alloc_text(PAGEVRFY1, ScsiPortGetUncachedExtensionVrfy)
  194. #pragma alloc_text(PAGEVRFY1, ScsiPortGetVirtualAddressVrfy)
  195. #pragma alloc_text(PAGEVRFY1, ScsiPortMoveMemoryVrfy)
  196. #pragma alloc_text(PAGEVRFY1, ScsiPortSetBusDataByOffsetVrfy)
  197. #pragma alloc_text(PAGEVRFY1, ScsiPortValidateRangeVrfy)
  198. #pragma alloc_text(PAGEVRFY1, ScsiPortStallExecutionVrfy)
  199. #pragma alloc_text(PAGEVRFY, SpHwFindAdapterVrfy)
  200. #pragma alloc_text(PAGEVRFY, SpHwInitializeVrfy)
  201. #pragma alloc_text(PAGEVRFY, SpHwStartIoVrfy)
  202. #pragma alloc_text(PAGEVRFY, SpHwInterruptVrfy)
  203. #pragma alloc_text(PAGEVRFY, SpHwResetBusVrfy)
  204. #pragma alloc_text(PAGEVRFY, SpHwDmaStartedVrfy)
  205. #pragma alloc_text(PAGEVRFY, SpHwRequestInterruptVrfy)
  206. #pragma alloc_text(PAGEVRFY, SpHwTimerRequestVrfy)
  207. #pragma alloc_text(PAGEVRFY, SpHwAdapterControlVrfy)
  208. #pragma alloc_text(PAGEVRFY, SpVerifySrbStatus)
  209. #pragma alloc_text(PAGEVRFY, SpAllocateContiguousChunk)
  210. #pragma alloc_text(PAGEVRFY, SpGetCommonBufferVrfy)
  211. #pragma alloc_text(PAGEVRFY, SpFreeCommonBufferVrfy)
  212. #pragma alloc_text(PAGEVRFY, SpGetOriginalSrbExtVa)
  213. #pragma alloc_text(PAGEVRFY, SpInsertSrbExtension)
  214. #pragma alloc_text(PAGEVRFY, SpPrepareSrbExtensionForUse)
  215. #pragma alloc_text(PAGEVRFY, SpPrepareSenseBufferForUse)
  216. #pragma alloc_text(PAGEVRFY, SpRemapBlock)
  217. #pragma alloc_text(PAGEVRFY, SpGetInaccessiblePage)
  218. #pragma alloc_text(PAGEVRFY, SpEnsureAllRequestsAreComplete)
  219. #pragma alloc_text(PAGEVRFY, SpCheckForActiveRequests)
  220. #endif
  221. //
  222. // Some defines and a macro for conditionally verifying based on the
  223. // verification level.
  224. //
  225. #define SP_DONT_CHK_HW_INITIALIZE_DURATION 0x80000000
  226. #define SP_DONT_CHK_ACTIVE_UNTAGGED_REQUEST 0x40000000
  227. #define SP_DONT_CHK_REQUESTS_ON_RESET 0x20000000
  228. #define SP_DONT_CHK_HW_ADAPTERCONTROL_DURATION 0x10000000
  229. #define VRFY_DO_CHECK(adapter, chk)\
  230. (((adapter)->VerifierExtension != NULL) &&\
  231. (((adapter)->VerifierExtension->VrfyLevel & (chk)) == 0))
  232. //
  233. // Indicates whether scsiport's verifier functionality has been initialized.
  234. //
  235. ULONG ScsiPortVerifierInitialized = 0;
  236. //
  237. // Handle to pageable verifier code sections. We manually lock the verify
  238. // code into memory iff we need it.
  239. //
  240. PVOID VerifierCodeSectionHandle = NULL;
  241. PVOID VerifierApiCodeSectionHandle = NULL;
  242. //
  243. // Time increment of the interval timer in 100 ns units. We use this to
  244. // calculate the time miniport routines execute so we can catch those that
  245. // run longer than they should.
  246. //
  247. ULONG TimeIncrement;
  248. //
  249. // Global variable used to control verification aggressiveness. This value
  250. // is used in conjuction with a per-adapter registry value, to control what
  251. // type of verification we do on a particular miniport.
  252. //
  253. ULONG SpVrfyLevel = 0;
  254. //
  255. // Global variable used to control how aggressively we seek out stall
  256. // offenders. Default is a tenth of a second.
  257. //
  258. ULONG SpVrfyMaximumStall = 100000;
  259. //
  260. // When verifier needs a unique address, this is what it uses.
  261. //
  262. ULONG SpMarker = 0x59465256;
  263. //
  264. // This table represents the functions verify will thunk for us.
  265. //
  266. #define SPVERIFIERFUNC(pfn) ((PDRIVER_VERIFIER_THUNK_ROUTINE)(pfn))
  267. const DRIVER_VERIFIER_THUNK_PAIRS ScsiPortVerifierFunctionTable[] =
  268. {
  269. {SPVERIFIERFUNC(ScsiPortInitialize), SPVERIFIERFUNC(ScsiPortInitializeVrfy)},
  270. {SPVERIFIERFUNC(ScsiPortGetSrb), SPVERIFIERFUNC(ScsiPortGetSrbVrfy)},
  271. {SPVERIFIERFUNC(ScsiPortCompleteRequest), SPVERIFIERFUNC(ScsiPortCompleteRequestVrfy)},
  272. {SPVERIFIERFUNC(ScsiPortGetDeviceBase), SPVERIFIERFUNC(ScsiPortGetDeviceBaseVrfy)},
  273. {SPVERIFIERFUNC(ScsiPortNotification), SPVERIFIERFUNC(ScsiPortNotificationVrfy)},
  274. {SPVERIFIERFUNC(ScsiPortFlushDma), SPVERIFIERFUNC(ScsiPortFlushDmaVrfy)},
  275. {SPVERIFIERFUNC(ScsiPortFreeDeviceBase), SPVERIFIERFUNC(ScsiPortFreeDeviceBaseVrfy)},
  276. {SPVERIFIERFUNC(ScsiPortGetBusData), SPVERIFIERFUNC(ScsiPortGetBusDataVrfy)},
  277. {SPVERIFIERFUNC(ScsiPortGetLogicalUnit), SPVERIFIERFUNC(ScsiPortGetLogicalUnitVrfy)},
  278. {SPVERIFIERFUNC(ScsiPortGetPhysicalAddress), SPVERIFIERFUNC(ScsiPortGetPhysicalAddressVrfy)},
  279. {SPVERIFIERFUNC(ScsiPortGetUncachedExtension), SPVERIFIERFUNC(ScsiPortGetUncachedExtensionVrfy)},
  280. {SPVERIFIERFUNC(ScsiPortGetVirtualAddress), SPVERIFIERFUNC(ScsiPortGetVirtualAddressVrfy)},
  281. {SPVERIFIERFUNC(ScsiPortIoMapTransfer), SPVERIFIERFUNC(ScsiPortIoMapTransferVrfy)},
  282. {SPVERIFIERFUNC(ScsiPortMoveMemory), SPVERIFIERFUNC(ScsiPortMoveMemoryVrfy)},
  283. {SPVERIFIERFUNC(ScsiPortSetBusDataByOffset), SPVERIFIERFUNC(ScsiPortSetBusDataByOffsetVrfy)},
  284. {SPVERIFIERFUNC(ScsiPortValidateRange), SPVERIFIERFUNC(ScsiPortValidateRangeVrfy)},
  285. {SPVERIFIERFUNC(ScsiPortStallExecution), SPVERIFIERFUNC(ScsiPortStallExecutionVrfy)},
  286. };
  287. BOOLEAN
  288. SpVerifierInitialization(
  289. VOID
  290. )
  291. /*++
  292. Routine Description:
  293. This routine initializes scsiport's verifier functionality.
  294. Adds several of scsiport's exported functions to the list of routines
  295. thunked by the system verifier.
  296. Arguments:
  297. VOID
  298. Return Value:
  299. TRUE if verifier is successfully initialized.
  300. --*/
  301. {
  302. ULONG Flags;
  303. NTSTATUS Status;
  304. PAGED_CODE();
  305. //
  306. // Query the system for verifier information. This is to ensure that
  307. // verifier is present and operational on the system. If this fails, we
  308. // give up and return FALSE.
  309. //
  310. Status = MmIsVerifierEnabled (&Flags);
  311. if (NT_SUCCESS(Status)) {
  312. //
  313. // Add scsiport APIs to the set that will be thunked by the system
  314. // for verification.
  315. //
  316. Status = MmAddVerifierThunks ((VOID *) ScsiPortVerifierFunctionTable,
  317. sizeof(ScsiPortVerifierFunctionTable));
  318. if (NT_SUCCESS(Status)) {
  319. //
  320. // Set the system query time increment. Our verifier code uses
  321. // this to calculate the time miniport routines take to execute.
  322. //
  323. TimeIncrement = KeQueryTimeIncrement();
  324. return TRUE;
  325. }
  326. }
  327. return FALSE;
  328. }
  329. ULONG
  330. ScsiPortInitializeVrfy(
  331. IN PVOID Argument1,
  332. IN PVOID Argument2,
  333. IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
  334. IN PVOID HwContext
  335. )
  336. {
  337. ULONG Result;
  338. PDRIVER_OBJECT DriverObject = Argument1;
  339. PSCSIPORT_DRIVER_EXTENSION DriverExtension;
  340. PAGED_CODE();
  341. //
  342. // Lock the thunked API routines down.
  343. //
  344. #ifdef ALLOC_PRAGMA
  345. if (VerifierApiCodeSectionHandle == NULL) {
  346. VerifierApiCodeSectionHandle = MmLockPagableCodeSection(ScsiPortGetSrbVrfy);
  347. }
  348. #endif
  349. if (Argument1 == NULL || Argument2 == NULL) {
  350. //
  351. // Argument1 and Argument2 must be non-NULL.
  352. //
  353. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  354. SCSIPORT_VERIFIER_BAD_INIT_PARAMS,
  355. (ULONG_PTR)Argument1,
  356. (ULONG_PTR)Argument2,
  357. 0);
  358. }
  359. //
  360. // Forward the call on to ScsiPortInitialize.
  361. //
  362. Result = ScsiPortInitialize (Argument1,
  363. Argument2,
  364. HwInitializationData,
  365. HwContext);
  366. //
  367. // If initialization was successful, try to initialize verifier settings.
  368. //
  369. if (NT_SUCCESS(Result)) {
  370. DriverExtension = IoGetDriverObjectExtension (DriverObject,
  371. ScsiPortInitialize);
  372. if (DriverExtension != NULL) {
  373. //
  374. // Indicate that the driver is being verified by scsiport.
  375. //
  376. InterlockedExchange(&DriverExtension->Verifying, 1);
  377. }
  378. }
  379. return Result;
  380. }
  381. PSCSI_REQUEST_BLOCK
  382. ScsiPortGetSrbVrfy(
  383. IN PVOID HwDeviceExtension,
  384. IN UCHAR PathId,
  385. IN UCHAR TargetId,
  386. IN UCHAR Lun,
  387. IN LONG QueueTag
  388. )
  389. {
  390. return ScsiPortGetSrb(HwDeviceExtension,
  391. PathId,
  392. TargetId,
  393. Lun,
  394. QueueTag);
  395. }
  396. VOID
  397. ScsiPortCompleteRequestVrfy(
  398. IN PVOID HwDeviceExtension,
  399. IN UCHAR PathId,
  400. IN UCHAR TargetId,
  401. IN UCHAR Lun,
  402. IN UCHAR SrbStatus
  403. )
  404. {
  405. ScsiPortCompleteRequest(HwDeviceExtension,
  406. PathId,
  407. TargetId,
  408. Lun,
  409. SrbStatus);
  410. }
  411. PVOID
  412. ScsiPortGetDeviceBaseVrfy(
  413. IN PVOID HwDeviceExtension,
  414. IN INTERFACE_TYPE BusType,
  415. IN ULONG SystemIoBusNumber,
  416. SCSI_PHYSICAL_ADDRESS IoAddress,
  417. ULONG NumberOfBytes,
  418. BOOLEAN InIoSpace
  419. )
  420. {
  421. return ScsiPortGetDeviceBase(HwDeviceExtension,
  422. BusType,
  423. SystemIoBusNumber,
  424. IoAddress,
  425. NumberOfBytes,
  426. InIoSpace);
  427. }
  428. VOID
  429. ScsiPortNotificationVrfy(
  430. IN SCSI_NOTIFICATION_TYPE NotificationType,
  431. IN PVOID HwDeviceExtension,
  432. ...
  433. )
  434. {
  435. PADAPTER_EXTENSION deviceExtension = GET_FDO_EXTENSION(HwDeviceExtension);
  436. PLOGICAL_UNIT_EXTENSION logicalUnit;
  437. PSCSI_REQUEST_BLOCK Srb;
  438. UCHAR PathId;
  439. UCHAR TargetId;
  440. UCHAR Lun;
  441. PHW_INTERRUPT HwRequestInterrupt;
  442. PHW_INTERRUPT HwTimerRequest;
  443. ULONG MiniportTimerValue;
  444. PWNODE_EVENT_ITEM WnodeEventItem;
  445. PSRB_DATA srbData;
  446. va_list ap;
  447. va_start(ap, HwDeviceExtension);
  448. switch (NotificationType) {
  449. case NextRequest:
  450. ScsiPortNotification(NotificationType, HwDeviceExtension);
  451. va_end(ap);
  452. return;
  453. case RequestComplete:
  454. Srb = va_arg(ap, PSCSI_REQUEST_BLOCK);
  455. //
  456. // Check that the status makes sense.
  457. //
  458. SpVerifySrbStatus(HwDeviceExtension, Srb);
  459. //
  460. // Check that this request has not already been completed.
  461. //
  462. if ((Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE) == 0) {
  463. KeBugCheckEx(
  464. SCSI_VERIFIER_DETECTED_VIOLATION,
  465. SCSIPORT_VERIFIER_REQUEST_COMPLETED_TWICE,
  466. (ULONG_PTR)HwDeviceExtension,
  467. (ULONG_PTR)Srb,
  468. 0);
  469. }
  470. //
  471. // Restore the DataBuffer in the SRB if we plugged in our
  472. // pointer to unmapped memory. We did this if the adapter
  473. // does not specify MappedBuffers because the miniport is
  474. // not supposed to touch the buffer in that case.
  475. //
  476. srbData = (PSRB_DATA)Srb->OriginalRequest;
  477. ASSERT_SRB_DATA(srbData);
  478. if (srbData->UnmappedDataBuffer != &SpMarker) {
  479. ASSERT(srbData->UnmappedDataBuffer != NULL);
  480. Srb->DataBuffer = srbData->UnmappedDataBuffer;
  481. }
  482. srbData->UnmappedDataBuffer = NULL;
  483. //
  484. // Forward on to the real ScsiPortNotification routine.
  485. //
  486. ScsiPortNotification(NotificationType,
  487. HwDeviceExtension,
  488. Srb);
  489. va_end(ap);
  490. return;
  491. case ResetDetected:
  492. ScsiPortNotification(NotificationType,
  493. HwDeviceExtension);
  494. va_end(ap);
  495. return;
  496. case NextLuRequest:
  497. //
  498. // The miniport driver is ready for the next request and
  499. // can accept a request for this logical unit.
  500. //
  501. PathId = va_arg(ap, UCHAR);
  502. TargetId = va_arg(ap, UCHAR);
  503. Lun = va_arg(ap, UCHAR);
  504. logicalUnit = deviceExtension->CachedLogicalUnit;
  505. if ((logicalUnit == NULL)
  506. || (logicalUnit->TargetId != TargetId)
  507. || (logicalUnit->PathId != PathId)
  508. || (logicalUnit->Lun != Lun)) {
  509. logicalUnit = GetLogicalUnitExtension(deviceExtension,
  510. PathId,
  511. TargetId,
  512. Lun,
  513. FALSE,
  514. FALSE);
  515. }
  516. //
  517. // Bugcheck if there is an untagged request active for this
  518. // logical unit.
  519. //
  520. if (VRFY_DO_CHECK(deviceExtension, SP_DONT_CHK_ACTIVE_UNTAGGED_REQUEST) &&
  521. logicalUnit != NULL &&
  522. logicalUnit->CurrentUntaggedRequest != NULL &&
  523. logicalUnit->CurrentUntaggedRequest->CurrentSrb != NULL &&
  524. logicalUnit->CurrentUntaggedRequest->CurrentSrb->SrbFlags & SRB_FLAGS_IS_ACTIVE) {
  525. KeBugCheckEx (
  526. SCSI_VERIFIER_DETECTED_VIOLATION,
  527. SCSIPORT_VERIFIER_UNTAGGED_REQUEST_ACTIVE,
  528. (ULONG_PTR)HwDeviceExtension,
  529. (ULONG_PTR)logicalUnit,
  530. 0);
  531. }
  532. //
  533. // Forward on to the real ScsiPortNotification.
  534. //
  535. ScsiPortNotification(NotificationType,
  536. HwDeviceExtension,
  537. PathId,
  538. TargetId,
  539. Lun);
  540. va_end(ap);
  541. return;
  542. case CallDisableInterrupts:
  543. HwRequestInterrupt = va_arg(ap, PHW_INTERRUPT);
  544. ScsiPortNotification(NotificationType,
  545. HwDeviceExtension,
  546. HwRequestInterrupt);
  547. va_end(ap);
  548. return;
  549. case CallEnableInterrupts:
  550. HwRequestInterrupt = va_arg(ap, PHW_INTERRUPT);
  551. ScsiPortNotification(NotificationType,
  552. HwDeviceExtension,
  553. HwRequestInterrupt);
  554. va_end(ap);
  555. return;
  556. case RequestTimerCall:
  557. HwTimerRequest = va_arg(ap, PHW_INTERRUPT);
  558. MiniportTimerValue = va_arg(ap, ULONG);
  559. ScsiPortNotification(NotificationType,
  560. HwDeviceExtension,
  561. HwTimerRequest,
  562. MiniportTimerValue);
  563. va_end(ap);
  564. return;
  565. case WMIEvent:
  566. WnodeEventItem = va_arg(ap, PWNODE_EVENT_ITEM);
  567. PathId = va_arg(ap, UCHAR);
  568. if (PathId != 0xFF) {
  569. TargetId = va_arg(ap, UCHAR);
  570. Lun = va_arg(ap, UCHAR);
  571. ScsiPortNotification(NotificationType,
  572. HwDeviceExtension,
  573. WnodeEventItem,
  574. PathId,
  575. TargetId,
  576. Lun);
  577. } else {
  578. ScsiPortNotification(NotificationType,
  579. HwDeviceExtension,
  580. WnodeEventItem,
  581. PathId);
  582. }
  583. va_end(ap);
  584. return;
  585. case WMIReregister:
  586. PathId = va_arg(ap, UCHAR);
  587. if (PathId != 0xFF) {
  588. TargetId = va_arg(ap, UCHAR);
  589. Lun = va_arg(ap, UCHAR);
  590. ScsiPortNotification(NotificationType,
  591. HwDeviceExtension,
  592. PathId,
  593. TargetId,
  594. Lun);
  595. } else {
  596. ScsiPortNotification(NotificationType,
  597. HwDeviceExtension,
  598. PathId);
  599. }
  600. va_end(ap);
  601. return;
  602. case BusChangeDetected:
  603. ScsiPortNotification(NotificationType,
  604. HwDeviceExtension);
  605. va_end(ap);
  606. return;
  607. default:
  608. ScsiPortNotification(NotificationType,
  609. HwDeviceExtension);
  610. va_end(ap);
  611. return;
  612. }
  613. }
  614. VOID
  615. ScsiPortFlushDmaVrfy(
  616. IN PVOID DeviceExtension
  617. )
  618. {
  619. ScsiPortFlushDma(DeviceExtension);
  620. return;
  621. }
  622. VOID
  623. ScsiPortFreeDeviceBaseVrfy(
  624. IN PVOID HwDeviceExtension,
  625. IN PVOID MappedAddress
  626. )
  627. {
  628. ScsiPortFreeDeviceBase(HwDeviceExtension, MappedAddress);
  629. return;
  630. }
  631. ULONG
  632. ScsiPortGetBusDataVrfy(
  633. IN PVOID DeviceExtension,
  634. IN ULONG BusDataType,
  635. IN ULONG SystemIoBusNumber,
  636. IN ULONG SlotNumber,
  637. IN PVOID Buffer,
  638. IN ULONG Length
  639. )
  640. {
  641. ULONG BusData;
  642. BusData = ScsiPortGetBusData(DeviceExtension,
  643. BusDataType,
  644. SystemIoBusNumber,
  645. SlotNumber,
  646. Buffer,
  647. Length);
  648. return BusData;
  649. }
  650. PVOID
  651. ScsiPortGetLogicalUnitVrfy(
  652. IN PVOID HwDeviceExtension,
  653. IN UCHAR PathId,
  654. IN UCHAR TargetId,
  655. IN UCHAR Lun
  656. )
  657. {
  658. PVOID LogicalUnit;
  659. LogicalUnit = ScsiPortGetLogicalUnit(HwDeviceExtension,
  660. PathId,
  661. TargetId,
  662. Lun);
  663. return LogicalUnit;
  664. }
  665. SCSI_PHYSICAL_ADDRESS
  666. ScsiPortGetPhysicalAddressVrfy(
  667. IN PVOID HwDeviceExtension,
  668. IN PSCSI_REQUEST_BLOCK Srb,
  669. IN PVOID VirtualAddress,
  670. OUT ULONG *Length
  671. )
  672. {
  673. PADAPTER_EXTENSION deviceExtension = GET_FDO_EXTENSION(HwDeviceExtension);
  674. PHYSICAL_ADDRESS address;
  675. PSP_VA_MAPPING_INFO MappingInfo;
  676. ULONG byteOffset;
  677. ULONG length;
  678. if ((deviceExtension->VerifierExtension != NULL) &&
  679. (deviceExtension->VerifierExtension->VrfyLevel & SP_VRFY_COMMON_BUFFERS) &&
  680. (Srb == NULL || Srb->SenseInfoBuffer == VirtualAddress)) {
  681. ULONG i;
  682. PVOID* BlkAddr;
  683. PUCHAR Beginning, End;
  684. PHYSICAL_ADDRESS *AddressBlock;
  685. //
  686. // Initialize a pointer to our array of common memory block
  687. // descriptors. We use this to locate the block that contains
  688. // the VA.
  689. //
  690. BlkAddr = deviceExtension->VerifierExtension->CommonBufferVAs;
  691. //
  692. // Look for the block that contains the VA.
  693. //
  694. for (i = 0; i < deviceExtension->NumberOfRequests; i++) {
  695. //
  696. // First, check if the VA is in the SRB extension.
  697. //
  698. MappingInfo = GET_VA_MAPPING_INFO(deviceExtension, BlkAddr[i]);
  699. if (MappingInfo->RemappedSrbExtVa != NULL) {
  700. Beginning = MappingInfo->RemappedSrbExtVa;
  701. } else {
  702. Beginning = BlkAddr[i];
  703. }
  704. End = (PUCHAR)ROUND_TO_PAGES((PUCHAR)Beginning + deviceExtension->SrbExtensionSize);
  705. if ((PUCHAR)VirtualAddress >= Beginning &&
  706. (PUCHAR)VirtualAddress < End) {
  707. byteOffset = (ULONG)((PUCHAR)VirtualAddress - Beginning);
  708. break;
  709. }
  710. //
  711. // Next, check if the VA is in the Sense Data Buffer.
  712. //
  713. if (deviceExtension->AutoRequestSense == TRUE) {
  714. if (MappingInfo->RemappedSenseVa != NULL) {
  715. Beginning = MappingInfo->RemappedSenseVa;
  716. } else {
  717. Beginning = (PUCHAR)BlkAddr[i] + ROUND_TO_PAGES(deviceExtension->SrbExtensionSize);
  718. }
  719. End = Beginning + PAGE_SIZE;
  720. if ((PUCHAR)VirtualAddress >= Beginning &&
  721. (PUCHAR)VirtualAddress < End) {
  722. byteOffset = (ULONG)((PUCHAR)VirtualAddress - Beginning) +
  723. (ULONG)ROUND_TO_PAGES(deviceExtension->SrbExtensionSize);
  724. break;
  725. }
  726. }
  727. }
  728. //
  729. // If we haven't found the VA yet, it must be in the non-cached
  730. // extension.
  731. //
  732. if (i == deviceExtension->NumberOfRequests) {
  733. if (deviceExtension->VerifierExtension->NonCachedBufferSize != 0) {
  734. Beginning = BlkAddr[i];
  735. End = (PUCHAR) ROUND_TO_PAGES(
  736. (PUCHAR)Beginning +
  737. deviceExtension->VerifierExtension->NonCachedBufferSize);
  738. if ((PUCHAR)VirtualAddress < Beginning &&
  739. (PUCHAR)VirtualAddress >= End) {
  740. KeBugCheckEx (SCSI_VERIFIER_DETECTED_VIOLATION,
  741. SCSIPORT_VERIFIER_BAD_VA,
  742. (ULONG_PTR)HwDeviceExtension,
  743. (ULONG_PTR)VirtualAddress,
  744. 0);
  745. }
  746. byteOffset = (ULONG)((PUCHAR)VirtualAddress - Beginning);
  747. } else {
  748. KeBugCheckEx (SCSI_VERIFIER_DETECTED_VIOLATION,
  749. SCSIPORT_VERIFIER_BAD_VA,
  750. (ULONG_PTR)HwDeviceExtension,
  751. (ULONG_PTR)VirtualAddress,
  752. 0);
  753. }
  754. }
  755. //
  756. // Get the physical address.
  757. //
  758. AddressBlock = deviceExtension->VerifierExtension->CommonBufferPAs;
  759. address.QuadPart = AddressBlock[i].QuadPart + byteOffset;
  760. //
  761. // Calculate the length of the block.
  762. //
  763. length = (ULONG)((End - (PUCHAR)VirtualAddress) + 1);
  764. return address;
  765. }
  766. //
  767. // Forward on to the real routine.
  768. //
  769. address = ScsiPortGetPhysicalAddress(HwDeviceExtension,
  770. Srb,
  771. VirtualAddress,
  772. Length);
  773. return address;
  774. }
  775. PVOID
  776. ScsiPortGetUncachedExtensionVrfy(
  777. IN PVOID HwDeviceExtension,
  778. IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
  779. IN ULONG NumberOfBytes
  780. )
  781. {
  782. PVOID Extension;
  783. Extension = ScsiPortGetUncachedExtension(HwDeviceExtension,
  784. ConfigInfo,
  785. NumberOfBytes);
  786. return Extension;
  787. }
  788. PVOID
  789. ScsiPortGetVirtualAddressVrfy(
  790. IN PVOID HwDeviceExtension,
  791. IN SCSI_PHYSICAL_ADDRESS PhysicalAddress
  792. )
  793. {
  794. PADAPTER_EXTENSION deviceExtension = GET_FDO_EXTENSION(HwDeviceExtension);
  795. PVOID* BlkAddr;
  796. PSP_VA_MAPPING_INFO MappingInfo;
  797. ULONG smallphysicalBase;
  798. ULONG smallAddress;
  799. PVOID address;
  800. ULONG offset;
  801. ULONG Size;
  802. ULONG i;
  803. //
  804. // If the adapter is not configured to allocate multiple common buffer
  805. // blocks during verification, just call the scsiport routine.
  806. //
  807. if ((deviceExtension->VerifierExtension == NULL) ||
  808. (deviceExtension->VerifierExtension->VrfyLevel & SP_VRFY_COMMON_BUFFERS) == 0) {
  809. return ScsiPortGetVirtualAddress(HwDeviceExtension, PhysicalAddress);
  810. }
  811. BlkAddr = deviceExtension->VerifierExtension->CommonBufferVAs;
  812. //
  813. // Convert the 64-bit physical address to a ULONG.
  814. //
  815. smallAddress = ScsiPortConvertPhysicalAddressToUlong(PhysicalAddress);
  816. //
  817. // Check first if the supplied physical address is in an SRB extension or
  818. // in a sense buffer.
  819. //
  820. for (i = 0; i < deviceExtension->NumberOfRequests; i++) {
  821. smallphysicalBase =
  822. ScsiPortConvertPhysicalAddressToUlong(
  823. deviceExtension->VerifierExtension->CommonBufferPAs[i]);
  824. if ((smallAddress < smallphysicalBase) ||
  825. (smallAddress >= smallphysicalBase +
  826. (deviceExtension->CommonBufferSize -
  827. PAGE_SIZE))) {
  828. continue;
  829. }
  830. //
  831. // Calculate the address of the buffer.
  832. //
  833. offset = smallAddress - smallphysicalBase;
  834. address = offset + (PUCHAR)BlkAddr[i];
  835. MappingInfo = GET_VA_MAPPING_INFO(deviceExtension, BlkAddr[i]);
  836. goto GotAddress;
  837. }
  838. //
  839. // Check if the supplied physical address is in the non-cached extension.
  840. //
  841. if (deviceExtension->VerifierExtension->NonCachedBufferSize == 0) {
  842. ASSERT(FALSE);
  843. return(NULL);
  844. } else {
  845. smallphysicalBase =
  846. ScsiPortConvertPhysicalAddressToUlong(
  847. deviceExtension->VerifierExtension->CommonBufferPAs[i]);
  848. if ((smallAddress < smallphysicalBase) ||
  849. (smallAddress >= smallphysicalBase +
  850. deviceExtension->VerifierExtension->NonCachedBufferSize)) {
  851. //
  852. // This is a bogus physical address return back NULL.
  853. //
  854. ASSERT(FALSE);
  855. return(NULL);
  856. }
  857. offset = smallAddress - smallphysicalBase;
  858. address = offset + (PUCHAR)BlkAddr[i];
  859. Size = (ULONG)ROUND_TO_PAGES(deviceExtension->VerifierExtension->NonCachedBufferSize);
  860. MappingInfo = (PSP_VA_MAPPING_INFO)((PUCHAR)BlkAddr[i] + (Size - PAGE_SIZE));
  861. }
  862. GotAddress:
  863. //
  864. // Find out if we've remapped this address. If we have, give the
  865. // caller the second mapping.
  866. //
  867. if (address < MappingInfo->OriginalSenseVa &&
  868. MappingInfo->RemappedSrbExtVa != NULL) {
  869. return(offset + (PUCHAR)MappingInfo->RemappedSrbExtVa);
  870. }
  871. else if (MappingInfo->RemappedSenseVa != NULL) {
  872. return(offset + (PUCHAR)MappingInfo->RemappedSenseVa);
  873. }
  874. return(address);
  875. }
  876. VOID
  877. ScsiPortIoMapTransferVrfy(
  878. IN PVOID HwDeviceExtension,
  879. IN PSCSI_REQUEST_BLOCK Srb,
  880. IN PVOID LogicalAddress,
  881. IN ULONG Length
  882. )
  883. {
  884. ScsiPortIoMapTransfer(HwDeviceExtension,
  885. Srb,
  886. LogicalAddress,
  887. Length);
  888. return;
  889. }
  890. VOID
  891. ScsiPortMoveMemoryVrfy(
  892. IN PVOID WriteBuffer,
  893. IN PVOID ReadBuffer,
  894. IN ULONG Length
  895. )
  896. {
  897. ScsiPortMoveMemory(WriteBuffer,
  898. ReadBuffer,
  899. Length);
  900. return;
  901. }
  902. ULONG
  903. ScsiPortSetBusDataByOffsetVrfy(
  904. IN PVOID DeviceExtension,
  905. IN ULONG BusDataType,
  906. IN ULONG SystemIoBusNumber,
  907. IN ULONG SlotNumber,
  908. IN PVOID Buffer,
  909. IN ULONG Offset,
  910. IN ULONG Length
  911. )
  912. {
  913. ULONG Result;
  914. Result = ScsiPortSetBusDataByOffset(DeviceExtension,
  915. BusDataType,
  916. SystemIoBusNumber,
  917. SlotNumber,
  918. Buffer,
  919. Offset,
  920. Length);
  921. return Result;
  922. }
  923. BOOLEAN
  924. ScsiPortValidateRangeVrfy(
  925. IN PVOID HwDeviceExtension,
  926. IN INTERFACE_TYPE BusType,
  927. IN ULONG SystemIoBusNumber,
  928. IN SCSI_PHYSICAL_ADDRESS IoAddress,
  929. IN ULONG NumberOfBytes,
  930. IN BOOLEAN InIoSpace
  931. )
  932. {
  933. BOOLEAN Result;
  934. Result = ScsiPortValidateRange(HwDeviceExtension,
  935. BusType,
  936. SystemIoBusNumber,
  937. IoAddress,
  938. NumberOfBytes,
  939. InIoSpace);
  940. return Result;
  941. }
  942. VOID
  943. ScsiPortStallExecutionVrfy(
  944. IN ULONG Delay
  945. )
  946. {
  947. //
  948. // Miniports must specify a delay not more than one millisecond.
  949. //
  950. if (Delay > SpVrfyMaximumStall) {
  951. KeBugCheckEx(SCSI_VERIFIER_DETECTED_VIOLATION,
  952. SCSIPORT_VERIFIER_STALL_TOO_LONG,
  953. (ULONG_PTR)Delay,
  954. 0,
  955. 0);
  956. }
  957. KeStallExecutionProcessor(Delay);
  958. }
  959. //
  960. // Timeout periods in ticks. To calculate, we divide the time limit in 100 ns
  961. // units by the TimeIncrement, which is the value returned by
  962. // KeQueryTimeIncrement. Since KeQueryTickCount rounds up to the next
  963. // tick, we'll add one tick to the defined limits.
  964. //
  965. #define SP_FIVE_SECOND_LIMIT ((50000000L / TimeIncrement) + 1)
  966. #define SP_TWO_SECOND_LIMIT ((20000000L / TimeIncrement) + 1)
  967. #define SP_HALF_SECOND_LIMIT ((5000000L / TimeIncrement) + 1)
  968. /*++
  969. Macro Description:
  970. This macro checks the number of ticks elapsed during the execution of a
  971. miniport routine against a maximum number allowed ticks. If the routine
  972. ran longer than the max allowable ticks, we bugcheck.
  973. Arguments:
  974. Ticks - number of ticks routine took to execute.
  975. MaxTicks - number of ticks the routine is allowed to execute.
  976. Routine - address of the routine we are checking.
  977. Extension - address of the miniport's HwDeviceExtension
  978. Notes:
  979. The format for the bugcheck is:
  980. Parameter 1: 0x1002
  981. Parameter 2: address of routine that ran too long
  982. Parameter 3: address of miniport's HwDeviceExtension
  983. Parameter 4: duration of routine in microseconds
  984. --*/
  985. #define SpCheckMiniportRoutineDuration(Ticks, MaxTicks, Routine, Extension) \
  986. { \
  987. if ((Ticks) > (MaxTicks)) { \
  988. KeBugCheckEx ( \
  989. SCSI_VERIFIER_DETECTED_VIOLATION, \
  990. SCSIPORT_VERIFIER_MINIPORT_ROUTINE_TIMEOUT, \
  991. (ULONG_PTR)(Routine), \
  992. (ULONG_PTR)(Extension), \
  993. (ULONG_PTR)(((Ticks) * TimeIncrement) / 10)); \
  994. } \
  995. }
  996. ULONG
  997. SpHwFindAdapterVrfy (
  998. IN PVOID HwDeviceExtension,
  999. IN PVOID HwContext,
  1000. IN PVOID BusInformation,
  1001. IN PCHAR ArgumentString,
  1002. IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
  1003. OUT PBOOLEAN Again
  1004. )
  1005. {
  1006. ULONG Result;
  1007. PADAPTER_EXTENSION AdapterExtension = GET_FDO_EXTENSION(HwDeviceExtension);
  1008. Result = AdapterExtension->VerifierExtension->RealHwFindAdapter(
  1009. HwDeviceExtension,
  1010. HwContext,
  1011. BusInformation,
  1012. ArgumentString,
  1013. ConfigInfo,
  1014. Again);
  1015. return Result;
  1016. }
  1017. BOOLEAN
  1018. SpHwInitializeVrfy (
  1019. IN PVOID HwDeviceExtension
  1020. )
  1021. {
  1022. BOOLEAN Result;
  1023. LARGE_INTEGER Start;
  1024. LARGE_INTEGER Duration;
  1025. PADAPTER_EXTENSION AdapterExtension = GET_FDO_EXTENSION(HwDeviceExtension);
  1026. KeQueryTickCount(&Start);
  1027. Result = AdapterExtension->VerifierExtension->RealHwInitialize(HwDeviceExtension);
  1028. KeQueryTickCount(&Duration);
  1029. Duration.QuadPart -= Start.QuadPart;
  1030. if (VRFY_DO_CHECK(AdapterExtension, SP_DONT_CHK_HW_INITIALIZE_DURATION)) {
  1031. SpCheckMiniportRoutineDuration(
  1032. Duration.LowPart,
  1033. SP_FIVE_SECOND_LIMIT,
  1034. AdapterExtension->VerifierExtension->RealHwInitialize,
  1035. HwDeviceExtension);
  1036. }
  1037. return Result;
  1038. }
  1039. BOOLEAN
  1040. SpHwStartIoVrfy (
  1041. IN PVOID HwDeviceExtension,
  1042. IN PSCSI_REQUEST_BLOCK Srb
  1043. )
  1044. {
  1045. BOOLEAN Result;
  1046. LARGE_INTEGER Start;
  1047. LARGE_INTEGER Duration;
  1048. PADAPTER_EXTENSION AdapterExtension = GET_FDO_EXTENSION(HwDeviceExtension);
  1049. PSRB_DATA srbData;
  1050. //
  1051. // If MapBuffers is not set, the miniport is not supposed to touch
  1052. // the DataBuffer field in the SRB. To verify this, we'll set
  1053. // DataBuffer to point to memory that will fault if the miniport tries
  1054. // to touch it.
  1055. //
  1056. ASSERT(Srb != NULL);
  1057. srbData = (PSRB_DATA)Srb->OriginalRequest;
  1058. ASSERT_SRB_DATA(srbData);
  1059. if (AdapterExtension->MapBuffers == FALSE
  1060. && !IS_MAPPED_SRB(Srb)
  1061. && Srb->DataBuffer != NULL
  1062. && AdapterExtension->VerifierExtension->InvalidPage != NULL) {
  1063. if (Srb->DataBuffer != AdapterExtension->VerifierExtension->InvalidPage) {
  1064. srbData->UnmappedDataBuffer = Srb->DataBuffer;
  1065. Srb->DataBuffer = AdapterExtension->VerifierExtension->InvalidPage;
  1066. } else {
  1067. ASSERT(srbData->UnmappedDataBuffer != &SpMarker);
  1068. ASSERT(srbData->UnmappedDataBuffer != NULL);
  1069. }
  1070. } else {
  1071. srbData->UnmappedDataBuffer = &SpMarker;
  1072. }
  1073. //
  1074. // Call the miniport's StartIo function and calculate the call's duration.
  1075. //
  1076. KeQueryTickCount(&Start);
  1077. Result = AdapterExtension->VerifierExtension->RealHwStartIo(
  1078. HwDeviceExtension,
  1079. Srb);
  1080. KeQueryTickCount(&Duration);
  1081. Duration.QuadPart -= Start.QuadPart;
  1082. //
  1083. // Bugcheck if the call took more than .5 seconds.
  1084. //
  1085. SpCheckMiniportRoutineDuration(
  1086. Duration.LowPart,
  1087. SP_HALF_SECOND_LIMIT,
  1088. AdapterExtension->VerifierExtension->RealHwStartIo,
  1089. HwDeviceExtension);
  1090. //
  1091. // If the HwStartIo returns failure, undo any fixups we performed on the SRB.
  1092. //
  1093. if (Result == FALSE
  1094. && srbData->UnmappedDataBuffer != &SpMarker) {
  1095. ASSERT(srbData->UnmappedDataBuffer != NULL);
  1096. Srb->DataBuffer = srbData->UnmappedDataBuffer;
  1097. srbData->UnmappedDataBuffer = NULL;
  1098. }
  1099. return Result;
  1100. }
  1101. BOOLEAN
  1102. SpHwInterruptVrfy (
  1103. IN PVOID HwDeviceExtension
  1104. )
  1105. {
  1106. BOOLEAN Result;
  1107. LARGE_INTEGER Start;
  1108. LARGE_INTEGER Duration;
  1109. PADAPTER_EXTENSION AdapterExtension = GET_FDO_EXTENSION(HwDeviceExtension);
  1110. KeQueryTickCount(&Start);
  1111. Result = AdapterExtension->VerifierExtension->RealHwInterrupt (
  1112. HwDeviceExtension);
  1113. KeQueryTickCount(&Duration);
  1114. Duration.QuadPart -= Start.QuadPart;
  1115. SpCheckMiniportRoutineDuration(
  1116. Duration.LowPart,
  1117. SP_HALF_SECOND_LIMIT,
  1118. AdapterExtension->VerifierExtension->RealHwInterrupt,
  1119. HwDeviceExtension);
  1120. return Result;
  1121. }
  1122. BOOLEAN
  1123. SpHwResetBusVrfy (
  1124. IN PVOID HwDeviceExtension,
  1125. IN ULONG PathId
  1126. )
  1127. {
  1128. BOOLEAN Result;
  1129. LARGE_INTEGER Start;
  1130. LARGE_INTEGER Duration;
  1131. PADAPTER_EXTENSION AdapterExtension = GET_FDO_EXTENSION(HwDeviceExtension);
  1132. KeQueryTickCount(&Start);
  1133. Result = AdapterExtension->VerifierExtension->RealHwResetBus(
  1134. HwDeviceExtension,
  1135. PathId);
  1136. KeQueryTickCount(&Duration);
  1137. Duration.QuadPart -= Start.QuadPart;
  1138. SpCheckMiniportRoutineDuration(
  1139. Duration.LowPart,
  1140. SP_HALF_SECOND_LIMIT,
  1141. AdapterExtension->VerifierExtension->RealHwResetBus,
  1142. HwDeviceExtension);
  1143. return Result;
  1144. }
  1145. VOID
  1146. SpHwDmaStartedVrfy (
  1147. IN PVOID HwDeviceExtension
  1148. )
  1149. {
  1150. LARGE_INTEGER Start;
  1151. LARGE_INTEGER Duration;
  1152. PADAPTER_EXTENSION AdapterExtension = GET_FDO_EXTENSION(HwDeviceExtension);
  1153. KeQueryTickCount(&Start);
  1154. AdapterExtension->VerifierExtension->RealHwDmaStarted(
  1155. HwDeviceExtension);
  1156. KeQueryTickCount(&Duration);
  1157. Duration.QuadPart -= Start.QuadPart;
  1158. SpCheckMiniportRoutineDuration(
  1159. Duration.LowPart,
  1160. SP_HALF_SECOND_LIMIT,
  1161. AdapterExtension->VerifierExtension->RealHwDmaStarted,
  1162. HwDeviceExtension);
  1163. }
  1164. BOOLEAN
  1165. SpHwRequestInterruptVrfy (
  1166. IN PVOID HwDeviceExtension
  1167. )
  1168. {
  1169. BOOLEAN Result;
  1170. LARGE_INTEGER Start;
  1171. LARGE_INTEGER Duration;
  1172. PADAPTER_EXTENSION AdapterExtension = GET_FDO_EXTENSION(HwDeviceExtension);
  1173. KeQueryTickCount(&Start);
  1174. Result = AdapterExtension->VerifierExtension->RealHwRequestInterrupt(
  1175. HwDeviceExtension);
  1176. KeQueryTickCount(&Duration);
  1177. Duration.QuadPart -= Start.QuadPart;
  1178. SpCheckMiniportRoutineDuration(
  1179. Duration.LowPart,
  1180. SP_HALF_SECOND_LIMIT,
  1181. AdapterExtension->VerifierExtension->RealHwRequestInterrupt,
  1182. HwDeviceExtension);
  1183. return Result;
  1184. }
  1185. BOOLEAN
  1186. SpHwTimerRequestVrfy (
  1187. IN PVOID HwDeviceExtension
  1188. )
  1189. {
  1190. BOOLEAN Result;
  1191. LARGE_INTEGER Start;
  1192. LARGE_INTEGER Duration;
  1193. PADAPTER_EXTENSION AdapterExtension = GET_FDO_EXTENSION(HwDeviceExtension);
  1194. KeQueryTickCount(&Start);
  1195. Result = AdapterExtension->VerifierExtension->RealHwTimerRequest(
  1196. HwDeviceExtension);
  1197. KeQueryTickCount(&Duration);
  1198. Duration.QuadPart -= Start.QuadPart;
  1199. SpCheckMiniportRoutineDuration(
  1200. Duration.LowPart,
  1201. SP_HALF_SECOND_LIMIT,
  1202. AdapterExtension->VerifierExtension->RealHwTimerRequest,
  1203. HwDeviceExtension);
  1204. return Result;
  1205. }
  1206. SCSI_ADAPTER_CONTROL_STATUS
  1207. SpHwAdapterControlVrfy (
  1208. IN PVOID HwDeviceExtension,
  1209. IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
  1210. IN PVOID Parameters
  1211. )
  1212. {
  1213. SCSI_ADAPTER_CONTROL_STATUS Result;
  1214. LARGE_INTEGER Start;
  1215. LARGE_INTEGER Duration;
  1216. PADAPTER_EXTENSION AdapterExtension = GET_FDO_EXTENSION(HwDeviceExtension);
  1217. KeQueryTickCount (&Start);
  1218. Result = AdapterExtension->VerifierExtension->RealHwAdapterControl(
  1219. HwDeviceExtension,
  1220. ControlType,
  1221. Parameters);
  1222. KeQueryTickCount(&Duration);
  1223. Duration.QuadPart -= Start.QuadPart;
  1224. if (VRFY_DO_CHECK(AdapterExtension, SP_DONT_CHK_HW_ADAPTERCONTROL_DURATION)) {
  1225. SpCheckMiniportRoutineDuration(
  1226. Duration.LowPart,
  1227. SP_HALF_SECOND_LIMIT,
  1228. AdapterExtension->VerifierExtension->RealHwAdapterControl,
  1229. HwDeviceExtension);
  1230. }
  1231. return Result;
  1232. }
  1233. VOID
  1234. SpVerifySrbStatus(
  1235. PVOID HwDeviceExtension,
  1236. PSCSI_REQUEST_BLOCK srb
  1237. )
  1238. /*++
  1239. Routine Description:
  1240. Verify that the SRB's status as set by the miniport driver is valid.
  1241. Arguments:
  1242. HwDeviceExtension - The port driver's device extension follows the
  1243. miniport's device extension and contains a pointer to
  1244. the logical device extension list.
  1245. srb - Points to the SRB.
  1246. Return Value:
  1247. VOID
  1248. --*/
  1249. {
  1250. UCHAR SrbStatus;
  1251. //
  1252. // Turn off internal bits used by scsiport.
  1253. //
  1254. SrbStatus = srb->SrbStatus & ~(SRB_STATUS_QUEUE_FROZEN |
  1255. SRB_STATUS_AUTOSENSE_VALID);
  1256. //
  1257. // Miniports may never set the status to SRB_STATUS_PENDING.
  1258. //
  1259. if (SrbStatus == SRB_STATUS_PENDING) {
  1260. goto BadStatus;
  1261. }
  1262. //
  1263. // If the function is SRB_FUNCTION_EXECUTE_SCSI, then the command must be
  1264. // either completed successfully, or ScsiStatus must be set to
  1265. // SCSISTAT_GOOD.
  1266. //
  1267. if (!(SrbStatus != SRB_STATUS_SUCCESS ||
  1268. srb->ScsiStatus == SCSISTAT_GOOD ||
  1269. srb->Function != SRB_FUNCTION_EXECUTE_SCSI)) {
  1270. goto BadStatus;
  1271. }
  1272. //
  1273. // Make sure the status is within the valid range.
  1274. //
  1275. if ((SrbStatus) == 0x0C ||
  1276. (SrbStatus > 0x16 && srb->SrbStatus < 0x20) ||
  1277. (SrbStatus > 0x23)) {
  1278. goto BadStatus;
  1279. }
  1280. //
  1281. // The SRB Status is ok.
  1282. //
  1283. return;
  1284. BadStatus:
  1285. //
  1286. // Bugcheck if the status is bad.
  1287. //
  1288. KeBugCheckEx (SCSI_VERIFIER_DETECTED_VIOLATION,
  1289. SCSIPORT_VERIFIER_BAD_SRBSTATUS,
  1290. (ULONG_PTR)srb,
  1291. (ULONG_PTR)HwDeviceExtension,
  1292. 0);
  1293. }
  1294. PVOID
  1295. SpRemapBlock(
  1296. IN PVOID BlockVa,
  1297. IN ULONG BlockSize,
  1298. OUT PMDL* Mdl
  1299. )
  1300. /*++
  1301. Routine Description:
  1302. This function attempts to remap the supplied VA range. If the block is
  1303. remapped, it will be made invalid for reading and writing.
  1304. Arguments:
  1305. BlockVa - Supplies the address of the block of memory to remap.
  1306. BlockSize - Supplies the size of the block of memory to remap.
  1307. Mdl - Supplies the address into which the function will store
  1308. a pointer to the MDL for the remapped range. If the MDL
  1309. cannot be allocated or if the range cannot be remapped,
  1310. this will be NULL upon return.
  1311. Return Value:
  1312. If the range is successfully remapped, the address of the beginning of
  1313. the remapped range is returned. Else, NULL is returned.
  1314. --*/
  1315. {
  1316. PVOID MappedRange;
  1317. NTSTATUS Status;
  1318. PMDL LocalMdl;
  1319. //
  1320. // Try to allocate a new MDL for the range we're trying to remap.
  1321. //
  1322. LocalMdl = IoAllocateMdl(BlockVa, BlockSize, FALSE, FALSE, NULL);
  1323. if (LocalMdl == NULL) {
  1324. *Mdl = NULL;
  1325. return NULL;
  1326. }
  1327. //
  1328. // Try to lock the pages. This initializes the MDL properly.
  1329. //
  1330. __try {
  1331. MmProbeAndLockPages(LocalMdl, KernelMode, IoModifyAccess);
  1332. }
  1333. __except(EXCEPTION_EXECUTE_HANDLER) {
  1334. IoFreeMdl(LocalMdl);
  1335. *Mdl = NULL;
  1336. return NULL;
  1337. }
  1338. //
  1339. // Try to remap the range represented by the new MDL.
  1340. //
  1341. MappedRange = MmMapLockedPagesSpecifyCache(LocalMdl,
  1342. KernelMode,
  1343. MmCached,
  1344. NULL,
  1345. FALSE,
  1346. NormalPagePriority);
  1347. if (MappedRange == NULL) {
  1348. IoFreeMdl(LocalMdl);
  1349. *Mdl = NULL;
  1350. return NULL;
  1351. }
  1352. //
  1353. // If we've gotten this far, we have successfully remapped the range.
  1354. // Now we want to invalidate the entire range so any accesses to it
  1355. // will be trapped by the system.
  1356. //
  1357. Status = MmProtectMdlSystemAddress(LocalMdl, PAGE_NOACCESS);
  1358. #if DBG==1
  1359. if (!NT_SUCCESS(Status)) {
  1360. DebugPrint((0, "SpRemapBlock: failed to remap block:%p mdl:%p (%x)\n",
  1361. BlockVa, LocalMdl, Status));
  1362. }
  1363. #endif
  1364. //
  1365. // Copy the MDL we allocated into the supplied address and return the
  1366. // address of the beginning of the remapped range.
  1367. //
  1368. *Mdl = LocalMdl;
  1369. return MappedRange;
  1370. }
  1371. VOID
  1372. SpRemapCommonBufferForMiniport(
  1373. PADAPTER_EXTENSION Adapter
  1374. )
  1375. /*++
  1376. Routine Description:
  1377. This routine attempts to remap all of the common buffer blocks allocated
  1378. for a particular adapter.
  1379. Arguments:
  1380. DeviceExtension - Supplies a pointer to the adapter device extension.
  1381. --*/
  1382. {
  1383. PVOID* BlkAddr = Adapter->VerifierExtension->CommonBufferVAs;
  1384. PSP_VA_MAPPING_INFO MappingInfo;
  1385. PVOID RemappedVa;
  1386. ULONG Size;
  1387. PMDL Mdl;
  1388. ULONG i;
  1389. //
  1390. // Iterate through all of the common buffer blocks, and attempt to remap
  1391. // the SRB extension and the sense buffer within each block.
  1392. //
  1393. for (i = 0; i < Adapter->VerifierExtension->CommonBufferBlocks; i++) {
  1394. //
  1395. // Get a pointer to the mapping info we keep at the end of the block.
  1396. //
  1397. MappingInfo = GET_VA_MAPPING_INFO(Adapter, BlkAddr[i]);
  1398. //
  1399. // Initialize the original VA info for the SRB extension.
  1400. //
  1401. MappingInfo->OriginalSrbExtVa = BlkAddr[i];
  1402. MappingInfo->SrbExtLen = (ULONG)ROUND_TO_PAGES(Adapter->SrbExtensionSize);
  1403. //
  1404. // Initialize the original VA info for the sense buffer.
  1405. //
  1406. MappingInfo->OriginalSenseVa = (PUCHAR)BlkAddr[i] + MappingInfo->SrbExtLen;
  1407. MappingInfo->SenseLen = PAGE_SIZE;
  1408. //
  1409. // Try to remap the SRB extension. If successful, initialize the
  1410. // remapped VA info for the SRB extension.
  1411. //
  1412. RemappedVa = SpRemapBlock(MappingInfo->OriginalSrbExtVa,
  1413. MappingInfo->SrbExtLen,
  1414. &Mdl);
  1415. if (RemappedVa != NULL) {
  1416. MappingInfo->RemappedSrbExtVa = RemappedVa;
  1417. MappingInfo->SrbExtMdl = Mdl;
  1418. }
  1419. #if 0
  1420. //
  1421. // Try to remap the sense buffer. If successful, initialize the
  1422. // remapped VA info for the sense buffer.
  1423. //
  1424. // For now, I think we can live without this. I don't know of any
  1425. // issues where overruns etc. occur in a sense buffer.
  1426. //
  1427. RemappedVa = SpRemapBlock(MappingInfo->OriginalSenseVa,
  1428. MappingInfo->SenseLen,
  1429. &Mdl);
  1430. if (RemappedVa != NULL) {
  1431. MappingInfo->RemappedSenseVa = RemappedVa;
  1432. MappingInfo->SenseMdl = Mdl;
  1433. }
  1434. #endif
  1435. }
  1436. if (Adapter->VerifierExtension->NonCachedBufferSize != 0) {
  1437. //
  1438. // Init uncached extension mapping info.
  1439. //
  1440. Size = (ULONG)ROUND_TO_PAGES(Adapter->VerifierExtension->NonCachedBufferSize);
  1441. MappingInfo = (PSP_VA_MAPPING_INFO)((PUCHAR)BlkAddr[i] + (Size - PAGE_SIZE));
  1442. MappingInfo->OriginalSrbExtVa = BlkAddr[i];
  1443. MappingInfo->SrbExtLen = Adapter->VerifierExtension->NonCachedBufferSize;
  1444. MappingInfo->OriginalSenseVa = (PUCHAR)BlkAddr[i] + Adapter->VerifierExtension->NonCachedBufferSize;
  1445. }
  1446. }
  1447. PVOID
  1448. SpAllocateContiguousChunk(
  1449. IN PDRIVER_OBJECT DriverObject,
  1450. IN PDMA_ADAPTER DmaAdapterObject,
  1451. IN BOOLEAN Dma64BitAddresses,
  1452. IN ULONG Length,
  1453. IN ULONG Align,
  1454. OUT PHYSICAL_ADDRESS *PhysicalCommonBuffer,
  1455. OUT BOOLEAN *CommonBuffer
  1456. )
  1457. /*++
  1458. Routine Description:
  1459. This routine allocates a chunk of memory which can be used for common
  1460. buffer io. Where the memory is allocated from depends on several
  1461. parameters. If no adapter object is specified, the memory is simply
  1462. allocated from non-paged pool. Else, the memory is allocated such
  1463. that it can be used in DMA operations.
  1464. Arguments:
  1465. DriverObject - Supplies a pointer to the driver object.
  1466. DmaAdapterObject - Supplies a pointer to the adapter's DMA adapter
  1467. object.
  1468. Dma64BitAddresses - Specifies whether the adapter supports 64-bit.
  1469. Length - Specifies the number of bytes to allocate.
  1470. Align - Alignment requirement for uncached extension.
  1471. PhysicalCommonBuffer - Specifies a pointer into which the physical
  1472. address of the allocated memory is to be copied
  1473. if the memory is allocated for DMA operations.
  1474. CommonBuffer - Supplies a pointer to a boolean that we set if the
  1475. memory is allocated using AllocateCommonBuffer.
  1476. Return Value:
  1477. Returns the VA of the allocated memory if the allocation succeeds. Else,
  1478. returns NULL.
  1479. --*/
  1480. {
  1481. PVOID Buffer;
  1482. if (DmaAdapterObject == NULL) {
  1483. //
  1484. // Since there is no adapter object just allocate from non-paged pool.
  1485. //
  1486. Buffer = SpAllocatePool(
  1487. NonPagedPool,
  1488. Length,
  1489. SCSIPORT_TAG_COMMON_BUFFER,
  1490. DriverObject);
  1491. } else {
  1492. ASSERT(PhysicalCommonBuffer != NULL);
  1493. //
  1494. // If the controller can do 64-bit addresses then we need to
  1495. // specifically force the uncached extension area below the 4GB mark.
  1496. //
  1497. if (((Sp64BitPhysicalAddresses) && (Dma64BitAddresses == TRUE)) ||
  1498. Align != 0) {
  1499. PHYSICAL_ADDRESS low;
  1500. PHYSICAL_ADDRESS high;
  1501. PHYSICAL_ADDRESS boundary;
  1502. if (Align != 0) {
  1503. boundary.QuadPart = Length;
  1504. } else {
  1505. boundary.QuadPart = 0;
  1506. }
  1507. low.QuadPart = 0;
  1508. high.HighPart = 0;
  1509. high.LowPart = 0xffffffff;
  1510. //
  1511. // We'll get page aligned memory out of this which is probably
  1512. // better than the requirements of the adapter.
  1513. //
  1514. Buffer = MmAllocateContiguousMemorySpecifyCache(
  1515. Length,
  1516. low,
  1517. high,
  1518. boundary,
  1519. MmCached);
  1520. if (Buffer != NULL) {
  1521. *PhysicalCommonBuffer = MmGetPhysicalAddress(Buffer);
  1522. }
  1523. if (CommonBuffer != NULL) {
  1524. *CommonBuffer = FALSE;
  1525. }
  1526. } else {
  1527. Buffer = AllocateCommonBuffer(
  1528. DmaAdapterObject,
  1529. Length,
  1530. PhysicalCommonBuffer,
  1531. FALSE);
  1532. if (CommonBuffer != NULL) {
  1533. *CommonBuffer = TRUE;
  1534. }
  1535. }
  1536. }
  1537. return Buffer;
  1538. }
  1539. NTSTATUS
  1540. SpGetCommonBufferVrfy(
  1541. PADAPTER_EXTENSION DeviceExtension,
  1542. ULONG NonCachedExtensionSize
  1543. )
  1544. /*++
  1545. Routine Description:
  1546. This function allocates multiple common buffer blocks instead of one
  1547. big one. The verifier does this so it can remap VA ranges within
  1548. each block in order to control their protection attributes. This
  1549. enables us to invalidate key VA ranges and catch miniports that attempt
  1550. to access these ranges when they should not.
  1551. If the remapping succeeds, the SCSI port driver hands out the remapped
  1552. VA ranges to miniports instead of the original ranges. If the remapping
  1553. fails, it just hands out the original ranges.
  1554. Arguments:
  1555. DeviceExtension - Supplies a pointer to the device extension.
  1556. NonCachedExtensionSize - Supplies the size of the noncached device
  1557. extension for the miniport driver.
  1558. Return Value:
  1559. Returns the status of the allocate operation.
  1560. --*/
  1561. {
  1562. NTSTATUS Status;
  1563. PVOID buffer;
  1564. ULONG length;
  1565. ULONG blockSize;
  1566. PVOID *srbExtension;
  1567. PVOID buffer2;
  1568. PMDL mdl;
  1569. ULONG TotalSize;
  1570. ULONG i;
  1571. PVOID* BlkAddr;
  1572. PHYSICAL_ADDRESS *PhysicalCommonBuffer;
  1573. PCCHAR InvalidRegion;
  1574. BOOLEAN commonBuffer;
  1575. PAGED_CODE();
  1576. DebugPrint((1, "SpGetCommonBufferVrfy: DeviceExtension:%p NonCachedExtensionSize:%d\n",
  1577. DeviceExtension, NonCachedExtensionSize));
  1578. //
  1579. // Now fixup the size if the adapter has special alignment requirements so
  1580. // the buffer we allocate may be aligned as required.
  1581. //
  1582. if (DeviceExtension->UncachedExtAlignment != 0) {
  1583. NonCachedExtensionSize =
  1584. ROUND_UP_COUNT(NonCachedExtensionSize,
  1585. DeviceExtension->UncachedExtAlignment);
  1586. }
  1587. //
  1588. // We maintain a couple of arrays in order to find our common
  1589. // buffer blocks at various times. Calculate the amount of space we
  1590. // need for these arrays. This amount depends on the number of
  1591. // simultaneous requests the adapter supports. We add one to the
  1592. // number of requests in order to accommodate the non-cached extension.
  1593. //
  1594. ASSERT(DeviceExtension->VerifierExtension->CommonBufferVAs == NULL);
  1595. i = DeviceExtension->NumberOfRequests + 1;
  1596. length = sizeof(PVOID) * i;
  1597. if (DeviceExtension->DmaAdapterObject != NULL) {
  1598. ASSERT(DeviceExtension->VerifierExtension->CommonBufferPAs == NULL);
  1599. length += (sizeof(PHYSICAL_ADDRESS) * i);
  1600. }
  1601. //
  1602. // Allocate a block of memory for these arrays. If this allocation fails,
  1603. // we return failure.
  1604. //
  1605. BlkAddr = SpAllocatePool(NonPagedPool,
  1606. length,
  1607. SCSIPORT_TAG_COMMON_BUFFER,
  1608. DeviceExtension->DeviceObject->DriverObject);
  1609. if (BlkAddr == NULL) {
  1610. return STATUS_INSUFFICIENT_RESOURCES;
  1611. }
  1612. //
  1613. // Save the number of common buffer blocks.
  1614. //
  1615. DeviceExtension->VerifierExtension->CommonBufferBlocks =
  1616. DeviceExtension->NumberOfRequests;
  1617. //
  1618. // Zero the entire block so when we're freeing resources we can tell if we
  1619. // have valid buffers to free.
  1620. //
  1621. RtlZeroMemory(BlkAddr, length);
  1622. //
  1623. // Save a pointer to the array of addresses in the adapter extension and,
  1624. // if there is an adapter object, initialize a pointer to the beginning of
  1625. // the physical address array and save a pointer to the array in the
  1626. // adapter extension.
  1627. //
  1628. DeviceExtension->VerifierExtension->CommonBufferVAs = (PVOID *)BlkAddr;
  1629. if (DeviceExtension->DmaAdapterObject != NULL) {
  1630. PhysicalCommonBuffer = (PHYSICAL_ADDRESS*) &BlkAddr[i];
  1631. DeviceExtension->VerifierExtension->CommonBufferPAs = PhysicalCommonBuffer;
  1632. }
  1633. //
  1634. // To ensure that we never transfer normal request data to the SrbExtension
  1635. // (ie. the case of Srb->SenseInfoBuffer == VirtualAddress in
  1636. // ScsiPortGetPhysicalAddress) on some platforms where an inconsistency in
  1637. // MM can result in the same Virtual address supplied for 2 different
  1638. // physical addresses, bump the SrbExtensionSize if it's zero.
  1639. //
  1640. if (DeviceExtension->SrbExtensionSize == 0) {
  1641. DeviceExtension->SrbExtensionSize = 16;
  1642. }
  1643. //
  1644. // Calculate the block size for an SRB extension/sense buffer block. If
  1645. // AutoRequestSense is FALSE, allocate 1 page anyway as a placeholder.
  1646. //
  1647. blockSize = (ULONG)ROUND_TO_PAGES(DeviceExtension->SrbExtensionSize);
  1648. if (DeviceExtension->AutoRequestSense == TRUE) {
  1649. blockSize += sizeof(SENSE_DATA) + DeviceExtension->AdditionalSenseBytes;
  1650. blockSize = (ULONG)ROUND_TO_PAGES(blockSize);
  1651. } else {
  1652. blockSize += PAGE_SIZE;
  1653. }
  1654. //
  1655. // Add a page for holding bookkeeping information.
  1656. //
  1657. blockSize += PAGE_SIZE;
  1658. //
  1659. // Allocate each block individually and link them all together into a
  1660. // list. If we fail to allocate any of the blocks, we clean everything up
  1661. // and return failure.
  1662. //
  1663. DeviceExtension->CommonBufferSize = blockSize;
  1664. srbExtension = NULL;
  1665. for (i = 0; i < DeviceExtension->NumberOfRequests; i++) {
  1666. //
  1667. // Allocate a contiguous chunk of memory for the block.
  1668. //
  1669. buffer = SpAllocateContiguousChunk(
  1670. DeviceExtension->DeviceObject->DriverObject,
  1671. DeviceExtension->DmaAdapterObject,
  1672. DeviceExtension->Dma64BitAddresses,
  1673. blockSize,
  1674. 0,
  1675. (DeviceExtension->DmaAdapterObject) ? &PhysicalCommonBuffer[i] : NULL,
  1676. &commonBuffer);
  1677. if (buffer == NULL) {
  1678. //
  1679. // Free everything we've allocated so far and return failure. This
  1680. // will also free the arrays we allocated at the beginning of this
  1681. // function.
  1682. //
  1683. DeviceExtension->VerifierExtension->IsCommonBuffer = commonBuffer;
  1684. SpFreeCommonBufferVrfy(DeviceExtension);
  1685. return STATUS_INSUFFICIENT_RESOURCES;
  1686. }
  1687. //
  1688. // Zero the entire block and save a pointer to it in our array.
  1689. //
  1690. RtlZeroMemory(buffer, blockSize);
  1691. BlkAddr[i] = buffer;
  1692. //
  1693. // Link the new block onto the front of the chain.
  1694. //
  1695. *((PVOID *) buffer) = srbExtension;
  1696. srbExtension = (PVOID *) buffer;
  1697. }
  1698. //
  1699. // Indicate whether the buffer was allocated as common buffer.
  1700. //
  1701. DeviceExtension->VerifierExtension->IsCommonBuffer = commonBuffer;
  1702. //
  1703. // Allocate the non-cached extension. Note that we align the uncached
  1704. // buffer on the next page boundary and allocate enough for a scratch page.
  1705. // If the allocation fails, free everything we've allocated so far and
  1706. // return failure.
  1707. //
  1708. if (NonCachedExtensionSize != 0) {
  1709. DeviceExtension->VerifierExtension->NonCachedBufferSize = NonCachedExtensionSize;
  1710. length = (ULONG)(ROUND_TO_PAGES(NonCachedExtensionSize));
  1711. BlkAddr[i] =
  1712. SpAllocateContiguousChunk(
  1713. DeviceExtension->DeviceObject->DriverObject,
  1714. DeviceExtension->DmaAdapterObject,
  1715. DeviceExtension->Dma64BitAddresses,
  1716. length,
  1717. DeviceExtension->UncachedExtAlignment,
  1718. (DeviceExtension->DmaAdapterObject) ? &PhysicalCommonBuffer[i] : NULL,
  1719. &DeviceExtension->UncachedExtensionIsCommonBuffer);
  1720. if (BlkAddr[i] == NULL) {
  1721. //
  1722. // Free everything we've allocated so far and return failure. This
  1723. // will also free the arrays we allocated at the beginning of this
  1724. // function.
  1725. //
  1726. SpFreeCommonBufferVrfy(DeviceExtension);
  1727. return STATUS_INSUFFICIENT_RESOURCES;
  1728. }
  1729. //
  1730. // Zero the entire block.
  1731. //
  1732. RtlZeroMemory(BlkAddr[i], length);
  1733. //
  1734. // Save a pointer to the beginning of the non-cached extension data.
  1735. // Note that the data is positioned such that it ends on a page
  1736. // boundary so if the miniport overwrites the buffer, the system will
  1737. // fault.
  1738. //
  1739. DeviceExtension->NonCachedExtension =
  1740. (PCCHAR)BlkAddr[i] +
  1741. (ROUND_TO_PAGES(NonCachedExtensionSize) - NonCachedExtensionSize);
  1742. } else {
  1743. DeviceExtension->NonCachedExtension = NULL;
  1744. DeviceExtension->VerifierExtension->NonCachedBufferSize = 0;
  1745. }
  1746. //
  1747. // If the miniport asked for an SRB Extension, point the SRB Extension List
  1748. // at the beginning of the list of blocks we allocated and chained together
  1749. // above.
  1750. //
  1751. if (DeviceExtension->AllocateSrbExtension == TRUE) {
  1752. DeviceExtension->SrbExtensionListHeader = srbExtension;
  1753. } else {
  1754. ASSERT(DeviceExtension->SrbExtensionListHeader == NULL);
  1755. }
  1756. //
  1757. // Create a second VA mapping of the common buffer area so we can make the
  1758. // range of addresses invalid when the miniport is not supposed to touch it.
  1759. // This will allow us to catch mis-behaving miniports.
  1760. //
  1761. SpRemapCommonBufferForMiniport(DeviceExtension);
  1762. DebugPrint((1, "SpGetCommonBufferVrfy: returning STATUS_SUCCESS\n"));
  1763. return(STATUS_SUCCESS);
  1764. }
  1765. VOID
  1766. SpFreeCommonBufferVrfy(
  1767. PADAPTER_EXTENSION Adapter
  1768. )
  1769. /*++
  1770. Routine Description:
  1771. This routine frees all of the common buffer space we've allocated for the
  1772. miniport on the supplied adapter. If only partially allocated, the routine
  1773. correctly cleans up the parts that are present. On exit, all the memory has
  1774. been freed and the associated pointers have been NULLed.
  1775. Arguments:
  1776. DeviceExtension - Supplies a pointer to the adapter device extension.
  1777. Return Value:
  1778. VOID
  1779. --*/
  1780. {
  1781. ULONG i;
  1782. PVOID* BlkAddr;
  1783. NTSTATUS Status;
  1784. PSP_VA_MAPPING_INFO MappingInfo;
  1785. ASSERT(Adapter->SrbExtensionBuffer == NULL);
  1786. if (Adapter->VerifierExtension != NULL &&
  1787. Adapter->VerifierExtension->CommonBufferVAs != NULL) {
  1788. //
  1789. // Initialize a pointer to the array of pointers we use to track and
  1790. // manage the common buffer blocks.
  1791. //
  1792. BlkAddr = Adapter->VerifierExtension->CommonBufferVAs;
  1793. //
  1794. // Cycle through the array of common memory descriptors, freeing each
  1795. // one. What we are freeing here is the SRB Extension/Sense Data
  1796. // buffers. Stop when we've deleted all the blocks.
  1797. //
  1798. for (i = 0; i < Adapter->VerifierExtension->CommonBufferBlocks && BlkAddr[i]; i++) {
  1799. //
  1800. // If there is a second VA range for the common block, free the
  1801. // MDL(s).
  1802. //
  1803. MappingInfo = GET_VA_MAPPING_INFO(Adapter, BlkAddr[i]);
  1804. if (MappingInfo->SrbExtMdl != NULL) {
  1805. MmProtectMdlSystemAddress(MappingInfo->SrbExtMdl, PAGE_READWRITE);
  1806. MmUnlockPages(MappingInfo->SrbExtMdl);
  1807. IoFreeMdl(MappingInfo->SrbExtMdl);
  1808. }
  1809. if (MappingInfo->SenseMdl != NULL) {
  1810. MmProtectMdlSystemAddress(MappingInfo->SrbExtMdl, PAGE_READWRITE);
  1811. MmUnlockPages(MappingInfo->SenseMdl);
  1812. IoFreeMdl(MappingInfo->SenseMdl);
  1813. }
  1814. //
  1815. // Free the memory. The method we use depends on how the memory
  1816. // was allocated.
  1817. //
  1818. if (Adapter->DmaAdapterObject == NULL) {
  1819. ExFreePool(BlkAddr[i]);
  1820. } else {
  1821. if (Adapter->VerifierExtension->IsCommonBuffer == FALSE) {
  1822. MmFreeContiguousMemorySpecifyCache(
  1823. BlkAddr[i],
  1824. Adapter->CommonBufferSize,
  1825. MmCached);
  1826. } else {
  1827. FreeCommonBuffer(
  1828. Adapter->DmaAdapterObject,
  1829. Adapter->CommonBufferSize,
  1830. Adapter->VerifierExtension->CommonBufferPAs[i],
  1831. BlkAddr[i],
  1832. FALSE);
  1833. }
  1834. }
  1835. }
  1836. //
  1837. // Free the uncached extension if we allocated one.
  1838. //
  1839. if (Adapter->NonCachedExtension != NULL) {
  1840. ULONG Length;
  1841. //
  1842. // Calculate the total length of the non-cached extension block we
  1843. // allocated. This is the non-cached buffer size asked for by the
  1844. // miniport rounded up to the next page boundary plus one full page.
  1845. //
  1846. Length = (ULONG)(ROUND_TO_PAGES(Adapter->VerifierExtension->NonCachedBufferSize));
  1847. //
  1848. // Free the memory. The method we use depends on how the memory
  1849. // was allocated.
  1850. //
  1851. if (Adapter->DmaAdapterObject == NULL) {
  1852. ExFreePool(BlkAddr[i]);
  1853. } else {
  1854. if (Adapter->UncachedExtensionIsCommonBuffer == FALSE) {
  1855. MmFreeContiguousMemorySpecifyCache(
  1856. BlkAddr[i],
  1857. Length,
  1858. MmCached);
  1859. } else {
  1860. FreeCommonBuffer(
  1861. Adapter->DmaAdapterObject,
  1862. Length,
  1863. Adapter->VerifierExtension->CommonBufferPAs[i],
  1864. BlkAddr[i],
  1865. FALSE);
  1866. }
  1867. }
  1868. Adapter->NonCachedExtension = NULL;
  1869. }
  1870. //
  1871. // Free the arrays we allocated to manage the common buffer area.
  1872. //
  1873. ExFreePool(Adapter->VerifierExtension->CommonBufferVAs);
  1874. Adapter->VerifierExtension->CommonBufferVAs = NULL;
  1875. Adapter->VerifierExtension->CommonBufferPAs = NULL;
  1876. Adapter->VerifierExtension->CommonBufferBlocks = 0;
  1877. Adapter->SrbExtensionListHeader = NULL;
  1878. }
  1879. }
  1880. PVOID
  1881. SpGetOriginalSrbExtVa(
  1882. PADAPTER_EXTENSION Adapter,
  1883. PVOID Va
  1884. )
  1885. /*++
  1886. Routine Description:
  1887. This function returns the original mapped virtual address of a common
  1888. block if the supplied VA is for one of the common buffer blocks we've
  1889. allocated.
  1890. Arguments:
  1891. Adapter - the adapter device extension
  1892. Va - virtual address of a common buffer block
  1893. Return Value:
  1894. If the supplied VA is the address of one of the common buffer blocks,
  1895. returns the original VA of the block. Else, returns NULL.
  1896. --*/
  1897. {
  1898. PVOID* BlkAddr = Adapter->VerifierExtension->CommonBufferVAs;
  1899. PSP_VA_MAPPING_INFO MappingInfo;
  1900. ULONG i;
  1901. for (i = 0; i < Adapter->VerifierExtension->CommonBufferBlocks; i++) {
  1902. MappingInfo = GET_VA_MAPPING_INFO(Adapter, *BlkAddr++);
  1903. if (Va == MappingInfo->RemappedSrbExtVa ||
  1904. Va == MappingInfo->OriginalSrbExtVa)
  1905. return MappingInfo->OriginalSrbExtVa;
  1906. }
  1907. return NULL;
  1908. }
  1909. VOID
  1910. SpInsertSrbExtension(
  1911. PADAPTER_EXTENSION Adapter,
  1912. PCCHAR SrbExtension
  1913. )
  1914. /*++
  1915. Routine Description:
  1916. This routine inserts the supplied SRB extension back into the SRB extension
  1917. list. The VA of the supplied extension lies within one of our common buffer
  1918. blocks and it may be a remapped VA. If it is a remapped address, this
  1919. routine invalidates the page(s) comprising the extension after it links the
  1920. extension back into the list.
  1921. Arguments:
  1922. Adapter - Pointer to an adapter device extension.
  1923. SrbExtension - Pointer to the beginning of an SRB extension within one of
  1924. our common buffer blocks. May or may not be within a
  1925. remapped range.
  1926. --*/
  1927. {
  1928. //
  1929. // Round the srb extension pointer down to the beginning of the page
  1930. // and link the block back into the list. Note that we're careful
  1931. // to point the list header at the original VA of the block.
  1932. //
  1933. SrbExtension = (PVOID)((ULONG_PTR)SrbExtension & ~(PAGE_SIZE - 1));
  1934. *((PVOID *) SrbExtension) = Adapter->SrbExtensionListHeader;
  1935. Adapter->SrbExtensionListHeader = SpGetOriginalSrbExtVa(
  1936. Adapter,
  1937. SrbExtension);
  1938. //
  1939. // If the original VA differs from the one supplied, the supplied
  1940. // one is one of our remapped VAs. In this case, we want to invalidate
  1941. // the range so the system will bugcheck if anyone tries to access it.
  1942. //
  1943. if (Adapter->SrbExtensionListHeader != SrbExtension) {
  1944. PMDL Mdl = SpGetRemappedSrbExt(Adapter, Adapter->SrbExtensionListHeader);
  1945. ASSERT(Mdl != NULL);
  1946. MmProtectMdlSystemAddress(Mdl, PAGE_NOACCESS);
  1947. //
  1948. // Just because we remapped the SRB extension does not mean we
  1949. // necessarily remapped the sense buffer.
  1950. //
  1951. Mdl = SpGetRemappedSenseBuffer(Adapter, Adapter->SrbExtensionListHeader);
  1952. if (Mdl != NULL) {
  1953. MmProtectMdlSystemAddress(Mdl, PAGE_NOACCESS);
  1954. }
  1955. }
  1956. }
  1957. PVOID
  1958. SpPrepareSrbExtensionForUse(
  1959. IN PADAPTER_EXTENSION Adapter,
  1960. IN OUT PCCHAR SrbExtension
  1961. )
  1962. /*++
  1963. Routine Description:
  1964. This function accepts a pointer to the beginning of one of the individual
  1965. common-buffer blocks allocated by the verifier for SRB extensions, sense
  1966. buffers, and non-cached extensions. It calculates the beginning of the
  1967. SRB extension within the block and, if the block has been remapped, makes
  1968. the page(s) of the SRB extension read/write valid.
  1969. Arguments:
  1970. Adapter - Pointer to an adapter device extension.
  1971. SrbExtension - Pointer to the beginning of a common-buffer block.
  1972. Return Value:
  1973. If the common buffer block containing the SRB extension has been remapped,
  1974. returns the address of the beginning of the remapped srb extension, valid
  1975. for reading and writing.
  1976. If the block has not been remapped, returns NULL.
  1977. Regardless of whether the block is remapped or not, the supplied pointer
  1978. is fixed up to point to the beginning of the SRB extension within the
  1979. original VA range.
  1980. --*/
  1981. {
  1982. PCCHAR RemappedSrbExt = NULL;
  1983. NTSTATUS Status;
  1984. PMDL Mdl;
  1985. ULONG srbExtensionSize = ROUND_UP_COUNT(Adapter->SrbExtensionSize, 8);
  1986. //
  1987. // If we've remapped the SRB extension, get the second mapping and make it
  1988. // valid. If we get the second mapping, but cannot make it valid, we just
  1989. // use the original mapping.
  1990. //
  1991. Mdl = SpGetRemappedSrbExt(Adapter, SrbExtension);
  1992. if (Mdl != NULL) {
  1993. Status = MmProtectMdlSystemAddress(Mdl, PAGE_READWRITE);
  1994. if (NT_SUCCESS(Status)) {
  1995. RemappedSrbExt = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
  1996. //
  1997. // Adjust the remapped srb extension pointer so the end of the
  1998. // buffer falls on a page boundary.
  1999. //
  2000. RemappedSrbExt += ((Adapter->CommonBufferSize - (PAGE_SIZE * 2)) - srbExtensionSize);
  2001. }
  2002. }
  2003. //
  2004. // Adjust the original srb extension pointer so it also ends on a page boundary.
  2005. //
  2006. SrbExtension += ((Adapter->CommonBufferSize - (PAGE_SIZE * 2)) - srbExtensionSize);
  2007. return RemappedSrbExt;
  2008. }
  2009. PCCHAR
  2010. SpPrepareSenseBufferForUse(
  2011. PADAPTER_EXTENSION Adapter,
  2012. PCCHAR SrbExtension
  2013. )
  2014. /*++
  2015. Routine Description:
  2016. This function accepts a pointer to the beginning of an SRB extension
  2017. within one of the individual common-buffer blocks allocated by the
  2018. verifier for SRB extensions, sense buffers, and non-cached extensions.
  2019. It calculates the beginning of the sense buffer within the block and,
  2020. if the block has been remapped, makes the page read/write valid.
  2021. It is assumed that a sense buffer will never be larger than one page.
  2022. Arguments:
  2023. Adapter - Pointer to an adapter device extension.
  2024. SrbExtension - Pointer to the beginning of the SRB extension within a
  2025. common-buffer block.
  2026. Return Value:
  2027. Returns the address of the beginning of a sense buffer valid for
  2028. reading and writing.
  2029. --*/
  2030. {
  2031. PVOID BeginningOfBlock;
  2032. ULONG SenseDataSize;
  2033. PCCHAR Base;
  2034. NTSTATUS Status;
  2035. PMDL Mdl;
  2036. ULONG srbExtensionSize = (ULONG)ROUND_TO_PAGES(Adapter->SrbExtensionSize);
  2037. //
  2038. // Initialize the size of the sense buffer and the base of the sense buffer
  2039. // within the originally allocated block. The base of the sense buffer
  2040. // immediately follows the srb extension and resides on a page boundary
  2041. // within a common buffer block.
  2042. //
  2043. SenseDataSize = sizeof(SENSE_DATA) + Adapter->AdditionalSenseBytes;
  2044. SenseDataSize = ROUND_UP_COUNT(SenseDataSize, 8);
  2045. Base = SrbExtension + srbExtensionSize;
  2046. //
  2047. // Initialize a pointer to the beginning of the common block the sense
  2048. // buffer resides in. This is needed in order to determine if the
  2049. // sense buffer has been remapped.
  2050. //
  2051. BeginningOfBlock = (PVOID)((ULONG_PTR)SrbExtension & ~(PAGE_SIZE - 1));
  2052. //
  2053. // If we've remapped the sense buffer, make the range valid and reset base
  2054. // to point to the beginning of the range.
  2055. //
  2056. Mdl = SpGetRemappedSenseBuffer(Adapter, BeginningOfBlock);
  2057. if (Mdl != NULL) {
  2058. Status = MmProtectMdlSystemAddress(Mdl, PAGE_READWRITE);
  2059. if (NT_SUCCESS(Status)) {
  2060. Base = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
  2061. ASSERT(Base != NULL);
  2062. }
  2063. }
  2064. //
  2065. // Return a pointer into the block such that the sense buffer ends aligned
  2066. // on a page boundary.
  2067. //
  2068. return (Base + PAGE_SIZE - SenseDataSize);
  2069. }
  2070. PVOID
  2071. SpGetInaccessiblePage(
  2072. PADAPTER_EXTENSION Adapter
  2073. )
  2074. /*++
  2075. Routine Description:
  2076. This function returns a pointer to a page of memory that is not valid
  2077. for reading or writing. This page is a shared resource, used by all
  2078. adapters that are actively verifying. The page is hung off of the driver
  2079. extension. The page is faulted in as needed, so if we haven't initialized
  2080. it yet, we try to do so here in an interlocked fashion.
  2081. Arguments:
  2082. Adapter - Pointer to an adapter device extension.
  2083. Return Value:
  2084. Either returns a pointer to an invalid page of VAs or NULL if the page
  2085. could not be allocated.
  2086. --*/
  2087. {
  2088. PSCSIPORT_DRIVER_EXTENSION DriverExtension;
  2089. PVOID UnusedPage;
  2090. PVOID InvalidPage;
  2091. PMDL UnusedPageMdl;
  2092. PVOID CurrentValue;
  2093. //
  2094. // Retrieve the driver extension. We must have it to proceed.
  2095. //
  2096. DriverExtension = IoGetDriverObjectExtension(
  2097. Adapter->DeviceObject->DriverObject,
  2098. ScsiPortInitialize);
  2099. if (DriverExtension == NULL) {
  2100. return NULL;
  2101. }
  2102. //
  2103. // If the invalid page is not yet initialized, go ahead and try to
  2104. // initialize it now.
  2105. //
  2106. if (DriverExtension->InvalidPage == NULL) {
  2107. //
  2108. // Allocate a page of memory.
  2109. //
  2110. UnusedPage = SpAllocatePool(NonPagedPool,
  2111. PAGE_SIZE,
  2112. SCSIPORT_TAG_VERIFIER,
  2113. Adapter->DeviceObject->DriverObject);
  2114. if (UnusedPage != NULL) {
  2115. //
  2116. // Zero the page and remap it. The remapped range will be inaccessible.
  2117. // If the remapping fails, just free the page; we just won't have an
  2118. // inaccessible page to work with.
  2119. //
  2120. RtlZeroMemory(UnusedPage, PAGE_SIZE);
  2121. InvalidPage = SpRemapBlock(UnusedPage,
  2122. PAGE_SIZE,
  2123. &UnusedPageMdl);
  2124. if (InvalidPage != NULL) {
  2125. //
  2126. // If nobody else has beaten us to it, init the pointer to the
  2127. // invalid page in the driver extension. If somebody has already
  2128. // done it, just free the page we created. This page is freed
  2129. // when scsiport is unloaded.
  2130. //
  2131. CurrentValue = InterlockedCompareExchangePointer(
  2132. &DriverExtension->InvalidPage,
  2133. InvalidPage,
  2134. NULL);
  2135. if (CurrentValue == NULL) {
  2136. DriverExtension->UnusedPage = UnusedPage;
  2137. DriverExtension->UnusedPageMdl = UnusedPageMdl;
  2138. } else {
  2139. MmProtectMdlSystemAddress(UnusedPageMdl, PAGE_READWRITE);
  2140. UnusedPageMdl->MdlFlags &= ~MDL_MAPPED_TO_SYSTEM_VA;
  2141. IoFreeMdl(UnusedPageMdl);
  2142. ExFreePool(UnusedPage);
  2143. }
  2144. } else {
  2145. //
  2146. // Couldn't make the page inaccessible, just free it.
  2147. //
  2148. ExFreePool(UnusedPage);
  2149. }
  2150. }
  2151. }
  2152. return DriverExtension->InvalidPage;
  2153. }
  2154. BOOLEAN
  2155. SpCheckForActiveRequests(
  2156. PADAPTER_EXTENSION Adapter
  2157. )
  2158. /*++
  2159. Routine Description:
  2160. This function walks through all of the logical units connected to the
  2161. supplied adapter looking for any outstanding requests. If it finds
  2162. any, it returns TRUE immediately.
  2163. Arguments:
  2164. Adapter - Pointer to an adapter device extension.
  2165. Return Value:
  2166. TRUE - If an outstanding requests is found on one of the logical units
  2167. connected to the adapter.
  2168. FALSE - If no outstanding requests on the adapter.
  2169. --*/
  2170. {
  2171. PLOGICAL_UNIT_EXTENSION LogicalUnit;
  2172. PLOGICAL_UNIT_BIN Bin;
  2173. ULONG BinNumber;
  2174. //
  2175. // Iterate through each LU bin. For each bin, if there are any LUs, iterate
  2176. // through each of those looking for an oustanding request. If we find one
  2177. // terminate the search and return TRUE.
  2178. //
  2179. for (BinNumber = 0; BinNumber < NUMBER_LOGICAL_UNIT_BINS; BinNumber++) {
  2180. Bin = &Adapter->LogicalUnitList[BinNumber];
  2181. LogicalUnit = Bin->List;
  2182. while (LogicalUnit != NULL) {
  2183. if (LogicalUnit->AbortSrb != NULL &&
  2184. LogicalUnit->AbortSrb->SrbFlags & SRB_FLAGS_IS_ACTIVE) {
  2185. return TRUE;
  2186. } else if (LogicalUnit->CurrentUntaggedRequest != NULL &&
  2187. LogicalUnit->CurrentUntaggedRequest->CurrentSrb->SrbFlags & SRB_FLAGS_IS_ACTIVE) {
  2188. return TRUE;
  2189. } else if (LogicalUnit->RequestList.Flink != &LogicalUnit->RequestList) {
  2190. PSRB_DATA srbData;
  2191. PVOID nextEntry = LogicalUnit->RequestList.Flink;
  2192. while (nextEntry != &LogicalUnit->RequestList) {
  2193. srbData = CONTAINING_RECORD(nextEntry, SRB_DATA, RequestList);
  2194. if (srbData->CurrentSrb->SrbFlags & SRB_FLAGS_IS_ACTIVE) {
  2195. return TRUE;
  2196. }
  2197. nextEntry = srbData->RequestList.Flink;
  2198. }
  2199. }
  2200. LogicalUnit = LogicalUnit->NextLogicalUnit;
  2201. }
  2202. }
  2203. return FALSE;
  2204. }
  2205. VOID
  2206. SpEnsureAllRequestsAreComplete(
  2207. PADAPTER_EXTENSION Adapter
  2208. )
  2209. /*++
  2210. Routine Description:
  2211. This routine bugchecks the system if there are any outstanding requests
  2212. on the supplied adapter. If the SP_DONT_CHK_REQUESTS_ON_RESET bit is
  2213. set on the adapter's verification level, don't do the check.
  2214. Arguments:
  2215. Adapter - Points to an adapter device extension.
  2216. --*/
  2217. {
  2218. //
  2219. // If there are any outstanding requests on any of the LUs connected to the
  2220. // adapter, bugcheck the system. Note that we only do this check if it
  2221. // has not been turned off.
  2222. //
  2223. if (VRFY_DO_CHECK(Adapter, SP_DONT_CHK_REQUESTS_ON_RESET)) {
  2224. BOOLEAN ActiveRequests = SpCheckForActiveRequests(Adapter);
  2225. if (ActiveRequests == TRUE) {
  2226. KeBugCheckEx(SCSI_VERIFIER_DETECTED_VIOLATION,
  2227. SCSIPORT_VERIFIER_RQSTS_NOT_COMPLETE,
  2228. (ULONG_PTR)Adapter,
  2229. (ULONG_PTR)Adapter->HwDeviceExtension,
  2230. 0);
  2231. }
  2232. }
  2233. }
  2234. VOID
  2235. SpDoVerifierInit(
  2236. IN PADAPTER_EXTENSION Adapter,
  2237. IN PHW_INITIALIZATION_DATA HwInitializationData
  2238. )
  2239. /*++
  2240. Routine Description:
  2241. This routine allocates and initializes a verifier extension for the
  2242. supplied adapter. A per-adapter verification level is read from the
  2243. registry before allocating the extension. A verfication level of -1
  2244. means "don't verify this adapter". If we do allocate the extension,
  2245. we also lock the verifier code section into memory.
  2246. Arguments:
  2247. Adapter - The adapter device extension.
  2248. HwInitializationData - A pointer to the HW_INITIALIZATION_DATA for
  2249. the adapter.
  2250. --*/
  2251. {
  2252. ULONG VerifyLevel;
  2253. NTSTATUS Status;
  2254. PAGED_CODE();
  2255. //
  2256. // Read adapter's verification level from the registry. If the adapter is
  2257. // configured for no verification, just return.
  2258. //
  2259. VerifyLevel = SpGetAdapterVerifyLevel(Adapter);
  2260. if (VerifyLevel == SP_VRFY_NONE) {
  2261. return;
  2262. }
  2263. //
  2264. // Go ahead and try to allocate the extension.
  2265. //
  2266. Adapter->VerifierExtension =
  2267. SpAllocatePool(NonPagedPool,
  2268. sizeof(VERIFIER_EXTENSION),
  2269. SCSIPORT_TAG_VERIFIER,
  2270. Adapter->DeviceObject->DriverObject);
  2271. if (Adapter->VerifierExtension != NULL) {
  2272. //
  2273. // Zero the extension.
  2274. //
  2275. RtlZeroMemory(Adapter->VerifierExtension, sizeof(VERIFIER_EXTENSION));
  2276. //
  2277. // Lock the pageable verifier code section into memory.
  2278. //
  2279. #ifdef ALLOC_PRAGMA
  2280. if (VerifierCodeSectionHandle == NULL) {
  2281. VerifierCodeSectionHandle = MmLockPagableCodeSection(SpHwFindAdapterVrfy);
  2282. } else {
  2283. MmLockPagableSectionByHandle(VerifierCodeSectionHandle);
  2284. }
  2285. #endif
  2286. //
  2287. // Set the verification level for this adapter. This value is the sum
  2288. // of the global verifier level and the per-adapter value we read above.
  2289. //
  2290. Adapter->VerifierExtension->VrfyLevel = (VerifyLevel | SpVrfyLevel);
  2291. //
  2292. // Initialize function pointers in the verifier extension to
  2293. // to point to the real miniport routines.
  2294. //
  2295. Adapter->VerifierExtension->RealHwFindAdapter = HwInitializationData->HwFindAdapter;
  2296. Adapter->VerifierExtension->RealHwInitialize = HwInitializationData->HwInitialize;
  2297. Adapter->VerifierExtension->RealHwStartIo = HwInitializationData->HwStartIo;
  2298. Adapter->VerifierExtension->RealHwInterrupt = HwInitializationData->HwInterrupt;
  2299. Adapter->VerifierExtension->RealHwResetBus = HwInitializationData->HwResetBus;
  2300. Adapter->VerifierExtension->RealHwDmaStarted = HwInitializationData->HwDmaStarted;
  2301. Adapter->VerifierExtension->RealHwAdapterControl = HwInitializationData->HwAdapterControl;
  2302. //
  2303. // Redirect the miniport routines to verifier routines.
  2304. //
  2305. Adapter->HwFindAdapter = SpHwFindAdapterVrfy;
  2306. Adapter->HwInitialize = SpHwInitializeVrfy;
  2307. Adapter->HwStartIo = SpHwStartIoVrfy;
  2308. Adapter->HwInterrupt = SpHwInterruptVrfy;
  2309. Adapter->HwResetBus = SpHwResetBusVrfy;
  2310. Adapter->HwDmaStarted = SpHwDmaStartedVrfy;
  2311. Adapter->HwAdapterControl = SpHwAdapterControlVrfy;
  2312. //
  2313. // Get a pointer to an invalid page of memory so we can catch
  2314. // miniports trying to touch memory when they shouldn't be.
  2315. //
  2316. Adapter->VerifierExtension->InvalidPage = SpGetInaccessiblePage(Adapter);
  2317. }
  2318. }
  2319. VOID
  2320. SpDoVerifierCleanup(
  2321. IN PADAPTER_EXTENSION Adapter
  2322. )
  2323. /*++
  2324. Routine Description:
  2325. This routine frees the supplied adapter's verifier extension and releases
  2326. its reference on the verifier code section.
  2327. This routine gets called as part of the adapter resource cleanup. When
  2328. called, all the actual resources allocated for the verifier have already
  2329. been cleaned up.
  2330. Arguments:
  2331. Adapter - the adapter device extension
  2332. --*/
  2333. {
  2334. //
  2335. // We should never arrive here if the scsiport verifier is not active.
  2336. // And when we get here we should have freed all the resources hanging
  2337. // off the extension.
  2338. //
  2339. ASSERT(Adapter->VerifierExtension != NULL);
  2340. ASSERT(Adapter->VerifierExtension->CommonBufferVAs == NULL);
  2341. ASSERT(Adapter->VerifierExtension->CommonBufferPAs == NULL);
  2342. ASSERT(Adapter->VerifierExtension->CommonBufferBlocks == 0);
  2343. //
  2344. // Free and NULL the verifier extension for this adapter.
  2345. //
  2346. ExFreePool(Adapter->VerifierExtension);
  2347. Adapter->VerifierExtension = NULL;
  2348. //
  2349. // Release our reference on the verifier code section.
  2350. //
  2351. #ifdef ALLOC_PRAGMA
  2352. ASSERT(VerifierCodeSectionHandle != NULL);
  2353. MmUnlockPagableImageSection(VerifierCodeSectionHandle);
  2354. #endif
  2355. }
  2356. ULONG
  2357. SpGetAdapterVerifyLevel(
  2358. IN PADAPTER_EXTENSION Adapter
  2359. )
  2360. /*++
  2361. Routine Description:
  2362. This function returns the verification level for the supplied adapter.
  2363. Arguments:
  2364. Adapter - Pointer to an adapter device extension.
  2365. Return Value:
  2366. The supplied adapter's verification level.
  2367. --*/
  2368. {
  2369. PSCSIPORT_DRIVER_EXTENSION DrvExt;
  2370. OBJECT_ATTRIBUTES ObjectAttributes;
  2371. UNICODE_STRING UnicodeString;
  2372. HANDLE ParametersKey;
  2373. HANDLE ServiceKey;
  2374. ULONG VerifyLevel = 0;
  2375. NTSTATUS Status;
  2376. PAGED_CODE();
  2377. //
  2378. // We need the driver extension to get the adapter's registry path. We use
  2379. // this to look up the adapter settings in the registry. If we cannot get
  2380. // the driver extension, we have to abort.
  2381. //
  2382. DrvExt = IoGetDriverObjectExtension(
  2383. Adapter->DeviceObject->DriverObject,
  2384. ScsiPortInitialize);
  2385. if (DrvExt == NULL) {
  2386. return 0;
  2387. }
  2388. //
  2389. // Try to open the adapter's registry key.
  2390. //
  2391. InitializeObjectAttributes(
  2392. &ObjectAttributes,
  2393. &DrvExt->RegistryPath,
  2394. OBJ_CASE_INSENSITIVE,
  2395. NULL,
  2396. NULL);
  2397. Status = ZwOpenKey(&ServiceKey, KEY_READ, &ObjectAttributes);
  2398. if (NT_SUCCESS(Status)) {
  2399. //
  2400. // Try to open the adapter's parameters key.
  2401. //
  2402. RtlInitUnicodeString(&UnicodeString, L"Parameters");
  2403. InitializeObjectAttributes(
  2404. &ObjectAttributes,
  2405. &UnicodeString,
  2406. OBJ_CASE_INSENSITIVE,
  2407. ServiceKey,
  2408. NULL);
  2409. Status = ZwOpenKey(&ParametersKey, KEY_READ, &ObjectAttributes);
  2410. if (NT_SUCCESS(Status)) {
  2411. //
  2412. // Try to read the verification level value under the adapter's
  2413. // parameters key.
  2414. //
  2415. RtlInitUnicodeString(&UnicodeString, L"VerifyLevel");
  2416. SpReadNumericValue(
  2417. ParametersKey,
  2418. NULL,
  2419. &UnicodeString,
  2420. &VerifyLevel);
  2421. ZwClose(ParametersKey);
  2422. }
  2423. ZwClose(ServiceKey);
  2424. }
  2425. return VerifyLevel;
  2426. }