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.

3108 lines
92 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. if (BusDataType != PCIConfiguration) {
  643. KeBugCheckEx(SCSI_VERIFIER_DETECTED_VIOLATION,
  644. SCSIPORT_VERIFIER_BAD_BUSDATATYPE,
  645. (ULONG_PTR)BusDataType,
  646. (ULONG_PTR)DeviceExtension,
  647. (ULONG_PTR)SystemIoBusNumber);
  648. }
  649. BusData = ScsiPortGetBusData(DeviceExtension,
  650. BusDataType,
  651. SystemIoBusNumber,
  652. SlotNumber,
  653. Buffer,
  654. Length);
  655. return BusData;
  656. }
  657. PVOID
  658. ScsiPortGetLogicalUnitVrfy(
  659. IN PVOID HwDeviceExtension,
  660. IN UCHAR PathId,
  661. IN UCHAR TargetId,
  662. IN UCHAR Lun
  663. )
  664. {
  665. PVOID LogicalUnit;
  666. LogicalUnit = ScsiPortGetLogicalUnit(HwDeviceExtension,
  667. PathId,
  668. TargetId,
  669. Lun);
  670. return LogicalUnit;
  671. }
  672. SCSI_PHYSICAL_ADDRESS
  673. ScsiPortGetPhysicalAddressVrfy(
  674. IN PVOID HwDeviceExtension,
  675. IN PSCSI_REQUEST_BLOCK Srb,
  676. IN PVOID VirtualAddress,
  677. OUT ULONG *Length
  678. )
  679. {
  680. PADAPTER_EXTENSION deviceExtension = GET_FDO_EXTENSION(HwDeviceExtension);
  681. PHYSICAL_ADDRESS address;
  682. PSP_VA_MAPPING_INFO MappingInfo;
  683. ULONG byteOffset;
  684. ULONG length;
  685. if ((deviceExtension->VerifierExtension != NULL) &&
  686. (deviceExtension->VerifierExtension->VrfyLevel & SP_VRFY_COMMON_BUFFERS) &&
  687. (Srb == NULL || Srb->SenseInfoBuffer == VirtualAddress)) {
  688. ULONG i;
  689. PVOID* BlkAddr;
  690. PUCHAR Beginning, End;
  691. PHYSICAL_ADDRESS *AddressBlock;
  692. //
  693. // Initialize a pointer to our array of common memory block
  694. // descriptors. We use this to locate the block that contains
  695. // the VA.
  696. //
  697. BlkAddr = deviceExtension->VerifierExtension->CommonBufferVAs;
  698. //
  699. // Look for the block that contains the VA.
  700. //
  701. for (i = 0; i < deviceExtension->NumberOfRequests; i++) {
  702. //
  703. // First, check if the VA is in the SRB extension.
  704. //
  705. MappingInfo = GET_VA_MAPPING_INFO(deviceExtension, BlkAddr[i]);
  706. if (MappingInfo->RemappedSrbExtVa != NULL) {
  707. Beginning = MappingInfo->RemappedSrbExtVa;
  708. } else {
  709. Beginning = BlkAddr[i];
  710. }
  711. End = (PUCHAR)ROUND_TO_PAGES((PUCHAR)Beginning + deviceExtension->SrbExtensionSize);
  712. if ((PUCHAR)VirtualAddress >= Beginning &&
  713. (PUCHAR)VirtualAddress < End) {
  714. byteOffset = (ULONG)((PUCHAR)VirtualAddress - Beginning);
  715. break;
  716. }
  717. //
  718. // Next, check if the VA is in the Sense Data Buffer.
  719. //
  720. if (deviceExtension->AutoRequestSense == TRUE) {
  721. if (MappingInfo->RemappedSenseVa != NULL) {
  722. Beginning = MappingInfo->RemappedSenseVa;
  723. } else {
  724. Beginning = (PUCHAR)BlkAddr[i] +
  725. ROUND_TO_PAGES(deviceExtension->SrbExtensionSize);
  726. }
  727. End = Beginning + PAGE_SIZE;
  728. if ((PUCHAR)VirtualAddress >= Beginning &&
  729. (PUCHAR)VirtualAddress < End) {
  730. byteOffset = (ULONG)((PUCHAR)VirtualAddress - Beginning) +
  731. (ULONG)ROUND_TO_PAGES(deviceExtension->SrbExtensionSize);
  732. break;
  733. }
  734. }
  735. }
  736. //
  737. // If we haven't found the VA yet, it must be in the non-cached
  738. // extension.
  739. //
  740. if (i == deviceExtension->NumberOfRequests) {
  741. if (deviceExtension->VerifierExtension->NonCachedBufferSize != 0) {
  742. Beginning = BlkAddr[i];
  743. End = (PUCHAR) ROUND_TO_PAGES(
  744. (PUCHAR)Beginning +
  745. deviceExtension->VerifierExtension->NonCachedBufferSize);
  746. if ((PUCHAR)VirtualAddress < Beginning &&
  747. (PUCHAR)VirtualAddress >= End) {
  748. KeBugCheckEx (SCSI_VERIFIER_DETECTED_VIOLATION,
  749. SCSIPORT_VERIFIER_BAD_VA,
  750. (ULONG_PTR)HwDeviceExtension,
  751. (ULONG_PTR)VirtualAddress,
  752. 0);
  753. }
  754. byteOffset = (ULONG)((PUCHAR)VirtualAddress - Beginning);
  755. } else {
  756. KeBugCheckEx (SCSI_VERIFIER_DETECTED_VIOLATION,
  757. SCSIPORT_VERIFIER_BAD_VA,
  758. (ULONG_PTR)HwDeviceExtension,
  759. (ULONG_PTR)VirtualAddress,
  760. 0);
  761. }
  762. }
  763. //
  764. // Get the physical address.
  765. //
  766. AddressBlock = deviceExtension->VerifierExtension->CommonBufferPAs;
  767. address.QuadPart = AddressBlock[i].QuadPart + byteOffset;
  768. //
  769. // Calculate the length of the block.
  770. //
  771. length = (ULONG)((End - (PUCHAR)VirtualAddress) + 1);
  772. return address;
  773. }
  774. //
  775. // Forward on to the real routine.
  776. //
  777. address = ScsiPortGetPhysicalAddress(HwDeviceExtension,
  778. Srb,
  779. VirtualAddress,
  780. Length);
  781. return address;
  782. }
  783. PVOID
  784. ScsiPortGetUncachedExtensionVrfy(
  785. IN PVOID HwDeviceExtension,
  786. IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
  787. IN ULONG NumberOfBytes
  788. )
  789. {
  790. PVOID Extension;
  791. Extension = ScsiPortGetUncachedExtension(HwDeviceExtension,
  792. ConfigInfo,
  793. NumberOfBytes);
  794. return Extension;
  795. }
  796. PVOID
  797. ScsiPortGetVirtualAddressVrfy(
  798. IN PVOID HwDeviceExtension,
  799. IN SCSI_PHYSICAL_ADDRESS PhysicalAddress
  800. )
  801. {
  802. PADAPTER_EXTENSION deviceExtension = GET_FDO_EXTENSION(HwDeviceExtension);
  803. PVOID* BlkAddr;
  804. PSP_VA_MAPPING_INFO MappingInfo;
  805. ULONG smallphysicalBase;
  806. ULONG smallAddress;
  807. PVOID address;
  808. ULONG offset;
  809. ULONG Size;
  810. ULONG i;
  811. //
  812. // If the adapter is not configured to allocate multiple common buffer
  813. // blocks during verification, just call the scsiport routine.
  814. //
  815. if ((deviceExtension->VerifierExtension == NULL) ||
  816. (deviceExtension->VerifierExtension->VrfyLevel & SP_VRFY_COMMON_BUFFERS) == 0) {
  817. return ScsiPortGetVirtualAddress(HwDeviceExtension, PhysicalAddress);
  818. }
  819. BlkAddr = deviceExtension->VerifierExtension->CommonBufferVAs;
  820. //
  821. // Convert the 64-bit physical address to a ULONG.
  822. //
  823. smallAddress = ScsiPortConvertPhysicalAddressToUlong(PhysicalAddress);
  824. //
  825. // Check first if the supplied physical address is in an SRB extension or
  826. // in a sense buffer.
  827. //
  828. for (i = 0; i < deviceExtension->NumberOfRequests; i++) {
  829. smallphysicalBase =
  830. ScsiPortConvertPhysicalAddressToUlong(
  831. deviceExtension->VerifierExtension->CommonBufferPAs[i]);
  832. if ((smallAddress < smallphysicalBase) ||
  833. (smallAddress >= smallphysicalBase +
  834. (deviceExtension->CommonBufferSize -
  835. PAGE_SIZE))) {
  836. continue;
  837. }
  838. //
  839. // Calculate the address of the buffer.
  840. //
  841. offset = smallAddress - smallphysicalBase;
  842. address = offset + (PUCHAR)BlkAddr[i];
  843. MappingInfo = GET_VA_MAPPING_INFO(deviceExtension, BlkAddr[i]);
  844. goto GotAddress;
  845. }
  846. //
  847. // Check if the supplied physical address is in the non-cached extension.
  848. //
  849. if (deviceExtension->VerifierExtension->NonCachedBufferSize == 0) {
  850. ASSERT(FALSE);
  851. return(NULL);
  852. } else {
  853. smallphysicalBase =
  854. ScsiPortConvertPhysicalAddressToUlong(
  855. deviceExtension->VerifierExtension->CommonBufferPAs[i]);
  856. if ((smallAddress < smallphysicalBase) ||
  857. (smallAddress >= smallphysicalBase +
  858. deviceExtension->VerifierExtension->NonCachedBufferSize)) {
  859. //
  860. // This is a bogus physical address return back NULL.
  861. //
  862. ASSERT(FALSE);
  863. return(NULL);
  864. }
  865. offset = smallAddress - smallphysicalBase;
  866. address = offset + (PUCHAR)BlkAddr[i];
  867. Size = (ULONG)ROUND_TO_PAGES(deviceExtension->VerifierExtension->NonCachedBufferSize);
  868. MappingInfo = (PSP_VA_MAPPING_INFO)((PUCHAR)BlkAddr[i] + (Size - PAGE_SIZE));
  869. }
  870. GotAddress:
  871. //
  872. // Find out if we've remapped this address. If we have, give the
  873. // caller the second mapping.
  874. //
  875. if (address < MappingInfo->OriginalSenseVa &&
  876. MappingInfo->RemappedSrbExtVa != NULL) {
  877. return(offset + (PUCHAR)MappingInfo->RemappedSrbExtVa);
  878. }
  879. else if (MappingInfo->RemappedSenseVa != NULL) {
  880. return(offset + (PUCHAR)MappingInfo->RemappedSenseVa);
  881. }
  882. return(address);
  883. }
  884. VOID
  885. ScsiPortIoMapTransferVrfy(
  886. IN PVOID HwDeviceExtension,
  887. IN PSCSI_REQUEST_BLOCK Srb,
  888. IN PVOID LogicalAddress,
  889. IN ULONG Length
  890. )
  891. {
  892. ScsiPortIoMapTransfer(HwDeviceExtension,
  893. Srb,
  894. LogicalAddress,
  895. Length);
  896. return;
  897. }
  898. VOID
  899. ScsiPortMoveMemoryVrfy(
  900. IN PVOID WriteBuffer,
  901. IN PVOID ReadBuffer,
  902. IN ULONG Length
  903. )
  904. {
  905. ScsiPortMoveMemory(WriteBuffer,
  906. ReadBuffer,
  907. Length);
  908. return;
  909. }
  910. ULONG
  911. ScsiPortSetBusDataByOffsetVrfy(
  912. IN PVOID DeviceExtension,
  913. IN ULONG BusDataType,
  914. IN ULONG SystemIoBusNumber,
  915. IN ULONG SlotNumber,
  916. IN PVOID Buffer,
  917. IN ULONG Offset,
  918. IN ULONG Length
  919. )
  920. {
  921. ULONG Result;
  922. if (BusDataType != PCIConfiguration) {
  923. KeBugCheckEx(SCSI_VERIFIER_DETECTED_VIOLATION,
  924. SCSIPORT_VERIFIER_BAD_BUSDATATYPE,
  925. (ULONG_PTR)BusDataType,
  926. (ULONG_PTR)DeviceExtension,
  927. (ULONG_PTR)SystemIoBusNumber);
  928. }
  929. Result = ScsiPortSetBusDataByOffset(DeviceExtension,
  930. BusDataType,
  931. SystemIoBusNumber,
  932. SlotNumber,
  933. Buffer,
  934. Offset,
  935. Length);
  936. return Result;
  937. }
  938. BOOLEAN
  939. ScsiPortValidateRangeVrfy(
  940. IN PVOID HwDeviceExtension,
  941. IN INTERFACE_TYPE BusType,
  942. IN ULONG SystemIoBusNumber,
  943. IN SCSI_PHYSICAL_ADDRESS IoAddress,
  944. IN ULONG NumberOfBytes,
  945. IN BOOLEAN InIoSpace
  946. )
  947. {
  948. BOOLEAN Result;
  949. Result = ScsiPortValidateRange(HwDeviceExtension,
  950. BusType,
  951. SystemIoBusNumber,
  952. IoAddress,
  953. NumberOfBytes,
  954. InIoSpace);
  955. return Result;
  956. }
  957. VOID
  958. ScsiPortStallExecutionVrfy(
  959. IN ULONG Delay
  960. )
  961. {
  962. //
  963. // Miniports must specify a delay not more than one millisecond.
  964. //
  965. if (Delay > SpVrfyMaximumStall) {
  966. KeBugCheckEx(SCSI_VERIFIER_DETECTED_VIOLATION,
  967. SCSIPORT_VERIFIER_STALL_TOO_LONG,
  968. (ULONG_PTR)Delay,
  969. 0,
  970. 0);
  971. }
  972. KeStallExecutionProcessor(Delay);
  973. }
  974. //
  975. // Timeout periods in ticks. To calculate, we divide the time limit in 100 ns
  976. // units by the TimeIncrement, which is the value returned by
  977. // KeQueryTimeIncrement. Since KeQueryTickCount rounds up to the next
  978. // tick, we'll add one tick to the defined limits.
  979. //
  980. #define SP_FIVE_SECOND_LIMIT ((50000000L / TimeIncrement) + 1)
  981. #define SP_TWO_SECOND_LIMIT ((20000000L / TimeIncrement) + 1)
  982. #define SP_HALF_SECOND_LIMIT ((5000000L / TimeIncrement) + 1)
  983. /*++
  984. Macro Description:
  985. This macro checks the number of ticks elapsed during the execution of a
  986. miniport routine against a maximum number allowed ticks. If the routine
  987. ran longer than the max allowable ticks, we bugcheck.
  988. Arguments:
  989. Ticks - number of ticks routine took to execute.
  990. MaxTicks - number of ticks the routine is allowed to execute.
  991. Routine - address of the routine we are checking.
  992. Extension - address of the miniport's HwDeviceExtension
  993. Notes:
  994. The format for the bugcheck is:
  995. Parameter 1: 0x1002
  996. Parameter 2: address of routine that ran too long
  997. Parameter 3: address of miniport's HwDeviceExtension
  998. Parameter 4: duration of routine in microseconds
  999. --*/
  1000. /*
  1001. #define SpCheckMiniportRoutineDuration(Ticks, MaxTicks, Routine, Extension) \
  1002. { \
  1003. if ((Ticks) > (MaxTicks)) { \
  1004. KeBugCheckEx ( \
  1005. SCSI_VERIFIER_DETECTED_VIOLATION, \
  1006. SCSIPORT_VERIFIER_MINIPORT_ROUTINE_TIMEOUT, \
  1007. (ULONG_PTR)(Routine), \
  1008. (ULONG_PTR)(Extension), \
  1009. (ULONG_PTR)(((Ticks) * TimeIncrement) / 10)); \
  1010. } \
  1011. }
  1012. */
  1013. #define SpCheckMiniportRoutineDuration(Ticks, MaxTicks, Routine, Extension)
  1014. ULONG
  1015. SpHwFindAdapterVrfy (
  1016. IN PVOID HwDeviceExtension,
  1017. IN PVOID HwContext,
  1018. IN PVOID BusInformation,
  1019. IN PCHAR ArgumentString,
  1020. IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
  1021. OUT PBOOLEAN Again
  1022. )
  1023. {
  1024. ULONG Result;
  1025. PADAPTER_EXTENSION AdapterExtension = GET_FDO_EXTENSION(HwDeviceExtension);
  1026. Result = AdapterExtension->VerifierExtension->RealHwFindAdapter(
  1027. HwDeviceExtension,
  1028. HwContext,
  1029. BusInformation,
  1030. ArgumentString,
  1031. ConfigInfo,
  1032. Again);
  1033. return Result;
  1034. }
  1035. BOOLEAN
  1036. SpHwInitializeVrfy (
  1037. IN PVOID HwDeviceExtension
  1038. )
  1039. {
  1040. BOOLEAN Result;
  1041. LARGE_INTEGER Start;
  1042. LARGE_INTEGER Duration;
  1043. PADAPTER_EXTENSION AdapterExtension = GET_FDO_EXTENSION(HwDeviceExtension);
  1044. KeQueryTickCount(&Start);
  1045. Result = AdapterExtension->VerifierExtension->RealHwInitialize(HwDeviceExtension);
  1046. KeQueryTickCount(&Duration);
  1047. Duration.QuadPart -= Start.QuadPart;
  1048. if (VRFY_DO_CHECK(AdapterExtension, SP_DONT_CHK_HW_INITIALIZE_DURATION)) {
  1049. SpCheckMiniportRoutineDuration(
  1050. Duration.LowPart,
  1051. SP_FIVE_SECOND_LIMIT,
  1052. AdapterExtension->VerifierExtension->RealHwInitialize,
  1053. HwDeviceExtension);
  1054. }
  1055. return Result;
  1056. }
  1057. BOOLEAN
  1058. SpHwStartIoVrfy (
  1059. IN PVOID HwDeviceExtension,
  1060. IN PSCSI_REQUEST_BLOCK Srb
  1061. )
  1062. {
  1063. BOOLEAN Result;
  1064. LARGE_INTEGER Start;
  1065. LARGE_INTEGER Duration;
  1066. PADAPTER_EXTENSION AdapterExtension = GET_FDO_EXTENSION(HwDeviceExtension);
  1067. PSRB_DATA srbData;
  1068. //
  1069. // If MapBuffers is not set, the miniport is not supposed to touch
  1070. // the DataBuffer field in the SRB. To verify this, we'll set
  1071. // DataBuffer to point to memory that will fault if the miniport tries
  1072. // to touch it.
  1073. //
  1074. ASSERT(Srb != NULL);
  1075. srbData = (PSRB_DATA)Srb->OriginalRequest;
  1076. ASSERT_SRB_DATA(srbData);
  1077. if (AdapterExtension->MapBuffers == FALSE
  1078. && !IS_MAPPED_SRB(Srb)
  1079. && Srb->Function != SRB_FUNCTION_WMI
  1080. && Srb->DataBuffer != NULL
  1081. && AdapterExtension->VerifierExtension->InvalidPage != NULL
  1082. && Srb->Cdb[0] != SCSIOP_INQUIRY
  1083. && Srb->Cdb[0] != SCSIOP_REPORT_LUNS) {
  1084. if (Srb->DataBuffer != AdapterExtension->VerifierExtension->InvalidPage) {
  1085. srbData->UnmappedDataBuffer = Srb->DataBuffer;
  1086. Srb->DataBuffer = AdapterExtension->VerifierExtension->InvalidPage;
  1087. } else {
  1088. ASSERT(srbData->UnmappedDataBuffer != &SpMarker);
  1089. ASSERT(srbData->UnmappedDataBuffer != NULL);
  1090. }
  1091. } else {
  1092. srbData->UnmappedDataBuffer = &SpMarker;
  1093. }
  1094. //
  1095. // Call the miniport's StartIo function and calculate the call's duration.
  1096. //
  1097. KeQueryTickCount(&Start);
  1098. Result = AdapterExtension->VerifierExtension->RealHwStartIo(
  1099. HwDeviceExtension,
  1100. Srb);
  1101. KeQueryTickCount(&Duration);
  1102. Duration.QuadPart -= Start.QuadPart;
  1103. //
  1104. // Bugcheck if the call took more than .5 seconds.
  1105. //
  1106. SpCheckMiniportRoutineDuration(
  1107. Duration.LowPart,
  1108. SP_HALF_SECOND_LIMIT,
  1109. AdapterExtension->VerifierExtension->RealHwStartIo,
  1110. HwDeviceExtension);
  1111. //
  1112. // If the HwStartIo returns failure, undo any fixups we performed on the SRB.
  1113. //
  1114. if (Result == FALSE
  1115. && srbData->UnmappedDataBuffer != &SpMarker) {
  1116. ASSERT(srbData->UnmappedDataBuffer != NULL);
  1117. Srb->DataBuffer = srbData->UnmappedDataBuffer;
  1118. srbData->UnmappedDataBuffer = NULL;
  1119. }
  1120. return Result;
  1121. }
  1122. BOOLEAN
  1123. SpHwInterruptVrfy (
  1124. IN PVOID HwDeviceExtension
  1125. )
  1126. {
  1127. BOOLEAN Result;
  1128. LARGE_INTEGER Start;
  1129. LARGE_INTEGER Duration;
  1130. PADAPTER_EXTENSION AdapterExtension = GET_FDO_EXTENSION(HwDeviceExtension);
  1131. if (AdapterExtension->VerifierExtension->RealHwInterrupt == NULL) {
  1132. return FALSE;
  1133. }
  1134. KeQueryTickCount(&Start);
  1135. Result = AdapterExtension->VerifierExtension->RealHwInterrupt (
  1136. HwDeviceExtension);
  1137. KeQueryTickCount(&Duration);
  1138. Duration.QuadPart -= Start.QuadPart;
  1139. SpCheckMiniportRoutineDuration(
  1140. Duration.LowPart,
  1141. SP_HALF_SECOND_LIMIT,
  1142. AdapterExtension->VerifierExtension->RealHwInterrupt,
  1143. HwDeviceExtension);
  1144. return Result;
  1145. }
  1146. BOOLEAN
  1147. SpHwResetBusVrfy (
  1148. IN PVOID HwDeviceExtension,
  1149. IN ULONG PathId
  1150. )
  1151. {
  1152. BOOLEAN Result;
  1153. LARGE_INTEGER Start;
  1154. LARGE_INTEGER Duration;
  1155. PADAPTER_EXTENSION AdapterExtension = GET_FDO_EXTENSION(HwDeviceExtension);
  1156. KeQueryTickCount(&Start);
  1157. Result = AdapterExtension->VerifierExtension->RealHwResetBus(
  1158. HwDeviceExtension,
  1159. PathId);
  1160. KeQueryTickCount(&Duration);
  1161. Duration.QuadPart -= Start.QuadPart;
  1162. SpCheckMiniportRoutineDuration(
  1163. Duration.LowPart,
  1164. SP_HALF_SECOND_LIMIT,
  1165. AdapterExtension->VerifierExtension->RealHwResetBus,
  1166. HwDeviceExtension);
  1167. return Result;
  1168. }
  1169. VOID
  1170. SpHwDmaStartedVrfy (
  1171. IN PVOID HwDeviceExtension
  1172. )
  1173. {
  1174. LARGE_INTEGER Start;
  1175. LARGE_INTEGER Duration;
  1176. PADAPTER_EXTENSION AdapterExtension = GET_FDO_EXTENSION(HwDeviceExtension);
  1177. KeQueryTickCount(&Start);
  1178. AdapterExtension->VerifierExtension->RealHwDmaStarted(
  1179. HwDeviceExtension);
  1180. KeQueryTickCount(&Duration);
  1181. Duration.QuadPart -= Start.QuadPart;
  1182. SpCheckMiniportRoutineDuration(
  1183. Duration.LowPart,
  1184. SP_HALF_SECOND_LIMIT,
  1185. AdapterExtension->VerifierExtension->RealHwDmaStarted,
  1186. HwDeviceExtension);
  1187. }
  1188. BOOLEAN
  1189. SpHwRequestInterruptVrfy (
  1190. IN PVOID HwDeviceExtension
  1191. )
  1192. {
  1193. BOOLEAN Result;
  1194. LARGE_INTEGER Start;
  1195. LARGE_INTEGER Duration;
  1196. PADAPTER_EXTENSION AdapterExtension = GET_FDO_EXTENSION(HwDeviceExtension);
  1197. KeQueryTickCount(&Start);
  1198. Result = AdapterExtension->VerifierExtension->RealHwRequestInterrupt(
  1199. HwDeviceExtension);
  1200. KeQueryTickCount(&Duration);
  1201. Duration.QuadPart -= Start.QuadPart;
  1202. SpCheckMiniportRoutineDuration(
  1203. Duration.LowPart,
  1204. SP_HALF_SECOND_LIMIT,
  1205. AdapterExtension->VerifierExtension->RealHwRequestInterrupt,
  1206. HwDeviceExtension);
  1207. return Result;
  1208. }
  1209. BOOLEAN
  1210. SpHwTimerRequestVrfy (
  1211. IN PVOID HwDeviceExtension
  1212. )
  1213. {
  1214. BOOLEAN Result;
  1215. LARGE_INTEGER Start;
  1216. LARGE_INTEGER Duration;
  1217. PADAPTER_EXTENSION AdapterExtension = GET_FDO_EXTENSION(HwDeviceExtension);
  1218. KeQueryTickCount(&Start);
  1219. Result = AdapterExtension->VerifierExtension->RealHwTimerRequest(
  1220. HwDeviceExtension);
  1221. KeQueryTickCount(&Duration);
  1222. Duration.QuadPart -= Start.QuadPart;
  1223. SpCheckMiniportRoutineDuration(
  1224. Duration.LowPart,
  1225. SP_HALF_SECOND_LIMIT,
  1226. AdapterExtension->VerifierExtension->RealHwTimerRequest,
  1227. HwDeviceExtension);
  1228. return Result;
  1229. }
  1230. SCSI_ADAPTER_CONTROL_STATUS
  1231. SpHwAdapterControlVrfy (
  1232. IN PVOID HwDeviceExtension,
  1233. IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
  1234. IN PVOID Parameters
  1235. )
  1236. {
  1237. SCSI_ADAPTER_CONTROL_STATUS Result;
  1238. LARGE_INTEGER Start;
  1239. LARGE_INTEGER Duration;
  1240. PADAPTER_EXTENSION AdapterExtension = GET_FDO_EXTENSION(HwDeviceExtension);
  1241. KeQueryTickCount (&Start);
  1242. Result = AdapterExtension->VerifierExtension->RealHwAdapterControl(
  1243. HwDeviceExtension,
  1244. ControlType,
  1245. Parameters);
  1246. KeQueryTickCount(&Duration);
  1247. Duration.QuadPart -= Start.QuadPart;
  1248. if (VRFY_DO_CHECK(AdapterExtension, SP_DONT_CHK_HW_ADAPTERCONTROL_DURATION)) {
  1249. SpCheckMiniportRoutineDuration(
  1250. Duration.LowPart,
  1251. SP_HALF_SECOND_LIMIT,
  1252. AdapterExtension->VerifierExtension->RealHwAdapterControl,
  1253. HwDeviceExtension);
  1254. }
  1255. return Result;
  1256. }
  1257. VOID
  1258. SpVerifySrbStatus(
  1259. PVOID HwDeviceExtension,
  1260. PSCSI_REQUEST_BLOCK srb
  1261. )
  1262. /*++
  1263. Routine Description:
  1264. Verify that the SRB's status as set by the miniport driver is valid.
  1265. Arguments:
  1266. HwDeviceExtension - The port driver's device extension follows the
  1267. miniport's device extension and contains a pointer to
  1268. the logical device extension list.
  1269. srb - Points to the SRB.
  1270. Return Value:
  1271. VOID
  1272. --*/
  1273. {
  1274. UCHAR SrbStatus;
  1275. //
  1276. // Turn off internal bits used by scsiport.
  1277. //
  1278. SrbStatus = srb->SrbStatus & ~(SRB_STATUS_QUEUE_FROZEN |
  1279. SRB_STATUS_AUTOSENSE_VALID);
  1280. //
  1281. // Miniports may never set the status to SRB_STATUS_PENDING.
  1282. //
  1283. if (SrbStatus == SRB_STATUS_PENDING) {
  1284. goto BadStatus;
  1285. }
  1286. //
  1287. // If the function is SRB_FUNCTION_EXECUTE_SCSI, then the command must be
  1288. // either completed successfully, or ScsiStatus must be set to
  1289. // SCSISTAT_GOOD.
  1290. //
  1291. if (!(SrbStatus != SRB_STATUS_SUCCESS ||
  1292. srb->ScsiStatus == SCSISTAT_GOOD ||
  1293. srb->Function != SRB_FUNCTION_EXECUTE_SCSI)) {
  1294. goto BadStatus;
  1295. }
  1296. //
  1297. // Make sure the status is within the valid range.
  1298. //
  1299. if ((SrbStatus) == 0x0C ||
  1300. (SrbStatus > 0x16 && srb->SrbStatus < 0x20) ||
  1301. (SrbStatus > 0x23)) {
  1302. goto BadStatus;
  1303. }
  1304. //
  1305. // The SRB Status is ok.
  1306. //
  1307. return;
  1308. BadStatus:
  1309. //
  1310. // Bugcheck if the status is bad.
  1311. //
  1312. KeBugCheckEx (SCSI_VERIFIER_DETECTED_VIOLATION,
  1313. SCSIPORT_VERIFIER_BAD_SRBSTATUS,
  1314. (ULONG_PTR)srb,
  1315. (ULONG_PTR)HwDeviceExtension,
  1316. 0);
  1317. }
  1318. PVOID
  1319. SpRemapBlock(
  1320. IN PVOID BlockVa,
  1321. IN ULONG BlockSize,
  1322. OUT PMDL* Mdl
  1323. )
  1324. /*++
  1325. Routine Description:
  1326. This function attempts to remap the supplied VA range. If the block is
  1327. remapped, it will be made invalid for reading and writing.
  1328. Arguments:
  1329. BlockVa - Supplies the address of the block of memory to remap.
  1330. BlockSize - Supplies the size of the block of memory to remap.
  1331. Mdl - Supplies the address into which the function will store
  1332. a pointer to the MDL for the remapped range. If the MDL
  1333. cannot be allocated or if the range cannot be remapped,
  1334. this will be NULL upon return.
  1335. Return Value:
  1336. If the range is successfully remapped, the address of the beginning of
  1337. the remapped range is returned. Else, NULL is returned.
  1338. --*/
  1339. {
  1340. PVOID MappedRange;
  1341. NTSTATUS Status;
  1342. PMDL LocalMdl;
  1343. //
  1344. // Try to allocate a new MDL for the range we're trying to remap.
  1345. //
  1346. LocalMdl = IoAllocateMdl(BlockVa, BlockSize, FALSE, FALSE, NULL);
  1347. if (LocalMdl == NULL) {
  1348. *Mdl = NULL;
  1349. return NULL;
  1350. }
  1351. //
  1352. // Try to lock the pages. This initializes the MDL properly.
  1353. //
  1354. __try {
  1355. MmProbeAndLockPages(LocalMdl, KernelMode, IoModifyAccess);
  1356. }
  1357. __except(EXCEPTION_EXECUTE_HANDLER) {
  1358. IoFreeMdl(LocalMdl);
  1359. *Mdl = NULL;
  1360. return NULL;
  1361. }
  1362. //
  1363. // Try to remap the range represented by the new MDL.
  1364. //
  1365. MappedRange = MmMapLockedPagesSpecifyCache(LocalMdl,
  1366. KernelMode,
  1367. MmCached,
  1368. NULL,
  1369. FALSE,
  1370. NormalPagePriority);
  1371. if (MappedRange == NULL) {
  1372. IoFreeMdl(LocalMdl);
  1373. *Mdl = NULL;
  1374. return NULL;
  1375. }
  1376. //
  1377. // If we've gotten this far, we have successfully remapped the range.
  1378. // Now we want to invalidate the entire range so any accesses to it
  1379. // will be trapped by the system.
  1380. //
  1381. Status = MmProtectMdlSystemAddress(LocalMdl, PAGE_NOACCESS);
  1382. #if DBG==1
  1383. if (!NT_SUCCESS(Status)) {
  1384. DebugPrint((0, "SpRemapBlock: failed to remap block:%p mdl:%p (%x)\n",
  1385. BlockVa, LocalMdl, Status));
  1386. }
  1387. #endif
  1388. //
  1389. // Copy the MDL we allocated into the supplied address and return the
  1390. // address of the beginning of the remapped range.
  1391. //
  1392. *Mdl = LocalMdl;
  1393. return MappedRange;
  1394. }
  1395. VOID
  1396. SpRemapCommonBufferForMiniport(
  1397. PADAPTER_EXTENSION Adapter
  1398. )
  1399. /*++
  1400. Routine Description:
  1401. This routine attempts to remap all of the common buffer blocks allocated
  1402. for a particular adapter.
  1403. Arguments:
  1404. DeviceExtension - Supplies a pointer to the adapter device extension.
  1405. --*/
  1406. {
  1407. PVOID* BlkAddr = Adapter->VerifierExtension->CommonBufferVAs;
  1408. PSP_VA_MAPPING_INFO MappingInfo;
  1409. PVOID RemappedVa;
  1410. ULONG Size;
  1411. PMDL Mdl;
  1412. ULONG i;
  1413. //
  1414. // Iterate through all of the common buffer blocks, and attempt to remap
  1415. // the SRB extension and the sense buffer within each block.
  1416. //
  1417. for (i = 0; i < Adapter->VerifierExtension->CommonBufferBlocks; i++) {
  1418. //
  1419. // Get a pointer to the mapping info we keep at the end of the block.
  1420. //
  1421. MappingInfo = GET_VA_MAPPING_INFO(Adapter, BlkAddr[i]);
  1422. //
  1423. // Initialize the original VA info for the SRB extension.
  1424. //
  1425. MappingInfo->OriginalSrbExtVa = BlkAddr[i];
  1426. MappingInfo->SrbExtLen = (ULONG)ROUND_TO_PAGES(Adapter->SrbExtensionSize);
  1427. //
  1428. // Initialize the original VA info for the sense buffer.
  1429. //
  1430. MappingInfo->OriginalSenseVa = (PUCHAR)BlkAddr[i] + MappingInfo->SrbExtLen;
  1431. MappingInfo->SenseLen = PAGE_SIZE;
  1432. //
  1433. // Try to remap the SRB extension. If successful, initialize the
  1434. // remapped VA info for the SRB extension.
  1435. //
  1436. RemappedVa = SpRemapBlock(MappingInfo->OriginalSrbExtVa,
  1437. MappingInfo->SrbExtLen,
  1438. &Mdl);
  1439. if (RemappedVa != NULL) {
  1440. MappingInfo->RemappedSrbExtVa = RemappedVa;
  1441. MappingInfo->SrbExtMdl = Mdl;
  1442. }
  1443. #if 0
  1444. //
  1445. // Try to remap the sense buffer. If successful, initialize the
  1446. // remapped VA info for the sense buffer.
  1447. //
  1448. // For now, I think we can live without this. I don't know of any
  1449. // issues where overruns etc. occur in a sense buffer.
  1450. //
  1451. RemappedVa = SpRemapBlock(MappingInfo->OriginalSenseVa,
  1452. MappingInfo->SenseLen,
  1453. &Mdl);
  1454. if (RemappedVa != NULL) {
  1455. MappingInfo->RemappedSenseVa = RemappedVa;
  1456. MappingInfo->SenseMdl = Mdl;
  1457. }
  1458. #endif
  1459. }
  1460. if (Adapter->VerifierExtension->NonCachedBufferSize != 0) {
  1461. //
  1462. // Init uncached extension mapping info.
  1463. //
  1464. Size = (ULONG)ROUND_TO_PAGES(Adapter->VerifierExtension->NonCachedBufferSize);
  1465. MappingInfo = (PSP_VA_MAPPING_INFO)((PUCHAR)BlkAddr[i] + (Size - PAGE_SIZE));
  1466. MappingInfo->OriginalSrbExtVa = BlkAddr[i];
  1467. MappingInfo->SrbExtLen = Adapter->VerifierExtension->NonCachedBufferSize;
  1468. MappingInfo->OriginalSenseVa = (PUCHAR)BlkAddr[i] + Adapter->VerifierExtension->NonCachedBufferSize;
  1469. }
  1470. }
  1471. PVOID
  1472. SpAllocateContiguousChunk(
  1473. IN PDRIVER_OBJECT DriverObject,
  1474. IN PDMA_ADAPTER DmaAdapterObject,
  1475. IN BOOLEAN Dma64BitAddresses,
  1476. IN ULONG Length,
  1477. IN ULONG Align,
  1478. OUT PHYSICAL_ADDRESS *PhysicalCommonBuffer,
  1479. OUT BOOLEAN *CommonBuffer
  1480. )
  1481. /*++
  1482. Routine Description:
  1483. This routine allocates a chunk of memory which can be used for common
  1484. buffer io. Where the memory is allocated from depends on several
  1485. parameters. If no adapter object is specified, the memory is simply
  1486. allocated from non-paged pool. Else, the memory is allocated such
  1487. that it can be used in DMA operations.
  1488. Arguments:
  1489. DriverObject - Supplies a pointer to the driver object.
  1490. DmaAdapterObject - Supplies a pointer to the adapter's DMA adapter
  1491. object.
  1492. Dma64BitAddresses - Specifies whether the adapter supports 64-bit.
  1493. Length - Specifies the number of bytes to allocate.
  1494. Align - Alignment requirement for uncached extension.
  1495. PhysicalCommonBuffer - Specifies a pointer into which the physical
  1496. address of the allocated memory is to be copied
  1497. if the memory is allocated for DMA operations.
  1498. CommonBuffer - Supplies a pointer to a boolean that we set if the
  1499. memory is allocated using AllocateCommonBuffer.
  1500. Return Value:
  1501. Returns the VA of the allocated memory if the allocation succeeds. Else,
  1502. returns NULL.
  1503. --*/
  1504. {
  1505. PVOID Buffer;
  1506. if (DmaAdapterObject == NULL) {
  1507. //
  1508. // Since there is no adapter object just allocate from non-paged pool.
  1509. //
  1510. Buffer = SpAllocatePool(
  1511. NonPagedPool,
  1512. Length,
  1513. SCSIPORT_TAG_COMMON_BUFFER,
  1514. DriverObject);
  1515. } else {
  1516. ASSERT(PhysicalCommonBuffer != NULL);
  1517. //
  1518. // If the controller can do 64-bit addresses then we need to
  1519. // specifically force the uncached extension area below the 4GB mark.
  1520. //
  1521. if (((Sp64BitPhysicalAddresses) && (Dma64BitAddresses == TRUE)) ||
  1522. Align != 0) {
  1523. PHYSICAL_ADDRESS low;
  1524. PHYSICAL_ADDRESS high;
  1525. PHYSICAL_ADDRESS boundary;
  1526. if (Align != 0) {
  1527. boundary.QuadPart = Length;
  1528. } else {
  1529. boundary.QuadPart = 0;
  1530. }
  1531. low.QuadPart = 0;
  1532. high.HighPart = 0;
  1533. high.LowPart = 0xffffffff;
  1534. //
  1535. // We'll get page aligned memory out of this which is probably
  1536. // better than the requirements of the adapter.
  1537. //
  1538. Buffer = MmAllocateContiguousMemorySpecifyCache(
  1539. Length,
  1540. low,
  1541. high,
  1542. boundary,
  1543. MmCached);
  1544. if (Buffer != NULL) {
  1545. *PhysicalCommonBuffer = MmGetPhysicalAddress(Buffer);
  1546. }
  1547. if (CommonBuffer != NULL) {
  1548. *CommonBuffer = FALSE;
  1549. }
  1550. } else {
  1551. Buffer = AllocateCommonBuffer(
  1552. DmaAdapterObject,
  1553. Length,
  1554. PhysicalCommonBuffer,
  1555. FALSE);
  1556. if (CommonBuffer != NULL) {
  1557. *CommonBuffer = TRUE;
  1558. }
  1559. }
  1560. }
  1561. return Buffer;
  1562. }
  1563. NTSTATUS
  1564. SpGetCommonBufferVrfy(
  1565. PADAPTER_EXTENSION DeviceExtension,
  1566. ULONG NonCachedExtensionSize
  1567. )
  1568. /*++
  1569. Routine Description:
  1570. This function allocates multiple common buffer blocks instead of one
  1571. big one. The verifier does this so it can remap VA ranges within
  1572. each block in order to control their protection attributes. This
  1573. enables us to invalidate key VA ranges and catch miniports that attempt
  1574. to access these ranges when they should not.
  1575. If the remapping succeeds, the SCSI port driver hands out the remapped
  1576. VA ranges to miniports instead of the original ranges. If the remapping
  1577. fails, it just hands out the original ranges.
  1578. Arguments:
  1579. DeviceExtension - Supplies a pointer to the device extension.
  1580. NonCachedExtensionSize - Supplies the size of the noncached device
  1581. extension for the miniport driver.
  1582. Return Value:
  1583. Returns the status of the allocate operation.
  1584. --*/
  1585. {
  1586. NTSTATUS Status;
  1587. PVOID buffer;
  1588. ULONG length;
  1589. ULONG blockSize;
  1590. PVOID *srbExtension;
  1591. PVOID buffer2;
  1592. PMDL mdl;
  1593. ULONG TotalSize;
  1594. ULONG i;
  1595. PVOID* BlkAddr;
  1596. PHYSICAL_ADDRESS *PhysicalCommonBuffer;
  1597. PCCHAR InvalidRegion;
  1598. BOOLEAN commonBuffer;
  1599. PAGED_CODE();
  1600. DebugPrint((1, "SpGetCommonBufferVrfy: DeviceExtension:%p NonCachedExtensionSize:%d\n",
  1601. DeviceExtension, NonCachedExtensionSize));
  1602. //
  1603. // Now fixup the size if the adapter has special alignment requirements so
  1604. // the buffer we allocate may be aligned as required.
  1605. //
  1606. if (DeviceExtension->UncachedExtAlignment != 0) {
  1607. NonCachedExtensionSize =
  1608. ROUND_UP_COUNT(NonCachedExtensionSize,
  1609. DeviceExtension->UncachedExtAlignment);
  1610. }
  1611. //
  1612. // We maintain a couple of arrays in order to find our common
  1613. // buffer blocks at various times. Calculate the amount of space we
  1614. // need for these arrays. This amount depends on the number of
  1615. // simultaneous requests the adapter supports. We add one to the
  1616. // number of requests in order to accommodate the non-cached extension.
  1617. //
  1618. ASSERT(DeviceExtension->VerifierExtension->CommonBufferVAs == NULL);
  1619. i = DeviceExtension->NumberOfRequests + 1;
  1620. length = sizeof(PVOID) * i;
  1621. if (DeviceExtension->DmaAdapterObject != NULL) {
  1622. ASSERT(DeviceExtension->VerifierExtension->CommonBufferPAs == NULL);
  1623. length += (sizeof(PHYSICAL_ADDRESS) * i);
  1624. }
  1625. //
  1626. // Allocate a block of memory for these arrays. If this allocation fails,
  1627. // we return failure.
  1628. //
  1629. BlkAddr = SpAllocatePool(NonPagedPool,
  1630. length,
  1631. SCSIPORT_TAG_COMMON_BUFFER,
  1632. DeviceExtension->DeviceObject->DriverObject);
  1633. if (BlkAddr == NULL) {
  1634. return STATUS_INSUFFICIENT_RESOURCES;
  1635. }
  1636. //
  1637. // Save the number of common buffer blocks.
  1638. //
  1639. DeviceExtension->VerifierExtension->CommonBufferBlocks =
  1640. DeviceExtension->NumberOfRequests;
  1641. //
  1642. // Zero the entire block so when we're freeing resources we can tell if we
  1643. // have valid buffers to free.
  1644. //
  1645. RtlZeroMemory(BlkAddr, length);
  1646. //
  1647. // Save a pointer to the array of addresses in the adapter extension and,
  1648. // if there is an adapter object, initialize a pointer to the beginning of
  1649. // the physical address array and save a pointer to the array in the
  1650. // adapter extension.
  1651. //
  1652. DeviceExtension->VerifierExtension->CommonBufferVAs = (PVOID *)BlkAddr;
  1653. if (DeviceExtension->DmaAdapterObject != NULL) {
  1654. PhysicalCommonBuffer = (PHYSICAL_ADDRESS*) &BlkAddr[i];
  1655. DeviceExtension->VerifierExtension->CommonBufferPAs = PhysicalCommonBuffer;
  1656. }
  1657. //
  1658. // To ensure that we never transfer normal request data to the SrbExtension
  1659. // (ie. the case of Srb->SenseInfoBuffer == VirtualAddress in
  1660. // ScsiPortGetPhysicalAddress) on some platforms where an inconsistency in
  1661. // MM can result in the same Virtual address supplied for 2 different
  1662. // physical addresses, bump the SrbExtensionSize if it's zero.
  1663. //
  1664. if (DeviceExtension->SrbExtensionSize == 0) {
  1665. DeviceExtension->SrbExtensionSize = 16;
  1666. }
  1667. //
  1668. // Calculate the block size for an SRB extension/sense buffer block. If
  1669. // AutoRequestSense is FALSE, allocate 1 page anyway as a placeholder.
  1670. //
  1671. blockSize = (ULONG)ROUND_TO_PAGES(DeviceExtension->SrbExtensionSize);
  1672. if (DeviceExtension->AutoRequestSense == TRUE) {
  1673. blockSize += sizeof(SENSE_DATA) + DeviceExtension->AdditionalSenseBytes;
  1674. blockSize = (ULONG)ROUND_TO_PAGES(blockSize);
  1675. } else {
  1676. blockSize += PAGE_SIZE;
  1677. }
  1678. //
  1679. // Add a page for holding bookkeeping information.
  1680. //
  1681. blockSize += PAGE_SIZE;
  1682. //
  1683. // Allocate each block individually and link them all together into a
  1684. // list. If we fail to allocate any of the blocks, we clean everything up
  1685. // and return failure.
  1686. //
  1687. DeviceExtension->CommonBufferSize = blockSize;
  1688. srbExtension = NULL;
  1689. for (i = 0; i < DeviceExtension->NumberOfRequests; i++) {
  1690. //
  1691. // Allocate a contiguous chunk of memory for the block.
  1692. //
  1693. buffer = SpAllocateContiguousChunk(
  1694. DeviceExtension->DeviceObject->DriverObject,
  1695. DeviceExtension->DmaAdapterObject,
  1696. DeviceExtension->Dma64BitAddresses,
  1697. blockSize,
  1698. 0,
  1699. (DeviceExtension->DmaAdapterObject) ? &PhysicalCommonBuffer[i] : NULL,
  1700. &commonBuffer);
  1701. if (buffer == NULL) {
  1702. //
  1703. // Free everything we've allocated so far and return failure. This
  1704. // will also free the arrays we allocated at the beginning of this
  1705. // function.
  1706. //
  1707. DeviceExtension->VerifierExtension->IsCommonBuffer = commonBuffer;
  1708. SpFreeCommonBufferVrfy(DeviceExtension);
  1709. return STATUS_INSUFFICIENT_RESOURCES;
  1710. }
  1711. //
  1712. // Zero the entire block and save a pointer to it in our array.
  1713. //
  1714. RtlZeroMemory(buffer, blockSize);
  1715. BlkAddr[i] = buffer;
  1716. //
  1717. // Link the new block onto the front of the chain.
  1718. //
  1719. *((PVOID *) buffer) = srbExtension;
  1720. srbExtension = (PVOID *) buffer;
  1721. }
  1722. //
  1723. // Indicate whether the buffer was allocated as common buffer.
  1724. //
  1725. DeviceExtension->VerifierExtension->IsCommonBuffer = commonBuffer;
  1726. //
  1727. // Allocate the non-cached extension. Note that we align the uncached
  1728. // buffer on the next page boundary and allocate enough for a scratch page.
  1729. // If the allocation fails, free everything we've allocated so far and
  1730. // return failure.
  1731. //
  1732. if (NonCachedExtensionSize != 0) {
  1733. DeviceExtension->VerifierExtension->NonCachedBufferSize = NonCachedExtensionSize;
  1734. length = (ULONG)(ROUND_TO_PAGES(NonCachedExtensionSize));
  1735. BlkAddr[i] =
  1736. SpAllocateContiguousChunk(
  1737. DeviceExtension->DeviceObject->DriverObject,
  1738. DeviceExtension->DmaAdapterObject,
  1739. DeviceExtension->Dma64BitAddresses,
  1740. length,
  1741. DeviceExtension->UncachedExtAlignment,
  1742. (DeviceExtension->DmaAdapterObject) ? &PhysicalCommonBuffer[i] : NULL,
  1743. &DeviceExtension->UncachedExtensionIsCommonBuffer);
  1744. if (BlkAddr[i] == NULL) {
  1745. //
  1746. // Free everything we've allocated so far and return failure. This
  1747. // will also free the arrays we allocated at the beginning of this
  1748. // function.
  1749. //
  1750. SpFreeCommonBufferVrfy(DeviceExtension);
  1751. return STATUS_INSUFFICIENT_RESOURCES;
  1752. }
  1753. //
  1754. // Zero the entire block.
  1755. //
  1756. RtlZeroMemory(BlkAddr[i], length);
  1757. //
  1758. // Save a pointer to the beginning of the non-cached extension data.
  1759. // Note that the data is positioned such that it ends on a page
  1760. // boundary so if the miniport overwrites the buffer, the system will
  1761. // fault.
  1762. //
  1763. DeviceExtension->NonCachedExtension =
  1764. (PCCHAR)BlkAddr[i] +
  1765. (ROUND_TO_PAGES(NonCachedExtensionSize) - NonCachedExtensionSize);
  1766. } else {
  1767. DeviceExtension->NonCachedExtension = NULL;
  1768. DeviceExtension->VerifierExtension->NonCachedBufferSize = 0;
  1769. }
  1770. //
  1771. // If the miniport asked for an SRB Extension, point the SRB Extension List
  1772. // at the beginning of the list of blocks we allocated and chained together
  1773. // above.
  1774. //
  1775. if (DeviceExtension->AllocateSrbExtension == TRUE) {
  1776. DeviceExtension->SrbExtensionListHeader = srbExtension;
  1777. } else {
  1778. ASSERT(DeviceExtension->SrbExtensionListHeader == NULL);
  1779. }
  1780. //
  1781. // Create a second VA mapping of the common buffer area so we can make the
  1782. // range of addresses invalid when the miniport is not supposed to touch it.
  1783. // This will allow us to catch mis-behaving miniports.
  1784. //
  1785. SpRemapCommonBufferForMiniport(DeviceExtension);
  1786. DebugPrint((1, "SpGetCommonBufferVrfy: returning STATUS_SUCCESS\n"));
  1787. return(STATUS_SUCCESS);
  1788. }
  1789. VOID
  1790. SpFreeCommonBufferVrfy(
  1791. PADAPTER_EXTENSION Adapter
  1792. )
  1793. /*++
  1794. Routine Description:
  1795. This routine frees all of the common buffer space we've allocated for the
  1796. miniport on the supplied adapter. If only partially allocated, the routine
  1797. correctly cleans up the parts that are present. On exit, all the memory has
  1798. been freed and the associated pointers have been NULLed.
  1799. Arguments:
  1800. DeviceExtension - Supplies a pointer to the adapter device extension.
  1801. Return Value:
  1802. VOID
  1803. --*/
  1804. {
  1805. ULONG i;
  1806. PVOID* BlkAddr;
  1807. NTSTATUS Status;
  1808. PSP_VA_MAPPING_INFO MappingInfo;
  1809. ASSERT(Adapter->SrbExtensionBuffer == NULL);
  1810. if (Adapter->VerifierExtension != NULL &&
  1811. Adapter->VerifierExtension->CommonBufferVAs != NULL) {
  1812. //
  1813. // Initialize a pointer to the array of pointers we use to track and
  1814. // manage the common buffer blocks.
  1815. //
  1816. BlkAddr = Adapter->VerifierExtension->CommonBufferVAs;
  1817. //
  1818. // Cycle through the array of common memory descriptors, freeing each
  1819. // one. What we are freeing here is the SRB Extension/Sense Data
  1820. // buffers. Stop when we've deleted all the blocks.
  1821. //
  1822. for (i = 0; i < Adapter->VerifierExtension->CommonBufferBlocks && BlkAddr[i]; i++) {
  1823. //
  1824. // If there is a second VA range for the common block, free the
  1825. // MDL(s).
  1826. //
  1827. MappingInfo = GET_VA_MAPPING_INFO(Adapter, BlkAddr[i]);
  1828. if (MappingInfo->SrbExtMdl != NULL) {
  1829. MmProtectMdlSystemAddress(MappingInfo->SrbExtMdl, PAGE_READWRITE);
  1830. MmUnlockPages(MappingInfo->SrbExtMdl);
  1831. IoFreeMdl(MappingInfo->SrbExtMdl);
  1832. }
  1833. if (MappingInfo->SenseMdl != NULL) {
  1834. MmProtectMdlSystemAddress(MappingInfo->SrbExtMdl, PAGE_READWRITE);
  1835. MmUnlockPages(MappingInfo->SenseMdl);
  1836. IoFreeMdl(MappingInfo->SenseMdl);
  1837. }
  1838. //
  1839. // Free the memory. The method we use depends on how the memory
  1840. // was allocated.
  1841. //
  1842. if (Adapter->DmaAdapterObject == NULL) {
  1843. ExFreePool(BlkAddr[i]);
  1844. } else {
  1845. if (Adapter->VerifierExtension->IsCommonBuffer == FALSE) {
  1846. MmFreeContiguousMemorySpecifyCache(
  1847. BlkAddr[i],
  1848. Adapter->CommonBufferSize,
  1849. MmCached);
  1850. } else {
  1851. FreeCommonBuffer(
  1852. Adapter->DmaAdapterObject,
  1853. Adapter->CommonBufferSize,
  1854. Adapter->VerifierExtension->CommonBufferPAs[i],
  1855. BlkAddr[i],
  1856. FALSE);
  1857. }
  1858. }
  1859. }
  1860. //
  1861. // Free the uncached extension if we allocated one.
  1862. //
  1863. if (Adapter->NonCachedExtension != NULL) {
  1864. ULONG Length;
  1865. //
  1866. // Calculate the total length of the non-cached extension block we
  1867. // allocated. This is the non-cached buffer size asked for by the
  1868. // miniport rounded up to the next page boundary plus one full page.
  1869. //
  1870. Length = (ULONG)(ROUND_TO_PAGES(Adapter->VerifierExtension->NonCachedBufferSize));
  1871. //
  1872. // Free the memory. The method we use depends on how the memory
  1873. // was allocated.
  1874. //
  1875. if (Adapter->DmaAdapterObject == NULL) {
  1876. ExFreePool(BlkAddr[i]);
  1877. } else {
  1878. if (Adapter->UncachedExtensionIsCommonBuffer == FALSE) {
  1879. MmFreeContiguousMemorySpecifyCache(
  1880. BlkAddr[i],
  1881. Length,
  1882. MmCached);
  1883. } else {
  1884. FreeCommonBuffer(
  1885. Adapter->DmaAdapterObject,
  1886. Length,
  1887. Adapter->VerifierExtension->CommonBufferPAs[i],
  1888. BlkAddr[i],
  1889. FALSE);
  1890. }
  1891. }
  1892. Adapter->NonCachedExtension = NULL;
  1893. }
  1894. //
  1895. // Free the arrays we allocated to manage the common buffer area.
  1896. //
  1897. ExFreePool(Adapter->VerifierExtension->CommonBufferVAs);
  1898. Adapter->VerifierExtension->CommonBufferVAs = NULL;
  1899. Adapter->VerifierExtension->CommonBufferPAs = NULL;
  1900. Adapter->VerifierExtension->CommonBufferBlocks = 0;
  1901. Adapter->SrbExtensionListHeader = NULL;
  1902. }
  1903. }
  1904. PVOID
  1905. SpGetOriginalSrbExtVa(
  1906. PADAPTER_EXTENSION Adapter,
  1907. PVOID Va
  1908. )
  1909. /*++
  1910. Routine Description:
  1911. This function returns the original mapped virtual address of a common
  1912. block if the supplied VA is for one of the common buffer blocks we've
  1913. allocated.
  1914. Arguments:
  1915. Adapter - the adapter device extension
  1916. Va - virtual address of a common buffer block
  1917. Return Value:
  1918. If the supplied VA is the address of one of the common buffer blocks,
  1919. returns the original VA of the block. Else, returns NULL.
  1920. --*/
  1921. {
  1922. PVOID* BlkAddr = Adapter->VerifierExtension->CommonBufferVAs;
  1923. PSP_VA_MAPPING_INFO MappingInfo;
  1924. ULONG i;
  1925. for (i = 0; i < Adapter->VerifierExtension->CommonBufferBlocks; i++) {
  1926. MappingInfo = GET_VA_MAPPING_INFO(Adapter, *BlkAddr++);
  1927. if (Va == MappingInfo->RemappedSrbExtVa ||
  1928. Va == MappingInfo->OriginalSrbExtVa)
  1929. return MappingInfo->OriginalSrbExtVa;
  1930. }
  1931. return NULL;
  1932. }
  1933. VOID
  1934. SpInsertSrbExtension(
  1935. PADAPTER_EXTENSION Adapter,
  1936. PCCHAR SrbExtension
  1937. )
  1938. /*++
  1939. Routine Description:
  1940. This routine inserts the supplied SRB extension back into the SRB extension
  1941. list. The VA of the supplied extension lies within one of our common buffer
  1942. blocks and it may be a remapped VA. If it is a remapped address, this
  1943. routine invalidates the page(s) comprising the extension after it links the
  1944. extension back into the list.
  1945. Arguments:
  1946. Adapter - Pointer to an adapter device extension.
  1947. SrbExtension - Pointer to the beginning of an SRB extension within one of
  1948. our common buffer blocks. May or may not be within a
  1949. remapped range.
  1950. --*/
  1951. {
  1952. //
  1953. // Round the srb extension pointer down to the beginning of the page
  1954. // and link the block back into the list. Note that we're careful
  1955. // to point the list header at the original VA of the block.
  1956. //
  1957. SrbExtension = (PVOID)((ULONG_PTR)SrbExtension & ~(PAGE_SIZE - 1));
  1958. *((PVOID *) SrbExtension) = Adapter->SrbExtensionListHeader;
  1959. Adapter->SrbExtensionListHeader = SpGetOriginalSrbExtVa(
  1960. Adapter,
  1961. SrbExtension);
  1962. //
  1963. // If the original VA differs from the one supplied, the supplied
  1964. // one is one of our remapped VAs. In this case, we want to invalidate
  1965. // the range so the system will bugcheck if anyone tries to access it.
  1966. //
  1967. if (Adapter->SrbExtensionListHeader != SrbExtension) {
  1968. PMDL Mdl = SpGetRemappedSrbExt(Adapter, Adapter->SrbExtensionListHeader);
  1969. ASSERT(Mdl != NULL);
  1970. MmProtectMdlSystemAddress(Mdl, PAGE_NOACCESS);
  1971. //
  1972. // Just because we remapped the SRB extension does not mean we
  1973. // necessarily remapped the sense buffer.
  1974. //
  1975. Mdl = SpGetRemappedSenseBuffer(Adapter, Adapter->SrbExtensionListHeader);
  1976. if (Mdl != NULL) {
  1977. MmProtectMdlSystemAddress(Mdl, PAGE_NOACCESS);
  1978. }
  1979. }
  1980. }
  1981. #if DBG
  1982. ULONG SpVerbose = 0;
  1983. #endif
  1984. PVOID
  1985. SpPrepareSrbExtensionForUse(
  1986. IN PADAPTER_EXTENSION Adapter,
  1987. IN OUT PCCHAR *SrbExtension
  1988. )
  1989. /*++
  1990. Routine Description:
  1991. This function accepts a pointer to the beginning of one of the individual
  1992. common-buffer blocks allocated by the verifier for SRB extensions, sense
  1993. buffers, and non-cached extensions. It calculates the beginning of the
  1994. SRB extension within the block and, if the block has been remapped, makes
  1995. the page(s) of the SRB extension read/write valid.
  1996. Arguments:
  1997. Adapter - Pointer to an adapter device extension.
  1998. SrbExtension - Pointer to the beginning of a common-buffer block.
  1999. Return Value:
  2000. If the common buffer block containing the SRB extension has been remapped,
  2001. returns the address of the beginning of the remapped srb extension, valid
  2002. for reading and writing.
  2003. If the block has not been remapped, returns NULL.
  2004. Regardless of whether the block is remapped or not, the supplied pointer
  2005. is fixed up to point to the beginning of the SRB extension within the
  2006. original VA range.
  2007. --*/
  2008. {
  2009. PCCHAR RemappedSrbExt = NULL;
  2010. NTSTATUS Status;
  2011. PMDL Mdl;
  2012. ULONG srbExtensionSize = ROUND_UP_COUNT(Adapter->SrbExtensionSize, 8);
  2013. //
  2014. // If we've remapped the SRB extension, get the second mapping and make it
  2015. // valid. If we get the second mapping, but cannot make it valid, we just
  2016. // use the original mapping.
  2017. //
  2018. Mdl = SpGetRemappedSrbExt(Adapter, *SrbExtension);
  2019. if (Mdl != NULL) {
  2020. Status = MmProtectMdlSystemAddress(Mdl, PAGE_READWRITE);
  2021. if (NT_SUCCESS(Status)) {
  2022. RemappedSrbExt = MmGetSystemAddressForMdlSafe(
  2023. Mdl,
  2024. NormalPagePriority);
  2025. //
  2026. // Adjust the remapped srb extension pointer so the end of the
  2027. // buffer falls on a page boundary.
  2028. //
  2029. RemappedSrbExt +=
  2030. ((Adapter->CommonBufferSize -
  2031. (PAGE_SIZE * 2)) - srbExtensionSize);
  2032. }
  2033. }
  2034. //
  2035. // Adjust the original srb extension pointer so it also ends on a page
  2036. // boundary.
  2037. //
  2038. *SrbExtension += ((Adapter->CommonBufferSize - (PAGE_SIZE * 2)) -
  2039. srbExtensionSize);
  2040. #if DBG
  2041. if (SpVerbose == 1) {
  2042. DebugPrint((0, "SpPrepareSrbExtensionForUse: SrbExt %p SrbExtSize %x\n",
  2043. *SrbExtension, srbExtensionSize));
  2044. }
  2045. #endif
  2046. return RemappedSrbExt;
  2047. }
  2048. PCCHAR
  2049. SpPrepareSenseBufferForUse(
  2050. PADAPTER_EXTENSION Adapter,
  2051. PCCHAR SrbExtension
  2052. )
  2053. /*++
  2054. Routine Description:
  2055. This function accepts a pointer to the beginning of an SRB extension
  2056. within one of the individual common-buffer blocks allocated by the
  2057. verifier for SRB extensions, sense buffers, and non-cached extensions.
  2058. It calculates the beginning of the sense buffer within the block and,
  2059. if the block has been remapped, makes the page read/write valid.
  2060. It is assumed that a sense buffer will never be larger than one page.
  2061. Arguments:
  2062. Adapter - Pointer to an adapter device extension.
  2063. SrbExtension - Pointer to the beginning of the SRB extension within a
  2064. common-buffer block.
  2065. Return Value:
  2066. Returns the address of the beginning of a sense buffer valid for
  2067. reading and writing.
  2068. --*/
  2069. {
  2070. PVOID BeginningOfBlock;
  2071. ULONG SenseDataSize;
  2072. PCCHAR Base;
  2073. NTSTATUS Status;
  2074. PMDL Mdl;
  2075. ULONG srbExtensionSize = (ULONG)ROUND_TO_PAGES(Adapter->SrbExtensionSize);
  2076. //
  2077. // Initialize the size of the sense buffer and the base of the sense buffer
  2078. // within the originally allocated block. The base of the sense buffer
  2079. // immediately follows the srb extension and resides on a page boundary
  2080. // within a common buffer block.
  2081. //
  2082. SenseDataSize = sizeof(SENSE_DATA) + Adapter->AdditionalSenseBytes;
  2083. SenseDataSize = ROUND_UP_COUNT(SenseDataSize, 8);
  2084. Base = SrbExtension + ROUND_UP_COUNT(Adapter->SrbExtensionSize, 8);
  2085. //
  2086. // Initialize a pointer to the beginning of the common block the sense
  2087. // buffer resides in. This is needed in order to determine if the
  2088. // sense buffer has been remapped.
  2089. //
  2090. BeginningOfBlock =
  2091. (PVOID)(((ULONG_PTR)SrbExtension +
  2092. ROUND_UP_COUNT(Adapter->SrbExtensionSize, 8)) -
  2093. srbExtensionSize);
  2094. //
  2095. // If we've remapped the sense buffer, make the range valid and reset base
  2096. // to point to the beginning of the range.
  2097. //
  2098. Mdl = SpGetRemappedSenseBuffer(Adapter, BeginningOfBlock);
  2099. if (Mdl != NULL) {
  2100. Status = MmProtectMdlSystemAddress(Mdl, PAGE_READWRITE);
  2101. if (NT_SUCCESS(Status)) {
  2102. Base = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
  2103. ASSERT(Base != NULL);
  2104. }
  2105. }
  2106. #if DBG
  2107. if (SpVerbose == 1) {
  2108. DebugPrint((0, "SpPrepareSenseBufferForUse: SrbExt %p Base %p BOB %p "
  2109. "SenseBuffer %p SrbExtSize %x\n",
  2110. SrbExtension,
  2111. Base,
  2112. BeginningOfBlock,
  2113. (Base + PAGE_SIZE - SenseDataSize),
  2114. srbExtensionSize));
  2115. }
  2116. #endif
  2117. //
  2118. // Return a pointer into the block such that the sense buffer ends aligned
  2119. // on a page boundary.
  2120. //
  2121. return (Base + PAGE_SIZE - SenseDataSize);
  2122. }
  2123. PVOID
  2124. SpGetInaccessiblePage(
  2125. PADAPTER_EXTENSION Adapter
  2126. )
  2127. /*++
  2128. Routine Description:
  2129. This function returns a pointer to a page of memory that is not valid
  2130. for reading or writing. This page is a shared resource, used by all
  2131. adapters that are actively verifying. The page is hung off of the driver
  2132. extension. The page is faulted in as needed, so if we haven't initialized
  2133. it yet, we try to do so here in an interlocked fashion.
  2134. Arguments:
  2135. Adapter - Pointer to an adapter device extension.
  2136. Return Value:
  2137. Either returns a pointer to an invalid page of VAs or NULL if the page
  2138. could not be allocated.
  2139. --*/
  2140. {
  2141. PSCSIPORT_DRIVER_EXTENSION DriverExtension;
  2142. PVOID UnusedPage;
  2143. PVOID InvalidPage;
  2144. PMDL UnusedPageMdl;
  2145. PVOID CurrentValue;
  2146. //
  2147. // Retrieve the driver extension. We must have it to proceed.
  2148. //
  2149. DriverExtension = IoGetDriverObjectExtension(
  2150. Adapter->DeviceObject->DriverObject,
  2151. ScsiPortInitialize);
  2152. if (DriverExtension == NULL) {
  2153. return NULL;
  2154. }
  2155. //
  2156. // If the invalid page is not yet initialized, go ahead and try to
  2157. // initialize it now.
  2158. //
  2159. if (DriverExtension->InvalidPage == NULL) {
  2160. //
  2161. // Allocate a page of memory.
  2162. //
  2163. UnusedPage = SpAllocatePool(NonPagedPool,
  2164. PAGE_SIZE,
  2165. SCSIPORT_TAG_VERIFIER,
  2166. Adapter->DeviceObject->DriverObject);
  2167. if (UnusedPage != NULL) {
  2168. //
  2169. // Zero the page and remap it. The remapped range will be inaccessible.
  2170. // If the remapping fails, just free the page; we just won't have an
  2171. // inaccessible page to work with.
  2172. //
  2173. RtlZeroMemory(UnusedPage, PAGE_SIZE);
  2174. InvalidPage = SpRemapBlock(UnusedPage,
  2175. PAGE_SIZE,
  2176. &UnusedPageMdl);
  2177. if (InvalidPage != NULL) {
  2178. //
  2179. // If nobody else has beaten us to it, init the pointer to the
  2180. // invalid page in the driver extension. If somebody has already
  2181. // done it, just free the page we created. This page is freed
  2182. // when scsiport is unloaded.
  2183. //
  2184. CurrentValue = InterlockedCompareExchangePointer(
  2185. &DriverExtension->InvalidPage,
  2186. InvalidPage,
  2187. NULL);
  2188. if (CurrentValue == NULL) {
  2189. DriverExtension->UnusedPage = UnusedPage;
  2190. DriverExtension->UnusedPageMdl = UnusedPageMdl;
  2191. } else {
  2192. MmProtectMdlSystemAddress(UnusedPageMdl, PAGE_READWRITE);
  2193. UnusedPageMdl->MdlFlags &= ~MDL_MAPPED_TO_SYSTEM_VA;
  2194. IoFreeMdl(UnusedPageMdl);
  2195. ExFreePool(UnusedPage);
  2196. }
  2197. } else {
  2198. //
  2199. // Couldn't make the page inaccessible, just free it.
  2200. //
  2201. ExFreePool(UnusedPage);
  2202. }
  2203. }
  2204. }
  2205. return DriverExtension->InvalidPage;
  2206. }
  2207. BOOLEAN
  2208. SpCheckForActiveRequests(
  2209. PADAPTER_EXTENSION Adapter
  2210. )
  2211. /*++
  2212. Routine Description:
  2213. This function walks through all of the logical units connected to the
  2214. supplied adapter looking for any outstanding requests. If it finds
  2215. any, it returns TRUE immediately.
  2216. Arguments:
  2217. Adapter - Pointer to an adapter device extension.
  2218. Return Value:
  2219. TRUE - If an outstanding requests is found on one of the logical units
  2220. connected to the adapter.
  2221. FALSE - If no outstanding requests on the adapter.
  2222. --*/
  2223. {
  2224. PLOGICAL_UNIT_EXTENSION LogicalUnit;
  2225. PLOGICAL_UNIT_BIN Bin;
  2226. ULONG BinNumber;
  2227. //
  2228. // Iterate through each LU bin. For each bin, if there are any LUs, iterate
  2229. // through each of those looking for an oustanding request. If we find one
  2230. // terminate the search and return TRUE.
  2231. //
  2232. for (BinNumber = 0; BinNumber < NUMBER_LOGICAL_UNIT_BINS; BinNumber++) {
  2233. Bin = &Adapter->LogicalUnitList[BinNumber];
  2234. LogicalUnit = Bin->List;
  2235. while (LogicalUnit != NULL) {
  2236. if (LogicalUnit->AbortSrb != NULL &&
  2237. LogicalUnit->AbortSrb->SrbFlags & SRB_FLAGS_IS_ACTIVE) {
  2238. return TRUE;
  2239. } else if (LogicalUnit->CurrentUntaggedRequest != NULL &&
  2240. LogicalUnit->CurrentUntaggedRequest->CurrentSrb->SrbFlags & SRB_FLAGS_IS_ACTIVE) {
  2241. return TRUE;
  2242. } else if (LogicalUnit->RequestList.Flink != &LogicalUnit->RequestList) {
  2243. PSRB_DATA srbData;
  2244. PVOID nextEntry = LogicalUnit->RequestList.Flink;
  2245. while (nextEntry != &LogicalUnit->RequestList) {
  2246. srbData = CONTAINING_RECORD(nextEntry, SRB_DATA, RequestList);
  2247. if (srbData->CurrentSrb->SrbFlags & SRB_FLAGS_IS_ACTIVE) {
  2248. return TRUE;
  2249. }
  2250. nextEntry = srbData->RequestList.Flink;
  2251. }
  2252. }
  2253. LogicalUnit = LogicalUnit->NextLogicalUnit;
  2254. }
  2255. }
  2256. return FALSE;
  2257. }
  2258. VOID
  2259. SpEnsureAllRequestsAreComplete(
  2260. PADAPTER_EXTENSION Adapter
  2261. )
  2262. /*++
  2263. Routine Description:
  2264. This routine bugchecks the system if there are any outstanding requests
  2265. on the supplied adapter. If the SP_DONT_CHK_REQUESTS_ON_RESET bit is
  2266. set on the adapter's verification level, don't do the check.
  2267. Arguments:
  2268. Adapter - Points to an adapter device extension.
  2269. --*/
  2270. {
  2271. //
  2272. // If there are any outstanding requests on any of the LUs connected to the
  2273. // adapter, bugcheck the system. Note that we only do this check if it
  2274. // has not been turned off.
  2275. //
  2276. if (VRFY_DO_CHECK(Adapter, SP_DONT_CHK_REQUESTS_ON_RESET)) {
  2277. BOOLEAN ActiveRequests = SpCheckForActiveRequests(Adapter);
  2278. if (ActiveRequests == TRUE) {
  2279. KeBugCheckEx(SCSI_VERIFIER_DETECTED_VIOLATION,
  2280. SCSIPORT_VERIFIER_RQSTS_NOT_COMPLETE,
  2281. (ULONG_PTR)Adapter,
  2282. (ULONG_PTR)Adapter->HwDeviceExtension,
  2283. 0);
  2284. }
  2285. }
  2286. }
  2287. VOID
  2288. SpDoVerifierInit(
  2289. IN PADAPTER_EXTENSION Adapter,
  2290. IN PHW_INITIALIZATION_DATA HwInitializationData
  2291. )
  2292. /*++
  2293. Routine Description:
  2294. This routine allocates and initializes a verifier extension for the
  2295. supplied adapter. A per-adapter verification level is read from the
  2296. registry before allocating the extension. A verfication level of -1
  2297. means "don't verify this adapter". If we do allocate the extension,
  2298. we also lock the verifier code section into memory.
  2299. Arguments:
  2300. Adapter - The adapter device extension.
  2301. HwInitializationData - A pointer to the HW_INITIALIZATION_DATA for
  2302. the adapter.
  2303. --*/
  2304. {
  2305. ULONG VerifyLevel;
  2306. NTSTATUS Status;
  2307. PAGED_CODE();
  2308. //
  2309. // Read adapter's verification level from the registry. If the adapter is
  2310. // configured for no verification, just return.
  2311. //
  2312. VerifyLevel = SpGetAdapterVerifyLevel(Adapter);
  2313. if (VerifyLevel == SP_VRFY_NONE) {
  2314. return;
  2315. }
  2316. //
  2317. // Go ahead and try to allocate the extension.
  2318. //
  2319. Adapter->VerifierExtension =
  2320. SpAllocatePool(NonPagedPool,
  2321. sizeof(VERIFIER_EXTENSION),
  2322. SCSIPORT_TAG_VERIFIER,
  2323. Adapter->DeviceObject->DriverObject);
  2324. if (Adapter->VerifierExtension != NULL) {
  2325. //
  2326. // Zero the extension.
  2327. //
  2328. RtlZeroMemory(Adapter->VerifierExtension, sizeof(VERIFIER_EXTENSION));
  2329. //
  2330. // Lock the pageable verifier code section into memory.
  2331. //
  2332. #ifdef ALLOC_PRAGMA
  2333. if (VerifierCodeSectionHandle == NULL) {
  2334. VerifierCodeSectionHandle = MmLockPagableCodeSection(SpHwFindAdapterVrfy);
  2335. } else {
  2336. MmLockPagableSectionByHandle(VerifierCodeSectionHandle);
  2337. }
  2338. #endif
  2339. //
  2340. // Set the verification level for this adapter. This value is the sum
  2341. // of the global verifier level and the per-adapter value we read above.
  2342. //
  2343. Adapter->VerifierExtension->VrfyLevel = (VerifyLevel | SpVrfyLevel);
  2344. //
  2345. // Initialize function pointers in the verifier extension to
  2346. // to point to the real miniport routines.
  2347. //
  2348. Adapter->VerifierExtension->RealHwFindAdapter = HwInitializationData->HwFindAdapter;
  2349. Adapter->VerifierExtension->RealHwInitialize = HwInitializationData->HwInitialize;
  2350. Adapter->VerifierExtension->RealHwStartIo = HwInitializationData->HwStartIo;
  2351. Adapter->VerifierExtension->RealHwInterrupt = HwInitializationData->HwInterrupt;
  2352. Adapter->VerifierExtension->RealHwResetBus = HwInitializationData->HwResetBus;
  2353. Adapter->VerifierExtension->RealHwDmaStarted = HwInitializationData->HwDmaStarted;
  2354. Adapter->VerifierExtension->RealHwAdapterControl = HwInitializationData->HwAdapterControl;
  2355. //
  2356. // Redirect the miniport routines to verifier routines.
  2357. //
  2358. Adapter->HwFindAdapter = SpHwFindAdapterVrfy;
  2359. Adapter->HwInitialize = SpHwInitializeVrfy;
  2360. Adapter->HwStartIo = SpHwStartIoVrfy;
  2361. Adapter->HwInterrupt = SpHwInterruptVrfy;
  2362. Adapter->HwResetBus = SpHwResetBusVrfy;
  2363. Adapter->HwDmaStarted = SpHwDmaStartedVrfy;
  2364. Adapter->HwAdapterControl = SpHwAdapterControlVrfy;
  2365. //
  2366. // Get a pointer to an invalid page of memory so we can catch
  2367. // miniports trying to touch memory when they shouldn't be.
  2368. //
  2369. Adapter->VerifierExtension->InvalidPage = SpGetInaccessiblePage(Adapter);
  2370. }
  2371. }
  2372. VOID
  2373. SpDoVerifierCleanup(
  2374. IN PADAPTER_EXTENSION Adapter
  2375. )
  2376. /*++
  2377. Routine Description:
  2378. This routine frees the supplied adapter's verifier extension and releases
  2379. its reference on the verifier code section.
  2380. This routine gets called as part of the adapter resource cleanup. When
  2381. called, all the actual resources allocated for the verifier have already
  2382. been cleaned up.
  2383. Arguments:
  2384. Adapter - the adapter device extension
  2385. --*/
  2386. {
  2387. //
  2388. // We should never arrive here if the scsiport verifier is not active.
  2389. // And when we get here we should have freed all the resources hanging
  2390. // off the extension.
  2391. //
  2392. ASSERT(Adapter->VerifierExtension != NULL);
  2393. ASSERT(Adapter->VerifierExtension->CommonBufferVAs == NULL);
  2394. ASSERT(Adapter->VerifierExtension->CommonBufferPAs == NULL);
  2395. ASSERT(Adapter->VerifierExtension->CommonBufferBlocks == 0);
  2396. //
  2397. // Free and NULL the verifier extension for this adapter.
  2398. //
  2399. ExFreePool(Adapter->VerifierExtension);
  2400. Adapter->VerifierExtension = NULL;
  2401. //
  2402. // Release our reference on the verifier code section.
  2403. //
  2404. #ifdef ALLOC_PRAGMA
  2405. ASSERT(VerifierCodeSectionHandle != NULL);
  2406. MmUnlockPagableImageSection(VerifierCodeSectionHandle);
  2407. #endif
  2408. }
  2409. ULONG
  2410. SpGetAdapterVerifyLevel(
  2411. IN PADAPTER_EXTENSION Adapter
  2412. )
  2413. /*++
  2414. Routine Description:
  2415. This function returns the verification level for the supplied adapter.
  2416. Arguments:
  2417. Adapter - Pointer to an adapter device extension.
  2418. Return Value:
  2419. The supplied adapter's verification level.
  2420. --*/
  2421. {
  2422. PSCSIPORT_DRIVER_EXTENSION DrvExt;
  2423. OBJECT_ATTRIBUTES ObjectAttributes;
  2424. UNICODE_STRING UnicodeString;
  2425. HANDLE ParametersKey;
  2426. HANDLE ServiceKey;
  2427. ULONG VerifyLevel = 0;
  2428. NTSTATUS Status;
  2429. PAGED_CODE();
  2430. //
  2431. // We need the driver extension to get the adapter's registry path. We use
  2432. // this to look up the adapter settings in the registry. If we cannot get
  2433. // the driver extension, we have to abort.
  2434. //
  2435. DrvExt = IoGetDriverObjectExtension(
  2436. Adapter->DeviceObject->DriverObject,
  2437. ScsiPortInitialize);
  2438. if (DrvExt == NULL) {
  2439. return 0;
  2440. }
  2441. //
  2442. // Try to open the adapter's registry key.
  2443. //
  2444. InitializeObjectAttributes(
  2445. &ObjectAttributes,
  2446. &DrvExt->RegistryPath,
  2447. OBJ_CASE_INSENSITIVE,
  2448. NULL,
  2449. NULL);
  2450. Status = ZwOpenKey(&ServiceKey, KEY_READ, &ObjectAttributes);
  2451. if (NT_SUCCESS(Status)) {
  2452. //
  2453. // Try to open the adapter's parameters key.
  2454. //
  2455. RtlInitUnicodeString(&UnicodeString, L"Parameters");
  2456. InitializeObjectAttributes(
  2457. &ObjectAttributes,
  2458. &UnicodeString,
  2459. OBJ_CASE_INSENSITIVE,
  2460. ServiceKey,
  2461. NULL);
  2462. Status = ZwOpenKey(&ParametersKey, KEY_READ, &ObjectAttributes);
  2463. if (NT_SUCCESS(Status)) {
  2464. //
  2465. // Try to read the verification level value under the adapter's
  2466. // parameters key.
  2467. //
  2468. RtlInitUnicodeString(&UnicodeString, L"VerifyLevel");
  2469. SpReadNumericValue(
  2470. ParametersKey,
  2471. NULL,
  2472. &UnicodeString,
  2473. &VerifyLevel);
  2474. ZwClose(ParametersKey);
  2475. }
  2476. ZwClose(ServiceKey);
  2477. }
  2478. return VerifyLevel;
  2479. }