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.

9591 lines
275 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1990 - 1999
  3. Module Name:
  4. internal.c
  5. Abstract:
  6. This is the NT SCSI port driver. This file contains the internal
  7. code.
  8. Authors:
  9. Mike Glass
  10. Jeff Havens
  11. Environment:
  12. kernel mode only
  13. Notes:
  14. This module is a driver dll for scsi miniports.
  15. Revision History:
  16. --*/
  17. #include "port.h"
  18. #include "wmilib.h"
  19. #define __FILE_ID__ 'intr'
  20. #if DBG
  21. static const char *__file__ = __FILE__;
  22. #endif
  23. #if DBG
  24. ULONG ScsiCheckInterrupts = 1;
  25. // These counters keep track of succesfull (and failed) calls to
  26. // IoWMIWriteEvent in the ScsiPortCompletionDpc function
  27. LONG ScsiPortWmiWriteCalls = 0;
  28. LONG ScsiPortWmiWriteCallsFailed = 0;
  29. #else
  30. ULONG ScsiCheckInterrupts = 0;
  31. #endif
  32. #if DBG
  33. ULONG ScsiSimulateNoVaCounter = 0;
  34. ULONG ScsiSimulateNoVaInterval = 0;
  35. ULONG ScsiSimulateNoVaBreak = TRUE;
  36. PVOID
  37. SpGetSystemAddressForMdlSafe(
  38. IN PMDL Mdl,
  39. IN MM_PAGE_PRIORITY Priority
  40. )
  41. {
  42. ScsiSimulateNoVaCounter++;
  43. if((ScsiSimulateNoVaInterval != 0) &&
  44. (Priority != HighPagePriority) &&
  45. ((ScsiSimulateNoVaCounter % ScsiSimulateNoVaInterval) == 0)) {
  46. if(TEST_FLAG(Mdl->MdlFlags, (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL))) {
  47. DbgPrint("SpGetSystemAddressForMdlSafe - not failing since MDL %#08p is already mapped\n", Mdl);
  48. return Mdl->MappedSystemVa;
  49. } else {
  50. DbgPrint("SpGetSystemAddressForMdlSafe - failing this MDL mapping (%#08p %x %x)\n", Mdl, ScsiSimulateNoVaInterval, ScsiSimulateNoVaCounter);
  51. ASSERT(ScsiSimulateNoVaBreak == FALSE);
  52. return NULL;
  53. }
  54. }
  55. return MmGetSystemAddressForMdlSafe(Mdl, Priority);
  56. }
  57. #else
  58. #define SpGetSystemAddressForMdlSafe MmGetSystemAddressForMdlSafe
  59. #endif
  60. //
  61. // module-local type declarations
  62. //
  63. typedef struct _REROUTE_CONTEXT {
  64. PIRP OriginalIrp;
  65. PLOGICAL_UNIT_EXTENSION LogicalUnit;
  66. } REROUTE_CONTEXT, *PREROUTE_CONTEXT;
  67. typedef struct _SP_ENUMERATION_CONTEXT {
  68. KEVENT Event;
  69. PIO_WORKITEM WorkItem;
  70. NTSTATUS Status;
  71. } SP_ENUMERATION_CONTEXT, *PSP_ENUMERATION_CONTEXT;
  72. //
  73. // Prototypes
  74. //
  75. VOID
  76. SpEnumerateAdapterWorker(
  77. IN PDEVICE_OBJECT DeviceObject,
  78. IN PSP_ENUMERATION_CONTEXT Context
  79. );
  80. NTSTATUS
  81. SpSendMiniPortIoctl(
  82. IN PADAPTER_EXTENSION DeviceExtension,
  83. IN PIRP RequestIrp
  84. );
  85. NTSTATUS
  86. SpSendPassThrough (
  87. IN PADAPTER_EXTENSION DeviceExtension,
  88. IN PIRP RequestIrp
  89. );
  90. #ifdef USE_DMA_MACROS
  91. VOID
  92. SpReceiveScatterGather(
  93. IN struct _DEVICE_OBJECT *DeviceObject,
  94. IN struct _IRP *Irp,
  95. IN PSCATTER_GATHER_LIST ScatterGather,
  96. IN PVOID Context
  97. );
  98. #else
  99. IO_ALLOCATION_ACTION
  100. SpBuildScatterGather(
  101. IN struct _DEVICE_OBJECT *DeviceObject,
  102. IN struct _IRP *Irp,
  103. IN PVOID MapRegisterBase,
  104. IN PVOID Context
  105. );
  106. #endif
  107. NTSTATUS
  108. SpSendResetCompletion(
  109. IN PDEVICE_OBJECT DeviceObject,
  110. IN PIRP Irp,
  111. IN PRESET_COMPLETION_CONTEXT Context
  112. );
  113. NTSTATUS
  114. SpSendReset(
  115. IN PDEVICE_OBJECT DeviceObject,
  116. IN PIRP RequestIrp
  117. );
  118. NTSTATUS
  119. SpRerouteLegacyRequest(
  120. IN PDEVICE_OBJECT AdapterObject,
  121. IN PIRP Irp
  122. );
  123. NTSTATUS
  124. SpFlushReleaseQueue(
  125. IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
  126. IN BOOLEAN Flush
  127. );
  128. VOID
  129. SpLogInterruptFailure(
  130. IN PADAPTER_EXTENSION Adapter
  131. );
  132. VOID
  133. SpDelayedWmiRegistrationControl(
  134. IN PDEVICE_OBJECT DeviceObject,
  135. IN PVOID Context);
  136. VOID
  137. SpCompletionDpcProcessWmi(
  138. IN PDEVICE_OBJECT DeviceObject,
  139. IN PINTERRUPT_DATA savedInterruptData
  140. );
  141. NTSTATUS
  142. IssueRequestSenseCompletion(
  143. PDEVICE_OBJECT DeviceObject,
  144. PIRP Irp,
  145. PLOGICAL_UNIT_EXTENSION LogicalUnit
  146. );
  147. VOID
  148. SpSendRequestSenseIrp(
  149. IN PADAPTER_EXTENSION Adapter,
  150. IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
  151. IN PSCSI_REQUEST_BLOCK FailingSrb
  152. );
  153. NTSTATUS
  154. SpFireSenseDataEvent(
  155. PSCSI_REQUEST_BLOCK Srb,
  156. PDEVICE_OBJECT DeviceObject
  157. );
  158. #if defined(FORWARD_PROGRESS)
  159. PMDL
  160. SpPrepareReservedMdlForUse(
  161. IN PADAPTER_EXTENSION Adapter,
  162. IN PSRB_DATA SrbData,
  163. IN PSCSI_REQUEST_BLOCK srb,
  164. IN ULONG ScatterListLength
  165. );
  166. PVOID
  167. SpMapLockedPagesWithReservedMapping(
  168. IN PADAPTER_EXTENSION Adapter,
  169. IN PSCSI_REQUEST_BLOCK Srb,
  170. IN PSRB_DATA SrbData,
  171. IN PMDL Mdl
  172. );
  173. #endif
  174. #ifdef ALLOC_PRAGMA
  175. #pragma alloc_text(PAGE, ScsiPortFdoDeviceControl)
  176. #pragma alloc_text(PAGE, SpSendMiniPortIoctl)
  177. #pragma alloc_text(PAGE, SpSendPassThrough)
  178. #pragma alloc_text(PAGE, ScsiPortFdoCreateClose)
  179. #pragma alloc_text(PAGE, SpSendReset)
  180. #pragma alloc_text(PAGE, SpEnumerateAdapterWorker)
  181. #pragma alloc_text(PAGELOCK, SpClaimLogicalUnit)
  182. #endif
  183. //
  184. // Routines start
  185. //
  186. NTSTATUS
  187. ScsiPortFdoDispatch(
  188. IN PDEVICE_OBJECT DeviceObject,
  189. IN PIRP Irp
  190. )
  191. /*++
  192. Routine Description:
  193. Arguments:
  194. DeviceObject - Address of device object.
  195. Irp - Address of I/O request packet.
  196. Return Value:
  197. Status.
  198. --*/
  199. {
  200. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  201. PADAPTER_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  202. PSCSI_REQUEST_BLOCK srb = irpStack->Parameters.Scsi.Srb;
  203. PSRB_DATA srbData;
  204. PKDEVICE_QUEUE_ENTRY packet;
  205. PIRP nextIrp;
  206. PIRP listIrp;
  207. PLOGICAL_UNIT_EXTENSION logicalUnit;
  208. NTSTATUS status;
  209. KIRQL currentIrql;
  210. ULONG isRemoved;
  211. //
  212. // If an SRB_DATA block has been setup then use it.
  213. //
  214. if(srb->OriginalRequest == Irp) {
  215. srbData = NULL;
  216. } else {
  217. srbData = srb->OriginalRequest;
  218. }
  219. isRemoved = SpAcquireRemoveLock(DeviceObject, Irp);
  220. if(isRemoved && !IS_CLEANUP_REQUEST(irpStack)) {
  221. Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
  222. SpReleaseRemoveLock(DeviceObject, Irp);
  223. SpCompleteRequest(DeviceObject,
  224. Irp,
  225. srbData,
  226. IO_NO_INCREMENT);
  227. return STATUS_DEVICE_DOES_NOT_EXIST;
  228. }
  229. //
  230. // If the adapter is configured to handle power-down requests during
  231. // shutdown, it is possible for it to be powered off and for the PDOs
  232. // to be powered up. We will fail requests when this condition arises.
  233. //
  234. // This should only occur at shutdown.
  235. //
  236. if (deviceExtension->CommonExtension.CurrentSystemState > PowerSystemHibernate &&
  237. deviceExtension->CommonExtension.CurrentDeviceState != PowerDeviceD0) {
  238. //
  239. // This should only occur if the adapter is configured to receive
  240. // power-down requests at shutdown.
  241. //
  242. ASSERT(deviceExtension->NeedsShutdown == TRUE);
  243. //
  244. // Lock and unlock commands don't require power and will work
  245. // regardless of the current power state.
  246. //
  247. if ((srb->Function != SRB_FUNCTION_UNLOCK_QUEUE &&
  248. srb->Function != SRB_FUNCTION_LOCK_QUEUE)) {
  249. Irp->IoStatus.Status = STATUS_POWER_STATE_INVALID;
  250. SpReleaseRemoveLock(DeviceObject, Irp);
  251. SpCompleteRequest(DeviceObject, Irp, srbData, IO_NO_INCREMENT);
  252. return STATUS_POWER_STATE_INVALID;
  253. }
  254. }
  255. //
  256. // If there's no SRB_DATA block for this request yet then we need to
  257. // allocate one.
  258. //
  259. if(srbData == NULL) {
  260. logicalUnit = GetLogicalUnitExtension(deviceExtension,
  261. srb->PathId,
  262. srb->TargetId,
  263. srb->Lun,
  264. FALSE,
  265. TRUE);
  266. if(logicalUnit == NULL) {
  267. DebugPrint((1, "ScsiPortFdoDispatch: Bad logical unit address.\n"));
  268. //
  269. // Fail the request. Set status in Irp and complete it.
  270. //
  271. srb->SrbStatus = SRB_STATUS_NO_DEVICE;
  272. Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
  273. SpReleaseRemoveLock(DeviceObject, Irp);
  274. SpCompleteRequest(DeviceObject, Irp, srbData, IO_NO_INCREMENT);
  275. return STATUS_NO_SUCH_DEVICE;
  276. }
  277. if((srb->Function == SRB_FUNCTION_IO_CONTROL) ||
  278. (srb->Function == SRB_FUNCTION_EXECUTE_SCSI) ||
  279. (srb->Function == SRB_FUNCTION_RELEASE_QUEUE) ||
  280. (srb->Function == SRB_FUNCTION_FLUSH_QUEUE)) {
  281. //
  282. // These are the only two types of requests which should
  283. // be able to get here without an SRB_DATA block. Any
  284. // other will need to be rerouted.
  285. //
  286. return SpRerouteLegacyRequest(DeviceObject, Irp);
  287. }
  288. } else {
  289. ASSERT_SRB_DATA(srbData);
  290. ASSERT(srbData->CurrentIrp == Irp);
  291. logicalUnit = srbData->LogicalUnit;
  292. ASSERT(logicalUnit != NULL);
  293. }
  294. switch (srb->Function) {
  295. case SRB_FUNCTION_SHUTDOWN:
  296. case SRB_FUNCTION_FLUSH: {
  297. //
  298. // Do not send shutdown requests unless the adapter
  299. // supports caching.
  300. //
  301. if (!deviceExtension->CachesData) {
  302. Irp->IoStatus.Status = STATUS_SUCCESS;
  303. srb->SrbStatus = SRB_STATUS_SUCCESS;
  304. SpReleaseRemoveLock(DeviceObject, Irp);
  305. SpCompleteRequest(DeviceObject, Irp, srbData, IO_NO_INCREMENT);
  306. return STATUS_SUCCESS;
  307. }
  308. DebugPrint((2, "ScsiPortFdoDispatch: Sending flush or shutdown "
  309. "request.\n"));
  310. goto ScsiPortFdoDispatchRunCommand;
  311. }
  312. case SRB_FUNCTION_LOCK_QUEUE:
  313. case SRB_FUNCTION_UNLOCK_QUEUE:
  314. case SRB_FUNCTION_IO_CONTROL:
  315. case SRB_FUNCTION_EXECUTE_SCSI:
  316. case SRB_FUNCTION_WMI: {
  317. ScsiPortFdoDispatchRunCommand:
  318. //
  319. // Mark Irp status pending.
  320. //
  321. IoMarkIrpPending(Irp);
  322. if(SpSrbIsBypassRequest(srb, logicalUnit->LuFlags)) {
  323. //
  324. // Call start io directly. This will by-pass the
  325. // frozen queue.
  326. //
  327. DebugPrint((2,
  328. "ScsiPortFdoDispatch: Bypass frozen queue, IRP %#p\n",
  329. Irp));
  330. srbData->TickCount = deviceExtension->TickCount;
  331. IoStartPacket(DeviceObject, Irp, (PULONG)NULL, NULL);
  332. } else {
  333. //
  334. // Queue the packet normally.
  335. //
  336. KeRaiseIrql(DISPATCH_LEVEL, &currentIrql);
  337. #if DBG
  338. // ASSERT(srb->Function != SRB_FUNCTION_UNLOCK_QUEUE);
  339. if (SpIsQueuePaused(logicalUnit)) {
  340. DebugPrint((1,"ScsiPortFdoDispatch: Irp %#p put in "
  341. "frozen queue %#p!\n", Irp, logicalUnit));
  342. }
  343. // ASSERT((srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE) == 0);
  344. #endif
  345. //
  346. // Set the tick count so we know how long this request has
  347. // been queued.
  348. //
  349. srbData->TickCount = deviceExtension->TickCount;
  350. if (!KeInsertByKeyDeviceQueue(
  351. &logicalUnit->DeviceObject->DeviceQueue,
  352. &Irp->Tail.Overlay.DeviceQueueEntry,
  353. srb->QueueSortKey)) {
  354. //
  355. // Clear the retry count.
  356. //
  357. logicalUnit->RetryCount = 0;
  358. //
  359. // Queue is empty; start request.
  360. //
  361. #if DBG
  362. if(SpIsQueuePaused(logicalUnit)) {
  363. DebugPrint((1, "ScsiPortFdoDispatch: Queue was empty - "
  364. "issuing request anyway\n"));
  365. }
  366. #endif
  367. IoStartPacket(DeviceObject, Irp, (PULONG)NULL, NULL);
  368. }
  369. KeLowerIrql(currentIrql);
  370. }
  371. return STATUS_PENDING;
  372. }
  373. case SRB_FUNCTION_RELEASE_QUEUE:
  374. case SRB_FUNCTION_FLUSH_QUEUE: {
  375. status = SpFlushReleaseQueue(
  376. logicalUnit,
  377. (BOOLEAN) (srb->Function == SRB_FUNCTION_FLUSH_QUEUE));
  378. ASSERT(NT_SUCCESS(status));
  379. if(NT_SUCCESS(status)) {
  380. srb->SrbStatus = SRB_STATUS_SUCCESS;
  381. } else {
  382. srb->SrbStatus = SRB_STATUS_ERROR;
  383. }
  384. break;
  385. }
  386. case SRB_FUNCTION_RESET_BUS: {
  387. RESET_CONTEXT resetContext;
  388. //
  389. // Acquire the spinlock to protect the flags structure and the saved
  390. // interrupt context.
  391. //
  392. KeAcquireSpinLock(&deviceExtension->SpinLock, &currentIrql);
  393. resetContext.DeviceExtension = deviceExtension;
  394. resetContext.PathId = srb->PathId;
  395. if (!deviceExtension->SynchronizeExecution(deviceExtension->InterruptObject,
  396. SpResetBusSynchronized,
  397. &resetContext)) {
  398. DebugPrint((1,"ScsiPortFdoDispatch: Reset failed\n"));
  399. srb->SrbStatus = SRB_STATUS_PHASE_SEQUENCE_FAILURE;
  400. status = STATUS_IO_DEVICE_ERROR;
  401. } else {
  402. SpLogResetError(deviceExtension,
  403. srb,
  404. ('R'<<24) | 256);
  405. srb->SrbStatus = SRB_STATUS_SUCCESS;
  406. status = STATUS_SUCCESS;
  407. }
  408. KeReleaseSpinLock(&deviceExtension->SpinLock, currentIrql);
  409. break;
  410. }
  411. case SRB_FUNCTION_ABORT_COMMAND: {
  412. DebugPrint((3, "ScsiPortFdoDispatch: SCSI Abort or Reset command\n"));
  413. //
  414. // Mark Irp status pending.
  415. //
  416. IoMarkIrpPending(Irp);
  417. //
  418. // Don't queue these requests in the logical unit
  419. // queue, rather queue them to the adapter queue.
  420. //
  421. KeRaiseIrql(DISPATCH_LEVEL, &currentIrql);
  422. IoStartPacket(DeviceObject, Irp, (PULONG)NULL, NULL);
  423. KeLowerIrql(currentIrql);
  424. return STATUS_PENDING;
  425. break;
  426. }
  427. case SRB_FUNCTION_ATTACH_DEVICE:
  428. case SRB_FUNCTION_CLAIM_DEVICE:
  429. case SRB_FUNCTION_RELEASE_DEVICE: {
  430. SpAcquireRemoveLock(logicalUnit->CommonExtension.DeviceObject,
  431. (PVOID) ((ULONG_PTR) Irp + 2));
  432. status = SpClaimLogicalUnit(deviceExtension, logicalUnit, Irp, TRUE);
  433. SpReleaseRemoveLock(logicalUnit->CommonExtension.DeviceObject,
  434. (PVOID) ((ULONG_PTR) Irp + 2));
  435. break;
  436. }
  437. default: {
  438. //
  439. // Found unsupported SRB function.
  440. //
  441. DebugPrint((1,"ScsiPortFdoDispatch: Unsupported function, SRB %p\n",
  442. srb));
  443. srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
  444. status = STATUS_INVALID_DEVICE_REQUEST;
  445. break;
  446. }
  447. }
  448. //
  449. // Set status in Irp.
  450. //
  451. Irp->IoStatus.Status = status;
  452. //
  453. // Complete request at raised IRQ.
  454. //
  455. SpReleaseRemoveLock(DeviceObject, Irp);
  456. SpCompleteRequest(DeviceObject, Irp, srbData, IO_NO_INCREMENT);
  457. return status;
  458. } // end ScsiPortFdoDispatch()
  459. NTSTATUS
  460. ScsiPortFdoCreateClose (
  461. IN PDEVICE_OBJECT DeviceObject,
  462. IN PIRP Irp
  463. )
  464. /*++
  465. Routine Description:
  466. I/O system disk create routine. This is called by the I/O system
  467. when the device is opened.
  468. If the fdo has not been started yet, this routine will try to start it.
  469. If the fdo cannot be started successfully this routine will return an error.
  470. Arguments:
  471. DriverObject - Pointer to driver object created by system.
  472. Irp - IRP involved.
  473. Return Value:
  474. NT Status
  475. --*/
  476. {
  477. PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
  478. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  479. NTSTATUS status = STATUS_SUCCESS;
  480. ULONG isRemoved;
  481. PAGED_CODE();
  482. isRemoved = SpAcquireRemoveLock(DeviceObject, Irp);
  483. //
  484. // Check to see if the adapter's been started first.
  485. //
  486. if(irpStack->MajorFunction == IRP_MJ_CREATE) {
  487. if(isRemoved != NO_REMOVE) {
  488. status = STATUS_DEVICE_DOES_NOT_EXIST;
  489. } else if(commonExtension->CurrentPnpState != IRP_MN_START_DEVICE) {
  490. status = STATUS_DEVICE_NOT_READY;
  491. }
  492. }
  493. Irp->IoStatus.Status = status;
  494. SpReleaseRemoveLock(DeviceObject, Irp);
  495. SpCompleteRequest(DeviceObject, Irp, NULL, IO_DISK_INCREMENT);
  496. return status;
  497. } // end ScsiPortCreateClose()
  498. VOID
  499. ScsiPortStartIo (
  500. IN PDEVICE_OBJECT DeviceObject,
  501. IN PIRP Irp
  502. )
  503. /*++
  504. Routine Description:
  505. Arguments:
  506. DeviceObject - Supplies pointer to Adapter device object.
  507. Irp - Supplies a pointer to an IRP.
  508. Return Value:
  509. Nothing.
  510. --*/
  511. {
  512. PADAPTER_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  513. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  514. PSCSI_REQUEST_BLOCK srb;
  515. PSRB_DATA srbData;
  516. PLOGICAL_UNIT_EXTENSION logicalUnit;
  517. LONG interlockResult;
  518. NTSTATUS status;
  519. BOOLEAN taggedRequest;
  520. DebugPrint((3,"ScsiPortStartIo: Enter routine\n"));
  521. if(irpStack->MajorFunction != IRP_MJ_SCSI) {
  522. //
  523. // Special processing.
  524. //
  525. if(irpStack->MajorFunction == IRP_MJ_POWER) {
  526. ScsiPortProcessAdapterPower(DeviceObject, Irp);
  527. } else {
  528. ASSERT(irpStack->MajorFunction == IRP_MJ_PNP);
  529. ASSERT(Irp->IoStatus.Information != (ULONG_PTR) NULL);
  530. //
  531. // The start-io routine is blocked now - signal the PNP code
  532. // so it can continue its processing.
  533. //
  534. KeSetEvent((PKEVENT) Irp->IoStatus.Information,
  535. IO_NO_INCREMENT,
  536. FALSE);
  537. }
  538. return;
  539. }
  540. srb = irpStack->Parameters.Scsi.Srb;
  541. srbData = srb->OriginalRequest;
  542. ASSERT_SRB_DATA(srbData);
  543. //
  544. // Start the srb status out as pending. If the srb is successful by the
  545. // end of this routine then it will be completed and the next request
  546. // will be fetched rather than issuing it to the miniport.
  547. //
  548. srb->SrbStatus = SRB_STATUS_PENDING;
  549. //
  550. // Clear the SCSI status if this is a scsi request.
  551. //
  552. if(srb->Function == SRB_FUNCTION_EXECUTE_SCSI) {
  553. srb->ScsiStatus = SCSISTAT_GOOD;
  554. }
  555. //
  556. // Get logical unit extension. The logical unit should have already been
  557. // locked with this IRP so we don't need to acquire it here.
  558. //
  559. logicalUnit = srbData->LogicalUnit;
  560. ASSERT(logicalUnit != NULL);
  561. //
  562. // We're already holding the remove lock so just check the is removed flag
  563. // to see if we should continue.
  564. //
  565. if((deviceExtension->CommonExtension.IsRemoved) &&
  566. (SpSrbIsBypassRequest(srb, logicalUnit->LuFlags))) {
  567. SpAcquireRemoveLock(DeviceObject, ScsiPortStartIo);
  568. SpReleaseRemoveLock(DeviceObject, Irp);
  569. Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
  570. srb->SrbStatus = SRB_STATUS_NO_DEVICE;
  571. SpCompleteRequest(DeviceObject, Irp, srbData, IO_DISK_INCREMENT);
  572. SpStartNextPacket(DeviceObject, FALSE);
  573. SpReleaseRemoveLock(DeviceObject, ScsiPortStartIo);
  574. return;
  575. }
  576. //
  577. // Check to see if there's a reason this shouldn't have made it into the
  578. // startio routine. if there is then requeue the request. This is a
  579. // stopgap measure to fix some cases where the miniport entices scsiport
  580. // into inserting multiple requests for a logical unit into the adapter
  581. // queue at one time.
  582. //
  583. // The one exception to this case is with bypass requests since there
  584. // may be a request pending for a power-up or queue-thaw condition. In
  585. // these cases we will let the command run.
  586. //
  587. // We can do a check for LU_PENDING_LU_REQUEST synchronously since the
  588. // only routines which set it are part of the startio process. If we
  589. // think it's set then we need to acquire the port spinlock and verify
  590. //
  591. if(TEST_FLAG(logicalUnit->LuFlags, LU_PENDING_LU_REQUEST)) {
  592. KeAcquireSpinLockAtDpcLevel(&(deviceExtension->SpinLock));
  593. if(TEST_FLAG(logicalUnit->LuFlags, LU_PENDING_LU_REQUEST) &&
  594. !SpSrbIsBypassRequest(srb, logicalUnit->LuFlags)) {
  595. BOOLEAN t;
  596. //
  597. // Since there's an outstanding command the queue should be
  598. // busy. However we've found that there are some times where it
  599. // isn't (with adapters which ask for more requests before
  600. // dispatching the ones they have). Here if it's not busy we
  601. // can force the request in anyway since we know that something
  602. // is still outstanding and thus will take the next request out
  603. // of the queue.
  604. //
  605. t = KeInsertByKeyDeviceQueue(
  606. &logicalUnit->DeviceObject->DeviceQueue,
  607. &Irp->Tail.Overlay.DeviceQueueEntry,
  608. srb->QueueSortKey);
  609. if(t == FALSE) {
  610. KeInsertByKeyDeviceQueue(
  611. &logicalUnit->DeviceObject->DeviceQueue,
  612. &Irp->Tail.Overlay.DeviceQueueEntry,
  613. srb->QueueSortKey);
  614. }
  615. //
  616. // Now set the lun's current key to the value we just inserted
  617. // so that it's the next one to get pulled out.
  618. //
  619. logicalUnit->CurrentKey = srb->QueueSortKey;
  620. KeReleaseSpinLockFromDpcLevel(&(deviceExtension->SpinLock));
  621. IoStartNextPacket(deviceExtension->DeviceObject, FALSE);
  622. return;
  623. }
  624. //
  625. // False alarm.
  626. //
  627. KeReleaseSpinLockFromDpcLevel(&(deviceExtension->SpinLock));
  628. }
  629. //
  630. // Set the default flags in the SRB.
  631. //
  632. srb->SrbFlags |= deviceExtension->CommonExtension.SrbFlags;
  633. //
  634. // If we're not in a valid power state for the request then block the
  635. // i/o and request that PO put us in such a state.
  636. //
  637. status = SpRequestValidPowerState(deviceExtension, logicalUnit, srb);
  638. if(status == STATUS_PENDING) {
  639. SpStartNextPacket(DeviceObject, FALSE);
  640. return;
  641. }
  642. if(srb->SrbFlags & SRB_FLAGS_BYPASS_LOCKED_QUEUE) {
  643. DebugPrint((1, "ScsiPortStartIo: Handling power bypass IRP %#p\n",
  644. Irp));
  645. }
  646. ASSERT(Irp == DeviceObject->CurrentIrp);
  647. if (deviceExtension->AllocateSrbExtension ||
  648. deviceExtension->SupportsMultipleRequests) {
  649. BOOLEAN StartNextPacket = FALSE;
  650. //
  651. // Allocate the special extensions or SRB data structure.
  652. // If NULL is returned then this request cannot be excuted at this
  653. // time so just return. This occurs when one the the data structures
  654. // could not be allocated or when unqueued request could not be
  655. // started because of actived queued requests.
  656. //
  657. //
  658. if(SpAllocateSrbExtension(deviceExtension,
  659. logicalUnit,
  660. srb,
  661. &StartNextPacket,
  662. &taggedRequest) == FALSE) {
  663. //
  664. // If the request could not be started on the logical unit,
  665. // then call SpStartNextPacket. Note that this may cause this
  666. // to be entered recursively; however, no resources have been
  667. // allocated, it is a tail recursion and the depth is limited by
  668. // the number of requests in the device queue.
  669. //
  670. if (StartNextPacket == TRUE) {
  671. SpStartNextPacket(DeviceObject, FALSE);
  672. }
  673. return;
  674. }
  675. } else {
  676. //
  677. // No special resources are required.
  678. //
  679. taggedRequest = FALSE;
  680. srb->SrbExtension = NULL;
  681. }
  682. //
  683. // Assign a queuetag to the srb
  684. //
  685. if (taggedRequest == TRUE) {
  686. //
  687. // If we get an SRB with an invalid QueueAction, fix it up here
  688. // to prevent problems.
  689. //
  690. if (!(srb->QueueAction == SRB_SIMPLE_TAG_REQUEST ||
  691. srb->QueueAction == SRB_HEAD_OF_QUEUE_TAG_REQUEST ||
  692. srb->QueueAction == SRB_ORDERED_QUEUE_TAG_REQUEST)) {
  693. DebugPrint((1,"ScsiPortStartIo: Invalid QueueAction (%02x) "
  694. "SRB:%p irp:%p\n", srb->QueueAction, srb, Irp));
  695. srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
  696. }
  697. srb->QueueTag = (UCHAR)srbData->QueueTag;
  698. } else {
  699. srb->QueueTag = SP_UNTAGGED;
  700. }
  701. //
  702. // Save the original SRB values away so that we can restore them
  703. // later if it becomes necessary to retry the request.
  704. //
  705. srbData->OriginalDataTransferLength = srb->DataTransferLength;
  706. //
  707. // Update the sequence number for this request if there is not already one
  708. // assigned.
  709. //
  710. if (!srbData->SequenceNumber) {
  711. //
  712. // Assign a sequence number to the request and store it in the logical
  713. // unit.
  714. //
  715. srbData->SequenceNumber = deviceExtension->SequenceNumber++;
  716. }
  717. //
  718. // If this is not an ABORT request the set the current srb.
  719. // NOTE: Lock should be held here!
  720. //
  721. if (srb->Function == SRB_FUNCTION_ABORT_COMMAND) {
  722. //
  723. // Only abort requests can be started when there is a current request
  724. // active.
  725. //
  726. ASSERT(logicalUnit->AbortSrb == NULL);
  727. logicalUnit->AbortSrb = srb;
  728. } else if((srb->Function == SRB_FUNCTION_LOCK_QUEUE) ||
  729. (srb->Function == SRB_FUNCTION_UNLOCK_QUEUE)) {
  730. BOOLEAN lock = (srb->Function == SRB_FUNCTION_LOCK_QUEUE);
  731. ULONG lockCount;
  732. //
  733. // Process power requests
  734. //
  735. DebugPrint((1, "ScsiPortStartIo: Power %s request %#p in "
  736. "start-io routine\n",
  737. lock ? "lock" : "unlock",
  738. Irp));
  739. KeAcquireSpinLockAtDpcLevel(&deviceExtension->SpinLock);
  740. if(lock) {
  741. lockCount = InterlockedIncrement(&(logicalUnit->QueueLockCount));
  742. SET_FLAG(logicalUnit->LuFlags, LU_QUEUE_LOCKED);
  743. } else {
  744. if(TEST_FLAG(logicalUnit->LuFlags, LU_QUEUE_LOCKED)) {
  745. ASSERT(logicalUnit->QueueLockCount != 0);
  746. lockCount = InterlockedDecrement(&(logicalUnit->QueueLockCount));
  747. if(lockCount == 0) {
  748. CLEAR_FLAG(logicalUnit->LuFlags, LU_QUEUE_LOCKED);
  749. }
  750. }
  751. }
  752. KeReleaseSpinLockFromDpcLevel(&deviceExtension->SpinLock);
  753. Irp->IoStatus.Status = STATUS_SUCCESS;
  754. srb->SrbStatus = SRB_STATUS_SUCCESS;
  755. }
  756. //
  757. // Flush the data buffer if necessary.
  758. //
  759. if (srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) {
  760. //
  761. // Save the current data buffer away in the srb data. We will always
  762. // restore it afterwards - partially because the miniport might change
  763. // it and partially because scsiport might. The tape drivers appear
  764. // to expect the same data buffer pointer back.
  765. //
  766. srbData->OriginalDataBuffer = srb->DataBuffer;
  767. //
  768. // Assuming that srb's data buffer uses the mdl's VA as a base address,
  769. // calculate the offset from the base. This offset will be used to
  770. // calculate VAs from derived system addresses.
  771. //
  772. srbData->DataOffset =
  773. (ULONG_PTR) ((ULONG_PTR) srb->DataBuffer -
  774. (ULONG_PTR) MmGetMdlVirtualAddress(Irp->MdlAddress));
  775. if (deviceExtension->DmaAdapterObject) {
  776. BOOLEAN dataIn;
  777. //
  778. // If the buffer is not mapped then the I/O buffer must be flushed.
  779. //
  780. dataIn = (srb->SrbFlags & SRB_FLAGS_DATA_IN) ? TRUE : FALSE;
  781. KeFlushIoBuffers(Irp->MdlAddress, dataIn, TRUE);
  782. }
  783. //
  784. // Determine if this adapter needs map registers
  785. //
  786. if (deviceExtension->MasterWithAdapter) {
  787. //
  788. // Calculate the number of map registers needed for this transfer.
  789. //
  790. srbData->NumberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(
  791. srb->DataBuffer,
  792. srb->DataTransferLength
  793. );
  794. ASSERT(srb->DataTransferLength != 0);
  795. //
  796. // Allocate the adapter channel with sufficient map registers
  797. // for the transfer.
  798. //
  799. #ifdef USE_DMA_MACROS
  800. status = GetScatterGatherList(
  801. deviceExtension->DmaAdapterObject,
  802. deviceExtension->DeviceObject,
  803. Irp->MdlAddress,
  804. srb->DataBuffer,
  805. srb->DataTransferLength,
  806. SpReceiveScatterGather,
  807. srbData,
  808. (BOOLEAN) (srb->SrbFlags & SRB_FLAGS_DATA_OUT ? TRUE : FALSE) );
  809. #else
  810. status = AllocateAdapterChannel(
  811. deviceExtension->DmaAdapterObject,
  812. deviceExtension->DeviceObject,
  813. srbData->NumberOfMapRegisters,
  814. SpBuildScatterGather,
  815. srbData);
  816. #endif
  817. if (!NT_SUCCESS(status)) {
  818. DebugPrint((1, "ScsiPortStartIo: IoAllocateAdapterChannel "
  819. "failed(%x)\n",
  820. status));
  821. srb->SrbStatus = SRB_STATUS_INTERNAL_ERROR;
  822. srb->ScsiStatus = 0xff;
  823. srbData->InternalStatus = status;
  824. goto ScsiPortStartIoFailedRequest;
  825. }
  826. //
  827. // The execution routine called by IoAllocateChannel will do the
  828. // rest of the work so just return.
  829. //
  830. return;
  831. } else if ((deviceExtension->MapBuffers == TRUE) ||
  832. (IS_MAPPED_SRB(srb) == TRUE)) {
  833. //
  834. // Determine if the adapter needs mapped memory.
  835. //
  836. if (Irp->MdlAddress) {
  837. PVOID systemAddress;
  838. //
  839. // Get the mapped system address and calculate offset into MDL.
  840. // At the moment don't allow KernelMode requests to fail since
  841. // not all scsiport's internally sent requests are correctly
  842. // marked as coming from non-paged pool.
  843. //
  844. systemAddress = SpGetSystemAddressForMdlSafe(
  845. Irp->MdlAddress,
  846. ((Irp->RequestorMode == KernelMode) ?
  847. HighPagePriority :
  848. NormalPagePriority));
  849. #if defined(FORWARD_PROGRESS)
  850. if (systemAddress == NULL && deviceExtension->ReservedPages != NULL) {
  851. //
  852. // The system could not map the pages necessary to complete this
  853. // request. We need to ensure forward progress, so we'll try to
  854. // use the reserve pages we allocated at initialization time.
  855. //
  856. KeAcquireSpinLockAtDpcLevel(&deviceExtension->SpinLock);
  857. systemAddress = SpMapLockedPagesWithReservedMapping(
  858. deviceExtension,
  859. srb,
  860. srbData,
  861. Irp->MdlAddress);
  862. if (systemAddress == (PVOID)-1) {
  863. DebugPrint((1, "ScsiPortStartIo: reserved pages in use - pending DevExt:%p srb:%p\n",
  864. deviceExtension, srb));
  865. //
  866. // The spare pages are already in use. At this point, this
  867. // request is still the current IRP on the adapter device
  868. // object, so let's pend it until the spare comes available.
  869. //
  870. ASSERT(Irp == DeviceObject->CurrentIrp);
  871. SET_FLAG(deviceExtension->Flags, PD_PENDING_DEVICE_REQUEST);
  872. //
  873. // If we allocated an SRB extension for this request, free
  874. // it now. I do this because when the request gets restarted
  875. // we'll try to allocate the SRB extension again and without
  876. // adding more state, there isn't a safe way to check if the
  877. // extension has already been allocated. Besides, it makes
  878. // sense to make the extension available for some other
  879. // request since it also is a limited resource.
  880. //
  881. if (srb->SrbExtension != NULL) {
  882. SpFreeSrbExtension(deviceExtension, srb->SrbExtension);
  883. }
  884. KeReleaseSpinLockFromDpcLevel(&deviceExtension->SpinLock);
  885. return;
  886. }
  887. KeReleaseSpinLockFromDpcLevel(&deviceExtension->SpinLock);
  888. }
  889. #endif
  890. if(systemAddress != NULL) {
  891. //
  892. // Since we mapped the original MDL rather we have to
  893. // compensate for the data buffer offset.
  894. //
  895. srb->DataBuffer =
  896. (PVOID) ((ULONG_PTR) systemAddress +
  897. (ULONG_PTR) srbData->DataOffset);
  898. } else {
  899. DebugPrint((1, "ScsiPortStartIo: Couldn't get system "
  900. "VA for irp %#08p\n", Irp));
  901. srb->SrbStatus = SRB_STATUS_INTERNAL_ERROR;
  902. srb->ScsiStatus = 0xff;
  903. srbData->InternalStatus = STATUS_INSUFFICIENT_RESOURCES;
  904. goto ScsiPortStartIoFailedRequest;
  905. }
  906. }
  907. }
  908. }
  909. //
  910. // Increment the active request count. If the is zero,
  911. // the adapter object needs to be allocated.
  912. // Note that at this point a slave device is assumed since master with
  913. // adapter has already been checked.
  914. //
  915. interlockResult =
  916. InterlockedIncrement(&deviceExtension->ActiveRequestCount);
  917. if (interlockResult == 0 &&
  918. srb->SrbStatus == SRB_STATUS_PENDING &&
  919. !deviceExtension->MasterWithAdapter &&
  920. deviceExtension->DmaAdapterObject != NULL) {
  921. //
  922. // Allocate the AdapterObject. The number of registers is equal to the
  923. // maximum transfer length supported by the adapter + 1. This insures
  924. // that there will always be a sufficient number of registers.
  925. //
  926. AllocateAdapterChannel(
  927. deviceExtension->DmaAdapterObject,
  928. DeviceObject,
  929. deviceExtension->Capabilities.MaximumPhysicalPages,
  930. ScsiPortAllocationRoutine,
  931. logicalUnit
  932. );
  933. //
  934. // The execution routine called by IoAllocateChannel will do the
  935. // rest of the work so just return.
  936. //
  937. return;
  938. }
  939. ScsiPortStartIoFailedRequest:
  940. //
  941. // Acquire the spinlock to protect the various structures.
  942. // SpStartIoSynchronized must be called with the spinlock held.
  943. //
  944. KeAcquireSpinLockAtDpcLevel(&deviceExtension->SpinLock);
  945. deviceExtension->SynchronizeExecution(
  946. deviceExtension->InterruptObject,
  947. SpStartIoSynchronized,
  948. DeviceObject
  949. );
  950. KeReleaseSpinLockFromDpcLevel(&deviceExtension->SpinLock);
  951. return;
  952. } // end ScsiPortStartIO()
  953. BOOLEAN
  954. ScsiPortInterrupt(
  955. IN PKINTERRUPT Interrupt,
  956. IN PDEVICE_OBJECT DeviceObject
  957. )
  958. /*++
  959. Routine Description:
  960. Arguments:
  961. Interrupt
  962. Device Object
  963. Return Value:
  964. Returns TRUE if interrupt expected.
  965. --*/
  966. {
  967. PADAPTER_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  968. PINTERRUPT_DATA interruptData = &(deviceExtension->InterruptData);
  969. BOOLEAN returnValue;
  970. UNREFERENCED_PARAMETER(Interrupt);
  971. //
  972. // If interrupts have been disabled then this should not be our interrupt,
  973. // so just return.
  974. //
  975. if (TEST_FLAG(interruptData->InterruptFlags,
  976. (PD_DISABLE_INTERRUPTS | PD_ADAPTER_REMOVED))) {
  977. #if DGB
  978. static int interruptCount;
  979. interruptCount++;
  980. ASSERT(interruptCount < 1000);
  981. #endif
  982. return(FALSE);
  983. }
  984. returnValue =
  985. deviceExtension->HwInterrupt(deviceExtension->HwDeviceExtension);
  986. if(returnValue) {
  987. deviceExtension->WatchdogInterruptCount = 1;
  988. }
  989. //
  990. // Check to see if a DPC needs to be queued.
  991. //
  992. if (TEST_FLAG(interruptData->InterruptFlags, PD_NOTIFICATION_REQUIRED)) {
  993. SpRequestCompletionDpc(DeviceObject);
  994. }
  995. return(returnValue);
  996. } // end ScsiPortInterrupt()
  997. VOID
  998. ScsiPortCompletionDpc(
  999. IN PKDPC Dpc,
  1000. IN PDEVICE_OBJECT DeviceObject,
  1001. IN PIRP Irp,
  1002. IN PVOID Context
  1003. )
  1004. /*++
  1005. Routine Description:
  1006. Arguments:
  1007. Dpc
  1008. DeviceObject
  1009. Irp - not used
  1010. Context - not used
  1011. Return Value:
  1012. None.
  1013. --*/
  1014. {
  1015. PADAPTER_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1016. INTERRUPT_CONTEXT interruptContext;
  1017. INTERRUPT_DATA savedInterruptData;
  1018. BOOLEAN callStartIo;
  1019. PLOGICAL_UNIT_EXTENSION logicalUnit;
  1020. PSRB_DATA srbData;
  1021. LONG interlockResult;
  1022. LARGE_INTEGER timeValue;
  1023. UNREFERENCED_PARAMETER(Dpc);
  1024. UNREFERENCED_PARAMETER(Context);
  1025. do {
  1026. //
  1027. // Acquire the spinlock to protect flush adapter buffers
  1028. // information.
  1029. //
  1030. KeAcquireSpinLockAtDpcLevel(&deviceExtension->SpinLock);
  1031. //
  1032. // Get the interrupt state. This copies the interrupt
  1033. // state to the saved state where it can be processed.
  1034. // It also clears the interrupt flags.
  1035. //
  1036. interruptContext.DeviceExtension = deviceExtension;
  1037. interruptContext.SavedInterruptData = &savedInterruptData;
  1038. if (!deviceExtension->SynchronizeExecution(
  1039. deviceExtension->InterruptObject,
  1040. SpGetInterruptState,
  1041. &interruptContext)) {
  1042. KeReleaseSpinLockFromDpcLevel(
  1043. &deviceExtension->SpinLock);
  1044. //
  1045. // There wasn't anything to do that time. Test the
  1046. // DPC flags and try again
  1047. //
  1048. continue;
  1049. }
  1050. if(savedInterruptData.InterruptFlags &
  1051. (PD_FLUSH_ADAPTER_BUFFERS |
  1052. PD_MAP_TRANSFER |
  1053. PD_TIMER_CALL_REQUEST |
  1054. PD_WMI_REQUEST |
  1055. PD_BUS_CHANGE_DETECTED |
  1056. PD_INTERRUPT_FAILURE)) {
  1057. //
  1058. // Check for a flush DMA adapter object request.
  1059. //
  1060. if (savedInterruptData.InterruptFlags &
  1061. PD_FLUSH_ADAPTER_BUFFERS) {
  1062. if(Sp64BitPhysicalAddresses) {
  1063. KeBugCheckEx(PORT_DRIVER_INTERNAL,
  1064. 3,
  1065. STATUS_NOT_SUPPORTED,
  1066. (ULONG_PTR) deviceExtension->HwDeviceExtension,
  1067. (ULONG_PTR) deviceExtension->DeviceObject->DriverObject);
  1068. }
  1069. //
  1070. // Call IoFlushAdapterBuffers using the parameters
  1071. // saved from the last IoMapTransfer call.
  1072. //
  1073. FlushAdapterBuffers(
  1074. deviceExtension->DmaAdapterObject,
  1075. deviceExtension->FlushAdapterParameters.SrbData->CurrentIrp->MdlAddress,
  1076. deviceExtension->MapRegisterBase,
  1077. deviceExtension->FlushAdapterParameters.LogicalAddress,
  1078. deviceExtension->FlushAdapterParameters.Length,
  1079. (BOOLEAN)(deviceExtension->FlushAdapterParameters.SrbFlags
  1080. & SRB_FLAGS_DATA_OUT ? TRUE : FALSE));
  1081. }
  1082. //
  1083. // Check for an IoMapTransfer DMA request. Don't do
  1084. // anything if the adapter's been removed in the time
  1085. // since it requested this service.
  1086. //
  1087. if (TEST_FLAG(savedInterruptData.InterruptFlags, PD_MAP_TRANSFER) &&
  1088. !TEST_FLAG(savedInterruptData.InterruptFlags, PD_ADAPTER_REMOVED)) {
  1089. PADAPTER_TRANSFER mapTransfer;
  1090. ULONG_PTR address;
  1091. PMDL mdl;
  1092. if(Sp64BitPhysicalAddresses) {
  1093. KeBugCheckEx(PORT_DRIVER_INTERNAL,
  1094. 4,
  1095. STATUS_NOT_SUPPORTED,
  1096. (ULONG_PTR) deviceExtension->HwDeviceExtension,
  1097. (ULONG_PTR) deviceExtension->DeviceObject->DriverObject);
  1098. }
  1099. mapTransfer = &savedInterruptData.MapTransferParameters;
  1100. srbData = mapTransfer->SrbData;
  1101. ASSERT_SRB_DATA(srbData);
  1102. mdl = srbData->CurrentIrp->MdlAddress;
  1103. //
  1104. // Adjust the logical address. This is necessary because the
  1105. // address in the srb may be a mapped system address rather
  1106. // than the virtual address for the MDL.
  1107. //
  1108. address = (ULONG_PTR) mapTransfer->LogicalAddress;
  1109. address -= (ULONG_PTR) srbData->DataOffset;
  1110. address += (ULONG_PTR) MmGetMdlVirtualAddress(mdl);
  1111. mapTransfer->LogicalAddress = (PCHAR) address;
  1112. //
  1113. // Call IoMapTransfer using the parameters saved from the
  1114. // interrupt level.
  1115. //
  1116. MapTransfer(
  1117. deviceExtension->DmaAdapterObject,
  1118. mdl,
  1119. deviceExtension->MapRegisterBase,
  1120. mapTransfer->LogicalAddress,
  1121. &mapTransfer->Length,
  1122. (BOOLEAN)(mapTransfer->SrbFlags & SRB_FLAGS_DATA_OUT ?
  1123. TRUE : FALSE));
  1124. //
  1125. // Save the paramters for IoFlushAdapterBuffers.
  1126. //
  1127. deviceExtension->FlushAdapterParameters =
  1128. savedInterruptData.MapTransferParameters;
  1129. //
  1130. // If necessary notify the miniport driver that the DMA has been
  1131. // started.
  1132. //
  1133. if (deviceExtension->HwDmaStarted) {
  1134. deviceExtension->SynchronizeExecution(
  1135. deviceExtension->InterruptObject,
  1136. (PKSYNCHRONIZE_ROUTINE) deviceExtension->HwDmaStarted,
  1137. deviceExtension->HwDeviceExtension);
  1138. }
  1139. //
  1140. // Check for miniport work requests. Note this is an unsynchonized
  1141. // test on a bit that can be set by the interrupt routine; however,
  1142. // the worst that can happen is that the completion DPC checks for work
  1143. // twice.
  1144. //
  1145. if (deviceExtension->InterruptData.InterruptFlags & PD_NOTIFICATION_REQUIRED) {
  1146. //
  1147. // Mark that there's more work to be processed so that we
  1148. // restart the DPC rather than exiting it.
  1149. //
  1150. InterlockedExchange(&(deviceExtension->DpcFlags),
  1151. (PD_DPC_RUNNING | PD_NOTIFICATION_REQUIRED));
  1152. }
  1153. }
  1154. //
  1155. // Check for timer requests.
  1156. // If the adapter is being removed then don't do anything.
  1157. //
  1158. if ((savedInterruptData.InterruptFlags & PD_TIMER_CALL_REQUEST) &&
  1159. (!TEST_FLAG(savedInterruptData.InterruptFlags, PD_ADAPTER_REMOVED))) {
  1160. //
  1161. // The miniport wants a timer request. Save the timer parameters.
  1162. //
  1163. if (SpVerifierActive(deviceExtension)) {
  1164. deviceExtension->VerifierExtension->RealHwTimerRequest =
  1165. savedInterruptData.HwTimerRequest;
  1166. deviceExtension->HwTimerRequest = SpHwTimerRequestVrfy;
  1167. } else {
  1168. deviceExtension->HwTimerRequest = savedInterruptData.HwTimerRequest;
  1169. }
  1170. //
  1171. // If the requested timer value is zero, then cancel the timer.
  1172. //
  1173. if (savedInterruptData.MiniportTimerValue == 0) {
  1174. KeCancelTimer(&deviceExtension->MiniPortTimer);
  1175. } else {
  1176. //
  1177. // We don't set the timer if we're in the process of shutting down.
  1178. //
  1179. if (!TEST_FLAG(deviceExtension->Flags, PD_SHUTDOWN_IN_PROGRESS)) {
  1180. //
  1181. // Convert the timer value from mircoseconds to a negative 100
  1182. // nanoseconds.
  1183. //
  1184. timeValue.QuadPart = Int32x32To64(
  1185. savedInterruptData.MiniportTimerValue,
  1186. -10);
  1187. //
  1188. // Set the timer.
  1189. //
  1190. KeSetTimer(&deviceExtension->MiniPortTimer,
  1191. timeValue,
  1192. &deviceExtension->MiniPortTimerDpc);
  1193. }
  1194. }
  1195. }
  1196. //
  1197. // Check for WMI requests from the miniport.
  1198. //
  1199. if (savedInterruptData.InterruptFlags & PD_WMI_REQUEST) {
  1200. SpCompletionDpcProcessWmi(
  1201. DeviceObject,
  1202. &savedInterruptData);
  1203. } // wmi request exists from miniport
  1204. if(TEST_FLAG(savedInterruptData.InterruptFlags,
  1205. PD_BUS_CHANGE_DETECTED)) {
  1206. //
  1207. // Request device enumeration.
  1208. // Force the next bus scan to happen.
  1209. //
  1210. deviceExtension->ForceNextBusScan = TRUE;
  1211. IoInvalidateDeviceRelations(deviceExtension->LowerPdo,
  1212. BusRelations);
  1213. }
  1214. if(TEST_FLAG(savedInterruptData.InterruptFlags,
  1215. PD_INTERRUPT_FAILURE)) {
  1216. SpLogInterruptFailure(deviceExtension);
  1217. }
  1218. }
  1219. //
  1220. // Verify that the ready for next request is ok.
  1221. //
  1222. if (savedInterruptData.InterruptFlags & PD_READY_FOR_NEXT_REQUEST) {
  1223. //
  1224. // If the device busy bit is not set, then this is a duplicate request.
  1225. // If a no disconnect request is executing, then don't call start I/O.
  1226. // This can occur when the miniport does a NextRequest followed by
  1227. // a NextLuRequest.
  1228. //
  1229. if ((deviceExtension->Flags & (PD_DEVICE_IS_BUSY | PD_DISCONNECT_RUNNING))
  1230. == (PD_DEVICE_IS_BUSY | PD_DISCONNECT_RUNNING)) {
  1231. //
  1232. // Clear the device busy flag. This flag is set by
  1233. // SpStartIoSynchonized.
  1234. //
  1235. deviceExtension->Flags &= ~PD_DEVICE_IS_BUSY;
  1236. if (!(savedInterruptData.InterruptFlags & PD_RESET_HOLD)) {
  1237. //
  1238. // The miniport is ready for the next request and there is
  1239. // not a pending reset hold, so clear the port timer.
  1240. //
  1241. deviceExtension->PortTimeoutCounter = PD_TIMER_STOPPED;
  1242. }
  1243. } else {
  1244. //
  1245. // If a no disconnect request is executing, then clear the
  1246. // busy flag. When the disconnect request completes an
  1247. // SpStartNextPacket will be done.
  1248. //
  1249. deviceExtension->Flags &= ~PD_DEVICE_IS_BUSY;
  1250. //
  1251. // Clear the ready for next request flag.
  1252. //
  1253. savedInterruptData.InterruptFlags &= ~PD_READY_FOR_NEXT_REQUEST;
  1254. }
  1255. }
  1256. //
  1257. // Check for any reported resets.
  1258. //
  1259. if (savedInterruptData.InterruptFlags & PD_RESET_REPORTED) {
  1260. //
  1261. // Start the hold timer.
  1262. //
  1263. deviceExtension->PortTimeoutCounter = PD_TIMER_RESET_HOLD_TIME;
  1264. }
  1265. if (savedInterruptData.ReadyLogicalUnit != NULL) {
  1266. PLOGICAL_UNIT_EXTENSION tmpLogicalUnit;
  1267. //
  1268. // Process the ready logical units.
  1269. //
  1270. for(logicalUnit = savedInterruptData.ReadyLogicalUnit;
  1271. logicalUnit != NULL;
  1272. (tmpLogicalUnit = logicalUnit,
  1273. logicalUnit = tmpLogicalUnit->ReadyLogicalUnit,
  1274. tmpLogicalUnit->ReadyLogicalUnit = NULL)) {
  1275. //
  1276. // Get the next request for this logical unit.
  1277. // Note this will release the device spin lock.
  1278. //
  1279. GetNextLuRequest(logicalUnit);
  1280. //
  1281. // Reacquire the device spinlock.
  1282. //
  1283. KeAcquireSpinLockAtDpcLevel(&deviceExtension->SpinLock);
  1284. }
  1285. }
  1286. //
  1287. // Release the spinlock.
  1288. //
  1289. KeReleaseSpinLockFromDpcLevel(&deviceExtension->SpinLock);
  1290. //
  1291. // Check for a ready for next packet.
  1292. //
  1293. if (savedInterruptData.InterruptFlags & PD_READY_FOR_NEXT_REQUEST) {
  1294. //
  1295. // Start the next request.
  1296. //
  1297. SpStartNextPacket(deviceExtension->DeviceObject, FALSE);
  1298. }
  1299. //
  1300. // Check for an error log requests.
  1301. //
  1302. if (savedInterruptData.InterruptFlags & PD_LOG_ERROR) {
  1303. //
  1304. // Process the request.
  1305. //
  1306. LogErrorEntry(deviceExtension,
  1307. &savedInterruptData.LogEntry);
  1308. }
  1309. //
  1310. // Process any completed requests. The list has already been cut free
  1311. // and the pointer is never tested except here, so there's no reason to
  1312. // waste cycles unlinking them from the list. The pointers will be
  1313. // overwritten later.
  1314. //
  1315. callStartIo = FALSE;
  1316. while (savedInterruptData.CompletedRequests != NULL) {
  1317. //
  1318. // Remove the request from the linked-list.
  1319. //
  1320. srbData = savedInterruptData.CompletedRequests;
  1321. ASSERT_SRB_DATA(srbData);
  1322. savedInterruptData.CompletedRequests = srbData->CompletedRequests;
  1323. srbData->CompletedRequests = NULL;
  1324. SpProcessCompletedRequest(deviceExtension,
  1325. srbData,
  1326. &callStartIo);
  1327. }
  1328. if(callStartIo) {
  1329. ASSERT(DeviceObject->CurrentIrp != NULL);
  1330. }
  1331. //
  1332. // Process any completed abort requests.
  1333. //
  1334. while (savedInterruptData.CompletedAbort != NULL) {
  1335. ASSERT(FALSE);
  1336. logicalUnit = savedInterruptData.CompletedAbort;
  1337. //
  1338. // Remove request from the completed abort list.
  1339. //
  1340. savedInterruptData.CompletedAbort = logicalUnit->CompletedAbort;
  1341. //
  1342. // Acquire the spinlock to protect the flags structure,
  1343. // and the free of the srb extension.
  1344. //
  1345. KeAcquireSpinLockAtDpcLevel(&deviceExtension->SpinLock);
  1346. //
  1347. // Free SrbExtension to the free list if necessary.
  1348. //
  1349. if (logicalUnit->AbortSrb->SrbExtension) {
  1350. if (SpVerifyingCommonBuffer(deviceExtension)) {
  1351. SpInsertSrbExtension(deviceExtension,
  1352. logicalUnit->AbortSrb->SrbExtension);
  1353. } else {
  1354. *((PVOID *) logicalUnit->AbortSrb->SrbExtension) =
  1355. deviceExtension->SrbExtensionListHeader;
  1356. deviceExtension->SrbExtensionListHeader =
  1357. logicalUnit->AbortSrb->SrbExtension;
  1358. }
  1359. }
  1360. //
  1361. // Note the timer which was started for the abort request is not
  1362. // stopped by the get interrupt routine. Rather the timer is stopped.
  1363. // when the aborted request completes.
  1364. //
  1365. Irp = logicalUnit->AbortSrb->OriginalRequest;
  1366. //
  1367. // Set IRP status. Class drivers will reset IRP status based
  1368. // on request sense if error.
  1369. //
  1370. if (SRB_STATUS(logicalUnit->AbortSrb->SrbStatus) == SRB_STATUS_SUCCESS) {
  1371. Irp->IoStatus.Status = STATUS_SUCCESS;
  1372. } else {
  1373. Irp->IoStatus.Status = SpTranslateScsiStatus(logicalUnit->AbortSrb);
  1374. }
  1375. Irp->IoStatus.Information = 0;
  1376. //
  1377. // Clear the abort request pointer.
  1378. //
  1379. logicalUnit->AbortSrb = NULL;
  1380. KeReleaseSpinLockFromDpcLevel(&deviceExtension->SpinLock);
  1381. //
  1382. // Decrement the number of active requests. If the count is negative,
  1383. // and this is a slave with an adapter then free the adapter object and
  1384. // map registers.
  1385. //
  1386. interlockResult = InterlockedDecrement(&deviceExtension->ActiveRequestCount);
  1387. if ( interlockResult < 0 &&
  1388. !deviceExtension->PortConfig->Master &&
  1389. deviceExtension->DmaAdapterObject != NULL ) {
  1390. //
  1391. // Clear the map register base for safety.
  1392. //
  1393. deviceExtension->MapRegisterBase = NULL;
  1394. FreeAdapterChannel(deviceExtension->DmaAdapterObject);
  1395. }
  1396. SpReleaseRemoveLock(DeviceObject, Irp);
  1397. SpCompleteRequest(DeviceObject, Irp, srbData, IO_DISK_INCREMENT);
  1398. }
  1399. //
  1400. // Call the start I/O routine if necessary.
  1401. //
  1402. if (callStartIo) {
  1403. ASSERT(DeviceObject->CurrentIrp != NULL);
  1404. ScsiPortStartIo(DeviceObject, DeviceObject->CurrentIrp);
  1405. }
  1406. //
  1407. // After all of the requested operations have been done check to see
  1408. // if an enable interrupts call request needs to be done.
  1409. //
  1410. if (TEST_FLAG(savedInterruptData.InterruptFlags, PD_ENABLE_CALL_REQUEST) &&
  1411. !TEST_FLAG(savedInterruptData.InterruptFlags, PD_ADAPTER_REMOVED)) {
  1412. //
  1413. // Acquire the spinlock so nothing else starts.
  1414. //
  1415. KeAcquireSpinLockAtDpcLevel(&deviceExtension->SpinLock);
  1416. deviceExtension->HwRequestInterrupt(deviceExtension->HwDeviceExtension);
  1417. ASSERT(deviceExtension->Flags & PD_DISABLE_CALL_REQUEST);
  1418. //
  1419. // Check to see if interrupts should be enabled again.
  1420. //
  1421. if (deviceExtension->Flags & PD_DISABLE_CALL_REQUEST) {
  1422. //
  1423. // Clear the flag.
  1424. //
  1425. deviceExtension->Flags &= ~PD_DISABLE_CALL_REQUEST;
  1426. //
  1427. // Synchronize with the interrupt routine.
  1428. //
  1429. deviceExtension->SynchronizeExecution(
  1430. deviceExtension->InterruptObject,
  1431. SpEnableInterruptSynchronized,
  1432. deviceExtension
  1433. );
  1434. }
  1435. //
  1436. // Release the spinlock.
  1437. //
  1438. KeReleaseSpinLockFromDpcLevel(&deviceExtension->SpinLock);
  1439. }
  1440. } while(((InterlockedCompareExchange(
  1441. &(deviceExtension->DpcFlags),
  1442. 0L,
  1443. PD_DPC_RUNNING)) &
  1444. PD_NOTIFICATION_REQUIRED) == PD_NOTIFICATION_REQUIRED);
  1445. return;
  1446. } // end ScsiPortCompletionDpc()
  1447. BOOLEAN
  1448. SpFakeInterrupt(
  1449. IN PDEVICE_OBJECT DeviceObject
  1450. )
  1451. {
  1452. PADAPTER_EXTENSION adapter = DeviceObject->DeviceExtension;
  1453. return ScsiPortInterrupt(adapter->InterruptObject, DeviceObject);
  1454. }
  1455. VOID
  1456. ScsiPortTickHandler(
  1457. IN PDEVICE_OBJECT DeviceObject,
  1458. IN PVOID Context
  1459. )
  1460. /*++
  1461. Routine Description:
  1462. Arguments:
  1463. Return Value:
  1464. None.
  1465. --*/
  1466. {
  1467. PADAPTER_EXTENSION deviceExtension =
  1468. (PADAPTER_EXTENSION) DeviceObject->DeviceExtension;
  1469. PLOGICAL_UNIT_EXTENSION logicalUnit;
  1470. PIRP irp;
  1471. ULONG target;
  1472. UNREFERENCED_PARAMETER(Context);
  1473. //
  1474. // Acquire the spinlock to protect the flags structure.
  1475. //
  1476. KeAcquireSpinLockAtDpcLevel(&deviceExtension->SpinLock);
  1477. //
  1478. // Increment the tick count. This is the only code which will change
  1479. // the count and we're inside a spinlock when we do it so we don't need
  1480. // an interlocked operation.
  1481. //
  1482. deviceExtension->TickCount++;
  1483. //
  1484. // Check whether we need to repopulate the WMI_REQUEST_ITEM
  1485. // free list
  1486. //
  1487. if ((deviceExtension->CommonExtension.WmiInitialized) &&
  1488. (deviceExtension->CommonExtension.WmiMiniPortSupport)) {
  1489. while (deviceExtension->WmiFreeMiniPortRequestCount <
  1490. deviceExtension->WmiFreeMiniPortRequestWatermark) {
  1491. // Add one to the free list
  1492. if (!NT_SUCCESS(
  1493. SpWmiPushFreeRequestItem(deviceExtension))) {
  1494. //
  1495. // We failed to add, most likely a memory
  1496. // problem, so just stop trying for now
  1497. //
  1498. break;
  1499. }
  1500. }
  1501. }
  1502. //
  1503. // Check for port timeouts.
  1504. //
  1505. if (deviceExtension->PortTimeoutCounter > 0) {
  1506. BOOLEAN timeout = FALSE;
  1507. if (--deviceExtension->PortTimeoutCounter == 0) {
  1508. //
  1509. // Process the port timeout.
  1510. //
  1511. if (deviceExtension->SynchronizeExecution(
  1512. deviceExtension->InterruptObject,
  1513. SpTimeoutSynchronized,
  1514. DeviceObject)){
  1515. //
  1516. // Log error if SpTimeoutSynchonized indicates this was an error
  1517. // timeout.
  1518. //
  1519. if (deviceExtension->CommonExtension.DeviceObject->CurrentIrp) {
  1520. SpLogTimeoutError(
  1521. deviceExtension,
  1522. DeviceObject->CurrentIrp,
  1523. 256);
  1524. }
  1525. }
  1526. timeout = TRUE;
  1527. }
  1528. //
  1529. // If a port timeout has been done then skip the rest of the
  1530. // processing.
  1531. //
  1532. if(timeout) {
  1533. KeReleaseSpinLockFromDpcLevel(&deviceExtension->SpinLock);
  1534. return;
  1535. }
  1536. }
  1537. //
  1538. // Scan each of the logical units. If it has an active request then
  1539. // decrement the timeout value and process a timeout if it is zero.
  1540. //
  1541. for (target = 0; target < NUMBER_LOGICAL_UNIT_BINS; target++) {
  1542. PLOGICAL_UNIT_BIN bin;
  1543. bin = &deviceExtension->LogicalUnitList[target];
  1544. RestartTimeoutLoop:
  1545. KeAcquireSpinLockAtDpcLevel(&bin->Lock);
  1546. logicalUnit = bin->List;
  1547. while (logicalUnit != NULL) {
  1548. //
  1549. // Check for busy requests.
  1550. //
  1551. if (logicalUnit->LuFlags & LU_LOGICAL_UNIT_IS_BUSY) {
  1552. //
  1553. // If a request sense is needed or the queue is
  1554. // frozen, defer processing this busy request until
  1555. // that special processing has completed. This prevents
  1556. // a random busy request from being started when a REQUEST
  1557. // SENSE needs to be sent.
  1558. //
  1559. // Exception: If the srb is flagged BYPASS_LOCKED_QUEUE, then
  1560. // go ahead and retry it
  1561. PSRB_DATA srbData;
  1562. srbData = logicalUnit->BusyRequest;
  1563. ASSERT_SRB_DATA(srbData);
  1564. if(!(logicalUnit->LuFlags & LU_NEED_REQUEST_SENSE) &&
  1565. ((!SpIsQueuePaused(logicalUnit)) ||
  1566. (TEST_FLAG(srbData->CurrentSrb->SrbFlags, SRB_FLAGS_BYPASS_LOCKED_QUEUE)))) {
  1567. DebugPrint((1,"ScsiPortTickHandler: Retrying busy status "
  1568. "request\n"));
  1569. //
  1570. // If there is a pending request, requeue it before we
  1571. // retry the busy request. Otherwise, the busy request
  1572. // will itself get requeued in ScsiPortStartIo because
  1573. // there is a pending request and if nothing else
  1574. // remains active, scsiport will stall.
  1575. //
  1576. if (logicalUnit->LuFlags & LU_PENDING_LU_REQUEST) {
  1577. BOOLEAN t;
  1578. PSRB_DATA pendingRqst;
  1579. DebugPrint((0, "ScsiPortTickHandler: Requeing pending "
  1580. "request %p before starting busy request %p\n",
  1581. logicalUnit->PendingRequest,
  1582. logicalUnit->BusyRequest->CurrentSrb));
  1583. CLEAR_FLAG(logicalUnit->LuFlags,
  1584. LU_PENDING_LU_REQUEST | LU_LOGICAL_UNIT_IS_ACTIVE);
  1585. pendingRqst = logicalUnit->PendingRequest;
  1586. logicalUnit->PendingRequest = NULL;
  1587. t = KeInsertByKeyDeviceQueue(
  1588. &logicalUnit->DeviceObject->DeviceQueue,
  1589. &pendingRqst->CurrentIrp->Tail.Overlay.DeviceQueueEntry,
  1590. pendingRqst->CurrentSrb->QueueSortKey);
  1591. if (t == FALSE) {
  1592. KeInsertByKeyDeviceQueue(
  1593. &logicalUnit->DeviceObject->DeviceQueue,
  1594. &pendingRqst->CurrentIrp->Tail.Overlay.DeviceQueueEntry,
  1595. pendingRqst->CurrentSrb->QueueSortKey);
  1596. }
  1597. }
  1598. //
  1599. // Clear the busy flag and retry the request. Release the
  1600. // spinlock while the call to IoStartPacket is made.
  1601. //
  1602. logicalUnit->LuFlags &= ~(LU_LOGICAL_UNIT_IS_BUSY |
  1603. LU_QUEUE_IS_FULL);
  1604. //
  1605. // Clear the busy request.
  1606. //
  1607. logicalUnit->BusyRequest = NULL;
  1608. KeReleaseSpinLockFromDpcLevel(&bin->Lock);
  1609. KeReleaseSpinLockFromDpcLevel(&deviceExtension->SpinLock);
  1610. srbData->TickCount = deviceExtension->TickCount;
  1611. IoStartPacket(DeviceObject,
  1612. srbData->CurrentIrp,
  1613. (PULONG)NULL,
  1614. NULL);
  1615. KeAcquireSpinLockAtDpcLevel(&deviceExtension->SpinLock);
  1616. goto RestartTimeoutLoop;
  1617. }
  1618. } else if (logicalUnit->RequestTimeoutCounter == 0) {
  1619. RESET_CONTEXT resetContext;
  1620. //
  1621. // Request timed out.
  1622. //
  1623. logicalUnit->RequestTimeoutCounter = PD_TIMER_STOPPED;
  1624. DebugPrint((1,"ScsiPortTickHandler: Request timed out lun:%p\n", logicalUnit));
  1625. resetContext.DeviceExtension = deviceExtension;
  1626. resetContext.PathId = logicalUnit->PathId;
  1627. //
  1628. // Release the bin spinlock before doing a reset. There are
  1629. // outstanding requests so the device object shouldn't go away.
  1630. //
  1631. KeReleaseSpinLockFromDpcLevel(&bin->Lock);
  1632. if (!deviceExtension->SynchronizeExecution(
  1633. deviceExtension->InterruptObject,
  1634. SpResetBusSynchronized,
  1635. &resetContext)) {
  1636. DebugPrint((1,"ScsiPortTickHandler: Reset failed\n"));
  1637. } else {
  1638. //
  1639. // Log the reset.
  1640. //
  1641. SpLogResetError(
  1642. deviceExtension,
  1643. (logicalUnit->CurrentUntaggedRequest ?
  1644. logicalUnit->CurrentUntaggedRequest->CurrentSrb :
  1645. NULL),
  1646. ('P'<<24) | 257);
  1647. }
  1648. //
  1649. // List may no longer be valid - restart running the bin.
  1650. //
  1651. goto RestartTimeoutLoop;
  1652. } else if (logicalUnit->RequestTimeoutCounter > 0) {
  1653. //
  1654. // Decrement timeout count.
  1655. //
  1656. logicalUnit->RequestTimeoutCounter--;
  1657. } else if (LU_OPERATING_IN_DEGRADED_STATE(logicalUnit->LuFlags)) {
  1658. //
  1659. // The LU is operating in a degraded performance state. Update
  1660. // state and restore to full power if conditions permit.
  1661. //
  1662. if (TEST_FLAG(logicalUnit->LuFlags, LU_PERF_MAXQDEPTH_REDUCED)) {
  1663. //
  1664. // The LU's maximum queue depth has been reduced because one
  1665. // or more requests failed with QUEUE FULL status. If the
  1666. // adapter is configured to recover from this state it's
  1667. // RemainInReducedMaxQueueState will be some value other
  1668. // than the default 0xffffffff. In this case, we increment
  1669. // the number of ticks the LU has been in this state and
  1670. // recover when we've reached the specified period.
  1671. //
  1672. if (deviceExtension->RemainInReducedMaxQueueState != 0xffffffff &&
  1673. ++logicalUnit->TicksInReducedMaxQueueDepthState >=
  1674. deviceExtension->RemainInReducedMaxQueueState) {
  1675. CLEAR_FLAG(logicalUnit->LuFlags, LU_PERF_MAXQDEPTH_REDUCED);
  1676. logicalUnit->MaxQueueDepth = 0xff;
  1677. }
  1678. }
  1679. }
  1680. logicalUnit = logicalUnit->NextLogicalUnit;
  1681. }
  1682. KeReleaseSpinLockFromDpcLevel(&bin->Lock);
  1683. }
  1684. KeReleaseSpinLockFromDpcLevel(&deviceExtension->SpinLock);
  1685. //
  1686. // Check to see if there are any requests waiting for memory to free up.
  1687. //
  1688. do {
  1689. PLIST_ENTRY entry;
  1690. PIRP request;
  1691. PSRB_DATA srbData;
  1692. BOOLEAN listIsEmpty;
  1693. //
  1694. // Grab the spinlock long enough to pull a request off the queue.
  1695. // The spinlock needs to be released when we're allocating
  1696. // memory.
  1697. //
  1698. KeAcquireSpinLockAtDpcLevel(
  1699. &deviceExtension->EmergencySrbDataSpinLock);
  1700. if(IsListEmpty(&deviceExtension->SrbDataBlockedRequests)) {
  1701. entry = NULL;
  1702. } else {
  1703. entry = RemoveHeadList(&(deviceExtension->SrbDataBlockedRequests));
  1704. }
  1705. KeReleaseSpinLockFromDpcLevel(
  1706. &deviceExtension->EmergencySrbDataSpinLock);
  1707. if(entry == NULL) {
  1708. break;
  1709. }
  1710. request = CONTAINING_RECORD(
  1711. entry,
  1712. IRP,
  1713. Tail.Overlay.DeviceQueueEntry);
  1714. ASSERT(request->Type == IO_TYPE_IRP);
  1715. //
  1716. // See if we can get an SRB_DATA for this request. This will
  1717. // requeue the request if there's still not enough free memory.
  1718. //
  1719. srbData = SpAllocateSrbData(deviceExtension,
  1720. request);
  1721. if(srbData != NULL) {
  1722. PLOGICAL_UNIT_EXTENSION luExtension;
  1723. PIO_STACK_LOCATION currentIrpStack;
  1724. PSCSI_REQUEST_BLOCK srb;
  1725. currentIrpStack = IoGetCurrentIrpStackLocation(request);
  1726. srb = currentIrpStack->Parameters.Scsi.Srb;
  1727. luExtension = currentIrpStack->DeviceObject->DeviceExtension;
  1728. ASSERT_PDO(currentIrpStack->DeviceObject);
  1729. srbData->CurrentIrp = request;
  1730. srbData->CurrentSrb = srb;
  1731. srbData->LogicalUnit = luExtension;
  1732. srb->OriginalRequest = srbData;
  1733. SpDispatchRequest(currentIrpStack->DeviceObject->DeviceExtension,
  1734. request);
  1735. #if TEST_LISTS
  1736. InterlockedIncrement64(
  1737. &deviceExtension->SrbDataServicedFromTickHandlerCount);
  1738. #endif
  1739. } else {
  1740. break;
  1741. }
  1742. } while(TRUE);
  1743. return;
  1744. } // end ScsiPortTickHandler()
  1745. NTSTATUS
  1746. ScsiPortFdoDeviceControl(
  1747. IN PDEVICE_OBJECT DeviceObject,
  1748. IN PIRP Irp
  1749. )
  1750. /*++
  1751. Routine Description:
  1752. This routine is the device control dispatcher.
  1753. Arguments:
  1754. DeviceObject
  1755. Irp
  1756. Return Value:
  1757. NTSTATUS
  1758. --*/
  1759. {
  1760. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  1761. PADAPTER_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1762. UCHAR scsiBus;
  1763. NTSTATUS status;
  1764. ULONG isRemoved;
  1765. PAGED_CODE();
  1766. isRemoved = SpAcquireRemoveLock(DeviceObject, Irp);
  1767. if(isRemoved) {
  1768. SpReleaseRemoveLock(DeviceObject, Irp);
  1769. Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
  1770. SpCompleteRequest(DeviceObject, Irp, NULL, IO_NO_INCREMENT);
  1771. return STATUS_DEVICE_DOES_NOT_EXIST;
  1772. }
  1773. //
  1774. // Set the adapter into a valid power state.
  1775. //
  1776. status = SpRequestValidAdapterPowerStateSynchronous(deviceExtension);
  1777. if(!NT_SUCCESS(status)) {
  1778. Irp->IoStatus.Status = status;
  1779. SpReleaseRemoveLock(DeviceObject, Irp);
  1780. SpCompleteRequest(DeviceObject, Irp, NULL, IO_NO_INCREMENT);
  1781. return status;
  1782. }
  1783. //
  1784. // Initialize the information field.
  1785. //
  1786. Irp->IoStatus.Information = 0;
  1787. switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
  1788. //
  1789. // Get adapter properites.
  1790. //
  1791. case IOCTL_STORAGE_QUERY_PROPERTY: {
  1792. PSTORAGE_PROPERTY_QUERY query = Irp->AssociatedIrp.SystemBuffer;
  1793. if(irpStack->Parameters.DeviceIoControl.InputBufferLength <
  1794. sizeof(STORAGE_PROPERTY_QUERY)) {
  1795. status = STATUS_INVALID_PARAMETER;
  1796. break;
  1797. }
  1798. //
  1799. // This routine will release the lock and complete the irp.
  1800. //
  1801. status = ScsiPortQueryProperty(DeviceObject, Irp);
  1802. return status;
  1803. break;
  1804. }
  1805. //
  1806. // Get adapter capabilities.
  1807. //
  1808. case IOCTL_SCSI_GET_CAPABILITIES: {
  1809. //
  1810. // If the output buffer is equal to the size of the a PVOID then just
  1811. // return a pointer to the buffer.
  1812. //
  1813. if (irpStack->Parameters.DeviceIoControl.OutputBufferLength
  1814. == sizeof(PVOID)) {
  1815. *((PVOID *)Irp->AssociatedIrp.SystemBuffer)
  1816. = &deviceExtension->Capabilities;
  1817. Irp->IoStatus.Information = sizeof(PVOID);
  1818. status = STATUS_SUCCESS;
  1819. break;
  1820. }
  1821. if (irpStack->Parameters.DeviceIoControl.OutputBufferLength
  1822. < sizeof(IO_SCSI_CAPABILITIES)) {
  1823. status = STATUS_BUFFER_TOO_SMALL;
  1824. break;
  1825. }
  1826. RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
  1827. &deviceExtension->Capabilities,
  1828. sizeof(IO_SCSI_CAPABILITIES));
  1829. Irp->IoStatus.Information = sizeof(IO_SCSI_CAPABILITIES);
  1830. status = STATUS_SUCCESS;
  1831. break;
  1832. }
  1833. case IOCTL_SCSI_PASS_THROUGH:
  1834. case IOCTL_SCSI_PASS_THROUGH_DIRECT: {
  1835. status = SpSendPassThrough(deviceExtension, Irp);
  1836. break;
  1837. }
  1838. case IOCTL_SCSI_MINIPORT: {
  1839. status = SpSendMiniPortIoctl( deviceExtension, Irp);
  1840. break;
  1841. }
  1842. case IOCTL_SCSI_GET_INQUIRY_DATA: {
  1843. //
  1844. // Return the inquiry data.
  1845. //
  1846. status = SpGetInquiryData(deviceExtension, Irp);
  1847. break;
  1848. case IOCTL_SCSI_RESCAN_BUS:
  1849. status = SpEnumerateAdapterSynchronous(deviceExtension, FALSE);
  1850. IoInvalidateDeviceRelations(deviceExtension->LowerPdo, BusRelations);
  1851. break;
  1852. }
  1853. case IOCTL_SCSI_GET_DUMP_POINTERS: {
  1854. PPORT_CONFIGURATION_INFORMATION portConfigCopy;
  1855. //
  1856. // Get parameters for crash dump driver.
  1857. //
  1858. if (Irp->RequestorMode != KernelMode) {
  1859. status = STATUS_ACCESS_DENIED;
  1860. } else if (irpStack->Parameters.DeviceIoControl.OutputBufferLength
  1861. < sizeof(DUMP_POINTERS)) {
  1862. status = STATUS_BUFFER_TOO_SMALL;
  1863. } else {
  1864. PDUMP_POINTERS dumpPointers =
  1865. (PDUMP_POINTERS)Irp->AssociatedIrp.SystemBuffer;
  1866. RtlZeroMemory (dumpPointers, sizeof(DUMP_POINTERS));
  1867. dumpPointers->AdapterObject = (PVOID)
  1868. deviceExtension->DmaAdapterObject;
  1869. dumpPointers->MappedRegisterBase =
  1870. &deviceExtension->MappedAddressList;
  1871. portConfigCopy = SpAllocatePool(
  1872. NonPagedPool,
  1873. sizeof(PORT_CONFIGURATION_INFORMATION),
  1874. SCSIPORT_TAG_PORT_CONFIG,
  1875. DeviceObject->DriverObject);
  1876. if(portConfigCopy == NULL) {
  1877. status = STATUS_INSUFFICIENT_RESOURCES;
  1878. break;
  1879. }
  1880. RtlCopyMemory(portConfigCopy,
  1881. deviceExtension->PortConfig,
  1882. sizeof(PORT_CONFIGURATION_INFORMATION));
  1883. if(deviceExtension->IsInVirtualSlot) {
  1884. portConfigCopy->SlotNumber =
  1885. deviceExtension->RealSlotNumber;
  1886. portConfigCopy->SystemIoBusNumber =
  1887. deviceExtension->RealBusNumber;
  1888. }
  1889. dumpPointers->DumpData = portConfigCopy;
  1890. dumpPointers->CommonBufferVa =
  1891. deviceExtension->SrbExtensionBuffer;
  1892. dumpPointers->CommonBufferPa =
  1893. deviceExtension->PhysicalCommonBuffer;
  1894. dumpPointers->CommonBufferSize =
  1895. SpGetCommonBufferSize(
  1896. deviceExtension,
  1897. deviceExtension->NonCachedExtensionSize,
  1898. NULL);
  1899. dumpPointers->AllocateCommonBuffers = TRUE;
  1900. status = STATUS_SUCCESS;
  1901. Irp->IoStatus.Information = sizeof(DUMP_POINTERS);
  1902. }
  1903. break;
  1904. }
  1905. case IOCTL_STORAGE_RESET_BUS:
  1906. case OBSOLETE_IOCTL_STORAGE_RESET_BUS:
  1907. case IOCTL_STORAGE_BREAK_RESERVATION: {
  1908. if(irpStack->Parameters.DeviceIoControl.InputBufferLength <
  1909. sizeof(STORAGE_BUS_RESET_REQUEST)) {
  1910. status = STATUS_INVALID_PARAMETER;
  1911. } else {
  1912. //
  1913. // Send an asynchronous srb through to ourself to handle this
  1914. // reset then return. SpSendReset will take care of completing
  1915. // the request when it's done
  1916. //
  1917. IoMarkIrpPending(Irp);
  1918. status = SpSendReset(DeviceObject, Irp);
  1919. if(!NT_SUCCESS(status)) {
  1920. DebugPrint((1, "IOCTL_STORAGE_BUS_RESET - error %#08lx "
  1921. "from SpSendReset\n",
  1922. status));
  1923. }
  1924. return STATUS_PENDING;
  1925. }
  1926. break;
  1927. }
  1928. default: {
  1929. DebugPrint((1,
  1930. "ScsiPortDeviceControl: Unsupported IOCTL (%x)\n",
  1931. irpStack->Parameters.DeviceIoControl.IoControlCode));
  1932. status = STATUS_INVALID_DEVICE_REQUEST;
  1933. break;
  1934. }
  1935. } // end switch
  1936. //
  1937. // Set status in Irp.
  1938. //
  1939. Irp->IoStatus.Status = status;
  1940. SpReleaseRemoveLock(DeviceObject, Irp);
  1941. SpCompleteRequest(DeviceObject, Irp, NULL, IO_NO_INCREMENT);
  1942. return status;
  1943. } // end ScsiPortDeviceControl()
  1944. BOOLEAN
  1945. SpStartIoSynchronized (
  1946. PVOID ServiceContext
  1947. )
  1948. /*++
  1949. Routine Description:
  1950. This routine calls the dependent driver start io routine.
  1951. It also starts the request timer for the logical unit if necesary and
  1952. inserts the SRB data structure in to the requset list.
  1953. Arguments:
  1954. ServiceContext - Supplies the pointer to the device object.
  1955. Return Value:
  1956. Returns the value returned by the dependent start I/O routine.
  1957. Notes:
  1958. The port driver spinlock must be held when this routine is called. Holding
  1959. this lock will keep any logical unit bins from being changed as well.
  1960. --*/
  1961. {
  1962. PDEVICE_OBJECT deviceObject = ServiceContext;
  1963. PADAPTER_EXTENSION deviceExtension = deviceObject->DeviceExtension;
  1964. PINTERRUPT_DATA interruptData = &(deviceExtension->InterruptData);
  1965. PIO_STACK_LOCATION irpStack;
  1966. PLOGICAL_UNIT_EXTENSION logicalUnit;
  1967. PSCSI_REQUEST_BLOCK srb;
  1968. PSRB_DATA srbData;
  1969. BOOLEAN returnValue;
  1970. DebugPrint((3, "ScsiPortStartIoSynchronized: Enter routine\n"));
  1971. irpStack = IoGetCurrentIrpStackLocation(deviceObject->CurrentIrp);
  1972. srb = irpStack->Parameters.Scsi.Srb;
  1973. srbData = srb->OriginalRequest;
  1974. ASSERT_SRB_DATA(srbData);
  1975. //
  1976. // Get the logical unit extension.
  1977. //
  1978. logicalUnit = srbData->LogicalUnit;
  1979. //
  1980. // Cache the logical unit for complete request calls.
  1981. //
  1982. deviceExtension->CachedLogicalUnit = logicalUnit;
  1983. //
  1984. // Check for a reset hold. If one is in progress then flag it and return.
  1985. // The timer will reset the current request. This check should be made
  1986. // before anything else is done.
  1987. //
  1988. if(TEST_FLAG(interruptData->InterruptFlags, PD_ADAPTER_REMOVED)) {
  1989. srb->SrbStatus = SRB_STATUS_NO_HBA;
  1990. SET_FLAG(srb->SrbFlags, SRB_FLAGS_BYPASS_LOCKED_QUEUE |
  1991. SRB_FLAGS_BYPASS_FROZEN_QUEUE);
  1992. } else if(TEST_FLAG(interruptData->InterruptFlags, PD_RESET_HOLD)) {
  1993. SET_FLAG(interruptData->InterruptFlags, PD_HELD_REQUEST);
  1994. return(TRUE);
  1995. }
  1996. //
  1997. // Set the device busy flag to indicate it is ok to start the next request.
  1998. //
  1999. deviceExtension->Flags |= PD_DEVICE_IS_BUSY;
  2000. if (srb->SrbFlags & SRB_FLAGS_DISABLE_DISCONNECT) {
  2001. //
  2002. // This request does not allow disconnects. Remember that so
  2003. // no more requests are started until this one completes.
  2004. //
  2005. deviceExtension->Flags &= ~PD_DISCONNECT_RUNNING;
  2006. }
  2007. logicalUnit->QueueCount++;
  2008. //
  2009. // Indicate that there maybe more requests queued, if this is not a bypass
  2010. // request.
  2011. //
  2012. if(!TEST_FLAG(srb->SrbFlags, SRB_FLAGS_BYPASS_FROZEN_QUEUE)) {
  2013. logicalUnit->LuFlags |= LU_LOGICAL_UNIT_IS_ACTIVE;
  2014. } else {
  2015. ASSERT(srb->Function != SRB_FUNCTION_ABORT_COMMAND);
  2016. //
  2017. // Any untagged request that bypasses the queue
  2018. // clears the need request sense flag.
  2019. //
  2020. if(SpSrbIsBypassRequest(srb, logicalUnit->LuFlags)) {
  2021. logicalUnit->LuFlags &= ~LU_NEED_REQUEST_SENSE;
  2022. }
  2023. //
  2024. // Set the timeout value in the logical unit.
  2025. //
  2026. logicalUnit->RequestTimeoutCounter = srb->TimeOutValue;
  2027. }
  2028. //
  2029. // Mark the Srb as active.
  2030. //
  2031. srb->SrbFlags |= SRB_FLAGS_IS_ACTIVE;
  2032. //
  2033. // Save away the tick count when we made this active.
  2034. //
  2035. srbData->TickCount = deviceExtension->TickCount;
  2036. //
  2037. // If this request is tagged, insert it into the logical unit
  2038. // request list. Note that bypass requsts are never never placed on
  2039. // the request list. In particular ABORT requests which may have
  2040. // a queue tag specified are not placed on the queue.
  2041. //
  2042. if (srb->QueueTag != SP_UNTAGGED) {
  2043. InsertTailList(&logicalUnit->RequestList,
  2044. &srbData->RequestList);
  2045. } else {
  2046. logicalUnit->CurrentUntaggedRequest = srbData;
  2047. }
  2048. //
  2049. // if the status in the SRB is still pending then we should go ahead and
  2050. // issue this request to to the miniport. Some error conditions and
  2051. // power requests will mark the srb as successful and then send it through
  2052. // here to clean up and start subsequent requests. If the status isn't
  2053. // pending then request completion.
  2054. //
  2055. if(srb->SrbStatus != SRB_STATUS_PENDING) {
  2056. DebugPrint((1, "SpStartIoSynchronized: Completeing successful srb "
  2057. "%#p before miniport\n", srb));
  2058. ScsiPortNotification(RequestComplete,
  2059. deviceExtension->HwDeviceExtension,
  2060. srb);
  2061. ScsiPortNotification(NextRequest,
  2062. deviceExtension->HwDeviceExtension);
  2063. returnValue = srb->SrbStatus;
  2064. } else {
  2065. //
  2066. // Start the port timer. This ensures that the miniport asks for
  2067. // the next request in a resonable amount of time.
  2068. //
  2069. deviceExtension->PortTimeoutCounter = srb->TimeOutValue;
  2070. //
  2071. // Start the logical unit timer if it is not currently running.
  2072. //
  2073. if (logicalUnit->RequestTimeoutCounter == PD_TIMER_STOPPED) {
  2074. //
  2075. // Set request timeout value from Srb SCSI extension in Irp.
  2076. //
  2077. logicalUnit->RequestTimeoutCounter = srb->TimeOutValue;
  2078. }
  2079. returnValue = deviceExtension->HwStartIo(
  2080. deviceExtension->HwDeviceExtension,
  2081. srb);
  2082. }
  2083. //
  2084. // Check for miniport work requests.
  2085. //
  2086. if (TEST_FLAG(interruptData->InterruptFlags, PD_NOTIFICATION_REQUIRED)) {
  2087. SpRequestCompletionDpc(deviceObject);
  2088. }
  2089. return returnValue;
  2090. } // end SpStartIoSynchronized()
  2091. BOOLEAN
  2092. SpTimeoutSynchronized (
  2093. PVOID ServiceContext
  2094. )
  2095. /*++
  2096. Routine Description:
  2097. This routine handles a port timeout. There are two reason these can occur
  2098. either because of a reset hold or a time out waiting for a read for next
  2099. request notification. If a reset hold completes, then any held request
  2100. must be started. If a timeout occurs, then the bus must be reset.
  2101. Arguments:
  2102. ServiceContext - Supplies the pointer to the device object.
  2103. Return Value:
  2104. TRUE - If a timeout error should be logged.
  2105. Notes:
  2106. The port driver spinlock must be held when this routine is called.
  2107. --*/
  2108. {
  2109. PDEVICE_OBJECT deviceObject = ServiceContext;
  2110. PADAPTER_EXTENSION deviceExtension = deviceObject->DeviceExtension;
  2111. PINTERRUPT_DATA interruptData = &(deviceExtension->InterruptData);
  2112. BOOLEAN result;
  2113. DebugPrint((3, "SpTimeoutSynchronized: Enter routine\n"));
  2114. //
  2115. // Make sure the timer is stopped.
  2116. //
  2117. deviceExtension->PortTimeoutCounter = PD_TIMER_STOPPED;
  2118. //
  2119. // Check for a reset hold. If one is in progress then clear it and check
  2120. // for a pending held request
  2121. //
  2122. if (TEST_FLAG(interruptData->InterruptFlags, PD_RESET_HOLD)) {
  2123. CLEAR_FLAG(interruptData->InterruptFlags, PD_RESET_HOLD);
  2124. //
  2125. // If verifier is enabled, make sure the miniport has completed all
  2126. // outstanding requests in the reset hold period.
  2127. //
  2128. if (SpVerifierActive(deviceExtension)) {
  2129. SpEnsureAllRequestsAreComplete(deviceExtension);
  2130. }
  2131. if (TEST_FLAG(interruptData->InterruptFlags, PD_HELD_REQUEST)) {
  2132. //
  2133. // Clear the held request flag and restart the request.
  2134. //
  2135. CLEAR_FLAG(interruptData->InterruptFlags, PD_HELD_REQUEST);
  2136. SpStartIoSynchronized(ServiceContext);
  2137. }
  2138. result = FALSE;
  2139. } else {
  2140. RESET_CONTEXT resetContext;
  2141. BOOLEAN interrupt;
  2142. ULONG interruptCount;
  2143. resetContext.DeviceExtension = deviceExtension;
  2144. //
  2145. // Make a call into the miniport's interrupt routine. If it says that
  2146. // there's an interrupt pending then break in.
  2147. //
  2148. ASSERT(!TEST_FLAG(interruptData->InterruptFlags,
  2149. PD_DISABLE_INTERRUPTS));
  2150. if (!TEST_FLAG(interruptData->InterruptFlags, PD_ADAPTER_REMOVED)) {
  2151. interruptCount = deviceExtension->WatchdogInterruptCount;
  2152. deviceExtension->WatchdogInterruptCount = 0;
  2153. if((interruptCount == 0) &&
  2154. (deviceExtension->HwInterrupt != NULL)) {
  2155. interrupt = deviceExtension->HwInterrupt(
  2156. deviceExtension->HwDeviceExtension);
  2157. if(interrupt) {
  2158. DbgPrint("SpTimeoutSynchronized: Adapter %#p had interrupt "
  2159. "pending - the system may not be delivering "
  2160. "interrupts from this adapter\n",
  2161. deviceObject);
  2162. if(ScsiCheckInterrupts) {
  2163. DbgBreakPoint();
  2164. }
  2165. SET_FLAG(interruptData->InterruptFlags,
  2166. PD_INTERRUPT_FAILURE | PD_NOTIFICATION_REQUIRED);
  2167. SpRequestCompletionDpc(deviceObject);
  2168. }
  2169. }
  2170. }
  2171. //
  2172. // Miniport is hung and not accepting new requests. So reset the
  2173. // bus to clear things up.
  2174. //
  2175. DebugPrint((1, "SpTimeoutSynchronized: Next request timed out. "
  2176. "Resetting bus\n"));
  2177. for(resetContext.PathId = 0;
  2178. resetContext.PathId < deviceExtension->NumberOfBuses;
  2179. resetContext.PathId++) {
  2180. result = SpResetBusSynchronized(&resetContext);
  2181. }
  2182. }
  2183. return(result);
  2184. } // end SpTimeoutSynchronized()
  2185. BOOLEAN
  2186. SpEnableInterruptSynchronized (
  2187. PVOID ServiceContext
  2188. )
  2189. /*++
  2190. Routine Description:
  2191. This routine calls the miniport request routine with interrupts disabled.
  2192. This is used by the miniport driver to enable interrupts on the adapter.
  2193. This routine clears the disable interrupt flag which prevents the
  2194. miniport interrupt routine from being called.
  2195. Arguments:
  2196. ServiceContext - Supplies the pointer to the device extension.
  2197. Return Value:
  2198. TRUE - Always.
  2199. Notes:
  2200. The port driver spinlock must be held when this routine is called.
  2201. --*/
  2202. {
  2203. PADAPTER_EXTENSION deviceExtension = ServiceContext;
  2204. PINTERRUPT_DATA interruptData = &(deviceExtension->InterruptData);
  2205. //
  2206. // Clear the interrupt disable flag.
  2207. //
  2208. CLEAR_FLAG(interruptData->InterruptFlags, PD_DISABLE_INTERRUPTS);
  2209. if(TEST_FLAG(interruptData->InterruptFlags, PD_ADAPTER_REMOVED)) {
  2210. return FALSE;
  2211. }
  2212. //
  2213. // Call the miniport routine.
  2214. //
  2215. deviceExtension->HwRequestInterrupt(deviceExtension->HwDeviceExtension);
  2216. if(TEST_FLAG(interruptData->InterruptFlags, PD_NOTIFICATION_REQUIRED)) {
  2217. SpRequestCompletionDpc(deviceExtension->CommonExtension.DeviceObject);
  2218. }
  2219. return(TRUE);
  2220. } // end SpEnableInterruptSynchronized()
  2221. VOID
  2222. IssueRequestSense(
  2223. IN PADAPTER_EXTENSION Adapter,
  2224. IN PSCSI_REQUEST_BLOCK FailingSrb
  2225. )
  2226. /*++
  2227. Routine Description:
  2228. This routine creates a REQUEST SENSE request and uses IoCallDriver to
  2229. renter the driver. The completion routine cleans up the data structures
  2230. and processes the logical unit queue according to the flags.
  2231. A pointer to failing SRB is stored at the end of the request sense
  2232. Srb, so that the completion routine can find it.
  2233. This routine must be called holding the remove lock.
  2234. Arguments:
  2235. DeviceExension - Supplies a pointer to the device extension for this
  2236. SCSI port.
  2237. FailingSrb - Supplies a pointer to the request that the request sense
  2238. is being done for.
  2239. Return Value:
  2240. None.
  2241. --*/
  2242. {
  2243. PSRB_DATA srbData;
  2244. PLOGICAL_UNIT_EXTENSION logicalUnit;
  2245. BOOLEAN blocked;
  2246. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  2247. DebugPrint((3,"IssueRequestSense: Enter routine\n"));
  2248. //
  2249. // Find the logical unit for this request and see if there's already a
  2250. // request sense in progress.
  2251. //
  2252. srbData = FailingSrb->OriginalRequest;
  2253. ASSERT_SRB_DATA(srbData);
  2254. logicalUnit = srbData->LogicalUnit;
  2255. KeAcquireSpinLockAtDpcLevel(&(logicalUnit->AdapterExtension->SpinLock));
  2256. //
  2257. // If we already have an active failed request then block this one -
  2258. // the completion routine will issue a new request sense irp when this
  2259. // one is run.
  2260. //
  2261. if(logicalUnit->ActiveFailedRequest == srbData) {
  2262. blocked = FALSE;
  2263. } else if(logicalUnit->BlockedFailedRequest == srbData) {
  2264. blocked = TRUE;
  2265. } else {
  2266. DbgPrint("Scsiport: unexpected request sense for srb %#08lx\n", FailingSrb);
  2267. ASSERT(FALSE);
  2268. }
  2269. KeReleaseSpinLockFromDpcLevel(&(logicalUnit->AdapterExtension->SpinLock));
  2270. if(blocked == FALSE) {
  2271. SpSendRequestSenseIrp(Adapter,
  2272. logicalUnit,
  2273. FailingSrb);
  2274. }
  2275. return;
  2276. } // end IssueRequestSense()
  2277. VOID
  2278. SpSendRequestSenseIrp(
  2279. IN PADAPTER_EXTENSION Adapter,
  2280. IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
  2281. IN PSCSI_REQUEST_BLOCK FailingSrb
  2282. )
  2283. /*++
  2284. Routine Description:
  2285. This routine creates a REQUEST SENSE request and uses IoCallDriver to
  2286. renter the driver. The completion routine cleans up the data structures
  2287. and processes the logical unit queue according to the flags.
  2288. This routine must be called holding the remove lock. The caller must also
  2289. ensure that no other failed request is using the preallocated resources in
  2290. the LogicalUnit extension.
  2291. Arguments:
  2292. Adapter - Supplies a pointer to the device extension for this SCSI port.
  2293. LogicalUnit - Supplies a pointer to logical unit on which the CA condition
  2294. exists. This extension contains the resources used to send
  2295. the REQUEST_SENSE irp.
  2296. FailingSrb - the request which failed. the sense info buffer, address
  2297. info and flags are pulled out of this request.
  2298. Return Value:
  2299. None.
  2300. --*/
  2301. {
  2302. PIRP irp;
  2303. PSCSI_REQUEST_BLOCK srb;
  2304. PMDL mdl;
  2305. PIO_STACK_LOCATION irpStack;
  2306. PCDB cdb;
  2307. PVOID *pointer;
  2308. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  2309. DebugPrint((3,"SpSendRequestSenseIrp: Enter routine\n"));
  2310. //
  2311. // Check if we are being asked to try to allocate a sense buffer of
  2312. // the correct size for the adapter. If the allocation fails, just
  2313. // use the one passed down to us. The driver that supplied the buffer
  2314. // is responsible for freeing the one we allocate.
  2315. //
  2316. if (FailingSrb->SrbFlags & SRB_FLAGS_PORT_DRIVER_ALLOCSENSE) {
  2317. ULONG BufferSize;
  2318. PSENSE_DATA SenseBuffer;
  2319. UCHAR SenseBufferLength;
  2320. SenseBufferLength = sizeof(SENSE_DATA)
  2321. + Adapter->AdditionalSenseBytes;
  2322. //
  2323. // Include space for the scsi port number in the buffer,
  2324. // aligned on a 4-byte boundary. In checked builds, a signature
  2325. // will precede the port number.
  2326. //
  2327. BufferSize = (SenseBufferLength + 3) & ~3;
  2328. BufferSize = SenseBufferLength + sizeof(ULONG64);
  2329. SenseBuffer = SpAllocatePool(NonPagedPoolCacheAligned,
  2330. BufferSize,
  2331. SCSIPORT_TAG_SENSE_BUFFER,
  2332. Adapter->DeviceObject->DriverObject);
  2333. if (SenseBuffer != NULL) {
  2334. PULONG PortNumber;
  2335. //
  2336. // Set a flag in the SRB to indicate that we have allocated
  2337. // a new sense buffer and that the class driver must free
  2338. // it.
  2339. //
  2340. SET_FLAG(FailingSrb->SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER);
  2341. //
  2342. // Set a flag in the SRB the indicates we are storing the
  2343. // scsi port number at the end of the sense buffer.
  2344. //
  2345. SET_FLAG(FailingSrb->SrbFlags, SRB_FLAGS_PORT_DRIVER_SENSEHASPORT);
  2346. //
  2347. // Copy the port number in the buffer.
  2348. //
  2349. PortNumber = (PULONG)((PUCHAR)SenseBuffer + SenseBufferLength);
  2350. PortNumber = (PULONG)(((ULONG_PTR)PortNumber + 3) & ~3);
  2351. *PortNumber = Adapter->PortNumber;
  2352. FailingSrb->SenseInfoBuffer = SenseBuffer;
  2353. FailingSrb->SenseInfoBufferLength = SenseBufferLength;
  2354. }
  2355. }
  2356. irp = LogicalUnit->RequestSenseIrp;
  2357. srb = &(LogicalUnit->RequestSenseSrb);
  2358. mdl = &(LogicalUnit->RequestSenseMdl);
  2359. IoInitializeIrp(irp, IoSizeOfIrp(1), 1);
  2360. MmInitializeMdl(mdl,
  2361. FailingSrb->SenseInfoBuffer,
  2362. FailingSrb->SenseInfoBufferLength);
  2363. RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
  2364. //
  2365. // The sense buffer had better be from non-pagable kernel memory.
  2366. //
  2367. MmBuildMdlForNonPagedPool(mdl);
  2368. irp->MdlAddress = mdl;
  2369. IoSetCompletionRoutine(irp,
  2370. IssueRequestSenseCompletion,
  2371. LogicalUnit,
  2372. TRUE,
  2373. TRUE,
  2374. TRUE);
  2375. irpStack = IoGetNextIrpStackLocation(irp);
  2376. irpStack->MajorFunction = IRP_MJ_SCSI;
  2377. irpStack->MinorFunction = 1;
  2378. //
  2379. // Build the REQUEST SENSE CDB.
  2380. //
  2381. srb->CdbLength = 6;
  2382. cdb = (PCDB)srb->Cdb;
  2383. cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
  2384. cdb->CDB6INQUIRY.LogicalUnitNumber = 0;
  2385. cdb->CDB6INQUIRY.Reserved1 = 0;
  2386. cdb->CDB6INQUIRY.PageCode = 0;
  2387. cdb->CDB6INQUIRY.IReserved = 0;
  2388. cdb->CDB6INQUIRY.AllocationLength = FailingSrb->SenseInfoBufferLength;
  2389. cdb->CDB6INQUIRY.Control = 0;
  2390. //
  2391. // Save SRB address in next stack for port driver.
  2392. //
  2393. irpStack->Parameters.Scsi.Srb = srb;
  2394. //
  2395. // Set up IRP Address.
  2396. //
  2397. srb->OriginalRequest = irp;
  2398. //
  2399. // Set up SCSI bus address.
  2400. //
  2401. srb->TargetId = LogicalUnit->TargetId;
  2402. srb->Lun = LogicalUnit->Lun;
  2403. srb->PathId = LogicalUnit->PathId;
  2404. srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
  2405. srb->Length = sizeof(SCSI_REQUEST_BLOCK);
  2406. //
  2407. // Set timeout value. Default is 2 seconds, but it's configurable.
  2408. //
  2409. srb->TimeOutValue = Adapter->RequestSenseTimeout;
  2410. //
  2411. // Disable auto request sense.
  2412. //
  2413. srb->SenseInfoBufferLength = 0;
  2414. //
  2415. // Sense buffer is in stack.
  2416. //
  2417. srb->SenseInfoBuffer = NULL;
  2418. //
  2419. // Set read and bypass frozen queue bits in flags.
  2420. //
  2421. //
  2422. // Set SRB flags to indicate the logical unit queue should be by
  2423. // passed and that no queue processing should be done when the request
  2424. // completes. Also disable disconnect and synchronous data
  2425. // transfer if necessary.
  2426. //
  2427. srb->SrbFlags = SRB_FLAGS_DATA_IN |
  2428. SRB_FLAGS_BYPASS_FROZEN_QUEUE |
  2429. SRB_FLAGS_DISABLE_DISCONNECT;
  2430. if(TEST_FLAG(FailingSrb->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE)) {
  2431. SET_FLAG(srb->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
  2432. }
  2433. if (TEST_FLAG(FailingSrb->SrbFlags, SRB_FLAGS_BYPASS_LOCKED_QUEUE)) {
  2434. SET_FLAG(srb->SrbFlags, SRB_FLAGS_BYPASS_LOCKED_QUEUE);
  2435. }
  2436. if (TEST_FLAG(FailingSrb->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER)) {
  2437. SET_FLAG(srb->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
  2438. }
  2439. srb->DataBuffer = FailingSrb->SenseInfoBuffer;
  2440. //
  2441. // Set the transfer length.
  2442. //
  2443. srb->DataTransferLength = FailingSrb->SenseInfoBufferLength;
  2444. //
  2445. // Zero out status.
  2446. //
  2447. srb->ScsiStatus = srb->SrbStatus = 0;
  2448. srb->NextSrb = 0;
  2449. IoCallDriver(LogicalUnit->DeviceObject, irp);
  2450. return;
  2451. } // end SpSendRequestSenseIrp()
  2452. NTSTATUS
  2453. IssueRequestSenseCompletion(
  2454. PDEVICE_OBJECT DeviceObject,
  2455. PIRP Irp,
  2456. PLOGICAL_UNIT_EXTENSION LogicalUnit
  2457. )
  2458. /*++
  2459. Routine Description:
  2460. Arguments:
  2461. Device object
  2462. IRP
  2463. Context - pointer to SRB
  2464. Return Value:
  2465. NTSTATUS
  2466. --*/
  2467. {
  2468. PSCSI_REQUEST_BLOCK srb = &(LogicalUnit->RequestSenseSrb);
  2469. PSRB_DATA failingSrbData = LogicalUnit->ActiveFailedRequest;
  2470. PSCSI_REQUEST_BLOCK failingSrb;
  2471. PIRP failingIrp;
  2472. PDEVICE_OBJECT deviceObject;
  2473. KIRQL oldIrql;
  2474. BOOLEAN needRequestSense;
  2475. UNREFERENCED_PARAMETER(DeviceObject);
  2476. DebugPrint((3,"IssueRequestSenseCompletion: Enter routine\n"));
  2477. //
  2478. // Request sense completed. If successful or data over/underrun
  2479. // get the failing SRB and indicate that the sense information
  2480. // is valid. The class driver will check for underrun and determine
  2481. // if there is enough sense information to be useful.
  2482. //
  2483. //
  2484. // Get a pointer to failing Irp and Srb.
  2485. //
  2486. ASSERT_SRB_DATA(failingSrbData);
  2487. failingSrb = failingSrbData->CurrentSrb;
  2488. failingIrp = failingSrbData->CurrentIrp;
  2489. deviceObject = LogicalUnit->AdapterExtension->DeviceObject;
  2490. if(failingIrp->PendingReturned) {
  2491. IoMarkIrpPending(failingIrp);
  2492. }
  2493. ASSERT(Irp->IoStatus.Status != STATUS_INSUFFICIENT_RESOURCES);
  2494. if ((SRB_STATUS(srb->SrbStatus) == SRB_STATUS_SUCCESS) ||
  2495. (SRB_STATUS(srb->SrbStatus) == SRB_STATUS_DATA_OVERRUN)) {
  2496. //
  2497. // Report sense buffer is valid.
  2498. //
  2499. failingSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
  2500. //
  2501. // Copy bytes transferred to failing SRB
  2502. // request sense length field to communicate
  2503. // to the class drivers the number of valid
  2504. // sense bytes.
  2505. //
  2506. failingSrb->SenseInfoBufferLength = (UCHAR) srb->DataTransferLength;
  2507. //
  2508. // If WMI Sense Data events are enabled for this adapter, fire
  2509. // the event.
  2510. //
  2511. if (LogicalUnit->AdapterExtension->EnableSenseDataEvent) {
  2512. NTSTATUS status;
  2513. status = SpFireSenseDataEvent(failingSrb, deviceObject);
  2514. if (status != STATUS_SUCCESS) {
  2515. DebugPrint((1, "Failed to send SenseData WMI event (%08X)\n", status));
  2516. }
  2517. }
  2518. }
  2519. //
  2520. // If the failing SRB had the no queue freeze flag set then unfreeze the
  2521. // queue.
  2522. //
  2523. if(TEST_FLAG(failingSrb->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE) &&
  2524. TEST_FLAG(failingSrb->SrbStatus, SRB_STATUS_QUEUE_FROZEN)) {
  2525. //
  2526. // Now release the queue.
  2527. //
  2528. SpFlushReleaseQueue(LogicalUnit, FALSE);
  2529. CLEAR_FLAG(failingSrb->SrbStatus, SRB_STATUS_QUEUE_FROZEN);
  2530. }
  2531. //
  2532. // Clear the active request. Promote the blocked request (if any) and
  2533. // send out a new request sense if necessary.
  2534. //
  2535. KeAcquireSpinLock(&(LogicalUnit->AdapterExtension->SpinLock), &oldIrql);
  2536. LogicalUnit->ActiveFailedRequest = LogicalUnit->BlockedFailedRequest;
  2537. LogicalUnit->BlockedFailedRequest = NULL;
  2538. needRequestSense = (LogicalUnit->ActiveFailedRequest != NULL);
  2539. KeReleaseSpinLock(&(LogicalUnit->AdapterExtension->SpinLock), oldIrql);
  2540. //
  2541. // Complete the failing request.
  2542. //
  2543. SpReleaseRemoveLock(deviceObject, failingIrp);
  2544. SpCompleteRequest(deviceObject,
  2545. failingIrp,
  2546. failingSrbData,
  2547. IO_DISK_INCREMENT);
  2548. //
  2549. // Reinitialize all the data structures.
  2550. //
  2551. MmPrepareMdlForReuse(&(LogicalUnit->RequestSenseMdl));
  2552. //
  2553. // Since we promoted the blocked request up we can test the active
  2554. // request pointer without holding the spinlock. Once that's been written
  2555. // in there no one can modify it unless they're completing a request
  2556. // sense irp and we've got the only one right here.
  2557. //
  2558. if(needRequestSense) {
  2559. SpSendRequestSenseIrp(LogicalUnit->AdapterExtension,
  2560. LogicalUnit,
  2561. LogicalUnit->ActiveFailedRequest->CurrentSrb);
  2562. }
  2563. return STATUS_MORE_PROCESSING_REQUIRED;
  2564. } // ScsiPortInternalCompletion()
  2565. #if DBG
  2566. VOID
  2567. SpDetectCycleInCompletedRequestList(
  2568. IN PINTERRUPT_CONTEXT InterruptContext
  2569. )
  2570. {
  2571. PSRB_DATA s1, s2;
  2572. DebugPrint((0, "SpDetectCycleInCompletedRequestList: context %p\n",
  2573. InterruptContext));
  2574. //
  2575. // Initialize two pointers to the head of the list.
  2576. //
  2577. s1 = s2 = InterruptContext->SavedInterruptData->CompletedRequests;
  2578. //
  2579. // We know the list is not empty so there is no need to check for that
  2580. // case. The scan will end when either the end of the list is found or
  2581. // both pointers point to the same item.
  2582. //
  2583. for (;;) {
  2584. //
  2585. // Update the pointers.
  2586. //
  2587. s1 = s1->CompletedRequests;
  2588. s2 = s2->CompletedRequests;
  2589. if (s2 != NULL) {
  2590. s2 = s2->CompletedRequests;
  2591. }
  2592. //
  2593. // If we've found the end of the list, we're done.
  2594. //
  2595. if (s2 == NULL) {
  2596. break;
  2597. }
  2598. //
  2599. // If both pointers point to the same item, we've found a cycle.
  2600. //
  2601. if (s1 == s2) {
  2602. KeBugCheckEx(PORT_DRIVER_INTERNAL,
  2603. 5,
  2604. STATUS_INTERNAL_ERROR,
  2605. (ULONG_PTR) InterruptContext,
  2606. (ULONG_PTR) 0);
  2607. }
  2608. }
  2609. }
  2610. #endif
  2611. BOOLEAN
  2612. SpGetInterruptState(
  2613. IN PVOID ServiceContext
  2614. )
  2615. /*++
  2616. Routine Description:
  2617. This routine saves the InterruptFlags, MapTransferParameters and
  2618. CompletedRequests fields and clears the InterruptFlags.
  2619. This routine also removes the request from the logical unit queue if it is
  2620. tag. Finally the request time is updated.
  2621. Arguments:
  2622. ServiceContext - Supplies a pointer to the interrupt context which contains
  2623. pointers to the interrupt data and where to save it.
  2624. Return Value:
  2625. Returns TURE if there is new work and FALSE otherwise.
  2626. Notes:
  2627. Called via KeSynchronizeExecution with the port device extension spinlock
  2628. held.
  2629. --*/
  2630. {
  2631. PINTERRUPT_CONTEXT interruptContext = ServiceContext;
  2632. ULONG limit = 0;
  2633. PADAPTER_EXTENSION deviceExtension;
  2634. PLOGICAL_UNIT_EXTENSION logicalUnit;
  2635. PSCSI_REQUEST_BLOCK srb;
  2636. PSRB_DATA srbData;
  2637. PSRB_DATA nextSrbData;
  2638. BOOLEAN isTimed;
  2639. deviceExtension = interruptContext->DeviceExtension;
  2640. //
  2641. // Check for pending work.
  2642. //
  2643. if (!(deviceExtension->InterruptData.InterruptFlags & PD_NOTIFICATION_REQUIRED)) {
  2644. //
  2645. // We scheduled a DPC (turned on the PD_NOTIFICATION_REQUIRED bit in
  2646. // the adapter extension's DpcFlags) while the DPC routine was
  2647. // running. Clear the bit before returning to prevent the completion
  2648. // DPC routine from spinning forever. The only bit we leave set is
  2649. // PD_DPC_RUNNING.
  2650. //
  2651. deviceExtension->DpcFlags &= PD_DPC_RUNNING;
  2652. return(FALSE);
  2653. }
  2654. //
  2655. // Move the interrupt state to save area.
  2656. //
  2657. *interruptContext->SavedInterruptData = deviceExtension->InterruptData;
  2658. //
  2659. // Clear the interrupt state.
  2660. //
  2661. deviceExtension->InterruptData.InterruptFlags &= PD_INTERRUPT_FLAG_MASK;
  2662. deviceExtension->InterruptData.CompletedRequests = NULL;
  2663. deviceExtension->InterruptData.ReadyLogicalUnit = NULL;
  2664. deviceExtension->InterruptData.CompletedAbort = NULL;
  2665. deviceExtension->InterruptData.WmiMiniPortRequests = NULL;
  2666. //
  2667. // Clear the notification required bit in the DPC flags.
  2668. //
  2669. {
  2670. ULONG oldDpcFlags = 0;
  2671. //
  2672. // If we've been called then the DPC is obviously running.
  2673. //
  2674. oldDpcFlags = (ULONG) InterlockedExchange(&(deviceExtension->DpcFlags),
  2675. PD_DPC_RUNNING);
  2676. //
  2677. // If we got this far then these two flags must have been set.
  2678. //
  2679. ASSERT(oldDpcFlags == (PD_NOTIFICATION_REQUIRED | PD_DPC_RUNNING));
  2680. }
  2681. srbData = interruptContext->SavedInterruptData->CompletedRequests;
  2682. while (srbData != NULL) {
  2683. #if DBG
  2684. BOOLEAN alreadyChecked = FALSE;
  2685. //
  2686. // Look for a cycle in the completed request list. Only need to check
  2687. // once because the list is static for the duration of this routine.
  2688. //
  2689. if (limit++ > (ULONG)deviceExtension->ActiveRequestCount &&
  2690. alreadyChecked == FALSE) {
  2691. alreadyChecked = TRUE;
  2692. SpDetectCycleInCompletedRequestList(interruptContext);
  2693. }
  2694. #endif // DBG
  2695. ASSERT(srbData->CurrentSrb != NULL);
  2696. //
  2697. // Get a pointer to the SRB and the logical unit extension.
  2698. //
  2699. srb = srbData->CurrentSrb;
  2700. ASSERT(!TEST_FLAG(srb->SrbFlags, SRB_FLAGS_IS_ACTIVE));
  2701. logicalUnit = srbData->LogicalUnit;
  2702. #if DBG
  2703. {
  2704. PLOGICAL_UNIT_EXTENSION tmp;
  2705. tmp = GetLogicalUnitExtension(
  2706. (PADAPTER_EXTENSION) deviceExtension,
  2707. srb->PathId,
  2708. srb->TargetId,
  2709. srb->Lun,
  2710. FALSE,
  2711. FALSE);
  2712. ASSERT(logicalUnit == srbData->LogicalUnit);
  2713. }
  2714. #endif
  2715. //
  2716. // If the request did not succeed, then check for the special cases.
  2717. //
  2718. if (srb->SrbStatus != SRB_STATUS_SUCCESS) {
  2719. //
  2720. // If this request failed and a REQUEST SENSE command needs to
  2721. // be done, then set a flag to indicate this and prevent other
  2722. // commands from being started.
  2723. //
  2724. if (NEED_REQUEST_SENSE(srb)) {
  2725. if (logicalUnit->LuFlags & LU_NEED_REQUEST_SENSE) {
  2726. //
  2727. // This implies that requests have completed with a
  2728. // status of check condition before a REQUEST SENSE
  2729. // command could be performed. This should never occur.
  2730. // Convert the request to another code so that only one
  2731. // auto request sense is issued.
  2732. //
  2733. srb->ScsiStatus = 0;
  2734. srb->SrbStatus = SRB_STATUS_REQUEST_SENSE_FAILED;
  2735. } else {
  2736. //
  2737. // Indicate that an auto request sense needs to be done.
  2738. //
  2739. logicalUnit->LuFlags |= LU_NEED_REQUEST_SENSE;
  2740. //
  2741. // Save a pointer to the failed request away somewhere.
  2742. // Caller is holding the port spinlock which is used to
  2743. // protect these pointers.
  2744. //
  2745. ASSERTMSG("Scsiport has more than two failed requests: ",
  2746. ((logicalUnit->ActiveFailedRequest == NULL) ||
  2747. (logicalUnit->BlockedFailedRequest == NULL)));
  2748. ASSERTMSG("Scsiport has blocked but no active failed request: ",
  2749. (((logicalUnit->ActiveFailedRequest == NULL) &&
  2750. (logicalUnit->BlockedFailedRequest == NULL)) ||
  2751. (logicalUnit->ActiveFailedRequest != NULL)));
  2752. if(logicalUnit->ActiveFailedRequest == NULL) {
  2753. logicalUnit->ActiveFailedRequest = srbData;
  2754. } else {
  2755. logicalUnit->BlockedFailedRequest = srbData;
  2756. }
  2757. }
  2758. }
  2759. //
  2760. // Check for a QUEUE FULL status.
  2761. //
  2762. if (srb->ScsiStatus == SCSISTAT_QUEUE_FULL) {
  2763. //
  2764. // Set the queue full flag in the logical unit to prevent
  2765. // any new requests from being started.
  2766. //
  2767. logicalUnit->LuFlags |= LU_QUEUE_IS_FULL;
  2768. //
  2769. // Assert to catch queue full condition when there are
  2770. // no requests.
  2771. //
  2772. ASSERT(logicalUnit->QueueCount);
  2773. //
  2774. // Update the maximum queue depth.
  2775. //
  2776. if (logicalUnit->QueueCount < logicalUnit->MaxQueueDepth &&
  2777. logicalUnit->QueueCount > 2) {
  2778. //
  2779. // Set a bit to indicate that we are operating below full
  2780. // power. The tick handler will increment a counter every
  2781. // second we're in this state until which we reach a
  2782. // tunable value that restores us to full power.
  2783. //
  2784. logicalUnit->LuFlags |= LU_PERF_MAXQDEPTH_REDUCED;
  2785. logicalUnit->MaxQueueDepth = logicalUnit->QueueCount - 1;
  2786. DebugPrint((1, "SpGetInterruptState: New queue depth %d.\n",
  2787. logicalUnit->MaxQueueDepth));
  2788. }
  2789. //
  2790. // Reset the number of ticks the LU has been in a reduced
  2791. // performance state due to QUEUE FULL conditions. This has the
  2792. // effect of keeping us in this state.
  2793. //
  2794. logicalUnit->TicksInReducedMaxQueueDepthState = 0;
  2795. }
  2796. }
  2797. //
  2798. // If this is an unqueued request or a request at the head of the queue,
  2799. // then the requset timer count must be updated.
  2800. // Note that the spinlock is held at this time.
  2801. //
  2802. if (srb->QueueTag == SP_UNTAGGED) {
  2803. isTimed = TRUE;
  2804. } else {
  2805. if (logicalUnit->RequestList.Flink == &srbData->RequestList) {
  2806. isTimed = TRUE;
  2807. } else {
  2808. isTimed = FALSE;
  2809. }
  2810. //
  2811. // Remove the SRB data structure from the queue.
  2812. //
  2813. RemoveEntryList(&srbData->RequestList);
  2814. }
  2815. if (isTimed) {
  2816. //
  2817. // The request timeout count needs to be updated. If the request
  2818. // list is empty then the timer should be stopped.
  2819. //
  2820. if (IsListEmpty(&logicalUnit->RequestList)) {
  2821. logicalUnit->RequestTimeoutCounter = PD_TIMER_STOPPED;
  2822. } else {
  2823. //
  2824. // Start timing the srb at the head of the list.
  2825. //
  2826. nextSrbData = CONTAINING_RECORD(
  2827. logicalUnit->RequestList.Flink,
  2828. SRB_DATA,
  2829. RequestList);
  2830. srb = nextSrbData->CurrentSrb;
  2831. logicalUnit->RequestTimeoutCounter = srb->TimeOutValue;
  2832. }
  2833. }
  2834. srbData = srbData->CompletedRequests;
  2835. }
  2836. return(TRUE);
  2837. }
  2838. #if DBG
  2839. PLOGICAL_UNIT_EXTENSION
  2840. GetLogicalUnitExtensionEx(
  2841. PADAPTER_EXTENSION deviceExtension,
  2842. UCHAR PathId,
  2843. UCHAR TargetId,
  2844. UCHAR Lun,
  2845. PVOID LockTag,
  2846. BOOLEAN AcquireBinLock,
  2847. PCSTR File,
  2848. ULONG Line
  2849. )
  2850. /*++
  2851. Routine Description:
  2852. Walk logical unit extension list looking for
  2853. extension with matching target id.
  2854. Arguments:
  2855. deviceExtension
  2856. TargetId
  2857. Return Value:
  2858. Requested logical unit extension if found,
  2859. else NULL.
  2860. --*/
  2861. {
  2862. PLOGICAL_UNIT_EXTENSION logicalUnit;
  2863. PLOGICAL_UNIT_BIN bin;
  2864. PLOGICAL_UNIT_EXTENSION foundMatch = NULL;
  2865. KIRQL oldIrql;
  2866. if (TargetId >= deviceExtension->MaximumTargetIds) {
  2867. return NULL;
  2868. }
  2869. bin =
  2870. &deviceExtension->LogicalUnitList[ADDRESS_TO_HASH(PathId,
  2871. TargetId,
  2872. Lun)];
  2873. if(AcquireBinLock) {
  2874. KeAcquireSpinLock(&bin->Lock, &oldIrql);
  2875. }
  2876. logicalUnit = bin->List;
  2877. while (logicalUnit != NULL) {
  2878. if ((logicalUnit->TargetId == TargetId) &&
  2879. (logicalUnit->PathId == PathId) &&
  2880. (logicalUnit->Lun == Lun)) {
  2881. if(foundMatch != NULL) {
  2882. DebugPrint((0, "GetLogicalUnitExtension: Found duplicate for "
  2883. "(%d,%d,%d) in list: %#08lx %s & %#08lx %s\n",
  2884. PathId, TargetId, Lun,
  2885. foundMatch, (foundMatch->IsMissing) ? "missing" : "",
  2886. logicalUnit, (logicalUnit->IsMissing) ? "missing" : ""));
  2887. ASSERTMSG("Duplicate found in lun list - this is bad\n", FALSE);
  2888. }
  2889. foundMatch = logicalUnit;
  2890. }
  2891. logicalUnit = logicalUnit->NextLogicalUnit;
  2892. }
  2893. if((ARGUMENT_PRESENT(LockTag)) && (foundMatch != NULL)) {
  2894. SpAcquireRemoveLockEx(foundMatch->CommonExtension.DeviceObject,
  2895. LockTag,
  2896. File,
  2897. Line);
  2898. }
  2899. if(AcquireBinLock) {
  2900. KeReleaseSpinLock(&bin->Lock, oldIrql);
  2901. }
  2902. return foundMatch;
  2903. } // end GetLogicalUnitExtension()
  2904. #else
  2905. PLOGICAL_UNIT_EXTENSION
  2906. GetLogicalUnitExtension(
  2907. PADAPTER_EXTENSION deviceExtension,
  2908. UCHAR PathId,
  2909. UCHAR TargetId,
  2910. UCHAR Lun,
  2911. PVOID LockTag,
  2912. BOOLEAN AcquireBinLock
  2913. )
  2914. {
  2915. PLOGICAL_UNIT_BIN bin;
  2916. PLOGICAL_UNIT_EXTENSION logicalUnit;
  2917. KIRQL oldIrql;
  2918. if (TargetId >= deviceExtension->MaximumTargetIds) {
  2919. return NULL;
  2920. }
  2921. bin = &deviceExtension->LogicalUnitList[ADDRESS_TO_HASH(PathId,
  2922. TargetId,
  2923. Lun)];
  2924. if(AcquireBinLock) {
  2925. KeAcquireSpinLock(&bin->Lock, &oldIrql);
  2926. }
  2927. logicalUnit = bin->List;
  2928. while (logicalUnit != NULL) {
  2929. if ((logicalUnit->TargetId == TargetId) &&
  2930. (logicalUnit->PathId == PathId) &&
  2931. (logicalUnit->Lun == Lun)) {
  2932. if(ARGUMENT_PRESENT(LockTag)) {
  2933. SpAcquireRemoveLock(logicalUnit->CommonExtension.DeviceObject,
  2934. LockTag);
  2935. }
  2936. if(AcquireBinLock) {
  2937. KeReleaseSpinLock(&bin->Lock, oldIrql);
  2938. }
  2939. return logicalUnit;
  2940. }
  2941. logicalUnit = logicalUnit->NextLogicalUnit;
  2942. }
  2943. //
  2944. // Logical unit extension not found.
  2945. //
  2946. if(AcquireBinLock) {
  2947. KeReleaseSpinLock(&bin->Lock, oldIrql);
  2948. }
  2949. return NULL;
  2950. }
  2951. #endif
  2952. IO_ALLOCATION_ACTION
  2953. ScsiPortAllocationRoutine (
  2954. IN PDEVICE_OBJECT DeviceObject,
  2955. IN PIRP Irp,
  2956. IN PVOID MapRegisterBase,
  2957. IN PVOID Context
  2958. )
  2959. /*++
  2960. Routine Description:
  2961. This function is called by IoAllocateAdapterChannel when sufficent resources
  2962. are available to the driver. This routine saves the MapRegisterBase in the
  2963. device object and starts the currently pending request.
  2964. Arguments:
  2965. DeviceObject - Pointer to the device object to which the adapter is being
  2966. allocated.
  2967. Irp - Unused.
  2968. MapRegisterBase - Supplied by the Io subsystem for use in IoMapTransfer.
  2969. Context - Supplies a pointer to the logical unit structure for the next
  2970. current request.
  2971. Return Value:
  2972. KeepObject - Indicates the adapter and mapregisters should remain allocated
  2973. after return.
  2974. --*/
  2975. {
  2976. KIRQL currentIrql;
  2977. PADAPTER_EXTENSION deviceExtension;
  2978. IO_ALLOCATION_ACTION action;
  2979. deviceExtension = DeviceObject->DeviceExtension;
  2980. //
  2981. // Initialize the return value.
  2982. //
  2983. action = deviceExtension->PortConfig->Master ?
  2984. DeallocateObjectKeepRegisters : KeepObject;
  2985. //
  2986. // Acquire the spinlock to protect the various structures.
  2987. //
  2988. KeAcquireSpinLock(&deviceExtension->SpinLock, &currentIrql);
  2989. //
  2990. // Save the map register base.
  2991. //
  2992. if (deviceExtension->PortConfig->Master) {
  2993. //
  2994. // Note: ScsiPort considers this device a slave even though it really may
  2995. // be a master. I won't go into why this is, but if it is really a
  2996. // master, we must free the map registers after the request
  2997. // completes, so we'll save the map register base and the number of
  2998. // map registers in the per-request SRB_DATA structure.
  2999. PIO_STACK_LOCATION irpStack;
  3000. PSCSI_REQUEST_BLOCK srb;
  3001. PSRB_DATA srbData;
  3002. irpStack = IoGetCurrentIrpStackLocation(DeviceObject->CurrentIrp);
  3003. srb = irpStack->Parameters.Scsi.Srb;
  3004. srbData = srb->OriginalRequest;
  3005. ASSERT_SRB_DATA(srbData);
  3006. srbData->MapRegisterBase = MapRegisterBase;
  3007. srbData->NumberOfMapRegisters = deviceExtension->Capabilities.MaximumPhysicalPages;
  3008. } else {
  3009. deviceExtension->MapRegisterBase = MapRegisterBase;
  3010. }
  3011. deviceExtension->SynchronizeExecution(
  3012. deviceExtension->InterruptObject,
  3013. SpStartIoSynchronized,
  3014. DeviceObject
  3015. );
  3016. KeReleaseSpinLock(&deviceExtension->SpinLock, currentIrql);
  3017. return action;
  3018. }
  3019. #ifdef USE_DMA_MACROS
  3020. VOID
  3021. SpReceiveScatterGather(
  3022. IN struct _DEVICE_OBJECT *DeviceObject,
  3023. IN struct _IRP *Irp,
  3024. IN PSCATTER_GATHER_LIST ScatterGather,
  3025. IN PVOID Context
  3026. )
  3027. /*++
  3028. Routine Description:
  3029. This function is called by the I/O system when an adapter object and map
  3030. registers have been allocated. This routine then builds a scatter/gather
  3031. list for use by the miniport driver. Next it sets the timeout and
  3032. the current Irp for the logical unit. Finally it calls the miniport
  3033. StartIo routine. Once that routines complete, this routine will return
  3034. requesting that the adapter be freed and but the registers remain allocated.
  3035. The registers will be freed the request completes.
  3036. Arguments:
  3037. DeviceObject - Supplies a pointer to the port driver device object.
  3038. Irp - Supplies a pointer to the current Irp.
  3039. MapRegisterBase - Supplies a context pointer to be used with calls the
  3040. adapter object routines.
  3041. Context - Supplies a pointer to the SRB_DATA structure.
  3042. Return Value:
  3043. Returns DeallocateObjectKeepRegisters so that the adapter object can be
  3044. used by other logical units.
  3045. --*/
  3046. {
  3047. KIRQL currentIrql;
  3048. PSCSI_REQUEST_BLOCK srb;
  3049. PSRB_DATA srbData = Context;
  3050. PADAPTER_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  3051. srb = srbData->CurrentSrb;
  3052. //
  3053. // Save the MapRegisterBase for later use to deallocate the map registers.
  3054. //
  3055. srbData->MapRegisterBase = ScatterGather;
  3056. srbData->ScatterGatherList = ScatterGather->Elements;
  3057. //
  3058. // See if we need to map or remap the buffer.
  3059. //
  3060. if((deviceExtension->MapBuffers == TRUE) ||
  3061. (IS_MAPPED_SRB(srb) == TRUE)) {
  3062. PMDL mdl = Irp->MdlAddress;
  3063. PVOID systemAddress;
  3064. BOOLEAN remap = FALSE;
  3065. tryRemapping:
  3066. if(deviceExtension->RemapBuffers || remap == TRUE) {
  3067. //
  3068. // Build an MDL for the actual data area being used for this
  3069. // request. We're using the data buffer address in the srb
  3070. // as the base, not the one in the original MDL so we don't
  3071. // need to compensate for the DataOffset originally calculated.
  3072. //
  3073. mdl = SpBuildMdlForMappedTransfer(
  3074. DeviceObject,
  3075. deviceExtension->DmaAdapterObject,
  3076. srbData->CurrentIrp->MdlAddress,
  3077. srb->DataBuffer,
  3078. srb->DataTransferLength,
  3079. srbData->ScatterGatherList,
  3080. ScatterGather->NumberOfElements
  3081. );
  3082. #if defined(FORWARD_PROGRESS)
  3083. if (mdl == NULL && deviceExtension->ReservedMdl != NULL) {
  3084. //
  3085. // We could not allocate a new MDL for the request and there is
  3086. // a spare one on the adapter extension. Let's try to use the
  3087. // spare.
  3088. //
  3089. KeAcquireSpinLockAtDpcLevel(&deviceExtension->SpinLock);
  3090. mdl = SpPrepareReservedMdlForUse(deviceExtension,
  3091. srbData,
  3092. srb,
  3093. ScatterGather->NumberOfElements);
  3094. if (mdl == (PMDL)-1) {
  3095. DebugPrint((1, "SpReceiveScatterGather: reserve mdl in use - pending DevExt:%p srb:%p\n",
  3096. deviceExtension, srb));
  3097. //
  3098. // The spare MDL is already in use. At this point, this
  3099. // request is still the current IRP on the adapter device
  3100. // object, so let's pend it until the spare comes available.
  3101. //
  3102. ASSERT(Irp == DeviceObject->CurrentIrp);
  3103. SET_FLAG(deviceExtension->Flags, PD_PENDING_DEVICE_REQUEST);
  3104. //
  3105. // If we allocated an SRB extension for this request, free
  3106. // it now. I do this because when the request gets restarted
  3107. // we'll try to allocate the SRB extension again and without
  3108. // adding more state, there isn't a safe way to check if the
  3109. // extension has already been allocated. Besides, it makes
  3110. // sense to make the extension available for some other
  3111. // request since it also is a limited resource.
  3112. //
  3113. if (srb->SrbExtension != NULL) {
  3114. SpFreeSrbExtension(deviceExtension, srb->SrbExtension);
  3115. }
  3116. //
  3117. // Free the map registers.
  3118. //
  3119. PutScatterGatherList(
  3120. deviceExtension->DmaAdapterObject,
  3121. srbData->MapRegisterBase,
  3122. (BOOLEAN)(srb->SrbFlags & SRB_FLAGS_DATA_IN ? FALSE : TRUE));
  3123. srbData->ScatterGatherList = NULL;
  3124. KeReleaseSpinLockFromDpcLevel(&deviceExtension->SpinLock);
  3125. return;
  3126. }
  3127. KeReleaseSpinLockFromDpcLevel(&deviceExtension->SpinLock);
  3128. }
  3129. #endif
  3130. srbData->RemappedMdl = mdl;
  3131. } else {
  3132. srbData->RemappedMdl = NULL;
  3133. }
  3134. if(mdl == NULL) {
  3135. srbData->InternalStatus = STATUS_INSUFFICIENT_RESOURCES;
  3136. srb->SrbStatus = SRB_STATUS_INTERNAL_ERROR;
  3137. srb->ScsiStatus = 0xff;
  3138. goto DoneMapping;
  3139. }
  3140. //
  3141. // Get the mapped system address and calculate offset into MDL.
  3142. // At the moment don't allow KernelMode requests to fail since
  3143. // not all scsiport's internally sent requests are correctly
  3144. // marked as comming from non-paged pool.
  3145. //
  3146. if(srbData->RemappedMdl == NULL) {
  3147. //
  3148. // We're using the original data address for the MDL here - we
  3149. // need to compensate for the data offset.
  3150. //
  3151. systemAddress = SpGetSystemAddressForMdlSafe(
  3152. mdl,
  3153. ((Irp->RequestorMode == KernelMode) ?
  3154. HighPagePriority : NormalPagePriority));
  3155. //
  3156. // If we could not map the entire MDL, check if we are trying to map
  3157. // more than we need. We do this when class splits the request
  3158. // because each IRP class sends down points to the orignal MDL
  3159. // that describes the entire buffer. The DataBuffer and TransferLength
  3160. // fields of the SRB, however, do represent the current portion of the
  3161. // buffer. So we try remapping using the info in the SRB.
  3162. //
  3163. if (systemAddress == NULL) {
  3164. if (remap == FALSE) {
  3165. ULONG mdlByteCount = MmGetMdlByteCount(mdl);
  3166. if (mdlByteCount > srb->DataTransferLength) {
  3167. remap = TRUE;
  3168. goto tryRemapping;
  3169. }
  3170. }
  3171. }
  3172. } else {
  3173. systemAddress = MmMapLockedPagesSpecifyCache(
  3174. mdl,
  3175. KernelMode,
  3176. MmCached,
  3177. NULL,
  3178. FALSE,
  3179. ((Irp->RequestorMode == KernelMode) ?
  3180. HighPagePriority :
  3181. NormalPagePriority));
  3182. }
  3183. #if defined(FORWARD_PROGRESS)
  3184. if (systemAddress == NULL && deviceExtension->ReservedPages != NULL) {
  3185. //
  3186. // The system could not map the pages necessary to complete this
  3187. // request. We need to ensure forward progress, so we'll try to
  3188. // use the reserve pages we allocated at initialization time.
  3189. //
  3190. KeAcquireSpinLockAtDpcLevel(&deviceExtension->SpinLock);
  3191. systemAddress = SpMapLockedPagesWithReservedMapping(
  3192. deviceExtension,
  3193. srb,
  3194. srbData,
  3195. mdl);
  3196. if (systemAddress == (PVOID)-1) {
  3197. DebugPrint((1, "SpReceiveScatterGather: reserve range in use - pending DevExt:%p srb:%p\n",
  3198. deviceExtension, srb));
  3199. //
  3200. // The spare pages are already in use. At this point, this
  3201. // request is still the current IRP on the adapter device
  3202. // object, so let's pend it until the spare comes available.
  3203. //
  3204. ASSERT(Irp == DeviceObject->CurrentIrp);
  3205. SET_FLAG(deviceExtension->Flags, PD_PENDING_DEVICE_REQUEST);
  3206. //
  3207. // If we allocated an SRB extension for this request, free
  3208. // it now. I do this because when the request gets restarted
  3209. // we'll try to allocate the SRB extension again and without
  3210. // adding more state, there isn't a safe way to check if the
  3211. // extension has already been allocated. Besides, it makes
  3212. // sense to make the extension available for some other
  3213. // request since it also is a limited resource.
  3214. //
  3215. if (srb->SrbExtension != NULL) {
  3216. SpFreeSrbExtension(deviceExtension, srb->SrbExtension);
  3217. }
  3218. //
  3219. // Free the map registers.
  3220. //
  3221. PutScatterGatherList(
  3222. deviceExtension->DmaAdapterObject,
  3223. srbData->MapRegisterBase,
  3224. (BOOLEAN)(srb->SrbFlags & SRB_FLAGS_DATA_IN ? FALSE : TRUE));
  3225. srbData->ScatterGatherList = NULL;
  3226. //
  3227. // If we have a remapping MDL, either one we allocated or
  3228. // the reserve, free it.
  3229. //
  3230. if (srbData->RemappedMdl != NULL) {
  3231. if (TEST_FLAG(srbData->Flags, SRB_DATA_RESERVED_MDL)) {
  3232. CLEAR_FLAG(srbData->Flags, SRB_DATA_RESERVED_MDL);
  3233. CLEAR_FLAG(deviceExtension->Flags, PD_RESERVED_MDL_IN_USE);
  3234. } else {
  3235. IoFreeMdl(srbData->RemappedMdl);
  3236. }
  3237. srbData->RemappedMdl = NULL;
  3238. }
  3239. KeReleaseSpinLockFromDpcLevel(&deviceExtension->SpinLock);
  3240. return;
  3241. }
  3242. KeReleaseSpinLockFromDpcLevel(&deviceExtension->SpinLock);
  3243. }
  3244. #endif
  3245. if(systemAddress != NULL) {
  3246. srb->DataBuffer = systemAddress;
  3247. if(srbData->RemappedMdl == NULL) {
  3248. //
  3249. // If we didn't remap the MDL then this system address is
  3250. // based on the original MDL's base address. Account for the
  3251. // offset of the srb's original data buffer pointer.
  3252. //
  3253. (PUCHAR) srb->DataBuffer += srbData->DataOffset;
  3254. }
  3255. } else {
  3256. DebugPrint((1, "SpReceiveScatterGather: Couldn't get system "
  3257. "VA for irp 0x%08p\n", Irp));
  3258. srb->SrbStatus = SRB_STATUS_INTERNAL_ERROR;
  3259. srb->ScsiStatus = 0xff;
  3260. srbData->InternalStatus = STATUS_INSUFFICIENT_RESOURCES;
  3261. //
  3262. // Free the remapped MDL here - this will keep the completion code
  3263. // from trying to unmap memory we never mapped.
  3264. //
  3265. if(srbData->RemappedMdl) {
  3266. IoFreeMdl(srbData->RemappedMdl);
  3267. srbData->RemappedMdl = NULL;
  3268. }
  3269. }
  3270. } else {
  3271. srbData->RemappedMdl = NULL;
  3272. }
  3273. DoneMapping:
  3274. //
  3275. // Update the active request count.
  3276. //
  3277. InterlockedIncrement( &deviceExtension->ActiveRequestCount );
  3278. //
  3279. // Acquire the spinlock to protect the various structures.
  3280. //
  3281. KeAcquireSpinLock(&deviceExtension->SpinLock, &currentIrql);
  3282. deviceExtension->SynchronizeExecution(
  3283. deviceExtension->InterruptObject,
  3284. SpStartIoSynchronized,
  3285. DeviceObject
  3286. );
  3287. KeReleaseSpinLock(&deviceExtension->SpinLock, currentIrql);
  3288. }
  3289. #else
  3290. IO_ALLOCATION_ACTION
  3291. SpBuildScatterGather(
  3292. IN struct _DEVICE_OBJECT *DeviceObject,
  3293. IN struct _IRP *Irp,
  3294. IN PVOID MapRegisterBase,
  3295. IN PVOID Context
  3296. )
  3297. /*++
  3298. Routine Description:
  3299. This function is called by the I/O system when an adapter object and map
  3300. registers have been allocated. This routine then builds a scatter/gather
  3301. list for use by the miniport driver. Next it sets the timeout and
  3302. the current Irp for the logical unit. Finally it calls the miniport
  3303. StartIo routine. Once that routines complete, this routine will return
  3304. requesting that the adapter be freed and but the registers remain allocated.
  3305. The registers will be freed the request completes.
  3306. Arguments:
  3307. DeviceObject - Supplies a pointer to the port driver device object.
  3308. Irp - Supplies a pointer to the current Irp.
  3309. MapRegisterBase - Supplies a context pointer to be used with calls the
  3310. adapter object routines.
  3311. Context - Supplies a pointer to the SRB_DATA structure.
  3312. Return Value:
  3313. Returns DeallocateObjectKeepRegisters so that the adapter object can be
  3314. used by other logical units.
  3315. --*/
  3316. {
  3317. BOOLEAN writeToDevice;
  3318. PSCSI_REQUEST_BLOCK srb;
  3319. PSRB_SCATTER_GATHER scatterList;
  3320. ULONG scatterListLength = 0;
  3321. PCCHAR dataVirtualAddress;
  3322. ULONG totalLength;
  3323. PSRB_DATA srbData = Context;
  3324. PADAPTER_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  3325. ULONG scatterGatherType;
  3326. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  3327. ASSERT(srbData->CurrentIrp == Irp);
  3328. srb = srbData->CurrentSrb;
  3329. //
  3330. // Determine if scatter/gather list must come from pool.
  3331. //
  3332. ASSERT(srbData->ScatterGatherList == NULL);
  3333. if (srbData->NumberOfMapRegisters <= SP_SMALL_PHYSICAL_BREAK_VALUE) {
  3334. //
  3335. // Use the builtin scatter gather list.
  3336. //
  3337. #if DBG
  3338. RtlFillMemory(srbData->SmallScatterGatherList,
  3339. sizeof(srbData->SmallScatterGatherList),
  3340. 'P');
  3341. #endif
  3342. srbData->ScatterGatherList = srbData->SmallScatterGatherList;
  3343. //
  3344. // Indicate the scatter gather list doesn't need to be freed.
  3345. //
  3346. scatterGatherType = SRB_DATA_SMALL_SG_LIST;
  3347. } else if (srbData->NumberOfMapRegisters >= SP_LARGE_PHYSICAL_BREAK_VALUE) {
  3348. //
  3349. // Allocate scatter/gather list from pool.
  3350. //
  3351. srbData->ScatterGatherList = SpAllocatePool(
  3352. NonPagedPool,
  3353. (srbData->NumberOfMapRegisters *
  3354. sizeof(SRB_SCATTER_GATHER)),
  3355. SCSIPORT_TAG_LARGE_SG_ENTRY,
  3356. DeviceObject->DriverObject);
  3357. #if DBG
  3358. if(srbData->ScatterGatherList != NULL) {
  3359. RtlFillMemory(srbData->ScatterGatherList,
  3360. sizeof(SRB_SCATTER_GATHER) * srbData->NumberOfMapRegisters,
  3361. 'P');
  3362. }
  3363. #endif
  3364. //
  3365. // Indicate scatter gather list came from pool.
  3366. //
  3367. scatterGatherType = SRB_DATA_LARGE_SG_LIST;
  3368. } else {
  3369. //
  3370. // Grab a scatter gather list off the lookaside list.
  3371. //
  3372. srbData->ScatterGatherList =
  3373. ExAllocateFromNPagedLookasideList(
  3374. &deviceExtension->MediumScatterGatherLookasideList);
  3375. #if DBG
  3376. if(srbData->ScatterGatherList != NULL) {
  3377. RtlFillMemory(srbData->ScatterGatherList,
  3378. sizeof(SRB_SCATTER_GATHER) * (SP_LARGE_PHYSICAL_BREAK_VALUE - 1),
  3379. 'P');
  3380. }
  3381. #endif
  3382. //
  3383. // Indicate scatter gather list came from lookaside list.
  3384. //
  3385. scatterGatherType = SRB_DATA_MEDIUM_SG_LIST;
  3386. }
  3387. if (srbData->ScatterGatherList != NULL) {
  3388. //
  3389. // Record what type of scatter gather list we're using.
  3390. //
  3391. srbData->Flags |= scatterGatherType;
  3392. #if TEST_LISTS
  3393. {
  3394. ULONG size = srbData->NumberOfMapRegisters;
  3395. deviceExtension->ScatterGatherAllocationCount++;
  3396. switch(scatterGatherType) {
  3397. case SRB_DATA_LARGE_SG_LIST: {
  3398. deviceExtension->LargeAllocationCount++;
  3399. deviceExtension->LargeAllocationSize += size;
  3400. break;
  3401. }
  3402. case SRB_DATA_SMALL_SG_LIST: {
  3403. deviceExtension->SmallAllocationCount++;
  3404. deviceExtension->SmallAllocationSize += size;
  3405. break;
  3406. }
  3407. case SRB_DATA_MEDIUM_SG_LIST: {
  3408. deviceExtension->MediumAllocationSize += size;
  3409. break;
  3410. }
  3411. }
  3412. }
  3413. #endif
  3414. scatterList = srbData->ScatterGatherList;
  3415. totalLength = 0;
  3416. //
  3417. // Determine the virtual address of the buffer for the Io map transfers
  3418. // based on the original MDL and the data offset for the SRB.
  3419. //
  3420. dataVirtualAddress = (PCHAR) MmGetMdlVirtualAddress(Irp->MdlAddress);
  3421. dataVirtualAddress += srbData->DataOffset;
  3422. ASSERT(srb->DataBuffer == dataVirtualAddress);
  3423. //
  3424. // Save the MapRegisterBase for later use to deallocate the map registers.
  3425. //
  3426. srbData->MapRegisterBase = MapRegisterBase;
  3427. //
  3428. // Build the scatter/gather list by looping throught the transfer calling
  3429. // I/O map transfer.
  3430. //
  3431. if ((srb->SrbFlags & SRB_FLAGS_DATA_OUT) ||
  3432. (srb->Function == SRB_FUNCTION_IO_CONTROL)) {
  3433. writeToDevice = TRUE;
  3434. } else {
  3435. writeToDevice = FALSE;
  3436. }
  3437. while (totalLength < srb->DataTransferLength) {
  3438. //
  3439. // Request that the rest of the transfer be mapped.
  3440. //
  3441. scatterList->Length = srb->DataTransferLength - totalLength;
  3442. //
  3443. // Since we are a master call I/O map transfer with a NULL adapter.
  3444. //
  3445. scatterList->Address = MapTransfer(deviceExtension->DmaAdapterObject,
  3446. Irp->MdlAddress,
  3447. MapRegisterBase,
  3448. (PCCHAR) dataVirtualAddress + totalLength,
  3449. &scatterList->Length,
  3450. writeToDevice);
  3451. totalLength += scatterList->Length;
  3452. scatterList++;
  3453. scatterListLength++;
  3454. }
  3455. } else {
  3456. srbData->InternalStatus = STATUS_INSUFFICIENT_RESOURCES;
  3457. srb->SrbStatus = SRB_STATUS_INTERNAL_ERROR;
  3458. srb->ScsiStatus = 0xff;
  3459. goto DoneMapping;
  3460. }
  3461. if((deviceExtension->MapBuffers == TRUE) ||
  3462. (IS_MAPPED_SRB(srb) == TRUE)) {
  3463. PMDL mdl = Irp->MdlAddress;
  3464. PVOID systemAddress;
  3465. BOOLEAN remap = FALSE;
  3466. tryRemapping:
  3467. if(deviceExtension->RemapBuffers || remap == TRUE) {
  3468. //
  3469. // Build an MDL for the actual data area being used for this
  3470. // request. We're using the data buffer address in the srb
  3471. // as the base, not the one in the original MDL so we don't
  3472. // need to compensate for the DataOffset originally calculated.
  3473. //
  3474. mdl = SpBuildMdlForMappedTransfer(
  3475. DeviceObject,
  3476. deviceExtension->DmaAdapterObject,
  3477. srbData->CurrentIrp->MdlAddress,
  3478. srb->DataBuffer,
  3479. srb->DataTransferLength,
  3480. srbData->ScatterGatherList,
  3481. scatterListLength);
  3482. #if defined(FORWARD_PROGRESS)
  3483. if (mdl == NULL && deviceExtension->ReservedMdl != NULL) {
  3484. //
  3485. // We could not allocate a new MDL for the request and there is
  3486. // a spare one on the adapter extension. Let's try to use the
  3487. // spare.
  3488. //
  3489. KeAcquireSpinLockAtDpcLevel(&deviceExtension->SpinLock);
  3490. mdl = SpPrepareReservedMdlForUse(deviceExtension,
  3491. srbData,
  3492. srb,
  3493. scatterListLength);
  3494. if (mdl == (PMDL)-1) {
  3495. DebugPrint((1, "SpBuildScatterGather: reserve MDL in use - pending DevExt:%p srb:%p\n",
  3496. deviceExtension, srb));
  3497. //
  3498. // The spare MDL is already in use. At this point, this
  3499. // request is still the current IRP on the adapter device
  3500. // object, so let's pend it until the spare comes available.
  3501. //
  3502. ASSERT(Irp == DeviceObject->CurrentIrp);
  3503. SET_FLAG(deviceExtension->Flags, PD_PENDING_DEVICE_REQUEST);
  3504. //
  3505. // If we allocated an SRB extension for this request, free
  3506. // it now. I do this because when the request gets restarted
  3507. // we'll try to allocate the SRB extension again and without
  3508. // adding more state, there isn't a safe way to check if the
  3509. // extension has already been allocated. Besides, it makes
  3510. // sense to make the extension available for some other
  3511. // request since it also is a limited resource.
  3512. //
  3513. if (srb->SrbExtension != NULL) {
  3514. SpFreeSrbExtension(deviceExtension, srb->SrbExtension);
  3515. }
  3516. //
  3517. // Free the SG list so another request can use it while we're
  3518. // pending.
  3519. //
  3520. if (srbData->ScatterGatherList != NULL) {
  3521. SpFreeSGList(deviceExtension, srbData);
  3522. }
  3523. KeReleaseSpinLockFromDpcLevel(&deviceExtension->SpinLock);
  3524. return(DeallocateObjectKeepRegisters);
  3525. }
  3526. KeReleaseSpinLockFromDpcLevel(&deviceExtension->SpinLock);
  3527. }
  3528. #endif
  3529. srbData->RemappedMdl = mdl;
  3530. } else {
  3531. srbData->RemappedMdl = NULL;
  3532. }
  3533. if(mdl == NULL) {
  3534. srbData->InternalStatus = STATUS_INSUFFICIENT_RESOURCES;
  3535. srb->SrbStatus = SRB_STATUS_INTERNAL_ERROR;
  3536. srb->ScsiStatus = 0xff;
  3537. goto DoneMapping;
  3538. }
  3539. //
  3540. // Get the mapped system address and calculate offset into MDL.
  3541. // At the moment don't allow KernelMode requests to fail since
  3542. // not all scsiport's internally sent requests are correctly
  3543. // marked as comming from non-paged pool.
  3544. //
  3545. if(srbData->RemappedMdl == NULL) {
  3546. //
  3547. // We're using the original data address for the MDL here - we
  3548. // need to compensate for the data offset.
  3549. //
  3550. systemAddress = SpGetSystemAddressForMdlSafe(
  3551. mdl,
  3552. ((Irp->RequestorMode == KernelMode) ?
  3553. HighPagePriority : NormalPagePriority));
  3554. //
  3555. // If we could not map the entire MDL, check if we are trying to map
  3556. // more than we need. We do this when class splits the request
  3557. // because each IRP class sends down points to the orignal MDL
  3558. // that describes the entire buffer. The DataBuffer and TransferLength
  3559. // fields of the SRB, however, do represent the current portion of the
  3560. // buffer. So we try remapping using the info in the SRB.
  3561. //
  3562. if (systemAddress == NULL) {
  3563. if (remap == FALSE) {
  3564. ULONG mdlByteCount = MmGetMdlByteCount(mdl);
  3565. if (mdlByteCount > srb->DataTransferLength) {
  3566. remap = TRUE;
  3567. goto tryRemapping;
  3568. }
  3569. }
  3570. }
  3571. } else {
  3572. systemAddress = MmMapLockedPagesSpecifyCache(
  3573. mdl,
  3574. KernelMode,
  3575. MmCached,
  3576. NULL,
  3577. FALSE,
  3578. ((Irp->RequestorMode == KernelMode) ?
  3579. HighPagePriority :
  3580. NormalPagePriority));
  3581. }
  3582. #if defined(FORWARD_PROGRESS)
  3583. if (systemAddress == NULL && deviceExtension->ReservedPages != NULL) {
  3584. //
  3585. // The system could not map the pages necessary to complete this
  3586. // request. We need to ensure forward progress, so we'll try to
  3587. // use the reserve pages we allocated at initialization time.
  3588. //
  3589. KeAcquireSpinLockAtDpcLevel(&deviceExtension->SpinLock);
  3590. systemAddress = SpMapLockedPagesWithReservedMapping(
  3591. deviceExtension,
  3592. srb,
  3593. srbData,
  3594. mdl);
  3595. if (systemAddress == (PVOID)-1) {
  3596. DebugPrint((1, "SpBuildScatterGather: reserve range in use - pending DevExt:%p srb:%p\n",
  3597. deviceExtension, srb));
  3598. //
  3599. // The spare pages are already in use. At this point, this
  3600. // request is still the current IRP on the adapter device
  3601. // object, so let's pend it until the spare comes available.
  3602. //
  3603. ASSERT(Irp == DeviceObject->CurrentIrp);
  3604. SET_FLAG(deviceExtension->Flags, PD_PENDING_DEVICE_REQUEST);
  3605. //
  3606. // If we allocated an SRB extension for this request, free
  3607. // it now. I do this because when the request gets restarted
  3608. // we'll try to allocate the SRB extension again and without
  3609. // adding more state, there isn't a safe way to check if the
  3610. // extension has already been allocated. Besides, it makes
  3611. // sense to make the extension available for some other
  3612. // request since it also is a limited resource.
  3613. //
  3614. if (srb->SrbExtension != NULL) {
  3615. SpFreeSrbExtension(deviceExtension, srb->SrbExtension);
  3616. }
  3617. //
  3618. // Free the SG list so another request can use it while we're
  3619. // pending.
  3620. //
  3621. if (srbData->ScatterGatherList != NULL) {
  3622. SpFreeSGList(deviceExtension, srbData);
  3623. }
  3624. //
  3625. // If we have a remapping MDL, either one we allocated or
  3626. // the reserve, free it.
  3627. //
  3628. if (srbData->RemappedMdl != NULL) {
  3629. if (TEST_FLAG(srbData->Flags, SRB_DATA_RESERVED_MDL)) {
  3630. CLEAR_FLAG(srbData->Flags, SRB_DATA_RESERVED_MDL);
  3631. CLEAR_FLAG(deviceExtension->Flags, PD_RESERVED_MDL_IN_USE);
  3632. } else {
  3633. IoFreeMdl(srbData->RemappedMdl);
  3634. }
  3635. srbData->RemappedMdl = NULL;
  3636. }
  3637. KeReleaseSpinLockFromDpcLevel(&deviceExtension->SpinLock);
  3638. return(DeallocateObjectKeepRegisters);
  3639. }
  3640. KeReleaseSpinLockFromDpcLevel(&deviceExtension->SpinLock);
  3641. }
  3642. #endif
  3643. if(systemAddress != NULL) {
  3644. srb->DataBuffer = systemAddress;
  3645. if(srbData->RemappedMdl == NULL) {
  3646. //
  3647. // If we didn't remap the MDL then this system address is
  3648. // based on the original MDL's base address. Account for the
  3649. // offset of the srb's original data buffer pointer.
  3650. //
  3651. (PUCHAR) srb->DataBuffer += srbData->DataOffset;
  3652. }
  3653. } else {
  3654. DebugPrint((1, "SpBuildScatterGather: Couldn't get system "
  3655. "VA for irp 0x%08p\n", Irp));
  3656. srb->SrbStatus = SRB_STATUS_INTERNAL_ERROR;
  3657. srb->ScsiStatus = 0xff;
  3658. srbData->InternalStatus = STATUS_INSUFFICIENT_RESOURCES;
  3659. //
  3660. // Free the remapped MDL here - this will keep the completion code
  3661. // from trying to unmap memory we never mapped.
  3662. //
  3663. if(srbData->RemappedMdl) {
  3664. IoFreeMdl(srbData->RemappedMdl);
  3665. srbData->RemappedMdl = NULL;
  3666. }
  3667. }
  3668. } else {
  3669. srbData->RemappedMdl = NULL;
  3670. }
  3671. DoneMapping:
  3672. //
  3673. // Update the active request count.
  3674. //
  3675. InterlockedIncrement( &deviceExtension->ActiveRequestCount );
  3676. //
  3677. // Acquire the spinlock to protect the various structures.
  3678. //
  3679. KeAcquireSpinLockAtDpcLevel(&deviceExtension->SpinLock);
  3680. deviceExtension->SynchronizeExecution(
  3681. deviceExtension->InterruptObject,
  3682. SpStartIoSynchronized,
  3683. DeviceObject
  3684. );
  3685. KeReleaseSpinLockFromDpcLevel(&deviceExtension->SpinLock);
  3686. return(DeallocateObjectKeepRegisters);
  3687. }
  3688. #endif
  3689. VOID
  3690. LogErrorEntry(
  3691. IN PADAPTER_EXTENSION DeviceExtension,
  3692. IN PERROR_LOG_ENTRY LogEntry
  3693. )
  3694. /*++
  3695. Routine Description:
  3696. This function allocates an I/O error log record, fills it in and writes it
  3697. to the I/O error log.
  3698. Arguments:
  3699. DeviceExtension - Supplies a pointer to the port device extension.
  3700. LogEntry - Supplies a pointer to the scsi port log entry.
  3701. Return Value:
  3702. None.
  3703. --*/
  3704. {
  3705. PIO_ERROR_LOG_PACKET errorLogEntry;
  3706. #define ERRLOG_DATA_ENTRIES 4
  3707. errorLogEntry = (PIO_ERROR_LOG_PACKET)
  3708. IoAllocateErrorLogEntry(
  3709. DeviceExtension->CommonExtension.DeviceObject,
  3710. (sizeof(IO_ERROR_LOG_PACKET) +
  3711. (ERRLOG_DATA_ENTRIES * sizeof(ULONG))));
  3712. if (errorLogEntry != NULL) {
  3713. //
  3714. // Translate the miniport error code into the NT I\O driver.
  3715. //
  3716. switch (LogEntry->ErrorCode) {
  3717. case SP_BUS_PARITY_ERROR:
  3718. errorLogEntry->ErrorCode = IO_ERR_PARITY;
  3719. break;
  3720. case SP_UNEXPECTED_DISCONNECT:
  3721. errorLogEntry->ErrorCode = IO_ERR_CONTROLLER_ERROR;
  3722. break;
  3723. case SP_INVALID_RESELECTION:
  3724. errorLogEntry->ErrorCode = IO_ERR_CONTROLLER_ERROR;
  3725. break;
  3726. case SP_BUS_TIME_OUT:
  3727. errorLogEntry->ErrorCode = IO_ERR_TIMEOUT;
  3728. break;
  3729. case SP_PROTOCOL_ERROR:
  3730. errorLogEntry->ErrorCode = IO_ERR_CONTROLLER_ERROR;
  3731. break;
  3732. case SP_INTERNAL_ADAPTER_ERROR:
  3733. errorLogEntry->ErrorCode = IO_ERR_CONTROLLER_ERROR;
  3734. break;
  3735. case SP_IRQ_NOT_RESPONDING:
  3736. errorLogEntry->ErrorCode = IO_ERR_INCORRECT_IRQL;
  3737. break;
  3738. case SP_BAD_FW_ERROR:
  3739. errorLogEntry->ErrorCode = IO_ERR_BAD_FIRMWARE;
  3740. break;
  3741. case SP_BAD_FW_WARNING:
  3742. errorLogEntry->ErrorCode = IO_WRN_BAD_FIRMWARE;
  3743. break;
  3744. default:
  3745. errorLogEntry->ErrorCode = IO_ERR_CONTROLLER_ERROR;
  3746. break;
  3747. }
  3748. errorLogEntry->SequenceNumber = LogEntry->SequenceNumber;
  3749. errorLogEntry->MajorFunctionCode = IRP_MJ_SCSI;
  3750. errorLogEntry->RetryCount = (UCHAR) LogEntry->ErrorLogRetryCount;
  3751. errorLogEntry->UniqueErrorValue = LogEntry->UniqueId;
  3752. errorLogEntry->FinalStatus = STATUS_SUCCESS;
  3753. errorLogEntry->DumpDataSize = ERRLOG_DATA_ENTRIES * sizeof(ULONG);
  3754. errorLogEntry->DumpData[0] = LogEntry->PathId;
  3755. errorLogEntry->DumpData[1] = LogEntry->TargetId;
  3756. errorLogEntry->DumpData[2] = LogEntry->Lun;
  3757. errorLogEntry->DumpData[3] = LogEntry->ErrorCode;
  3758. IoWriteErrorLogEntry(errorLogEntry);
  3759. #undef ERRLOG_DATA_ENTRIES
  3760. }
  3761. #if SCSIDBG_ENABLED
  3762. {
  3763. PCHAR errorCodeString;
  3764. switch (LogEntry->ErrorCode) {
  3765. case SP_BUS_PARITY_ERROR:
  3766. errorCodeString = "SCSI bus partity error";
  3767. break;
  3768. case SP_UNEXPECTED_DISCONNECT:
  3769. errorCodeString = "Unexpected disconnect";
  3770. break;
  3771. case SP_INVALID_RESELECTION:
  3772. errorCodeString = "Invalid reselection";
  3773. break;
  3774. case SP_BUS_TIME_OUT:
  3775. errorCodeString = "SCSI bus time out";
  3776. break;
  3777. case SP_PROTOCOL_ERROR:
  3778. errorCodeString = "SCSI protocol error";
  3779. break;
  3780. case SP_INTERNAL_ADAPTER_ERROR:
  3781. errorCodeString = "Internal adapter error";
  3782. break;
  3783. default:
  3784. errorCodeString = "Unknown error code";
  3785. break;
  3786. }
  3787. DebugPrint((1,"LogErrorEntry: Logging SCSI error packet. ErrorCode = %s.\n",
  3788. errorCodeString
  3789. ));
  3790. DebugPrint((1,
  3791. "PathId = %2x, TargetId = %2x, Lun = %2x, UniqueId = %x.\n",
  3792. LogEntry->PathId,
  3793. LogEntry->TargetId,
  3794. LogEntry->Lun,
  3795. LogEntry->UniqueId
  3796. ));
  3797. }
  3798. #endif
  3799. }
  3800. VOID
  3801. FASTCALL
  3802. GetNextLuRequest(
  3803. IN PLOGICAL_UNIT_EXTENSION LogicalUnit
  3804. )
  3805. /*++
  3806. Routine Description:
  3807. This routine get the next request for the specified logical unit. It does
  3808. the necessary initialization to the logical unit structure and submitts the
  3809. request to the device queue. The DeviceExtension SpinLock must be held
  3810. when this function called. It is released by this function.
  3811. Arguments:
  3812. LogicalUnit - Supplies a pointer to the logical unit extension to get the
  3813. next request from.
  3814. Return Value:
  3815. None.
  3816. --*/
  3817. {
  3818. PADAPTER_EXTENSION DeviceExtension = LogicalUnit->AdapterExtension;
  3819. PKDEVICE_QUEUE_ENTRY packet;
  3820. PIO_STACK_LOCATION irpStack;
  3821. PSCSI_REQUEST_BLOCK srb;
  3822. PIRP nextIrp;
  3823. //
  3824. // If the active flag is not set, then the queue is not busy or there is
  3825. // a request being processed and the next request should not be started..
  3826. //
  3827. if (!(LogicalUnit->LuFlags & LU_LOGICAL_UNIT_IS_ACTIVE) ||
  3828. (LogicalUnit->QueueCount >= LogicalUnit->MaxQueueDepth)) {
  3829. //
  3830. // Release the spinlock.
  3831. //
  3832. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
  3833. return;
  3834. }
  3835. //
  3836. // Check for pending requests, queue full or busy requests. Pending
  3837. // requests occur when untagged request is started and there are active
  3838. // queued requests. Busy requests occur when the target returns a BUSY
  3839. // or QUEUE FULL status. Busy requests are started by the timer code.
  3840. // Also if the need request sense flag is set, it indicates that
  3841. // an error status was detected on the logical unit. No new requests
  3842. // should be started until this flag is cleared. This flag is cleared
  3843. // by an untagged command that by-passes the LU queue i.e.
  3844. //
  3845. // The busy flag and the need request sense flag have the effect of
  3846. // forcing the queue of outstanding requests to drain after an error or
  3847. // until a busy request gets started.
  3848. //
  3849. if (TEST_FLAG(LogicalUnit->LuFlags, (LU_QUEUE_FROZEN |
  3850. LU_QUEUE_LOCKED))) {
  3851. #if DBG
  3852. DebugPrint((1, "ScsiPort: GetNextLuRequest: Ignoring a get next lu "
  3853. "call for %#p - \n", LogicalUnit));
  3854. if(TEST_FLAG(LogicalUnit->LuFlags, LU_QUEUE_FROZEN)) {
  3855. DebugPrint((1, "\tQueue is frozen\n"));
  3856. }
  3857. if(TEST_FLAG(LogicalUnit->LuFlags, LU_QUEUE_LOCKED)) {
  3858. DebugPrint((1, "\tQueue is locked\n"));
  3859. }
  3860. #endif
  3861. //
  3862. // Note the active flag is not cleared. So the next request
  3863. // will be processed when the other requests have completed.
  3864. // Release the spinlock
  3865. //
  3866. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
  3867. return;
  3868. }
  3869. if (TEST_FLAG(LogicalUnit->LuFlags, LU_PENDING_LU_REQUEST |
  3870. LU_LOGICAL_UNIT_IS_BUSY |
  3871. LU_QUEUE_IS_FULL |
  3872. LU_NEED_REQUEST_SENSE)) {
  3873. //
  3874. // If the request queue is now empty, then the pending request can
  3875. // be started.
  3876. //
  3877. if (IsListEmpty(&LogicalUnit->RequestList) &&
  3878. !TEST_FLAG(LogicalUnit->LuFlags, LU_LOGICAL_UNIT_IS_BUSY |
  3879. LU_QUEUE_IS_FULL |
  3880. LU_NEED_REQUEST_SENSE)) {
  3881. PSRB_DATA nextSrbData;
  3882. ASSERT(LogicalUnit->CurrentUntaggedRequest == NULL);
  3883. //
  3884. // Clear the pending bit and active flag, release the spinlock,
  3885. // and start the pending request.
  3886. //
  3887. CLEAR_FLAG(LogicalUnit->LuFlags, LU_PENDING_LU_REQUEST |
  3888. LU_LOGICAL_UNIT_IS_ACTIVE);
  3889. nextSrbData = LogicalUnit->PendingRequest;
  3890. LogicalUnit->PendingRequest = NULL;
  3891. LogicalUnit->RetryCount = 0;
  3892. //
  3893. // Release the spinlock.
  3894. //
  3895. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
  3896. nextSrbData->TickCount = DeviceExtension->TickCount;
  3897. IoStartPacket(DeviceExtension->CommonExtension.DeviceObject,
  3898. nextSrbData->CurrentIrp,
  3899. (PULONG)NULL,
  3900. NULL);
  3901. return;
  3902. } else {
  3903. DebugPrint((1, "ScsiPort: GetNextLuRequest: Ignoring a get next "
  3904. "lu call.\n"));
  3905. //
  3906. // Note the active flag is not cleared. So the next request
  3907. // will be processed when the other requests have completed.
  3908. // Release the spinlock.
  3909. //
  3910. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
  3911. return;
  3912. }
  3913. }
  3914. //
  3915. // Clear the active flag. If there is another request, the flag will be
  3916. // set again when the request is passed to the miniport.
  3917. //
  3918. CLEAR_FLAG(LogicalUnit->LuFlags, LU_LOGICAL_UNIT_IS_ACTIVE);
  3919. LogicalUnit->RetryCount = 0;
  3920. //
  3921. // Remove the packet from the logical unit device queue. We must use the
  3922. // IfBusy varient here to work around the trivial case where the queue is
  3923. // not actually busy.
  3924. //
  3925. // If a request is returned with scsi BUSY, the device queue busy flag may
  3926. // have already been cleared by the miniport requests a get next lu request
  3927. // in the dispatch routine. In this case, when the busy request is
  3928. // reissued, SpStartIoSynchronized will set the LU_ACTIVE flag assuming
  3929. // this request came out of the queue. Unfortunately it did not and get
  3930. // next lu request will foolishly come down here looking for an active
  3931. // queue and assert on a checked build unless we use the IfBusy varient
  3932. //
  3933. packet = KeRemoveByKeyDeviceQueueIfBusy(
  3934. &LogicalUnit->CommonExtension.DeviceObject->DeviceQueue,
  3935. LogicalUnit->CurrentKey);
  3936. if (packet != NULL) {
  3937. PSRB_DATA srbData;
  3938. nextIrp = CONTAINING_RECORD(packet, IRP, Tail.Overlay.DeviceQueueEntry);
  3939. //
  3940. // Set the new current key.
  3941. //
  3942. irpStack = IoGetCurrentIrpStackLocation(nextIrp);
  3943. srb = (PSCSI_REQUEST_BLOCK)irpStack->Parameters.Others.Argument1;
  3944. srbData = (PSRB_DATA) srb->OriginalRequest;
  3945. ASSERT_SRB_DATA(srbData);
  3946. //
  3947. // Hack to work-around the starvation led to by numerous requests
  3948. // touching the same sector.
  3949. //
  3950. LogicalUnit->CurrentKey = srb->QueueSortKey + 1;
  3951. //
  3952. // Release the spinlock.
  3953. //
  3954. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
  3955. srbData->TickCount = DeviceExtension->TickCount;
  3956. IoStartPacket(DeviceExtension->DeviceObject,
  3957. nextIrp,
  3958. NULL,
  3959. NULL);
  3960. } else {
  3961. //
  3962. // Release the spinlock.
  3963. //
  3964. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
  3965. }
  3966. } // end GetNextLuRequest()
  3967. VOID
  3968. SpLogTimeoutError(
  3969. IN PADAPTER_EXTENSION DeviceExtension,
  3970. IN PIRP Irp,
  3971. IN ULONG UniqueId
  3972. )
  3973. /*++
  3974. Routine Description:
  3975. This function logs an error when a request times out.
  3976. Arguments:
  3977. DeviceExtension - Supplies a pointer to the port device extension.
  3978. Irp - Supplies a pointer to the request which timedout.
  3979. UniqueId - Supplies the UniqueId for this error.
  3980. Return Value:
  3981. None.
  3982. Notes:
  3983. The port device extension spinlock should be held when this routine is
  3984. called.
  3985. --*/
  3986. {
  3987. PIO_ERROR_LOG_PACKET errorLogEntry;
  3988. PIO_STACK_LOCATION irpStack;
  3989. PSRB_DATA srbData;
  3990. PSCSI_REQUEST_BLOCK srb;
  3991. irpStack = IoGetCurrentIrpStackLocation(Irp);
  3992. srb = (PSCSI_REQUEST_BLOCK)irpStack->Parameters.Others.Argument1;
  3993. srbData = srb->OriginalRequest;
  3994. ASSERT_SRB_DATA(srbData);
  3995. if (!srbData) {
  3996. return;
  3997. }
  3998. #define ERRLOG_DATA_ENTRIES 4
  3999. errorLogEntry = (PIO_ERROR_LOG_PACKET)
  4000. IoAllocateErrorLogEntry(DeviceExtension->DeviceObject,
  4001. (sizeof(IO_ERROR_LOG_PACKET) +
  4002. (ERRLOG_DATA_ENTRIES * sizeof(ULONG))));
  4003. if (errorLogEntry != NULL) {
  4004. errorLogEntry->ErrorCode = IO_ERR_TIMEOUT;
  4005. errorLogEntry->SequenceNumber = srbData->SequenceNumber;
  4006. errorLogEntry->MajorFunctionCode = irpStack->MajorFunction;
  4007. errorLogEntry->RetryCount = (UCHAR) srbData->ErrorLogRetryCount;
  4008. errorLogEntry->UniqueErrorValue = UniqueId;
  4009. errorLogEntry->FinalStatus = STATUS_SUCCESS;
  4010. errorLogEntry->DumpDataSize = ERRLOG_DATA_ENTRIES * sizeof(ULONG);
  4011. errorLogEntry->DumpData[0] = srb->PathId;
  4012. errorLogEntry->DumpData[1] = srb->TargetId;
  4013. errorLogEntry->DumpData[2] = srb->Lun;
  4014. errorLogEntry->DumpData[3] = SP_REQUEST_TIMEOUT;
  4015. #undef ERRLOG_DATA_ENTRIES
  4016. IoWriteErrorLogEntry(errorLogEntry);
  4017. }
  4018. }
  4019. VOID
  4020. SpLogResetError(
  4021. IN PADAPTER_EXTENSION DeviceExtension,
  4022. IN PSCSI_REQUEST_BLOCK Srb,
  4023. IN ULONG UniqueId
  4024. )
  4025. /*++
  4026. Routine Description:
  4027. This function logs an error when the bus is reset.
  4028. Arguments:
  4029. DeviceExtension - Supplies a pointer to the port device extension.
  4030. Srb - Supplies a pointer to the request which timed-out.
  4031. UniqueId - Supplies the UniqueId for this error.
  4032. Return Value:
  4033. None.
  4034. Notes:
  4035. The port device extension spinlock should be held when this routine is
  4036. called.
  4037. --*/
  4038. {
  4039. PIO_ERROR_LOG_PACKET errorLogEntry;
  4040. PIO_STACK_LOCATION irpStack;
  4041. PIRP irp;
  4042. PSRB_DATA srbData;
  4043. ULONG sequenceNumber = 0;
  4044. UCHAR function = 0,
  4045. pathId = 0,
  4046. targetId = 0,
  4047. lun = 0,
  4048. retryCount = 0;
  4049. if (Srb) {
  4050. srbData = Srb->OriginalRequest;
  4051. ASSERT(srbData != NULL);
  4052. ASSERT_SRB_DATA(srbData);
  4053. irp = srbData->CurrentIrp;
  4054. if (irp) {
  4055. irpStack = IoGetCurrentIrpStackLocation(irp);
  4056. function = irpStack->MajorFunction;
  4057. }
  4058. pathId = Srb->PathId;
  4059. targetId = Srb->TargetId;
  4060. lun = Srb->Lun;
  4061. retryCount = (UCHAR) srbData->ErrorLogRetryCount;
  4062. sequenceNumber = srbData->SequenceNumber;
  4063. }
  4064. #define ERRLOG_DATA_ENTRIES 4
  4065. errorLogEntry = (PIO_ERROR_LOG_PACKET)
  4066. IoAllocateErrorLogEntry(DeviceExtension->DeviceObject,
  4067. (sizeof(IO_ERROR_LOG_PACKET) +
  4068. (ERRLOG_DATA_ENTRIES * sizeof(ULONG))));
  4069. if (errorLogEntry != NULL) {
  4070. errorLogEntry->ErrorCode = IO_ERR_TIMEOUT;
  4071. errorLogEntry->SequenceNumber = sequenceNumber;
  4072. errorLogEntry->MajorFunctionCode = function;
  4073. errorLogEntry->RetryCount = retryCount;
  4074. errorLogEntry->UniqueErrorValue = UniqueId;
  4075. errorLogEntry->FinalStatus = STATUS_SUCCESS;
  4076. errorLogEntry->DumpDataSize = ERRLOG_DATA_ENTRIES * sizeof(ULONG);
  4077. errorLogEntry->DumpData[0] = pathId;
  4078. errorLogEntry->DumpData[1] = targetId;
  4079. errorLogEntry->DumpData[2] = lun;
  4080. errorLogEntry->DumpData[3] = SP_REQUEST_TIMEOUT;
  4081. IoWriteErrorLogEntry(errorLogEntry);
  4082. }
  4083. #undef ERRLOG_DATA_ENTRIES
  4084. }
  4085. BOOLEAN
  4086. SpResetBusSynchronized (
  4087. PVOID ServiceContext
  4088. )
  4089. /*++
  4090. Routine Description:
  4091. This function resets the bus and sets up the port timer so the reset hold
  4092. flag is clean when necessary.
  4093. Arguments:
  4094. ServiceContext - Supplies a pointer to the reset context which includes a
  4095. pointer to the device extension and the pathid to be reset.
  4096. Return Value:
  4097. TRUE - if the reset succeeds.
  4098. --*/
  4099. {
  4100. PRESET_CONTEXT resetContext = ServiceContext;
  4101. PADAPTER_EXTENSION deviceExtension;
  4102. BOOLEAN result;
  4103. deviceExtension = resetContext->DeviceExtension;
  4104. if(TEST_FLAG(deviceExtension->InterruptData.InterruptFlags,
  4105. PD_ADAPTER_REMOVED)) {
  4106. return FALSE;
  4107. }
  4108. result = deviceExtension->HwResetBus(deviceExtension->HwDeviceExtension,
  4109. resetContext->PathId);
  4110. //
  4111. // Set the reset hold flag and start the counter.
  4112. //
  4113. deviceExtension->InterruptData.InterruptFlags |= PD_RESET_HOLD;
  4114. deviceExtension->PortTimeoutCounter = PD_TIMER_RESET_HOLD_TIME;
  4115. //
  4116. // Check for miniport work requests.
  4117. //
  4118. if (deviceExtension->InterruptData.InterruptFlags & PD_NOTIFICATION_REQUIRED) {
  4119. //
  4120. // Queue a DPC.
  4121. //
  4122. SpRequestCompletionDpc(deviceExtension->CommonExtension.DeviceObject);
  4123. }
  4124. return(result);
  4125. }
  4126. VOID
  4127. SpProcessCompletedRequest(
  4128. IN PADAPTER_EXTENSION DeviceExtension,
  4129. IN PSRB_DATA SrbData,
  4130. OUT PBOOLEAN CallStartIo
  4131. )
  4132. /*++
  4133. Routine Description:
  4134. This routine processes a request which has completed. It completes any
  4135. pending transfers, releases the adapter objects and map registers when
  4136. necessary. It deallocates any resources allocated for the request.
  4137. It processes the return status, by requeueing busy request, requesting
  4138. sense information or logging an error.
  4139. Arguments:
  4140. DeviceExtension - Supplies a pointer to the device extension for the
  4141. adapter data.
  4142. SrbData - Supplies a pointer to the SRB data block to be completed.
  4143. CallStartIo - This value is set if the start I/O routine needs to be
  4144. called.
  4145. Return Value:
  4146. None.
  4147. --*/
  4148. {
  4149. PLOGICAL_UNIT_EXTENSION logicalUnit;
  4150. PSCSI_REQUEST_BLOCK srb;
  4151. PIO_ERROR_LOG_PACKET errorLogEntry;
  4152. ULONG sequenceNumber;
  4153. LONG interlockResult;
  4154. PIRP irp;
  4155. PDEVICE_OBJECT deviceObject = DeviceExtension->DeviceObject;
  4156. NTSTATUS internalStatus = SrbData->InternalStatus;
  4157. ASSERT_SRB_DATA(SrbData);
  4158. srb = SrbData->CurrentSrb;
  4159. irp = SrbData->CurrentIrp;
  4160. logicalUnit = SrbData->LogicalUnit;
  4161. //
  4162. // If miniport needs mapped system addresses, the the
  4163. // data buffer address in the SRB must be restored to
  4164. // original unmapped virtual address. Ensure that this request requires
  4165. // a data transfer.
  4166. //
  4167. if (TEST_FLAG(srb->SrbFlags, SRB_FLAGS_UNSPECIFIED_DIRECTION)) {
  4168. //
  4169. // Restore the data buffer pointer to the original value.
  4170. //
  4171. srb->DataBuffer = SrbData->OriginalDataBuffer;
  4172. //
  4173. // If we map every transfer then obviously we need to flush now.
  4174. // However the only way we know that we've forced a mapping for a
  4175. // particular command (like we will for INQUIRY & REQUEST_SENSE ... see
  4176. // IS_MAPPED_SRB) is to see if there's a RemappedMdl.
  4177. //
  4178. // NOTE: this will not figure out if a miniport which did not
  4179. // orignally request mapped buffers needs to have the caches flushed
  4180. // unless we're remapping buffers (so a 32-bit driver on a 32-bit
  4181. // system will not get through here when completing an INQUIRY command).
  4182. // This should be okay - most drivers which need INQUIRYs mapped do so
  4183. // because they write to the memory normally, not because they're using
  4184. // PIO to get the data from machine registers.
  4185. //
  4186. if ((DeviceExtension->MapBuffers) || (SrbData->RemappedMdl)) {
  4187. if (irp->MdlAddress) {
  4188. //
  4189. // If an IRP is for a transfer larger than a miniport driver
  4190. // can handle, the request is broken up into multiple smaller
  4191. // requests. Each request uses the same MDL and the data
  4192. // buffer address field in the SRB may not be at the
  4193. // beginning of the memory described by the MDL.
  4194. //
  4195. //
  4196. // Since this driver driver did programmaged I/O then the buffer
  4197. // needs to flushed if this an data-in transfer.
  4198. //
  4199. if (srb->SrbFlags & SRB_FLAGS_DATA_IN) {
  4200. KeFlushIoBuffers(irp->MdlAddress,
  4201. TRUE,
  4202. FALSE);
  4203. }
  4204. }
  4205. //
  4206. // If this request has a remapped buffer then unmap it and release
  4207. // the remapped MDL.
  4208. //
  4209. if(SrbData->RemappedMdl) {
  4210. PVOID remappedAddress;
  4211. ASSERT(TEST_FLAG(SrbData->RemappedMdl->MdlFlags,
  4212. MDL_MAPPED_TO_SYSTEM_VA));
  4213. #if defined(FORWARD_PROGRESS)
  4214. if (TEST_FLAG(SrbData->Flags, SRB_DATA_RESERVED_PAGES)) {
  4215. DebugPrint((1, "SpProcessCompletedRequest: unmapping remapped buffer from reserved range DevExt:%p srb:%p\n",
  4216. DeviceExtension, srb));
  4217. //
  4218. // This request is using the adapter's reserved PTE range
  4219. // to map the MDL's pages. Unmap the pages and release
  4220. // our claim on the reserve range.
  4221. //
  4222. KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock);
  4223. ASSERT(TEST_FLAG(DeviceExtension->Flags, PD_RESERVED_PAGES_IN_USE));
  4224. MmUnmapReservedMapping(DeviceExtension->ReservedPages,
  4225. SCSIPORT_TAG_MAPPING_LIST,
  4226. SrbData->RemappedMdl);
  4227. CLEAR_FLAG(DeviceExtension->Flags, PD_RESERVED_PAGES_IN_USE);
  4228. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
  4229. CLEAR_FLAG(SrbData->Flags, SRB_DATA_RESERVED_PAGES);
  4230. } else {
  4231. remappedAddress =
  4232. SpGetSystemAddressForMdlSafe(
  4233. SrbData->RemappedMdl,
  4234. ((irp->RequestorMode == KernelMode) ?
  4235. HighPagePriority : NormalPagePriority));
  4236. if (remappedAddress != NULL) {
  4237. MmUnmapLockedPages(remappedAddress,
  4238. SrbData->RemappedMdl);
  4239. }
  4240. }
  4241. //
  4242. // Check if the request is using the adapter's reserved MDL.
  4243. // If it is, we don't free it.
  4244. //
  4245. if (TEST_FLAG(SrbData->Flags, SRB_DATA_RESERVED_MDL)) {
  4246. DebugPrint((1, "SpProcessCompletedRequest: releasing reserved MDL DevExt:%p srb:%p\n",
  4247. DeviceExtension, srb));
  4248. //
  4249. // This request is using the adapter's reserved MDL.
  4250. // Release our claim on it now so another request can
  4251. // use it.
  4252. //
  4253. KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock);
  4254. ASSERT(TEST_FLAG(DeviceExtension->Flags, PD_RESERVED_MDL_IN_USE));
  4255. CLEAR_FLAG(DeviceExtension->Flags, PD_RESERVED_MDL_IN_USE);
  4256. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
  4257. CLEAR_FLAG(SrbData->Flags, SRB_DATA_RESERVED_MDL);
  4258. } else {
  4259. IoFreeMdl(SrbData->RemappedMdl);
  4260. }
  4261. #else
  4262. remappedAddress =
  4263. SpGetSystemAddressForMdl(
  4264. SrbData->RemappedMdl,
  4265. ((irp->RequestorMode == KernelMode) ?
  4266. HightPagePriority : NormalPagePriority));
  4267. if (remappedAddress != NULL) {
  4268. MmUnmapLockedPages(remappedAddress, SrbData->RemappedMdl);
  4269. }
  4270. IoFreeMdl(SrbData->RemappedMdl);
  4271. #endif
  4272. SrbData->RemappedMdl = NULL;
  4273. }
  4274. }
  4275. }
  4276. //
  4277. // Flush the adapter buffers if necessary.
  4278. //
  4279. if (SrbData->MapRegisterBase) {
  4280. PCHAR dataVirtualAddress;
  4281. //
  4282. // We're using the base address of the original MDL - compensate
  4283. // for the offset of the srb's data buffer.
  4284. //
  4285. // Note: For master devices that scsiport considers slaves, we
  4286. // store the map register base in the SRB_DATA independent of
  4287. // whether the request is actually an IO request. So we must
  4288. // check if there is a valid MDL.
  4289. //
  4290. dataVirtualAddress = (PCHAR) ((irp->MdlAddress != NULL) ?
  4291. MmGetMdlVirtualAddress(irp->MdlAddress) : NULL);
  4292. dataVirtualAddress += SrbData->DataOffset;
  4293. #ifdef USE_DMA_MACROS
  4294. PutScatterGatherList(
  4295. DeviceExtension->DmaAdapterObject,
  4296. SrbData->MapRegisterBase,
  4297. (BOOLEAN)(srb->SrbFlags & SRB_FLAGS_DATA_IN ? FALSE : TRUE));
  4298. SrbData->ScatterGatherList = NULL;
  4299. #else
  4300. if (DeviceExtension->MasterWithAdapter == FALSE &&
  4301. irp->MdlAddress == NULL) {
  4302. //
  4303. // To scsiport, this is a slave device. Since there is no MDL,
  4304. // don't try to flush the buffer.
  4305. //
  4306. NOTHING;
  4307. } else {
  4308. //
  4309. // Since we are a master call I/O flush adapter buffers with a NULL
  4310. // adapter.
  4311. //
  4312. FlushAdapterBuffers(DeviceExtension->DmaAdapterObject,
  4313. irp->MdlAddress,
  4314. SrbData->MapRegisterBase,
  4315. dataVirtualAddress,
  4316. srb->DataTransferLength,
  4317. (BOOLEAN)(srb->SrbFlags & SRB_FLAGS_DATA_IN ? FALSE : TRUE));
  4318. }
  4319. //
  4320. // Free the map registers.
  4321. //
  4322. FreeMapRegisters(DeviceExtension->DmaAdapterObject,
  4323. SrbData->MapRegisterBase,
  4324. SrbData->NumberOfMapRegisters);
  4325. #endif
  4326. //
  4327. // Clear the MapRegisterBase.
  4328. //
  4329. SrbData->MapRegisterBase = NULL;
  4330. }
  4331. //
  4332. // Clear the current untagged request if this one is it.
  4333. //
  4334. if(SrbData == logicalUnit->CurrentUntaggedRequest) {
  4335. ASSERT(SrbData->CurrentSrb->QueueTag == SP_UNTAGGED);
  4336. logicalUnit->CurrentUntaggedRequest = NULL;
  4337. }
  4338. #if defined(FORWARD_PROGRESS)
  4339. //
  4340. // If we used the adapter's reserved range on this request, we need to
  4341. // unmap the pages and start the next request if the miniport is ready
  4342. // for it.
  4343. //
  4344. if (TEST_FLAG(SrbData->Flags, SRB_DATA_RESERVED_PAGES)) {
  4345. DebugPrint((1, "SpProcessCompletedRequest: unmapping reserved range DevExt:%p SRB:%p\n",
  4346. DeviceExtension, srb));
  4347. KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock);
  4348. //
  4349. // The reserved pages should be in use.
  4350. //
  4351. ASSERT(TEST_FLAG(DeviceExtension->Flags, PD_RESERVED_PAGES_IN_USE));
  4352. //
  4353. // Unmap the reserved pages.
  4354. //
  4355. MmUnmapReservedMapping(DeviceExtension->ReservedPages,
  4356. SCSIPORT_TAG_MAPPING_LIST,
  4357. irp->MdlAddress);
  4358. //
  4359. // Indicate that the reserved pages are no longer in use so the
  4360. // next request can be started.
  4361. //
  4362. CLEAR_FLAG(SrbData->Flags, SRB_DATA_RESERVED_PAGES);
  4363. CLEAR_FLAG(DeviceExtension->Flags, PD_RESERVED_PAGES_IN_USE);
  4364. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
  4365. }
  4366. #endif
  4367. //
  4368. // If the no disconnect flag was set for this SRB, then check to see
  4369. // if SpStartNextPacket must be called.
  4370. //
  4371. if (TEST_FLAG(srb->SrbFlags, SRB_FLAGS_DISABLE_DISCONNECT)) {
  4372. //
  4373. // Acquire the spinlock to protect the flags strcuture.
  4374. //
  4375. KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock);
  4376. //
  4377. // Set the disconnect running flag and check the busy flag.
  4378. //
  4379. SET_FLAG(DeviceExtension->Flags, PD_DISCONNECT_RUNNING);
  4380. //
  4381. // The interrupt flags are checked unsynchonized. This works because
  4382. // the RESET_HOLD flag is cleared with the spinlock held and the
  4383. // counter is only set with the spinlock held. So the only case where
  4384. // there is a problem is is a reset occurs before this code get run,
  4385. // but this code runs before the timer is set for a reset hold;
  4386. // the timer will soon set for the new value.
  4387. //
  4388. if (!TEST_FLAG(DeviceExtension->InterruptData.InterruptFlags,
  4389. PD_RESET_HOLD)) {
  4390. //
  4391. // The miniport is ready for the next request and there is not a
  4392. // pending reset hold, so clear the port timer.
  4393. //
  4394. DeviceExtension->PortTimeoutCounter = PD_TIMER_STOPPED;
  4395. }
  4396. //
  4397. // Release the spinlock.
  4398. //
  4399. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
  4400. if (!(*CallStartIo) &&
  4401. !TEST_FLAG(DeviceExtension->Flags, (PD_DEVICE_IS_BUSY |
  4402. PD_PENDING_DEVICE_REQUEST))) {
  4403. //
  4404. // The busy flag is clear so the miniport has requested the
  4405. // next request. Call SpStartNextPacket.
  4406. //
  4407. SpStartNextPacket(DeviceExtension->DeviceObject, FALSE);
  4408. }
  4409. }
  4410. #ifndef USE_DMA_MACROS
  4411. if(SrbData->ScatterGatherList != NULL) {
  4412. SpFreeSGList(DeviceExtension, SrbData);
  4413. }
  4414. #endif
  4415. //
  4416. // Move bytes transfered to IRP.
  4417. //
  4418. irp->IoStatus.Information = srb->DataTransferLength;
  4419. //
  4420. // Save the sequence number in case an error needs to be logged later.
  4421. //
  4422. sequenceNumber = SrbData->SequenceNumber;
  4423. SrbData->ErrorLogRetryCount = 0;
  4424. //
  4425. // Acquire the spinlock to protect the flags structure,
  4426. // and the free of the srb extension.
  4427. //
  4428. KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock);
  4429. //
  4430. // Free SrbExtension to list if necessary.
  4431. //
  4432. if (srb->SrbExtension) {
  4433. if ((srb->Function != SRB_FUNCTION_WMI) &&
  4434. DeviceExtension->AutoRequestSense &&
  4435. (srb->SenseInfoBuffer != NULL)) {
  4436. ASSERT(SrbData->RequestSenseSave != NULL ||
  4437. srb->SenseInfoBuffer == NULL);
  4438. //
  4439. // If the request sense data is valid then copy the data to the
  4440. // real buffer.
  4441. //
  4442. if (TEST_FLAG(srb->SrbStatus, SRB_STATUS_AUTOSENSE_VALID)) {
  4443. //
  4444. // If WMI Sense Data events are enabled for this adapter, fire
  4445. // the event.
  4446. //
  4447. if (DeviceExtension->EnableSenseDataEvent) {
  4448. NTSTATUS status;
  4449. status = SpFireSenseDataEvent(srb, deviceObject);
  4450. if (status != STATUS_SUCCESS) {
  4451. DebugPrint((1, "Failed to send SenseData WMI event (%08X)\n", status));
  4452. }
  4453. }
  4454. //
  4455. // Check the srb flags to see if we are supposed to allocate
  4456. // the sense data buffer. The buffer we allocate will be
  4457. // freed for us by whoever is requesting us to do the
  4458. // allocation.
  4459. //
  4460. if (srb->SrbFlags & SRB_FLAGS_PORT_DRIVER_ALLOCSENSE) {
  4461. PSENSE_DATA ReturnBuffer;
  4462. UCHAR AlignmentFixup;
  4463. ULONG BufferSize;
  4464. //
  4465. // We communicate the scsi port number to the class driver
  4466. // by allocating enough space in the sense buffer and
  4467. // copying it there. We align the location into which we
  4468. // copy the port number on a 4-byte boundary.
  4469. //
  4470. AlignmentFixup =
  4471. ((srb->SenseInfoBufferLength + 3) & ~3)
  4472. - srb->SenseInfoBufferLength;
  4473. BufferSize = srb->SenseInfoBufferLength
  4474. + AlignmentFixup
  4475. + sizeof(ULONG64);
  4476. ReturnBuffer = SpAllocatePool(
  4477. NonPagedPoolCacheAligned,
  4478. BufferSize,
  4479. SCSIPORT_TAG_SENSE_BUFFER,
  4480. deviceObject->DriverObject);
  4481. if (ReturnBuffer) {
  4482. PULONG PortNumber;
  4483. //
  4484. // Set a flag in the SRB to indicate that we have
  4485. // allocated a new sense buffer and that the class
  4486. // driver must free it.
  4487. //
  4488. SET_FLAG(srb->SrbFlags,
  4489. SRB_FLAGS_FREE_SENSE_BUFFER);
  4490. //
  4491. // We've successfully allocated a sense buffer.
  4492. // Set a flag in the srb flags to indicate that
  4493. // the scsi port number resides adjacent to the
  4494. // sense info.
  4495. //
  4496. srb->SrbFlags |= SRB_FLAGS_PORT_DRIVER_SENSEHASPORT;
  4497. //
  4498. // Initialize a pointer to the location at the end of
  4499. // the sense buffer into which we copy the scsi port
  4500. // number.
  4501. //
  4502. PortNumber = (PULONG)((PUCHAR)ReturnBuffer
  4503. + srb->SenseInfoBufferLength
  4504. + AlignmentFixup);
  4505. *PortNumber = DeviceExtension->PortNumber;
  4506. //
  4507. // Overwrite the pointer we've saved to the original
  4508. // sense buffer passed down to us with the one we've
  4509. // allocated. This is where we will copy the sense
  4510. // data we've collected in our own buffer.
  4511. //
  4512. SrbData->RequestSenseSave = ReturnBuffer;
  4513. } else {
  4514. srb->SenseInfoBufferLength =
  4515. SrbData->RequestSenseLengthSave;
  4516. }
  4517. } else {
  4518. //
  4519. // Restore the original sense info buffer length which we
  4520. // modified in SpAllocateSrbExtension. We modified then
  4521. // to reflect the adapter specified size.
  4522. //
  4523. srb->SenseInfoBufferLength = SrbData->RequestSenseLengthSave;
  4524. }
  4525. //
  4526. // Copy the sense info we've collected in our own buffer into
  4527. // a buffer that is returned back up the stack. This may be
  4528. // the buffer supplied to us, or it may be one we've allocated.
  4529. //
  4530. RtlCopyMemory(SrbData->RequestSenseSave,
  4531. srb->SenseInfoBuffer,
  4532. srb->SenseInfoBufferLength);
  4533. } else {
  4534. //
  4535. // If there is no request sense data, restore the request sense
  4536. // length.
  4537. //
  4538. srb->SenseInfoBufferLength = SrbData->RequestSenseLengthSave;
  4539. }
  4540. //
  4541. // Restore the SenseInfoBuffer pointer in the srb.
  4542. //
  4543. srb->SenseInfoBuffer = SrbData->RequestSenseSave;
  4544. }
  4545. if (SpVerifyingCommonBuffer(DeviceExtension)) {
  4546. SpInsertSrbExtension(DeviceExtension,
  4547. srb->SrbExtension);
  4548. } else {
  4549. *((PVOID *) srb->SrbExtension) = DeviceExtension->SrbExtensionListHeader;
  4550. DeviceExtension->SrbExtensionListHeader = srb->SrbExtension;
  4551. }
  4552. }
  4553. //
  4554. // Decrement the queue count for the logical unit.
  4555. //
  4556. logicalUnit->QueueCount--;
  4557. if (DeviceExtension->Flags & PD_PENDING_DEVICE_REQUEST) {
  4558. //
  4559. // The start I/O routine needs to be called because it could not
  4560. // allocate an srb extension. Clear the pending flag and note
  4561. // that it needs to be called later.
  4562. //
  4563. DebugPrint(((deviceObject->CurrentIrp == NULL) ? 0 : 2,
  4564. "SpProcessCompletedRequest(%#p): will call start "
  4565. "i/o when we return to process irp %#p\n",
  4566. SrbData,
  4567. deviceObject->CurrentIrp));
  4568. ASSERT(deviceObject->CurrentIrp != NULL);
  4569. DeviceExtension->Flags &= ~PD_PENDING_DEVICE_REQUEST;
  4570. *CallStartIo = TRUE;
  4571. }
  4572. //
  4573. // If success then start next packet.
  4574. // Not starting packet effectively
  4575. // freezes the queue.
  4576. //
  4577. if (SRB_STATUS(srb->SrbStatus) == SRB_STATUS_SUCCESS) {
  4578. irp->IoStatus.Status = STATUS_SUCCESS;
  4579. //
  4580. // If the queue is being bypassed then keep the queue frozen.
  4581. // If there are outstanding requests as indicated by the timer
  4582. // being active then don't start the then next request.
  4583. //
  4584. if(!TEST_FLAG(srb->SrbFlags, SRB_FLAGS_BYPASS_FROZEN_QUEUE) &&
  4585. logicalUnit->RequestTimeoutCounter == PD_TIMER_STOPPED) {
  4586. //
  4587. // This is a normal request start the next packet.
  4588. //
  4589. GetNextLuRequest(logicalUnit);
  4590. } else {
  4591. //
  4592. // Release the spinlock.
  4593. //
  4594. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
  4595. }
  4596. DebugPrint((3,
  4597. "SpProcessCompletedRequests: Iocompletion IRP %p\n",
  4598. irp));
  4599. //
  4600. // Note that the retry count and sequence number are not cleared
  4601. // for completed packets which were generated by the port driver.
  4602. //
  4603. srb->OriginalRequest = irp;
  4604. SpReleaseRemoveLock(deviceObject, irp);
  4605. SpCompleteRequest(deviceObject, irp, SrbData, IO_DISK_INCREMENT);
  4606. //
  4607. // Decrement the number of active requests. If the count is negitive, and
  4608. // this is a slave with an adapter then free the adapter object and
  4609. // map registers. Doing this allows another request to be started for
  4610. // this logical unit before adapter is released.
  4611. //
  4612. interlockResult = InterlockedDecrement( &DeviceExtension->ActiveRequestCount );
  4613. if ((interlockResult < 0) &&
  4614. (!DeviceExtension->PortConfig->Master) &&
  4615. (DeviceExtension->DmaAdapterObject != NULL)) {
  4616. //
  4617. // Clear the map register base for safety.
  4618. //
  4619. DeviceExtension->MapRegisterBase = NULL;
  4620. FreeAdapterChannel(DeviceExtension->DmaAdapterObject);
  4621. }
  4622. return;
  4623. }
  4624. //
  4625. // Decrement the number of active requests. If the count is negative, and
  4626. // this is a slave with an adapter then free the adapter object and
  4627. // map registers.
  4628. //
  4629. interlockResult = InterlockedDecrement( &DeviceExtension->ActiveRequestCount );
  4630. if (interlockResult < 0 &&
  4631. !DeviceExtension->PortConfig->Master &&
  4632. DeviceExtension->DmaAdapterObject != NULL) {
  4633. //
  4634. // Clear the map register base for safety.
  4635. //
  4636. DeviceExtension->MapRegisterBase = NULL;
  4637. FreeAdapterChannel(DeviceExtension->DmaAdapterObject);
  4638. }
  4639. //
  4640. // Set IRP status. Class drivers will reset IRP status based
  4641. // on request sense if error.
  4642. //
  4643. if(srb->SrbStatus != SRB_STATUS_INTERNAL_ERROR) {
  4644. irp->IoStatus.Status = SpTranslateScsiStatus(srb);
  4645. } else {
  4646. ASSERT(srb->ScsiStatus == 0xff);
  4647. ASSERT(logicalUnit->ActiveFailedRequest != SrbData);
  4648. ASSERT(logicalUnit->BlockedFailedRequest != SrbData);
  4649. srb->InternalStatus = internalStatus;
  4650. irp->IoStatus.Status = internalStatus;
  4651. }
  4652. DebugPrint((2, "SpProcessCompletedRequests: Queue frozen TID %d\n",
  4653. srb->TargetId));
  4654. //
  4655. // Perform busy processing if a busy type status was returned and this
  4656. // is not a recovery request.
  4657. //
  4658. // For now we're choosing to complete the SRB's with BYPASS_FROZEN_QUEUE
  4659. // set in them if they are completed as BUSY.
  4660. // Though if we wanted to do busy processing on them, the
  4661. // if statement below should be changed, along with the next if statement
  4662. // to get them to be placed on the lun-extension slot, and then
  4663. // modify the scsiport tick handler so that it will retry SRB's
  4664. // that have the BYPASS_FROZEN_QUEUE flag set when the queue is frozen.
  4665. //
  4666. if ((srb->ScsiStatus == SCSISTAT_BUSY ||
  4667. srb->SrbStatus == SRB_STATUS_BUSY ||
  4668. srb->ScsiStatus == SCSISTAT_QUEUE_FULL) &&
  4669. !(srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE)) {
  4670. DebugPrint((1,
  4671. "SCSIPORT: Busy SRB status %x, SCSI status %x)\n",
  4672. srb->SrbStatus,
  4673. srb->ScsiStatus));
  4674. //
  4675. // Restore the request transfer length in case the miniport
  4676. // destroyed it.
  4677. //
  4678. srb->DataTransferLength = SrbData->OriginalDataTransferLength;
  4679. //
  4680. // If the logical unit is already busy then just requeue this request.
  4681. // Unless the SRB is a BYPASS_LOCKED_QUEUE SRB
  4682. //
  4683. if ((TEST_FLAG(logicalUnit->LuFlags, LU_LOGICAL_UNIT_IS_BUSY)) &&
  4684. (!TEST_FLAG(srb->SrbFlags, SRB_FLAGS_BYPASS_LOCKED_QUEUE))) {
  4685. DebugPrint((1,
  4686. "SpProcessCompletedRequest: Requeuing busy request\n"));
  4687. srb->SrbStatus = SRB_STATUS_PENDING;
  4688. srb->ScsiStatus = 0;
  4689. //
  4690. // Set the tick count so we know how long this request has
  4691. // been queued.
  4692. //
  4693. SrbData->TickCount = DeviceExtension->TickCount;
  4694. if (!KeInsertByKeyDeviceQueue(
  4695. &logicalUnit->DeviceObject->DeviceQueue,
  4696. &irp->Tail.Overlay.DeviceQueueEntry,
  4697. srb->QueueSortKey)) {
  4698. //
  4699. // The LU says it is busy, so there should be a busy request.
  4700. //
  4701. ASSERT(logicalUnit->BusyRequest != NULL);
  4702. //
  4703. // We can arrive here if the LU's device queue was drained by
  4704. // the DCP routine prior to calling us, transitioning the queue
  4705. // from busy to not busy. It is safe for us to force the
  4706. // request into the queue because we know we have a busy
  4707. // request that will get restarted by our TickHandler routine.
  4708. //
  4709. KeInsertByKeyDeviceQueue(
  4710. &logicalUnit->DeviceObject->DeviceQueue,
  4711. &irp->Tail.Overlay.DeviceQueueEntry,
  4712. srb->QueueSortKey);
  4713. }
  4714. //
  4715. // Release the spinlock.
  4716. //
  4717. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
  4718. return;
  4719. } else if (logicalUnit->RetryCount++ < BUSY_RETRY_COUNT) {
  4720. //
  4721. // If busy status is returned, then indicate that the logical
  4722. // unit is busy. The timeout code will restart the request
  4723. // when it fires. Reset the status to pending.
  4724. //
  4725. srb->SrbStatus = SRB_STATUS_PENDING;
  4726. srb->ScsiStatus = 0;
  4727. SET_FLAG(logicalUnit->LuFlags, LU_LOGICAL_UNIT_IS_BUSY);
  4728. logicalUnit->BusyRequest = SrbData;
  4729. //
  4730. // Release the spinlock.
  4731. //
  4732. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
  4733. return;
  4734. } else {
  4735. //
  4736. // Freeze the queue if it isn't already locked.
  4737. //
  4738. if((!TEST_FLAG(logicalUnit->LuFlags, LU_QUEUE_LOCKED)) &&
  4739. !TEST_FLAG(srb->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE)) {
  4740. SET_FLAG(srb->SrbStatus, SRB_STATUS_QUEUE_FROZEN);
  4741. SET_FLAG(logicalUnit->LuFlags, LU_QUEUE_FROZEN);
  4742. }
  4743. //
  4744. // Clear the queue full flag.
  4745. //
  4746. CLEAR_FLAG(logicalUnit->LuFlags, LU_QUEUE_IS_FULL);
  4747. //
  4748. // Log an a timeout erorr.
  4749. //
  4750. #define ERRLOG_DATA_ENTRIES 6
  4751. errorLogEntry = (PIO_ERROR_LOG_PACKET)
  4752. IoAllocateErrorLogEntry(DeviceExtension->DeviceObject,
  4753. (sizeof(IO_ERROR_LOG_PACKET) +
  4754. (ERRLOG_DATA_ENTRIES * sizeof(ULONG))));
  4755. if (errorLogEntry != NULL) {
  4756. errorLogEntry->ErrorCode = IO_ERR_NOT_READY;
  4757. errorLogEntry->SequenceNumber = sequenceNumber;
  4758. errorLogEntry->MajorFunctionCode =
  4759. IoGetCurrentIrpStackLocation(irp)->MajorFunction;
  4760. errorLogEntry->RetryCount = logicalUnit->RetryCount;
  4761. errorLogEntry->UniqueErrorValue = 259;
  4762. errorLogEntry->FinalStatus = STATUS_DEVICE_NOT_READY;
  4763. errorLogEntry->DumpDataSize = ERRLOG_DATA_ENTRIES * sizeof(ULONG);
  4764. errorLogEntry->DumpData[0] = srb->PathId;
  4765. errorLogEntry->DumpData[1] = srb->TargetId;
  4766. errorLogEntry->DumpData[2] = srb->Lun;
  4767. errorLogEntry->DumpData[3] = srb->ScsiStatus;
  4768. errorLogEntry->DumpData[4] = SP_REQUEST_TIMEOUT;
  4769. errorLogEntry->DumpData[5] = srb->SrbStatus;
  4770. IoWriteErrorLogEntry(errorLogEntry);
  4771. }
  4772. #undef ERRLOG_DATA_ENTRIES
  4773. irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
  4774. //
  4775. // Fall through and complete this as a failed request. This that ensures
  4776. // we propagate ourselves by handling any queued requests.
  4777. //
  4778. }
  4779. }
  4780. //
  4781. // If the request sense data is valid, or none is needed and this request
  4782. // is not going to freeze the queue, then start the next request for this
  4783. // logical unit if it is idle.
  4784. //
  4785. if (!NEED_REQUEST_SENSE(srb) &&
  4786. TEST_FLAG(srb->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE)) {
  4787. if (logicalUnit->RequestTimeoutCounter == PD_TIMER_STOPPED) {
  4788. GetNextLuRequest(logicalUnit);
  4789. //
  4790. // The spinlock is released by GetNextLuRequest.
  4791. //
  4792. } else {
  4793. //
  4794. // Release the spinlock.
  4795. //
  4796. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
  4797. }
  4798. } else {
  4799. //
  4800. // NOTE: This will also freeze the queue. For a case where there
  4801. // is no request sense.
  4802. //
  4803. //
  4804. // Don't freeze the queue if it's already been locked. Frozen and
  4805. // locked queue are mutually exclusive.
  4806. //
  4807. if(!TEST_FLAG(logicalUnit->LuFlags, LU_QUEUE_LOCKED)) {
  4808. //
  4809. // If the caller asked us not to freeze the queue and we don't need
  4810. // to do a request sense then don't freeze the queue. If we do
  4811. // need to do a request sense then the queue will be unfrozen
  4812. // once it's finished.
  4813. //
  4814. if(!TEST_FLAG(srb->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE) ||
  4815. NEED_REQUEST_SENSE(srb)) {
  4816. SET_FLAG(srb->SrbStatus, SRB_STATUS_QUEUE_FROZEN);
  4817. SET_FLAG(logicalUnit->LuFlags, LU_QUEUE_FROZEN);
  4818. }
  4819. }
  4820. //
  4821. // Determine if a REQUEST SENSE command needs to be done.
  4822. // Check that a CHECK_CONDITION was received, an autosense has not
  4823. // been done already, and that autosense has been requested.
  4824. //
  4825. if (NEED_REQUEST_SENSE(srb)) {
  4826. //
  4827. // If a request sense is going to be issued then any busy
  4828. // requests must be requeue so that the time out routine does
  4829. // not restart them while the request sense is being executed.
  4830. //
  4831. if (TEST_FLAG(logicalUnit->LuFlags, LU_LOGICAL_UNIT_IS_BUSY)) {
  4832. DebugPrint((1, "SpProcessCompletedRequest: Requeueing busy "
  4833. "request to allow request sense.\n"));
  4834. //
  4835. // Set the tick count so we know how long this request has
  4836. // been queued.
  4837. //
  4838. SrbData->TickCount = DeviceExtension->TickCount;
  4839. if (!KeInsertByKeyDeviceQueue(
  4840. &logicalUnit->CommonExtension.DeviceObject->DeviceQueue,
  4841. &logicalUnit->BusyRequest->CurrentIrp->Tail.Overlay.DeviceQueueEntry,
  4842. srb->QueueSortKey)) {
  4843. //
  4844. // This should never occur since there is a busy request.
  4845. // Complete the current request without request sense
  4846. // informaiton.
  4847. //
  4848. ASSERT(FALSE);
  4849. DebugPrint((3, "SpProcessCompletedRequests: Iocompletion IRP %p\n", irp ));
  4850. //
  4851. // Release the spinlock.
  4852. //
  4853. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
  4854. SpReleaseRemoveLock(deviceObject, irp);
  4855. SpCompleteRequest(deviceObject, irp, SrbData, IO_DISK_INCREMENT);
  4856. return;
  4857. }
  4858. //
  4859. // Clear the busy flag.
  4860. //
  4861. logicalUnit->LuFlags &= ~(LU_LOGICAL_UNIT_IS_BUSY | LU_QUEUE_IS_FULL);
  4862. }
  4863. //
  4864. // Release the spinlock.
  4865. //
  4866. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
  4867. //
  4868. // Call IssueRequestSense and it will complete the request
  4869. // after the REQUEST SENSE completes.
  4870. //
  4871. IssueRequestSense(DeviceExtension, srb);
  4872. return;
  4873. } else {
  4874. ASSERTMSG("Srb is failed request but doesn't indicate needing requests sense: ",
  4875. ((SrbData != logicalUnit->ActiveFailedRequest) &&
  4876. (SrbData != logicalUnit->BlockedFailedRequest)));
  4877. }
  4878. //
  4879. // Release the spinlock.
  4880. //
  4881. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
  4882. }
  4883. SpReleaseRemoveLock(deviceObject, irp);
  4884. SpCompleteRequest(deviceObject, irp, SrbData, IO_DISK_INCREMENT);
  4885. }
  4886. PSRB_DATA
  4887. SpGetSrbData(
  4888. IN PADAPTER_EXTENSION DeviceExtension,
  4889. UCHAR PathId,
  4890. UCHAR TargetId,
  4891. UCHAR Lun,
  4892. UCHAR QueueTag,
  4893. BOOLEAN AcquireBinLock
  4894. )
  4895. /*++
  4896. Routine Description:
  4897. This function returns the SRB data for the addressed unit.
  4898. Arguments:
  4899. DeviceExtension - Supplies a pointer to the device extension.
  4900. Address - Supplies the address of the logical unit.
  4901. QueueTag - Supplies the queue tag if the request is tagged.
  4902. Return Value:
  4903. Returns a pointer to the SRB data. NULL is returned if the address is not
  4904. valid.
  4905. --*/
  4906. {
  4907. PLOGICAL_UNIT_EXTENSION logicalUnit;
  4908. //
  4909. // We're going to have to search the appropriate logical unit for this
  4910. // request.
  4911. //
  4912. logicalUnit = GetLogicalUnitExtension(DeviceExtension,
  4913. PathId,
  4914. TargetId,
  4915. Lun,
  4916. FALSE,
  4917. AcquireBinLock);
  4918. if(logicalUnit == NULL) {
  4919. return NULL;
  4920. }
  4921. //
  4922. // Check for an untagged request.
  4923. //
  4924. if (QueueTag == SP_UNTAGGED) {
  4925. return logicalUnit->CurrentUntaggedRequest;
  4926. } else {
  4927. PLIST_ENTRY listEntry;
  4928. for(listEntry = logicalUnit->RequestList.Flink;
  4929. listEntry != &(logicalUnit->RequestList);
  4930. listEntry = (PLIST_ENTRY) listEntry->Flink) {
  4931. PSRB_DATA srbData;
  4932. srbData = CONTAINING_RECORD(listEntry,
  4933. SRB_DATA,
  4934. RequestList);
  4935. if(srbData->CurrentSrb->QueueTag == QueueTag) {
  4936. return srbData;
  4937. }
  4938. }
  4939. return NULL;
  4940. }
  4941. }
  4942. VOID
  4943. SpCompleteSrb(
  4944. IN PADAPTER_EXTENSION DeviceExtension,
  4945. IN PSRB_DATA SrbData,
  4946. IN UCHAR SrbStatus
  4947. )
  4948. /*++
  4949. Routine Description:
  4950. The routine completes the specified request.
  4951. Arguments:
  4952. DeviceExtension - Supplies a pointer to the device extension.
  4953. SrbData - Supplies a pointer to the SrbData for the request to be
  4954. completed.
  4955. Return Value:
  4956. None.
  4957. --*/
  4958. {
  4959. PSCSI_REQUEST_BLOCK srb;
  4960. //
  4961. // Make sure there is a current request.
  4962. //
  4963. srb = SrbData->CurrentSrb;
  4964. if (srb == NULL || !(srb->SrbFlags & SRB_FLAGS_IS_ACTIVE)) {
  4965. return;
  4966. }
  4967. //
  4968. // Update SRB status.
  4969. //
  4970. srb->SrbStatus = SrbStatus;
  4971. //
  4972. // Indicate no bytes transferred.
  4973. //
  4974. srb->DataTransferLength = 0;
  4975. //
  4976. // Call notification routine.
  4977. //
  4978. ScsiPortNotification(RequestComplete,
  4979. DeviceExtension->HwDeviceExtension,
  4980. srb);
  4981. }
  4982. BOOLEAN
  4983. SpAllocateSrbExtension(
  4984. IN PADAPTER_EXTENSION DeviceExtension,
  4985. IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
  4986. IN PSCSI_REQUEST_BLOCK Srb,
  4987. OUT BOOLEAN *StartNextRequest,
  4988. OUT BOOLEAN *Tagged
  4989. )
  4990. /*++
  4991. Routine Description:
  4992. The routine allocates an SRB data structure and/or an SRB extension for
  4993. the request.
  4994. It first determines if the request is can be executed at this time.
  4995. In particular, untagged requests cannot execute if there are any active
  4996. tagged queue requests. If the request cannot be executed, the pending
  4997. flag is set in the logical unit FALSE is returned. The request will be
  4998. retried after the last tagged queue request completes.
  4999. If one of the structures cannot be allocated, then the pending flag is
  5000. set in the device extension and FALSE is returned. The request will be
  5001. retried the next time a request completes.
  5002. Arguments:
  5003. DeviceExtension - Supplies a pointer to the devcie extension for this
  5004. adapter.
  5005. LogicalUnit - Supplies a pointer to the logical unit that this request is
  5006. is for.
  5007. Srb - Supplies a pointer to the SCSI request.
  5008. StartNextRequest - Pointer to a BOOLEAN that we'll set to TRUE if the caller
  5009. needs to start the next packet.
  5010. Tagged - Supplies a pointer to a BOOLEAN that we'll set to TRUE if the
  5011. request is to receive a queue tag and can be dispatched to the
  5012. miniport while other tagged commands are active.
  5013. Return Value:
  5014. TRUE if the SRB can be execute currently. If FALSE is returneed the reuqest
  5015. should not be started.
  5016. --*/
  5017. {
  5018. PSRB_DATA srbData = (PSRB_DATA) Srb->OriginalRequest;
  5019. PCCHAR srbExtension;
  5020. PCCHAR remappedSrbExt;
  5021. ULONG tagValue = 0;
  5022. ASSERT_SRB_DATA(srbData);
  5023. //
  5024. // Acquire the spinlock while the allocations are attempted.
  5025. //
  5026. KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock);
  5027. //
  5028. // If the adapter supports mulitple requests, then determine if it can
  5029. // be executed.
  5030. //
  5031. if (DeviceExtension->SupportsMultipleRequests == TRUE) {
  5032. //
  5033. // SupportsMultipleRequests means the miniport supports tagged queuing,
  5034. // MultipleRequestPerLu, or both. Here is the way we handle each
  5035. // case:
  5036. // 1) TaggedQueuing and SupportsMultipleLu:
  5037. // In this case, if the command's QUEUE_ACTION_ENABLE bit OR the
  5038. // NO_QUEUE_FREEZE bit is set, we give the command a tag and
  5039. // hand it to the miniport.
  5040. // 2) TaggedQueuing Only:
  5041. // In this case the miniport does not expect to receive any
  5042. // untagged commands while there are active tagged commands, so
  5043. // we only give the SRB a tag if QUEUE_ACTION_ENABLE is set.
  5044. // 3) MultipleRequestPerLu Only:
  5045. // This can be treated the same as case 1. Any command that has
  5046. // QUEUE_ACTION_ENABLE or NO_QUEUE_FREEZE set can be assigned a
  5047. // tag and given to the miniport.
  5048. //
  5049. ULONG tagMask = SRB_FLAGS_QUEUE_ACTION_ENABLE;
  5050. if (DeviceExtension->MultipleRequestPerLu == TRUE) {
  5051. tagMask |= SRB_FLAGS_NO_QUEUE_FREEZE;
  5052. }
  5053. if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND) {
  5054. ASSERT(FALSE);
  5055. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
  5056. return FALSE;
  5057. } else if (TEST_FLAG(Srb->SrbFlags, tagMask) &&
  5058. !TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_DISABLE_DISCONNECT)) {
  5059. //
  5060. // If the need request sense flag is set then tagged commands cannot
  5061. // be started and must be marked as pending.
  5062. //
  5063. *Tagged = TRUE;
  5064. if (TEST_FLAG(LogicalUnit->LuFlags, LU_NEED_REQUEST_SENSE)) {
  5065. DebugPrint((1, "SCSIPORT: SpAllocateSrbExtension: "
  5066. "Marking tagged request as pending.\n"));
  5067. //
  5068. // This request cannot be executed now. Mark it as pending
  5069. // in the logical unit structure and return.
  5070. // GetNextLogicalUnit will restart the commnad after all of the
  5071. // active commands have completed.
  5072. //
  5073. ASSERT(!(LogicalUnit->LuFlags & LU_PENDING_LU_REQUEST));
  5074. ASSERT(LogicalUnit->PendingRequest == NULL);
  5075. LogicalUnit->LuFlags |= LU_PENDING_LU_REQUEST;
  5076. LogicalUnit->PendingRequest = Srb->OriginalRequest;
  5077. LogicalUnit->PendingRequest->TickCount = DeviceExtension->TickCount;
  5078. //
  5079. // Indicate that the logical unit is still active so that the
  5080. // request will get processed when the request list is empty.
  5081. //
  5082. LogicalUnit->LuFlags |= LU_LOGICAL_UNIT_IS_ACTIVE;
  5083. //
  5084. // Notify the caller that it needs to start the next request.
  5085. //
  5086. *StartNextRequest = TRUE;
  5087. //
  5088. // Release the spinlock and return.
  5089. //
  5090. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
  5091. return FALSE;
  5092. }
  5093. } else {
  5094. //
  5095. // This is an untagged command. It is only allowed to execute, if
  5096. // logical unit queue is being by-passed or there are no other
  5097. // requests active.
  5098. //
  5099. *Tagged = FALSE;
  5100. if ((!IsListEmpty(&LogicalUnit->RequestList) ||
  5101. LogicalUnit->LuFlags & LU_NEED_REQUEST_SENSE) &&
  5102. !SpSrbIsBypassRequest(Srb, LogicalUnit->LuFlags)) {
  5103. //
  5104. // This request cannot be executed now. Mark it as pending
  5105. // in the logical unit structure and return.
  5106. // GetNextLogicalUnit will restart the commnad after all of the
  5107. // active commands have completed.
  5108. //
  5109. ASSERT(!(LogicalUnit->LuFlags & LU_PENDING_LU_REQUEST));
  5110. LogicalUnit->LuFlags |= LU_PENDING_LU_REQUEST;
  5111. LogicalUnit->PendingRequest = Srb->OriginalRequest;
  5112. LogicalUnit->PendingRequest->TickCount = DeviceExtension->TickCount;
  5113. //
  5114. // Indicate that the logical unit is still active so that the
  5115. // request will get processed when the request list is empty.
  5116. //
  5117. LogicalUnit->LuFlags |= LU_LOGICAL_UNIT_IS_ACTIVE;
  5118. //
  5119. // Notify the caller that it needs to start the next request.
  5120. //
  5121. *StartNextRequest = TRUE;
  5122. //
  5123. // Release the spinlock and return.
  5124. //
  5125. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
  5126. return FALSE;
  5127. }
  5128. //
  5129. // Set the QueueTag to SP_UNTAGGED
  5130. // Set use the SRB data in the logical unit extension.
  5131. //
  5132. Srb->QueueTag = SP_UNTAGGED;
  5133. srbData->TickCount = DeviceExtension->TickCount;
  5134. LogicalUnit->CurrentUntaggedRequest = srbData;
  5135. }
  5136. } else {
  5137. //
  5138. // The adapter does not support multiple requests.
  5139. //
  5140. *Tagged = FALSE;
  5141. Srb->QueueTag = SP_UNTAGGED;
  5142. srbData->TickCount = DeviceExtension->TickCount;
  5143. LogicalUnit->CurrentUntaggedRequest = srbData;
  5144. }
  5145. ASSERT(Srb->QueueTag != 0);
  5146. if (DeviceExtension->AllocateSrbExtension) {
  5147. //
  5148. // Allocate SRB extension from list if available.
  5149. //
  5150. srbExtension = DeviceExtension->SrbExtensionListHeader;
  5151. //
  5152. // If the Srb extension cannot be allocated, then special processing
  5153. // is required.
  5154. //
  5155. if (srbExtension == NULL) {
  5156. //
  5157. // Indicate there is a pending request. The DPC completion routine
  5158. // will call this function again after it has freed at least one
  5159. // Srb extension.
  5160. //
  5161. DeviceExtension->Flags |= PD_PENDING_DEVICE_REQUEST;
  5162. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
  5163. return FALSE;
  5164. }
  5165. //
  5166. // Remove SRB extension from list.
  5167. //
  5168. DeviceExtension->SrbExtensionListHeader = *((PVOID *) srbExtension);
  5169. if (SpVerifyingCommonBuffer(DeviceExtension)) {
  5170. remappedSrbExt = SpPrepareSrbExtensionForUse(DeviceExtension,
  5171. srbExtension);
  5172. } else {
  5173. remappedSrbExt = NULL;
  5174. }
  5175. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
  5176. Srb->SrbExtension = (remappedSrbExt != NULL) ? remappedSrbExt :
  5177. srbExtension;
  5178. //
  5179. // If the adapter supports auto request sense, the SenseInfoBuffer
  5180. // needs to point to the Srb extension. This buffer is already mapped
  5181. // for the adapter. Note that this is not done for WMI requests.
  5182. //
  5183. if ((Srb->Function != SRB_FUNCTION_WMI) &&
  5184. (DeviceExtension->AutoRequestSense &&
  5185. Srb->SenseInfoBuffer != NULL)) {
  5186. //
  5187. // Save the request sense buffer and the length of the buffer.
  5188. //
  5189. srbData->RequestSenseSave = Srb->SenseInfoBuffer;
  5190. srbData->RequestSenseLengthSave = Srb->SenseInfoBufferLength;
  5191. //
  5192. // Make sure the allocated buffer is large enough for the requested
  5193. // sense buffer.
  5194. //
  5195. if (Srb->SenseInfoBufferLength >
  5196. (sizeof(SENSE_DATA) + DeviceExtension->AdditionalSenseBytes)) {
  5197. //
  5198. // Auto request sense cannot be done for this request sense
  5199. // because the buffer is larger than the adapter supports.
  5200. // Disable auto request sense.
  5201. //
  5202. DebugPrint((1,"SpAllocateSrbExtension: SenseInfoBuffer too big "
  5203. "SenseInfoBufferLength:%x MaxSupported:%x\n",
  5204. Srb->SenseInfoBufferLength,
  5205. (sizeof(SENSE_DATA) + DeviceExtension->AdditionalSenseBytes)));
  5206. Srb->SrbFlags |= SRB_FLAGS_DISABLE_AUTOSENSE;
  5207. } else {
  5208. //
  5209. // Modify the size of the sense buffer to reflect the size of
  5210. // the one we redirect to.
  5211. //
  5212. Srb->SenseInfoBufferLength =
  5213. sizeof(SENSE_DATA) + DeviceExtension->AdditionalSenseBytes;
  5214. //
  5215. // Replace it with the request sense buffer in the Srb
  5216. // extension.
  5217. //
  5218. if (SpVerifyingCommonBuffer(DeviceExtension)) {
  5219. Srb->SenseInfoBuffer = SpPrepareSenseBufferForUse(
  5220. DeviceExtension,
  5221. srbExtension);
  5222. } else {
  5223. Srb->SenseInfoBuffer = srbExtension +
  5224. DeviceExtension->SrbExtensionSize;
  5225. }
  5226. }
  5227. }
  5228. } else {
  5229. Srb->SrbExtension = NULL;
  5230. //
  5231. // Release the spinlock before returning.
  5232. //
  5233. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
  5234. }
  5235. return TRUE;
  5236. }
  5237. NTSTATUS
  5238. SpSendMiniPortIoctl(
  5239. IN PADAPTER_EXTENSION DeviceExtension,
  5240. IN PIRP RequestIrp
  5241. )
  5242. /*++
  5243. Routine Description:
  5244. This function sends a miniport ioctl to the miniport driver.
  5245. It creates an srb which is processed normally by the port driver.
  5246. This call is synchronous.
  5247. Arguments:
  5248. DeviceExtension - Supplies a pointer the SCSI adapter device extension.
  5249. RequestIrp - Supplies a pointe to the Irp which made the original request.
  5250. Return Value:
  5251. Returns a status indicating the success or failure of the operation.
  5252. --*/
  5253. {
  5254. PIRP irp;
  5255. PIO_STACK_LOCATION irpStack;
  5256. PSRB_IO_CONTROL srbControl;
  5257. SCSI_REQUEST_BLOCK srb;
  5258. KEVENT event;
  5259. LARGE_INTEGER startingOffset;
  5260. IO_STATUS_BLOCK ioStatusBlock;
  5261. PLOGICAL_UNIT_EXTENSION logicalUnit;
  5262. ULONG outputLength;
  5263. ULONG length;
  5264. ULONG target;
  5265. NTSTATUS status;
  5266. PAGED_CODE();
  5267. startingOffset.QuadPart = (LONGLONG) 1;
  5268. DebugPrint((3,"SpSendMiniPortIoctl: Enter routine\n"));
  5269. //
  5270. // Get a pointer to the control block.
  5271. //
  5272. irpStack = IoGetCurrentIrpStackLocation(RequestIrp);
  5273. srbControl = RequestIrp->AssociatedIrp.SystemBuffer;
  5274. RequestIrp->IoStatus.Information = 0;
  5275. //
  5276. // Validiate the user buffer.
  5277. //
  5278. if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SRB_IO_CONTROL)){
  5279. RequestIrp->IoStatus.Status = STATUS_INVALID_PARAMETER;
  5280. return(STATUS_INVALID_PARAMETER);
  5281. }
  5282. if (srbControl->HeaderLength != sizeof(SRB_IO_CONTROL)) {
  5283. RequestIrp->IoStatus.Status = STATUS_REVISION_MISMATCH;
  5284. return(STATUS_REVISION_MISMATCH);
  5285. }
  5286. length = srbControl->HeaderLength + srbControl->Length;
  5287. if ((length < srbControl->HeaderLength) ||
  5288. (length < srbControl->Length)) {
  5289. //
  5290. // total length overflows a ULONG
  5291. //
  5292. return(STATUS_INVALID_PARAMETER);
  5293. }
  5294. outputLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  5295. if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < length &&
  5296. irpStack->Parameters.DeviceIoControl.InputBufferLength < length ) {
  5297. RequestIrp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
  5298. return(STATUS_BUFFER_TOO_SMALL);
  5299. }
  5300. //
  5301. // Set the logical unit addressing to the first logical unit. This is
  5302. // merely used for addressing purposes.
  5303. //
  5304. logicalUnit = SpFindSafeLogicalUnit(
  5305. DeviceExtension->CommonExtension.DeviceObject,
  5306. 0xff,
  5307. RequestIrp);
  5308. if (logicalUnit == NULL) {
  5309. RequestIrp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
  5310. return(STATUS_DEVICE_DOES_NOT_EXIST);
  5311. }
  5312. //
  5313. // Must be at PASSIVE_LEVEL to use synchronous FSD.
  5314. //
  5315. ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  5316. //
  5317. // Initialize the notification event.
  5318. //
  5319. KeInitializeEvent(&event,
  5320. NotificationEvent,
  5321. FALSE);
  5322. //
  5323. // Build IRP for this request.
  5324. // Note we do this synchronously for two reasons. If it was done
  5325. // asynchonously then the completion code would have to make a special
  5326. // check to deallocate the buffer. Second if a completion routine were
  5327. // used then an additional IRP stack location would be needed.
  5328. //
  5329. irp = IoBuildSynchronousFsdRequest(
  5330. IRP_MJ_SCSI,
  5331. DeviceExtension->CommonExtension.DeviceObject,
  5332. srbControl,
  5333. length,
  5334. &startingOffset,
  5335. &event,
  5336. &ioStatusBlock);
  5337. irpStack = IoGetNextIrpStackLocation(irp);
  5338. //
  5339. // Set major and minor codes.
  5340. //
  5341. irpStack->MajorFunction = IRP_MJ_SCSI;
  5342. irpStack->MinorFunction = 1;
  5343. //
  5344. // Fill in SRB fields.
  5345. //
  5346. irpStack->Parameters.Others.Argument1 = &srb;
  5347. //
  5348. // Zero out the srb.
  5349. //
  5350. RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
  5351. srb.PathId = logicalUnit->PathId;
  5352. srb.TargetId = logicalUnit->TargetId;
  5353. srb.Lun = logicalUnit->Lun;
  5354. srb.Function = SRB_FUNCTION_IO_CONTROL;
  5355. srb.Length = sizeof(SCSI_REQUEST_BLOCK);
  5356. srb.SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_NO_QUEUE_FREEZE;
  5357. srb.QueueAction = SRB_SIMPLE_TAG_REQUEST;
  5358. srb.OriginalRequest = irp;
  5359. //
  5360. // Set timeout to requested value.
  5361. //
  5362. srb.TimeOutValue = srbControl->Timeout;
  5363. //
  5364. // Set the data buffer.
  5365. //
  5366. srb.DataBuffer = srbControl;
  5367. srb.DataTransferLength = length;
  5368. //
  5369. // Flush the data buffer for output. This will insure that the data is
  5370. // written back to memory. Since the data-in flag is the the port driver
  5371. // will flush the data again for input which will ensure the data is not
  5372. // in the cache.
  5373. //
  5374. KeFlushIoBuffers(irp->MdlAddress, FALSE, TRUE);
  5375. //
  5376. // Call port driver to handle this request.
  5377. //
  5378. status = IoCallDriver(DeviceExtension->CommonExtension.DeviceObject, irp);
  5379. //
  5380. // Wait for request to complete.
  5381. //
  5382. if(status == STATUS_PENDING) {
  5383. KeWaitForSingleObject(&event,
  5384. Executive,
  5385. KernelMode,
  5386. FALSE,
  5387. NULL);
  5388. }
  5389. //
  5390. // Set the information length to the smaller of the output buffer length
  5391. // and the length returned in the srb.
  5392. //
  5393. RequestIrp->IoStatus.Information = srb.DataTransferLength > outputLength ?
  5394. outputLength : srb.DataTransferLength;
  5395. RequestIrp->IoStatus.Status = ioStatusBlock.Status;
  5396. SpReleaseRemoveLock(logicalUnit->CommonExtension.DeviceObject,
  5397. RequestIrp);
  5398. return RequestIrp->IoStatus.Status;
  5399. }
  5400. NTSTATUS
  5401. SpSendPassThrough (
  5402. IN PADAPTER_EXTENSION DeviceExtension,
  5403. IN PIRP RequestIrp
  5404. )
  5405. /*++
  5406. Routine Description:
  5407. This function sends a user specified SCSI request block.
  5408. It creates an srb which is processed normally by the port driver.
  5409. This call is synchornous.
  5410. Arguments:
  5411. DeviceExtension - Supplies a pointer the SCSI adapter device extension.
  5412. RequestIrp - Supplies a pointe to the Irp which made the original request.
  5413. Return Value:
  5414. Returns a status indicating the success or failure of the operation.
  5415. --*/
  5416. {
  5417. PIRP irp;
  5418. PIO_STACK_LOCATION irpStack;
  5419. PSCSI_PASS_THROUGH srbControl;
  5420. SCSI_REQUEST_BLOCK srb;
  5421. KEVENT event;
  5422. LARGE_INTEGER startingOffset;
  5423. IO_STATUS_BLOCK ioStatusBlock;
  5424. KIRQL currentIrql;
  5425. PLOGICAL_UNIT_EXTENSION logicalUnit;
  5426. ULONG outputLength;
  5427. ULONG length;
  5428. ULONG bufferOffset;
  5429. PVOID buffer;
  5430. PVOID senseBuffer;
  5431. UCHAR majorCode;
  5432. NTSTATUS status;
  5433. #if defined (_WIN64)
  5434. PSCSI_PASS_THROUGH32 srbControl32;
  5435. #endif
  5436. PAGED_CODE();
  5437. startingOffset.QuadPart = (LONGLONG) 1;
  5438. DebugPrint((3,"SpSendPassThrough: Enter routine\n"));
  5439. //
  5440. // Get a pointer to the control block.
  5441. //
  5442. irpStack = IoGetCurrentIrpStackLocation(RequestIrp);
  5443. srbControl = RequestIrp->AssociatedIrp.SystemBuffer;
  5444. //
  5445. // Validiate the user buffer.
  5446. //
  5447. #if defined (_WIN64)
  5448. if (IoIs32bitProcess(RequestIrp)) {
  5449. ULONG32 dataBufferOffset;
  5450. ULONG senseInfoOffset;
  5451. srbControl32 = (PSCSI_PASS_THROUGH32) (RequestIrp->AssociatedIrp.SystemBuffer);
  5452. //
  5453. // copy the fields that follow the ULONG_PTR
  5454. //
  5455. dataBufferOffset = (ULONG32) (srbControl32->DataBufferOffset);
  5456. senseInfoOffset = srbControl32->SenseInfoOffset;
  5457. srbControl->DataBufferOffset = (ULONG_PTR) dataBufferOffset;
  5458. srbControl->SenseInfoOffset = senseInfoOffset;
  5459. RtlCopyMemory(srbControl->Cdb,
  5460. srbControl32->Cdb,
  5461. 16*sizeof(UCHAR)
  5462. );
  5463. if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH32)){
  5464. return(STATUS_INVALID_PARAMETER);
  5465. }
  5466. if (srbControl->Length != sizeof(SCSI_PASS_THROUGH32) &&
  5467. srbControl->Length != sizeof(SCSI_PASS_THROUGH_DIRECT32)) {
  5468. return(STATUS_REVISION_MISMATCH);
  5469. }
  5470. } else {
  5471. #endif
  5472. if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH)){
  5473. DebugPrint((2, "SpSendPassThrough: Input buffer length %#08lx too small\n",
  5474. irpStack->Parameters.DeviceIoControl.InputBufferLength));
  5475. return(STATUS_INVALID_PARAMETER);
  5476. }
  5477. if (srbControl->Length != sizeof(SCSI_PASS_THROUGH) &&
  5478. srbControl->Length != sizeof(SCSI_PASS_THROUGH_DIRECT)) {
  5479. DebugPrint((2, "SpSendPassThrough: SrbControl length %#08lx incorrect\n",
  5480. srbControl->Length));
  5481. return(STATUS_REVISION_MISMATCH);
  5482. }
  5483. #if defined (_WIN64)
  5484. }
  5485. #endif
  5486. //
  5487. // Get a pointer to the logical unit extension. If none exists it's a
  5488. // fatal error.
  5489. //
  5490. logicalUnit = GetLogicalUnitExtension(DeviceExtension,
  5491. srbControl->PathId,
  5492. srbControl->TargetId,
  5493. srbControl->Lun,
  5494. RequestIrp,
  5495. TRUE);
  5496. if(logicalUnit == NULL) {
  5497. RequestIrp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
  5498. DebugPrint((2, "SpSendPassThrough: no such logical unit (%d,%d,%d)\n",
  5499. srbControl->PathId,
  5500. srbControl->TargetId,
  5501. srbControl->Lun));
  5502. return STATUS_NO_SUCH_DEVICE;
  5503. }
  5504. if(logicalUnit->CommonExtension.IsRemoved) {
  5505. DebugPrint((2, "SpSendPassThrough: lun (%d,%d,%d) is removed\n",
  5506. srbControl->PathId,
  5507. srbControl->TargetId,
  5508. srbControl->Lun));
  5509. SpReleaseRemoveLock(logicalUnit->DeviceObject,
  5510. RequestIrp);
  5511. return STATUS_DEVICE_DOES_NOT_EXIST;
  5512. }
  5513. outputLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  5514. //
  5515. // Validate the rest of the buffer parameters.
  5516. //
  5517. if (srbControl->CdbLength > 16) {
  5518. DebugPrint((2, "SpSendPassThrough: CdbLength %#x is incorrect\n",
  5519. srbControl->CdbLength));
  5520. SpReleaseRemoveLock(logicalUnit->DeviceObject,
  5521. RequestIrp);
  5522. return(STATUS_INVALID_PARAMETER);
  5523. }
  5524. //
  5525. // If there's a sense buffer then its offset cannot be shorter than the
  5526. // length of the srbControl block, nor can it be located after the data
  5527. // buffer (if any)
  5528. //
  5529. if (srbControl->SenseInfoLength != 0 &&
  5530. (srbControl->Length > srbControl->SenseInfoOffset ||
  5531. (srbControl->SenseInfoOffset + srbControl->SenseInfoLength >
  5532. srbControl->DataBufferOffset && srbControl->DataTransferLength != 0))) {
  5533. DebugPrint((2, "SpSendPassThrough: Bad sense info offset\n"));
  5534. SpReleaseRemoveLock(logicalUnit->DeviceObject,
  5535. RequestIrp);
  5536. return(STATUS_INVALID_PARAMETER);
  5537. }
  5538. majorCode = !srbControl->DataIn ? IRP_MJ_WRITE : IRP_MJ_READ;
  5539. if (srbControl->DataTransferLength == 0) {
  5540. length = 0;
  5541. buffer = NULL;
  5542. bufferOffset = 0;
  5543. majorCode = IRP_MJ_FLUSH_BUFFERS;
  5544. } else if (srbControl->DataBufferOffset > outputLength &&
  5545. srbControl->DataBufferOffset > irpStack->Parameters.DeviceIoControl.InputBufferLength) {
  5546. //
  5547. // The data buffer offset is greater than system buffer. Assume this
  5548. // is a user mode address.
  5549. //
  5550. if (srbControl->SenseInfoOffset + srbControl->SenseInfoLength > outputLength
  5551. && srbControl->SenseInfoLength) {
  5552. DebugPrint((2, "SpSendPassThrough: sense buffer is not in ioctl buffer\n"));
  5553. SpReleaseRemoveLock(logicalUnit->DeviceObject,
  5554. RequestIrp);
  5555. return(STATUS_INVALID_PARAMETER);
  5556. }
  5557. //
  5558. // Make sure the buffer is properly aligned.
  5559. //
  5560. if (srbControl->DataBufferOffset &
  5561. logicalUnit->DeviceObject->AlignmentRequirement) {
  5562. DebugPrint((2, "SpSendPassThrough: data buffer not aligned "
  5563. "[%#p doesn't have alignment of %#0x\n",
  5564. srbControl->DataBufferOffset,
  5565. logicalUnit->DeviceObject->AlignmentRequirement));
  5566. SpReleaseRemoveLock(logicalUnit->DeviceObject,
  5567. RequestIrp);
  5568. return(STATUS_INVALID_PARAMETER);
  5569. }
  5570. length = srbControl->DataTransferLength;
  5571. buffer = (PCHAR) srbControl->DataBufferOffset;
  5572. bufferOffset = 0;
  5573. //
  5574. // make sure the user buffer is valid. The last byte must be at or
  5575. // below the highest possible user address. Additionally the end of
  5576. // the buffer must not wrap around in memory (taking care to ensure that
  5577. // a one-byte length buffer is okay)
  5578. //
  5579. if (RequestIrp->RequestorMode != KernelMode) {
  5580. if (length) {
  5581. ULONG_PTR endByte = (ULONG_PTR) buffer + length - 1;
  5582. if ((endByte > (ULONG_PTR) MM_HIGHEST_USER_ADDRESS) ||
  5583. ((ULONG_PTR) buffer >= endByte + 1)) {
  5584. DebugPrint((2, "SpSendPassThrough: user buffer invalid\n"));
  5585. SpReleaseRemoveLock(logicalUnit->DeviceObject,
  5586. RequestIrp);
  5587. return STATUS_INVALID_USER_BUFFER;
  5588. }
  5589. }
  5590. }
  5591. } else {
  5592. if (srbControl->DataIn != SCSI_IOCTL_DATA_IN) {
  5593. if ((srbControl->SenseInfoOffset + srbControl->SenseInfoLength > outputLength
  5594. && srbControl->SenseInfoLength != 0) ||
  5595. srbControl->DataBufferOffset + srbControl->DataTransferLength >
  5596. irpStack->Parameters.DeviceIoControl.InputBufferLength ||
  5597. srbControl->Length > srbControl->DataBufferOffset) {
  5598. DebugPrint((2, "SpSendPassThrough: sense or data buffer not in ioctl buffer\n"));
  5599. SpReleaseRemoveLock(logicalUnit->DeviceObject, RequestIrp);
  5600. return STATUS_INVALID_PARAMETER;
  5601. }
  5602. }
  5603. //
  5604. // Make sure the buffer is properly aligned.
  5605. //
  5606. if (srbControl->DataBufferOffset &
  5607. logicalUnit->DeviceObject->AlignmentRequirement) {
  5608. DebugPrint((2, "SpSendPassThrough: data buffer not aligned "
  5609. "[%#p doesn't have alignment of %#0x\n",
  5610. srbControl->DataBufferOffset,
  5611. logicalUnit->DeviceObject->AlignmentRequirement));
  5612. SpReleaseRemoveLock(logicalUnit->DeviceObject,
  5613. RequestIrp);
  5614. return STATUS_INVALID_PARAMETER;
  5615. }
  5616. if (srbControl->DataIn) {
  5617. if (srbControl->DataBufferOffset + srbControl->DataTransferLength > outputLength ||
  5618. srbControl->Length > srbControl->DataBufferOffset) {
  5619. DebugPrint((2, "SpSendPassThrough: data buffer not in ioctl buffer or offset too small\n"));
  5620. SpReleaseRemoveLock(logicalUnit->DeviceObject, RequestIrp);
  5621. return STATUS_INVALID_PARAMETER;
  5622. }
  5623. }
  5624. length = (ULONG)srbControl->DataBufferOffset +
  5625. srbControl->DataTransferLength;
  5626. buffer = (PUCHAR) srbControl;
  5627. bufferOffset = (ULONG)srbControl->DataBufferOffset;
  5628. }
  5629. //
  5630. // Validate that the request isn't too large for the miniport.
  5631. //
  5632. if (srbControl->DataTransferLength &&
  5633. ((ADDRESS_AND_SIZE_TO_SPAN_PAGES(
  5634. (PUCHAR)buffer+bufferOffset,
  5635. srbControl->DataTransferLength
  5636. ) > DeviceExtension->Capabilities.MaximumPhysicalPages) ||
  5637. (DeviceExtension->Capabilities.MaximumTransferLength <
  5638. srbControl->DataTransferLength))) {
  5639. DebugPrint((2, "SpSendPassThrough: request is too large for this miniport\n"));
  5640. SpReleaseRemoveLock(logicalUnit->DeviceObject, RequestIrp);
  5641. return(STATUS_INVALID_PARAMETER);
  5642. }
  5643. if (srbControl->TimeOutValue == 0 ||
  5644. srbControl->TimeOutValue > 30 * 60 * 60) {
  5645. DebugPrint((2, "SpSendPassThrough: timeout value %d is invalid\n",
  5646. srbControl->TimeOutValue));
  5647. SpReleaseRemoveLock(logicalUnit->DeviceObject, RequestIrp);
  5648. return STATUS_INVALID_PARAMETER;
  5649. }
  5650. //
  5651. // Check for illegal command codes.
  5652. //
  5653. if (srbControl->Cdb[0] == SCSIOP_COPY ||
  5654. srbControl->Cdb[0] == SCSIOP_COMPARE ||
  5655. srbControl->Cdb[0] == SCSIOP_COPY_COMPARE) {
  5656. DebugPrint((2, "SpSendPassThrough: failing attempt to send restricted "
  5657. "SCSI command %#x\n", srbControl->Cdb[0]));
  5658. SpReleaseRemoveLock(logicalUnit->DeviceObject, RequestIrp);
  5659. return STATUS_INVALID_DEVICE_REQUEST;
  5660. }
  5661. //
  5662. // If this request came through a normal device control rather than from
  5663. // class driver then the device must exist and be unclaimed. Class drivers
  5664. // will set the minor function code for the device control. It is always
  5665. // zero for a user request.
  5666. //
  5667. if((irpStack->MinorFunction == 0) &&
  5668. (logicalUnit->IsClaimed)) {
  5669. DebugPrint((2, "SpSendPassThrough: Pass through request to claimed "
  5670. "device must come through the driver which claimed it\n"));
  5671. SpReleaseRemoveLock(logicalUnit->DeviceObject, RequestIrp);
  5672. return STATUS_INVALID_DEVICE_REQUEST;
  5673. }
  5674. //
  5675. // Allocate an aligned request sense buffer.
  5676. //
  5677. if (srbControl->SenseInfoLength != 0) {
  5678. senseBuffer = SpAllocatePool(
  5679. NonPagedPoolCacheAligned,
  5680. srbControl->SenseInfoLength,
  5681. SCSIPORT_TAG_SENSE_BUFFER,
  5682. DeviceExtension->DeviceObject->DriverObject);
  5683. if (senseBuffer == NULL) {
  5684. DebugPrint((2, "SpSendPassThrogh: Unable to allocate sense buffer\n"));
  5685. SpReleaseRemoveLock(logicalUnit->DeviceObject, RequestIrp);
  5686. return(STATUS_INSUFFICIENT_RESOURCES);
  5687. }
  5688. } else {
  5689. senseBuffer = NULL;
  5690. }
  5691. //
  5692. // Must be at PASSIVE_LEVEL to use synchronous FSD.
  5693. //
  5694. ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  5695. //
  5696. // Initialize the notification event.
  5697. //
  5698. KeInitializeEvent(&event,
  5699. NotificationEvent,
  5700. FALSE);
  5701. //
  5702. // Build IRP for this request.
  5703. // Note we do this synchronously for two reasons. If it was done
  5704. // asynchonously then the completion code would have to make a special
  5705. // check to deallocate the buffer. Second if a completion routine were
  5706. // used then an addation stack locate would be needed.
  5707. //
  5708. try {
  5709. irp = IoBuildSynchronousFsdRequest(
  5710. majorCode,
  5711. logicalUnit->DeviceObject,
  5712. buffer,
  5713. length,
  5714. &startingOffset,
  5715. &event,
  5716. &ioStatusBlock);
  5717. } except(EXCEPTION_EXECUTE_HANDLER) {
  5718. NTSTATUS exceptionCode;
  5719. //
  5720. // An exception was incurred while attempting to probe the
  5721. // caller's parameters. Dereference the file object and return
  5722. // an appropriate error status code.
  5723. //
  5724. if (senseBuffer != NULL) {
  5725. ExFreePool(senseBuffer);
  5726. }
  5727. exceptionCode = GetExceptionCode();
  5728. DebugPrint((2, "SpSendPassThrough: Exception %#08lx building irp\n",
  5729. exceptionCode));
  5730. SpReleaseRemoveLock(logicalUnit->DeviceObject, RequestIrp);
  5731. return exceptionCode;
  5732. }
  5733. if (irp == NULL) {
  5734. if (senseBuffer != NULL) {
  5735. ExFreePool(senseBuffer);
  5736. }
  5737. DebugPrint((2, "SpSendPassThrough: Couldn't allocate irp\n"));
  5738. SpReleaseRemoveLock(logicalUnit->DeviceObject,
  5739. RequestIrp);
  5740. return(STATUS_INSUFFICIENT_RESOURCES);
  5741. }
  5742. irpStack = IoGetNextIrpStackLocation(irp);
  5743. //
  5744. // Set major code.
  5745. //
  5746. irpStack->MajorFunction = IRP_MJ_SCSI;
  5747. irpStack->MinorFunction = 1;
  5748. //
  5749. // Fill in SRB fields.
  5750. //
  5751. irpStack->Parameters.Others.Argument1 = &srb;
  5752. //
  5753. // Zero out the srb.
  5754. //
  5755. RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
  5756. //
  5757. // Fill in the srb.
  5758. //
  5759. srb.Length = SCSI_REQUEST_BLOCK_SIZE;
  5760. srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
  5761. srb.SrbStatus = SRB_STATUS_PENDING;
  5762. srb.PathId = srbControl->PathId;
  5763. srb.TargetId = srbControl->TargetId;
  5764. srb.Lun = srbControl->Lun;
  5765. srb.CdbLength = srbControl->CdbLength;
  5766. srb.SenseInfoBufferLength = srbControl->SenseInfoLength;
  5767. switch (srbControl->DataIn) {
  5768. case SCSI_IOCTL_DATA_OUT:
  5769. if (srbControl->DataTransferLength) {
  5770. srb.SrbFlags = SRB_FLAGS_DATA_OUT;
  5771. }
  5772. break;
  5773. case SCSI_IOCTL_DATA_IN:
  5774. if (srbControl->DataTransferLength) {
  5775. srb.SrbFlags = SRB_FLAGS_DATA_IN;
  5776. }
  5777. break;
  5778. default:
  5779. srb.SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT;
  5780. break;
  5781. }
  5782. if (srbControl->DataTransferLength == 0) {
  5783. srb.SrbFlags = 0;
  5784. } else {
  5785. //
  5786. // Flush the data buffer for output. This will insure that the data is
  5787. // written back to memory.
  5788. //
  5789. KeFlushIoBuffers(irp->MdlAddress, FALSE, TRUE);
  5790. }
  5791. srb.SrbFlags |= logicalUnit->CommonExtension.SrbFlags;
  5792. srb.SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER & DeviceExtension->CommonExtension.SrbFlags);
  5793. srb.SrbFlags |= SRB_FLAGS_NO_QUEUE_FREEZE;
  5794. srb.DataTransferLength = srbControl->DataTransferLength;
  5795. srb.TimeOutValue = srbControl->TimeOutValue;
  5796. srb.DataBuffer = (PCHAR) buffer + bufferOffset;
  5797. srb.SenseInfoBuffer = senseBuffer;
  5798. srb.OriginalRequest = irp;
  5799. RtlCopyMemory(srb.Cdb, srbControl->Cdb, srbControl->CdbLength);
  5800. //
  5801. // Disable autosense if there's no sense buffer to put the data in.
  5802. //
  5803. if(senseBuffer == NULL) {
  5804. srb.SrbFlags |= SRB_FLAGS_DISABLE_AUTOSENSE;
  5805. }
  5806. //
  5807. // Call port driver to handle this request.
  5808. //
  5809. status = IoCallDriver(logicalUnit->DeviceObject, irp);
  5810. //
  5811. // Wait for request to complete.
  5812. //
  5813. if (status == STATUS_PENDING) {
  5814. KeWaitForSingleObject(&event,
  5815. Executive,
  5816. KernelMode,
  5817. FALSE,
  5818. NULL);
  5819. } else {
  5820. ioStatusBlock.Status = status;
  5821. }
  5822. //
  5823. // Copy the returned values from the srb to the control structure.
  5824. //
  5825. srbControl->ScsiStatus = srb.ScsiStatus;
  5826. if (srb.SrbStatus & SRB_STATUS_AUTOSENSE_VALID) {
  5827. //
  5828. // Set the status to success so that the data is returned.
  5829. //
  5830. ioStatusBlock.Status = STATUS_SUCCESS;
  5831. srbControl->SenseInfoLength = srb.SenseInfoBufferLength;
  5832. //
  5833. // Copy the sense data to the system buffer.
  5834. //
  5835. RtlCopyMemory((PUCHAR) srbControl + srbControl->SenseInfoOffset,
  5836. senseBuffer,
  5837. srb.SenseInfoBufferLength);
  5838. } else {
  5839. srbControl->SenseInfoLength = 0;
  5840. }
  5841. //
  5842. // Free the sense buffer.
  5843. //
  5844. if (senseBuffer != NULL) {
  5845. ExFreePool(senseBuffer);
  5846. }
  5847. //
  5848. // If the srb status is buffer underrun then set the status to success.
  5849. // This insures that the data will be returned to the caller.
  5850. //
  5851. if (SRB_STATUS(srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN) {
  5852. ioStatusBlock.Status = STATUS_SUCCESS;
  5853. }
  5854. srbControl->DataTransferLength = srb.DataTransferLength;
  5855. //
  5856. // Set the information length
  5857. //
  5858. if (!srbControl->DataIn || bufferOffset == 0) {
  5859. RequestIrp->IoStatus.Information = srbControl->SenseInfoOffset +
  5860. srbControl->SenseInfoLength;
  5861. } else {
  5862. RequestIrp->IoStatus.Information = srbControl->DataBufferOffset +
  5863. srbControl->DataTransferLength;
  5864. }
  5865. RequestIrp->IoStatus.Status = ioStatusBlock.Status;
  5866. ASSERT(TEST_FLAG(srb.SrbStatus, SRB_STATUS_QUEUE_FROZEN) == 0);
  5867. SpReleaseRemoveLock(logicalUnit->DeviceObject, RequestIrp);
  5868. return ioStatusBlock.Status;
  5869. }
  5870. VOID
  5871. SpMiniPortTimerDpc(
  5872. IN struct _KDPC *Dpc,
  5873. IN PVOID DeviceObject,
  5874. IN PVOID SystemArgument1,
  5875. IN PVOID SystemArgument2
  5876. )
  5877. /*++
  5878. Routine Description:
  5879. This routine calls the miniport when its requested timer fires.
  5880. It interlocks either with the port spinlock and the interrupt object.
  5881. Arguments:
  5882. Dpc - Unsed.
  5883. DeviceObject - Supplies a pointer to the device object for this adapter.
  5884. SystemArgument1 - Unused.
  5885. SystemArgument2 - Unused.
  5886. Return Value:
  5887. None.
  5888. --*/
  5889. {
  5890. PADAPTER_EXTENSION deviceExtension = ((PDEVICE_OBJECT) DeviceObject)->DeviceExtension;
  5891. //
  5892. // Acquire the port spinlock.
  5893. //
  5894. KeAcquireSpinLockAtDpcLevel(&deviceExtension->SpinLock);
  5895. //
  5896. // Make sure we haven't removed the adapter in the meantime.
  5897. //
  5898. if (!TEST_FLAG(deviceExtension->InterruptData.InterruptFlags,
  5899. PD_ADAPTER_REMOVED)) {
  5900. //
  5901. // Make sure the timer routine is still desired.
  5902. //
  5903. if (deviceExtension->HwTimerRequest != NULL) {
  5904. deviceExtension->SynchronizeExecution(
  5905. deviceExtension->InterruptObject,
  5906. (PKSYNCHRONIZE_ROUTINE) deviceExtension->HwTimerRequest,
  5907. deviceExtension->HwDeviceExtension
  5908. );
  5909. }
  5910. }
  5911. //
  5912. // Release the spinlock.
  5913. //
  5914. KeReleaseSpinLockFromDpcLevel(&deviceExtension->SpinLock);
  5915. // Check for miniport work requests. Note this is an unsynchonized
  5916. // test on a bit that can be set by the interrupt routine; however,
  5917. // the worst that can happen is that the completion DPC checks for work
  5918. // twice.
  5919. //
  5920. if (deviceExtension->InterruptData.InterruptFlags & PD_NOTIFICATION_REQUIRED) {
  5921. SpRequestCompletionDpc(DeviceObject);
  5922. }
  5923. }
  5924. BOOLEAN
  5925. SpSynchronizeExecution (
  5926. IN PKINTERRUPT Interrupt,
  5927. IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine,
  5928. IN PVOID SynchronizeContext
  5929. )
  5930. /*++
  5931. Routine Description:
  5932. This routine calls the miniport entry point which was passed in as
  5933. a parameter. It acquires a spin lock so that all accesses to the
  5934. miniport's routines are synchronized. This routine is used as a
  5935. subsitute for KeSynchronizedExecution for miniports which do not use
  5936. hardware interrupts.
  5937. Arguments:
  5938. Interrrupt - Supplies a pointer to the port device extension.
  5939. SynchronizeRoutine - Supplies a pointer to the routine to be called.
  5940. SynchronizeContext - Supplies the context to pass to the
  5941. SynchronizeRoutine.
  5942. Return Value:
  5943. Returns the returned by the SynchronizeRoutine.
  5944. --*/
  5945. {
  5946. PADAPTER_EXTENSION deviceExtension = (PADAPTER_EXTENSION) Interrupt;
  5947. BOOLEAN returnValue;
  5948. KIRQL oldIrql;
  5949. KeAcquireSpinLock(&deviceExtension->InterruptSpinLock, &oldIrql);
  5950. returnValue = SynchronizeRoutine(SynchronizeContext);
  5951. KeReleaseSpinLock(&deviceExtension->InterruptSpinLock, oldIrql);
  5952. return(returnValue);
  5953. }
  5954. NTSTATUS
  5955. SpClaimLogicalUnit(
  5956. IN PADAPTER_EXTENSION AdapterExtension,
  5957. IN PLOGICAL_UNIT_EXTENSION LogicalUnitExtension,
  5958. IN PIRP Irp,
  5959. IN BOOLEAN LegacyClaim
  5960. )
  5961. /*++
  5962. Routine Description:
  5963. This function finds the specified device in the logical unit information
  5964. and either updates the device object point or claims the device. If the
  5965. device is already claimed, then the request fails. If the request succeeds,
  5966. then the current device object is returned in the data buffer pointer
  5967. of the SRB.
  5968. This routine must be called with the remove lock held for the logical
  5969. unit.
  5970. Arguments:
  5971. DeviceExtension - Supplies a pointer the SCSI adapter device extension.
  5972. Irp - Supplies a pointer to the Irp which made the original request.
  5973. LegacyClaim - indicates whether the device should be started before being
  5974. claimed. Used for to start the device before allowing
  5975. legacy drivers to claim it.
  5976. Return Value:
  5977. Returns the status of the operation. Either success, no device or busy.
  5978. --*/
  5979. {
  5980. KIRQL currentIrql;
  5981. PIO_STACK_LOCATION irpStack;
  5982. PSCSI_REQUEST_BLOCK srb;
  5983. PDEVICE_OBJECT saveDevice;
  5984. PVOID sectionHandle;
  5985. NTSTATUS status;
  5986. PAGED_CODE();
  5987. //
  5988. // Get SRB address from current IRP stack.
  5989. //
  5990. irpStack = IoGetCurrentIrpStackLocation(Irp);
  5991. srb = (PSCSI_REQUEST_BLOCK) irpStack->Parameters.Others.Argument1;
  5992. //
  5993. // Make sure the device can be started - this needs to be done outside
  5994. // of the spinlock.
  5995. //
  5996. if(LegacyClaim) {
  5997. status = ScsiPortStartLogicalUnit(LogicalUnitExtension);
  5998. if(!NT_SUCCESS(status)) {
  5999. srb->SrbStatus = SRB_STATUS_ERROR;
  6000. return status;
  6001. }
  6002. LogicalUnitExtension->IsLegacyClaim = TRUE;
  6003. }
  6004. #ifdef ALLOC_PRAGMA
  6005. sectionHandle = MmLockPagableCodeSection(SpClaimLogicalUnit);
  6006. InterlockedIncrement(&SpPAGELOCKLockCount);
  6007. #endif
  6008. //
  6009. // Lock the data.
  6010. //
  6011. KeAcquireSpinLock(&AdapterExtension->SpinLock, &currentIrql);
  6012. if (srb->Function == SRB_FUNCTION_RELEASE_DEVICE) {
  6013. LogicalUnitExtension->IsClaimed = FALSE;
  6014. KeReleaseSpinLock(&AdapterExtension->SpinLock, currentIrql);
  6015. srb->SrbStatus = SRB_STATUS_SUCCESS;
  6016. return(STATUS_SUCCESS);
  6017. }
  6018. //
  6019. // Check for a claimed device.
  6020. //
  6021. if (LogicalUnitExtension->IsClaimed) {
  6022. KeReleaseSpinLock(&AdapterExtension->SpinLock, currentIrql);
  6023. srb->SrbStatus = SRB_STATUS_BUSY;
  6024. return(STATUS_DEVICE_BUSY);
  6025. }
  6026. //
  6027. // Save the current device object.
  6028. //
  6029. saveDevice = LogicalUnitExtension->CommonExtension.DeviceObject;
  6030. //
  6031. // Update the lun information based on the operation type.
  6032. //
  6033. if (srb->Function == SRB_FUNCTION_CLAIM_DEVICE) {
  6034. LogicalUnitExtension->IsClaimed = TRUE;
  6035. }
  6036. if (srb->Function == SRB_FUNCTION_ATTACH_DEVICE) {
  6037. ASSERT(FALSE);
  6038. LogicalUnitExtension->CommonExtension.DeviceObject = srb->DataBuffer;
  6039. }
  6040. srb->DataBuffer = saveDevice;
  6041. KeReleaseSpinLock(&AdapterExtension->SpinLock, currentIrql);
  6042. srb->SrbStatus = SRB_STATUS_SUCCESS;
  6043. #ifdef ALLOC_PRAGMA
  6044. InterlockedDecrement(&SpPAGELOCKLockCount);
  6045. MmUnlockPagableImageSection(sectionHandle);
  6046. #endif
  6047. return(STATUS_SUCCESS);
  6048. }
  6049. NTSTATUS
  6050. SpSendReset(
  6051. IN PDEVICE_OBJECT Adapter,
  6052. IN PIRP RequestIrp
  6053. )
  6054. /*++
  6055. Routine Description:
  6056. This routine will create an assynchronous request to reset the scsi bus
  6057. and route that through the port driver. The completion routine on the
  6058. request will take care of completing the original irp
  6059. This call is asynchronous.
  6060. Arguments:
  6061. Adapter - the port driver to be reset
  6062. Irp - a pointer to the reset request - this request will already have been
  6063. marked as PENDING.
  6064. Return Value:
  6065. STATUS_PENDING if the request is pending
  6066. STATUS_SUCCESS if the request completed successfully
  6067. or an error status
  6068. --*/
  6069. {
  6070. PADAPTER_EXTENSION adapterExtension = Adapter->DeviceExtension;
  6071. PSTORAGE_BUS_RESET_REQUEST resetRequest =
  6072. RequestIrp->AssociatedIrp.SystemBuffer;
  6073. PIRP irp = NULL;
  6074. PIO_STACK_LOCATION irpStack = NULL;
  6075. PRESET_COMPLETION_CONTEXT completionContext = NULL;
  6076. BOOLEAN completeRequest = FALSE;
  6077. NTSTATUS status;
  6078. PLOGICAL_UNIT_EXTENSION logicalUnit = NULL;
  6079. PAGED_CODE();
  6080. ASSERT_FDO(Adapter);
  6081. //
  6082. // use finally handler to complete request if necessary
  6083. //
  6084. try {
  6085. //
  6086. // Make sure the path id is valid
  6087. //
  6088. if(resetRequest->PathId >= adapterExtension->NumberOfBuses) {
  6089. status = STATUS_INVALID_PARAMETER;
  6090. completeRequest = TRUE;
  6091. leave;
  6092. }
  6093. //
  6094. // Find a logical unit that's going to be sticking around for a while
  6095. // and lock it using the original request irp. We'll unlock it in the
  6096. // completion routine.
  6097. //
  6098. logicalUnit = SpFindSafeLogicalUnit(Adapter,
  6099. resetRequest->PathId,
  6100. RequestIrp);
  6101. if(logicalUnit == NULL) {
  6102. //
  6103. // There's nothing safe on this bus so in this case we won't bother
  6104. // resetting it
  6105. // XXX - this may be a bug
  6106. //
  6107. status = STATUS_DEVICE_DOES_NOT_EXIST;
  6108. completeRequest = TRUE;
  6109. leave;
  6110. }
  6111. //
  6112. // Try to allocate a completion context block
  6113. //
  6114. completionContext = SpAllocatePool(NonPagedPool,
  6115. sizeof(RESET_COMPLETION_CONTEXT),
  6116. SCSIPORT_TAG_RESET,
  6117. Adapter->DriverObject);
  6118. if(completionContext == NULL) {
  6119. DebugPrint((1, "SpSendReset: Unable to allocate completion "
  6120. "context\n"));
  6121. status = STATUS_INSUFFICIENT_RESOURCES;
  6122. completeRequest = TRUE;
  6123. leave;
  6124. }
  6125. RtlZeroMemory(completionContext, sizeof(RESET_COMPLETION_CONTEXT));
  6126. completionContext->OriginalIrp = RequestIrp;
  6127. completionContext->SafeLogicalUnit = logicalUnit->DeviceObject;
  6128. completionContext->AdapterDeviceObject = Adapter;
  6129. irp = IoBuildAsynchronousFsdRequest(
  6130. IRP_MJ_FLUSH_BUFFERS,
  6131. logicalUnit->DeviceObject,
  6132. NULL,
  6133. 0,
  6134. NULL,
  6135. NULL);
  6136. if(irp == NULL) {
  6137. DebugPrint((1, "SpSendReset: unable to allocate irp\n"));
  6138. status = STATUS_INSUFFICIENT_RESOURCES;
  6139. completeRequest = TRUE;
  6140. leave;
  6141. }
  6142. //
  6143. // Stick the srb pointer into the irp stack
  6144. //
  6145. irpStack = IoGetNextIrpStackLocation(irp);
  6146. irpStack->MajorFunction = IRP_MJ_SCSI;
  6147. irpStack->MinorFunction = 1;
  6148. irpStack->Parameters.Scsi.Srb = &(completionContext->Srb);
  6149. //
  6150. // Fill in the srb
  6151. //
  6152. completionContext->Srb.Function = SRB_FUNCTION_RESET_BUS;
  6153. completionContext->Srb.SrbStatus = SRB_STATUS_PENDING;
  6154. completionContext->Srb.OriginalRequest = irp;
  6155. IoSetCompletionRoutine(
  6156. irp,
  6157. SpSendResetCompletion,
  6158. completionContext,
  6159. TRUE,
  6160. TRUE,
  6161. TRUE);
  6162. completeRequest = FALSE;
  6163. status = IoCallDriver(logicalUnit->DeviceObject, irp);
  6164. } finally {
  6165. if(completeRequest) {
  6166. if(completionContext != NULL) {
  6167. ExFreePool(completionContext);
  6168. }
  6169. if(irp != NULL) {
  6170. IoFreeIrp(irp);
  6171. }
  6172. RequestIrp->IoStatus.Status = status;
  6173. if(logicalUnit != NULL) {
  6174. SpReleaseRemoveLock(logicalUnit->DeviceObject,
  6175. RequestIrp);
  6176. }
  6177. //
  6178. // Release the remove lock for the adapter.
  6179. //
  6180. SpReleaseRemoveLock(Adapter, RequestIrp);
  6181. SpCompleteRequest(Adapter, RequestIrp, NULL, IO_NO_INCREMENT);
  6182. }
  6183. }
  6184. return status;
  6185. }
  6186. NTSTATUS
  6187. SpSendResetCompletion(
  6188. IN PDEVICE_OBJECT DeviceObject,
  6189. IN PIRP Irp,
  6190. IN PRESET_COMPLETION_CONTEXT Context
  6191. )
  6192. /*++
  6193. Routine Description:
  6194. This routine handles completion of the srb generated from an asynchronous
  6195. IOCTL_SCSI_RESET_BUS request. It will take care of freeing all resources
  6196. allocated during SpSendReset as well as completing the original request.
  6197. Arguments:
  6198. DeviceObject - a pointer to the device object
  6199. Irp - a pointer to the irp sent to the port driver
  6200. Context - a pointer to a reset completion context which contains
  6201. the original request and a pointer to the srb sent down
  6202. Return Value:
  6203. STATUS_MORE_PROCESSING_REQUIRED
  6204. --*/
  6205. {
  6206. PIRP originalIrp = Context->OriginalIrp;
  6207. originalIrp->IoStatus.Status = Irp->IoStatus.Status;
  6208. SpReleaseRemoveLock(Context->SafeLogicalUnit, originalIrp);
  6209. SpReleaseRemoveLock(Context->AdapterDeviceObject, originalIrp);
  6210. SpCompleteRequest(Context->AdapterDeviceObject,
  6211. originalIrp,
  6212. NULL,
  6213. IO_NO_INCREMENT);
  6214. ExFreePool(Context);
  6215. IoFreeIrp(Irp);
  6216. return STATUS_MORE_PROCESSING_REQUIRED;
  6217. }
  6218. PLOGICAL_UNIT_EXTENSION
  6219. SpFindSafeLogicalUnit(
  6220. IN PDEVICE_OBJECT DeviceObject,
  6221. IN UCHAR PathId,
  6222. IN PVOID LockTag
  6223. )
  6224. /*++
  6225. Routine Description:
  6226. This routine will scan the bus in question and return a pointer to the
  6227. first logical unit on the bus that is not involved in a rescan operation.
  6228. This can be used to find a logical unit for ioctls or other requests that
  6229. may not specify one (IOCTL_SCSI_MINIPORT, IOCTL_SCSI_RESET_BUS, etc)
  6230. Arguments:
  6231. DeviceObject - a pointer to the device object
  6232. PathId - The path number to be searched for a logical unit. If this is 0xff
  6233. then the first unit on any path will be found.
  6234. Return Value:
  6235. a pointer to a logical unit extension
  6236. NULL if none was found
  6237. --*/
  6238. {
  6239. PADAPTER_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  6240. UCHAR target;
  6241. PLOGICAL_UNIT_EXTENSION logicalUnit;
  6242. ASSERT_FDO(DeviceObject);
  6243. //
  6244. // Set the logical unit addressing to the first logical unit. This is
  6245. // merely used for addressing purposes.
  6246. //
  6247. for (target = 0; target < NUMBER_LOGICAL_UNIT_BINS; target++) {
  6248. PLOGICAL_UNIT_BIN bin = &deviceExtension->LogicalUnitList[target];
  6249. KIRQL oldIrql;
  6250. KeAcquireSpinLock(&bin->Lock, &oldIrql);
  6251. logicalUnit = bin->List;
  6252. //
  6253. // Walk the logical unit list to the end, looking for a safe one.
  6254. // If it was created for a rescan, it might be freed before this
  6255. // request is complete.
  6256. //
  6257. for(logicalUnit = bin->List;
  6258. logicalUnit != NULL;
  6259. logicalUnit = logicalUnit->NextLogicalUnit) {
  6260. if ((logicalUnit->IsTemporary == FALSE) &&
  6261. ((PathId == 0xff) || (logicalUnit->PathId == PathId))) {
  6262. ULONG isRemoved;
  6263. //
  6264. // This lu isn't being rescanned and if a path id was specified
  6265. // it matches so this must be the right one
  6266. //
  6267. isRemoved = SpAcquireRemoveLock(
  6268. logicalUnit->DeviceObject,
  6269. LockTag);
  6270. if(isRemoved) {
  6271. SpReleaseRemoveLock(
  6272. logicalUnit->DeviceObject,
  6273. LockTag);
  6274. continue;
  6275. }
  6276. KeReleaseSpinLock(&bin->Lock, oldIrql);
  6277. return logicalUnit;
  6278. }
  6279. }
  6280. KeReleaseSpinLock(&bin->Lock, oldIrql);
  6281. }
  6282. return NULL;
  6283. }
  6284. NTSTATUS
  6285. SpRerouteLegacyRequest(
  6286. IN PDEVICE_OBJECT AdapterObject,
  6287. IN PIRP Irp
  6288. )
  6289. /*++
  6290. Routine Description:
  6291. This routine is called when the adapter receives requests which have
  6292. not been assigned SRB_DATA blocks. The routine will build a new irp
  6293. for the SRB and issue that irp to the appropriate logical unit for
  6294. processing.
  6295. The adapter remove lock should NOT be held when processing this
  6296. request.
  6297. Arguments:
  6298. AdapterObject - the adapter which received the request
  6299. Irp - the request
  6300. Return Value:
  6301. status
  6302. --*/
  6303. {
  6304. PADAPTER_EXTENSION adapter = AdapterObject->DeviceExtension;
  6305. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  6306. PSCSI_REQUEST_BLOCK srb = irpStack->Parameters.Scsi.Srb;
  6307. ULONG_PTR tag;
  6308. PLOGICAL_UNIT_EXTENSION logicalUnit;
  6309. NTSTATUS status;
  6310. //
  6311. // Acqire a lock on the logical unit we're going to send this through.
  6312. // use IRP+1 so we don't collide with the regular i/o locks.
  6313. //
  6314. tag = ((ULONG_PTR) Irp) + 1;
  6315. logicalUnit = GetLogicalUnitExtension(adapter,
  6316. srb->PathId,
  6317. srb->TargetId,
  6318. srb->Lun,
  6319. (PVOID) tag,
  6320. TRUE);
  6321. //
  6322. // Release the lock the caller acquired on the adapter.
  6323. //
  6324. SpReleaseRemoveLock(AdapterObject, Irp);
  6325. if(logicalUnit == NULL) {
  6326. status = STATUS_DEVICE_DOES_NOT_EXIST;
  6327. Irp->IoStatus.Status = status;
  6328. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  6329. } else {
  6330. //
  6331. // Reference the device object. That way it won't go away and we
  6332. // don't have to keep a remove lock around.
  6333. //
  6334. ObReferenceObject(logicalUnit->DeviceObject);
  6335. SpReleaseRemoveLock(logicalUnit->DeviceObject, (PVOID) tag);
  6336. //
  6337. // Skip the current irp stack location. That will cause it
  6338. // to get rerun by the logical unit we call.
  6339. //
  6340. IoSkipCurrentIrpStackLocation(Irp);
  6341. status = IoCallDriver(logicalUnit->DeviceObject, Irp);
  6342. ObDereferenceObject(logicalUnit->DeviceObject);
  6343. }
  6344. return status;
  6345. }
  6346. NTSTATUS
  6347. SpFlushReleaseQueue(
  6348. IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
  6349. IN BOOLEAN Flush
  6350. )
  6351. {
  6352. PADAPTER_EXTENSION adapter = LogicalUnit->AdapterExtension;
  6353. KIRQL oldIrql;
  6354. NTSTATUS status = STATUS_SUCCESS;
  6355. DebugPrint((2,"SpFlushReleaseQueue: SCSI unfreeze queue TID %d\n",
  6356. LogicalUnit->TargetId));
  6357. ASSERT(!TEST_FLAG(LogicalUnit->LuFlags, LU_QUEUE_LOCKED));
  6358. //
  6359. // Acquire the spinlock to protect the flags structure and the saved
  6360. // interrupt context.
  6361. //
  6362. KeAcquireSpinLock(&adapter->SpinLock, &oldIrql);
  6363. //
  6364. // Make sure the queue is frozen.
  6365. //
  6366. if (!TEST_FLAG(LogicalUnit->LuFlags, LU_QUEUE_FROZEN)) {
  6367. DebugPrint((1,"ScsiPortFdoDispatch: Request to unfreeze an "
  6368. "unfrozen queue!\n"));
  6369. KeReleaseSpinLock(&adapter->SpinLock, oldIrql);
  6370. if(Flush) {
  6371. status = STATUS_INVALID_DEVICE_REQUEST;
  6372. }
  6373. return status;
  6374. }
  6375. CLEAR_FLAG(LogicalUnit->LuFlags, LU_QUEUE_FROZEN);
  6376. if(Flush) {
  6377. PIRP listIrp = NULL;
  6378. PKDEVICE_QUEUE_ENTRY packet;
  6379. PIRP nextIrp;
  6380. PIO_STACK_LOCATION irpStack;
  6381. PSCSI_REQUEST_BLOCK srb;
  6382. //
  6383. // The queue may not be busy so we have to use the IfBusy variant.
  6384. // Use a zero key to pull items from the head of it (if any are there)
  6385. //
  6386. while ((packet =
  6387. KeRemoveByKeyDeviceQueueIfBusy(
  6388. &(LogicalUnit->DeviceObject->DeviceQueue),
  6389. 0))
  6390. != NULL) {
  6391. PIRP nextIrp;
  6392. PIO_STACK_LOCATION irpStack;
  6393. PSCSI_REQUEST_BLOCK srb;
  6394. nextIrp = CONTAINING_RECORD(packet,
  6395. IRP,
  6396. Tail.Overlay.DeviceQueueEntry);
  6397. //
  6398. // Get the srb.
  6399. //
  6400. irpStack = IoGetCurrentIrpStackLocation(nextIrp);
  6401. srb = irpStack->Parameters.Scsi.Srb;
  6402. //
  6403. // Set the status code.
  6404. //
  6405. srb->SrbStatus = SRB_STATUS_REQUEST_FLUSHED;
  6406. nextIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
  6407. //
  6408. // Link the requests. They will be completed after the
  6409. // spinlock is released.
  6410. //
  6411. nextIrp->Tail.Overlay.ListEntry.Flink = (PLIST_ENTRY)
  6412. listIrp;
  6413. listIrp = nextIrp;
  6414. }
  6415. //
  6416. // If there is a pending request on the LU, add it to the list so it
  6417. // gets flushed along with the queued requests.
  6418. //
  6419. if (LogicalUnit->PendingRequest != NULL) {
  6420. PIRP irp = LogicalUnit->PendingRequest->CurrentIrp;
  6421. PSCSI_REQUEST_BLOCK srb = LogicalUnit->PendingRequest->CurrentSrb;
  6422. DebugPrint((1, "SpFlushReleaseQueue: flushing pending request irp:%p srb:%p\n", irp, srb));
  6423. srb->SrbStatus = SRB_STATUS_REQUEST_FLUSHED;
  6424. irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
  6425. irp->Tail.Overlay.ListEntry.Flink = (PLIST_ENTRY) listIrp;
  6426. listIrp = irp;
  6427. LogicalUnit->PendingRequest = NULL;
  6428. ASSERT(LogicalUnit->LuFlags | LU_PENDING_LU_REQUEST);
  6429. CLEAR_FLAG(LogicalUnit->LuFlags, LU_PENDING_LU_REQUEST);
  6430. }
  6431. //
  6432. // Mark the queue as unfrozen. Since all the requests have
  6433. // been removed and the device queue is no longer busy, it
  6434. // is effectively unfrozen.
  6435. //
  6436. CLEAR_FLAG(LogicalUnit->LuFlags, LU_QUEUE_FROZEN);
  6437. //
  6438. // Release the spinlock.
  6439. //
  6440. KeReleaseSpinLock(&adapter->SpinLock, oldIrql);
  6441. //
  6442. // Complete the flushed requests.
  6443. //
  6444. while (listIrp != NULL) {
  6445. PSRB_DATA srbData;
  6446. nextIrp = listIrp;
  6447. listIrp = (PIRP) nextIrp->Tail.Overlay.ListEntry.Flink;
  6448. //
  6449. // Get the srb.
  6450. //
  6451. irpStack = IoGetCurrentIrpStackLocation(nextIrp);
  6452. srb = irpStack->Parameters.Scsi.Srb;
  6453. srbData = srb->OriginalRequest;
  6454. srb->OriginalRequest = nextIrp;
  6455. SpReleaseRemoveLock(adapter->DeviceObject, nextIrp);
  6456. SpCompleteRequest(adapter->DeviceObject,
  6457. nextIrp,
  6458. srbData,
  6459. IO_NO_INCREMENT);
  6460. }
  6461. } else {
  6462. //
  6463. // If there is not an untagged request running then start the
  6464. // next request for this logical unit. Otherwise free the
  6465. // spin lock.
  6466. //
  6467. if (LogicalUnit->CurrentUntaggedRequest == NULL) {
  6468. //
  6469. // GetNextLuRequest frees the spinlock.
  6470. //
  6471. GetNextLuRequest(LogicalUnit);
  6472. KeLowerIrql(oldIrql);
  6473. } else {
  6474. DebugPrint((1,"SpFlushReleaseQueue: Request to unfreeze queue "
  6475. "with active request.\n"));
  6476. KeReleaseSpinLock(&adapter->SpinLock, oldIrql);
  6477. }
  6478. }
  6479. return status;
  6480. }
  6481. VOID
  6482. SpLogInterruptFailure(
  6483. IN PADAPTER_EXTENSION Adapter
  6484. )
  6485. /*++
  6486. Routine Description:
  6487. This function logs an error when an interrupt has not been delivered.
  6488. Arguments:
  6489. DeviceExtension - Supplies a pointer to the port device extension.
  6490. Srb - Supplies a pointer to the request which timed-out.
  6491. UniqueId - Supplies the UniqueId for this error.
  6492. Return Value:
  6493. None.
  6494. Notes:
  6495. The port device extension spinlock should be held when this routine is
  6496. called.
  6497. --*/
  6498. {
  6499. PIO_ERROR_LOG_PACKET errorLogEntry;
  6500. errorLogEntry = (PIO_ERROR_LOG_PACKET)
  6501. IoAllocateErrorLogEntry(Adapter->DeviceObject,
  6502. sizeof(IO_ERROR_LOG_PACKET));
  6503. if (errorLogEntry != NULL) {
  6504. errorLogEntry->ErrorCode = IO_WARNING_INTERRUPT_STILL_PENDING;
  6505. errorLogEntry->SequenceNumber = 0;
  6506. errorLogEntry->MajorFunctionCode = 0;
  6507. errorLogEntry->RetryCount = 0;
  6508. errorLogEntry->UniqueErrorValue = 0x215;
  6509. errorLogEntry->FinalStatus = STATUS_PENDING;
  6510. errorLogEntry->DumpDataSize = 0;
  6511. IoWriteErrorLogEntry(errorLogEntry);
  6512. }
  6513. DbgPrint("SpTimeoutSynchronized: Adapter %#p had interrupt "
  6514. "pending - the system may not be delivering "
  6515. "interrupts from this adapter\n",
  6516. Adapter->DeviceObject);
  6517. if(ScsiCheckInterrupts) {
  6518. DbgBreakPoint();
  6519. }
  6520. return;
  6521. }
  6522. VOID
  6523. SpDelayedWmiRegistrationControl(
  6524. IN PDEVICE_OBJECT DeviceObject,
  6525. IN PVOID Context
  6526. )
  6527. /*++
  6528. Routine Description:
  6529. This funciton is a callback for a IOWorkItem that will be queued in the CompltetionDpc
  6530. for scsiport. The completion DPC cannot call IoWMIRegistrationControl because
  6531. it is running at DPC level.
  6532. Arguments:
  6533. DeviceObject - The device object for which this WorkItem was queued.
  6534. Context - The context contains a pointer to the IOWorkItem so
  6535. we can free it.
  6536. Return Value:
  6537. This work item has to be called with the remove lock held so that the
  6538. device doesn't go before we get to run.
  6539. Notes:
  6540. This routine should be called with the RemoveLock held for the deviceObject
  6541. --*/
  6542. {
  6543. PIO_WORKITEM pIOWorkItem = (PIO_WORKITEM) Context;
  6544. IoWMIRegistrationControl(DeviceObject, WMIREG_ACTION_REREGISTER);
  6545. // Free the IOWorkItem
  6546. IoFreeWorkItem(pIOWorkItem);
  6547. // Release the remove lock on the device object
  6548. SpReleaseRemoveLock(DeviceObject, pIOWorkItem);
  6549. }
  6550. VOID
  6551. SpCompletionDpcProcessWmi(
  6552. IN PDEVICE_OBJECT DeviceObject,
  6553. IN PINTERRUPT_DATA savedInterruptData
  6554. )
  6555. /*++
  6556. Routine Description:
  6557. Will do the processing for WMI events (and registration) for
  6558. completionDpc.
  6559. Arguments:
  6560. Return Value:
  6561. None
  6562. Notes:
  6563. --*/
  6564. {
  6565. LARGE_INTEGER currentTime;
  6566. PLOGICAL_UNIT_EXTENSION logicalUnit;
  6567. PDEVICE_OBJECT providerDeviceObject;
  6568. PADAPTER_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  6569. // Pointers to the WMIEventRequests passed in for execution
  6570. PWMI_MINIPORT_REQUEST_ITEM wmiMiniPortRequestCurrent;
  6571. PWMI_MINIPORT_REQUEST_ITEM nextRequest = NULL;
  6572. PWNODE_HEADER wnodeEventItemHeader;
  6573. //
  6574. // Process the requests in the same order they were posted. All
  6575. // requests are stamped with the same time.
  6576. //
  6577. KeQuerySystemTime(&currentTime);
  6578. wmiMiniPortRequestCurrent =
  6579. savedInterruptData->WmiMiniPortRequests;
  6580. while (wmiMiniPortRequestCurrent) {
  6581. // Initialize the next request
  6582. nextRequest = wmiMiniPortRequestCurrent->NextRequest;
  6583. //
  6584. // Determine if the WMI data provider is the
  6585. // adapter (FDO; PathId=0xFF) or one of the SCSI
  6586. // targets (PDO; identified by
  6587. // PathId,TargedId,Lun).
  6588. //
  6589. if (wmiMiniPortRequestCurrent->PathId == 0xFF) { // [FDO]
  6590. providerDeviceObject = DeviceObject;
  6591. } else { // [PDO]
  6592. logicalUnit = GetLogicalUnitExtension(
  6593. deviceExtension,
  6594. wmiMiniPortRequestCurrent->PathId,
  6595. wmiMiniPortRequestCurrent->TargetId,
  6596. wmiMiniPortRequestCurrent->Lun,
  6597. FALSE,
  6598. TRUE);
  6599. if (logicalUnit) {
  6600. providerDeviceObject =
  6601. logicalUnit->CommonExtension.DeviceObject;
  6602. } else {
  6603. // [SCSI target does not exist]
  6604. providerDeviceObject = NULL;
  6605. // The deviceObject is NULL, then we should
  6606. // delete the entry. Because the deviceObject
  6607. // becomes NULL when the adapter or LUN has
  6608. // been removed. That means that there is no
  6609. // free list for this cell to go back to,
  6610. // if we dont delete the cell it will be leaked
  6611. ExFreePool(wmiMiniPortRequestCurrent);
  6612. }
  6613. }
  6614. //
  6615. // Ignore this WMI request if we cannot locate
  6616. // the WMI ProviderId (device object pointer) or
  6617. // WMI is not initialized for some reason,
  6618. // therwise process the request.
  6619. //
  6620. if (providerDeviceObject && ((PCOMMON_EXTENSION)
  6621. providerDeviceObject->DeviceExtension)->WmiInitialized) {
  6622. // Do we place the cell back onto the free list
  6623. BOOLEAN freeCell;
  6624. freeCell = TRUE;
  6625. if (wmiMiniPortRequestCurrent->TypeOfRequest == WMIReregister) {
  6626. //
  6627. // Re-register this device object with WMI, instructing WMI to
  6628. // requery for the GUIDs we support.
  6629. //
  6630. // The Call to IoWMIRegistrationControl is not supported at
  6631. // DPC level (must be made at PASSIVE level, so we will
  6632. // queue a work item.
  6633. PIO_WORKITEM pIOWorkItem;
  6634. // The remove lock will be release by the IOWorkItem
  6635. // callback
  6636. pIOWorkItem = IoAllocateWorkItem(providerDeviceObject);
  6637. if (pIOWorkItem) {
  6638. // Acquire the RemoveLock on this deviceObject
  6639. SpAcquireRemoveLock(providerDeviceObject, pIOWorkItem);
  6640. // We succesfully allocated the work item
  6641. IoQueueWorkItem(pIOWorkItem,
  6642. SpDelayedWmiRegistrationControl,
  6643. DelayedWorkQueue,
  6644. pIOWorkItem);
  6645. } else {
  6646. DebugPrint((1, "ScsiPortCompletionDPC: IoAllocateWorkItem failed for WmiRegistrationControl event\n"));
  6647. }
  6648. //
  6649. // Falling through we'll place the cell into the free list later
  6650. //
  6651. } else if (wmiMiniPortRequestCurrent->TypeOfRequest == WMIEvent) {
  6652. //
  6653. // The miniport posted a WMI event.
  6654. //
  6655. // Make sure we have an event item, then stamp it with
  6656. NTSTATUS status;
  6657. wnodeEventItemHeader =
  6658. (PWNODE_HEADER) wmiMiniPortRequestCurrent->WnodeEventItem;
  6659. ASSERT(wnodeEventItemHeader->Flags & WNODE_FLAG_EVENT_ITEM);
  6660. wnodeEventItemHeader->ProviderId = IoWMIDeviceObjectToProviderId(providerDeviceObject);
  6661. wnodeEventItemHeader->TimeStamp = currentTime;
  6662. //
  6663. // We will be passing this WMI_MINIPORT_REQUEST_ITEM directly
  6664. // to WMI and allocating a new request item to take its place.
  6665. //
  6666. // Note that WMI is expecting a WNODE_EVENT_ITEM to be passed
  6667. // in, however we are passing it a WMI_MINIPORT_REQUEST_ITEM.
  6668. // This is alright, since the WNODE_EVENT_ITEM buffer is the
  6669. // very first field in WMI_MINIPORT_REQUEST_ITEM. This is an
  6670. // optimization to save one copy operation. The alternative
  6671. // was to allocate a WNODE_EVENT_ITEM and copy in the data.
  6672. //
  6673. status = IoWMIWriteEvent(
  6674. (PWNODE_EVENT_ITEM)wmiMiniPortRequestCurrent);
  6675. if (NT_SUCCESS(status)) {
  6676. // Dont put this cell back onto the free list
  6677. freeCell = FALSE;
  6678. #if DBG
  6679. // This is a global counter, it wont
  6680. // make sense if you have more than
  6681. // one scsiport adapter
  6682. ScsiPortWmiWriteCalls++;
  6683. #endif
  6684. } else {
  6685. // WMI Wont release the memory that we're
  6686. // currently pointing to
  6687. #if DBG
  6688. // This is a global counter, it wont
  6689. // make sense if you have more than
  6690. // one scsiport adapter
  6691. ScsiPortWmiWriteCallsFailed++;
  6692. #endif
  6693. DebugPrint((1, "ScsiPortCompletionDPC: IoWMIWriteEvent failed\n"));
  6694. }
  6695. } else { // unknown TypeOfRequest, ignore the request
  6696. ASSERT(FALSE);
  6697. }
  6698. if (freeCell) {
  6699. //
  6700. // Free the cell back onto the free list.
  6701. //
  6702. SpWmiPushExistingFreeRequestItem(
  6703. deviceExtension,
  6704. wmiMiniPortRequestCurrent);
  6705. }
  6706. } // good providerId / WMI initialized
  6707. // Advance the Current request pointer
  6708. wmiMiniPortRequestCurrent = nextRequest;
  6709. } // while more requests exist
  6710. // Clear the Request List
  6711. savedInterruptData->WmiMiniPortRequests = NULL;
  6712. // See if we need to repopulate the free
  6713. // REQUEST_ITEM list
  6714. while (deviceExtension->WmiFreeMiniPortRequestCount <
  6715. deviceExtension->WmiFreeMiniPortRequestWatermark) {
  6716. // Add one to the free list
  6717. if (!NT_SUCCESS(
  6718. SpWmiPushFreeRequestItem(
  6719. deviceExtension))) {
  6720. // We failed to add, most likely a memory
  6721. // problem, so just stop trying for now
  6722. break;
  6723. }
  6724. } // re-populate the free list (REQUEST_ITEMS)
  6725. return;
  6726. }
  6727. NTSTATUS
  6728. SpFireSenseDataEvent(
  6729. PSCSI_REQUEST_BLOCK Srb,
  6730. PDEVICE_OBJECT DeviceObject
  6731. )
  6732. /*++
  6733. Routine Description:
  6734. This routine fires a WMI event which contains the SenseData
  6735. returned by a REQUEST SENSE command.
  6736. WMI frees the buffer we alloc and pass to it.
  6737. This routine must be called at IRQL <= DISPATCH_LEVEL, as
  6738. required by WmiFireEvent.
  6739. Arguments:
  6740. Srb - Points to the failed SRB for which a REQUEST SENSE
  6741. was performed.
  6742. DeviceObject - Points to the driver's device object.
  6743. Return Value:
  6744. STATUS_SUCCESS if successful
  6745. Notes:
  6746. --*/
  6747. {
  6748. typedef struct _SCSIPORTSENSEDATA{
  6749. ULONG Port;
  6750. UCHAR Cdb[16];
  6751. UCHAR SenseData[255];
  6752. } SCSIPORTSENSEDATA, *PSCSIPORTSENSEDATA;
  6753. NTSTATUS status;
  6754. PSCSIPORTSENSEDATA SenseData;
  6755. ULONG SenseDataLength = 255;
  6756. PADAPTER_EXTENSION AdapterExtension;
  6757. //
  6758. // Allocate a buffer into which the event data will be copied. This
  6759. // buffer gets freed by WMI.
  6760. //
  6761. SenseData = SpAllocatePool(NonPagedPoolCacheAligned,
  6762. sizeof(SCSIPORTSENSEDATA),
  6763. SCSIPORT_TAG_SENSE_BUFFER,
  6764. DeviceObject->DriverObject);
  6765. if (NULL == SenseData) {
  6766. DebugPrint((1, "Unable to alloc buffer for SenseData WMI event\n"));
  6767. return STATUS_INSUFFICIENT_RESOURCES;
  6768. }
  6769. //
  6770. // Initialize a pointer to the adapter extension. We use it below to
  6771. // get information for firing the event and filling out the event
  6772. // data.
  6773. //
  6774. AdapterExtension = DeviceObject->DeviceExtension;
  6775. //
  6776. // Zero the buffer, then copy the event information into it.
  6777. //
  6778. RtlZeroMemory(SenseData, sizeof(SCSIPORTSENSEDATA));
  6779. SenseData->Port = AdapterExtension->PortNumber;
  6780. RtlCopyMemory(&SenseData->Cdb,
  6781. Srb->Cdb,
  6782. Srb->CdbLength);
  6783. RtlCopyMemory(&SenseData->SenseData,
  6784. Srb->SenseInfoBuffer,
  6785. Srb->SenseInfoBufferLength);
  6786. //
  6787. // Fire the event.
  6788. //
  6789. DebugPrint((3, "SpFireSenseDataEvent: DeviceObject %p\n", DeviceObject));
  6790. status = WmiFireEvent(DeviceObject,
  6791. (LPGUID)&AdapterExtension->SenseDataEventClass,
  6792. 0,
  6793. sizeof(SCSIPORTSENSEDATA),
  6794. SenseData);
  6795. return status;
  6796. }
  6797. #if defined(FORWARD_PROGRESS)
  6798. PMDL
  6799. SpPrepareReservedMdlForUse(
  6800. IN PADAPTER_EXTENSION Adapter,
  6801. IN PSRB_DATA SrbData,
  6802. IN PSCSI_REQUEST_BLOCK Srb,
  6803. IN ULONG ScatterListLength
  6804. )
  6805. /*++
  6806. Routine Description:
  6807. This routine attempts to prepare the reserved MDL on the supplied adapter
  6808. for use.
  6809. Arguments:
  6810. Adapter - Points to an adapter extension object.
  6811. SrbData - Points to the SRB_DATA structure for this request.
  6812. Srb - Points to the SRB that describes the request for which
  6813. we are enabling forward progress.
  6814. ScatterListLength - The size of the SG list.
  6815. Return Value:
  6816. Pointer to the reserved MDL if successful.
  6817. NULL if the reserved MDL is too small.
  6818. -1 if the reserved MDL are already in use.
  6819. Notes:
  6820. This routine is called with the adapter spinlock held.
  6821. --*/
  6822. {
  6823. PMDL Mdl;
  6824. //
  6825. // Check if the reserved MDL is already in use by another request.
  6826. //
  6827. if (TEST_FLAG(Adapter->Flags, PD_RESERVED_MDL_IN_USE)) {
  6828. //
  6829. // The spare is already in use.
  6830. //
  6831. Mdl = (PMDL)-1;
  6832. } else {
  6833. //
  6834. // The spare is available. Check if it's big enough enough to
  6835. // accommodate this request.
  6836. //
  6837. ULONG PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(
  6838. Srb->DataBuffer,
  6839. Srb->DataTransferLength);
  6840. if (PageCount > SP_RESERVED_PAGES) {
  6841. //
  6842. // The spare MDL is not big enough to accommodate the request.
  6843. // return NULL.
  6844. //
  6845. Mdl = NULL;
  6846. } else {
  6847. DebugPrint((1, "SpPrepareReservedMdlForUse: using reserved MDL DevExt:%p srb:%p\n",
  6848. Adapter, Srb));
  6849. //
  6850. // The spare is adequate. Claim it and prepare it
  6851. // for use with this request.
  6852. //
  6853. SET_FLAG(Adapter->Flags, PD_RESERVED_MDL_IN_USE);
  6854. SET_FLAG(SrbData->Flags, SRB_DATA_RESERVED_MDL);
  6855. Mdl = Adapter->ReservedMdl;
  6856. MmInitializeMdl(Mdl,Srb->DataBuffer,Srb->DataTransferLength);
  6857. SpPrepareMdlForMappedTransfer(
  6858. Mdl,
  6859. Adapter->DeviceObject,
  6860. Adapter->DmaAdapterObject,
  6861. SrbData->CurrentIrp->MdlAddress,
  6862. Srb->DataBuffer,
  6863. Srb->DataTransferLength,
  6864. SrbData->ScatterGatherList,
  6865. ScatterListLength);
  6866. }
  6867. }
  6868. return Mdl;
  6869. }
  6870. PVOID
  6871. SpMapLockedPagesWithReservedMapping(
  6872. IN PADAPTER_EXTENSION Adapter,
  6873. IN PSCSI_REQUEST_BLOCK Srb,
  6874. IN PSRB_DATA SrbData,
  6875. IN PMDL Mdl
  6876. )
  6877. /*++
  6878. Routine Description:
  6879. This routine attempts to map the physical pages represented by the supplied
  6880. MDL using the adapter's reserved page range.
  6881. Arguments:
  6882. Adapter - Points to an adapter extension object.
  6883. Srb - Points to the SRB that describes the request for which we
  6884. are enabling forward progress.
  6885. SrbData - Points to the SRB_DATA structure for this request.
  6886. Mdl - Points to an MDL that describes the physical range we
  6887. are tring to map.
  6888. Return Value:
  6889. Kernel VA of the mapped pages if mapped successfully.
  6890. NULL if the reserved page range is too small or if the pages are
  6891. not successfully mapped.
  6892. -1 if the reserved pages are already in use.
  6893. Notes:
  6894. This routine is called with the adapter spinlock held.
  6895. --*/
  6896. {
  6897. ULONG_PTR NumberOfPages;
  6898. PVOID StartingVa;
  6899. PVOID SystemAddress;
  6900. //
  6901. // Determine if the reserved range is already in use by another
  6902. // request.
  6903. //
  6904. if (TEST_FLAG(Adapter->Flags, PD_RESERVED_PAGES_IN_USE)) {
  6905. //
  6906. // The reserved range is already in use, return -1.
  6907. //
  6908. SystemAddress = (PVOID)-1;
  6909. } else {
  6910. //
  6911. // The reserved range is available. Calculate the number of pages
  6912. // spanned by the MDL and determine if the reserved range is large
  6913. // enough to map the pages.
  6914. //
  6915. StartingVa = (PVOID)((PCHAR)Mdl->StartVa + Mdl->ByteOffset);
  6916. NumberOfPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(StartingVa, Mdl->ByteCount);
  6917. if (NumberOfPages > SP_RESERVED_PAGES) {
  6918. //
  6919. // Not enough reserved pages to map the required physical memory.
  6920. // Return NULL.
  6921. //
  6922. SystemAddress = NULL;
  6923. } else {
  6924. DebugPrint((1, "SpMapLockedPagesWithReservedMapping: using reserved range DevExt:%p srb:%p\n",
  6925. Adapter, Srb));
  6926. //
  6927. // The reserved range is large enough to map all the pages. Go ahead
  6928. // and try to map them. Since we are specifying MmCached as cache
  6929. // type and we've ensured that we have enough reserved pages to
  6930. // cover the request, this should never fail.
  6931. //
  6932. SystemAddress = MmMapLockedPagesWithReservedMapping(
  6933. Adapter->ReservedPages,
  6934. SCSIPORT_TAG_MAPPING_LIST,
  6935. Mdl,
  6936. MmCached);
  6937. if (SystemAddress == NULL) {
  6938. ASSERT(FALSE);
  6939. } else {
  6940. //
  6941. // The mapping succeeded. Claim the reserved range and mark the
  6942. // request so we'll know at completion that it's using the
  6943. // reserved range.
  6944. //
  6945. SET_FLAG(Adapter->Flags, PD_RESERVED_PAGES_IN_USE);
  6946. SET_FLAG(SrbData->Flags, SRB_DATA_RESERVED_PAGES);
  6947. }
  6948. }
  6949. }
  6950. return SystemAddress;
  6951. }
  6952. #endif