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

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