Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5869 lines
176 KiB

  1. /*++
  2. Copyright (c) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. SCSI.C
  5. Abstract:
  6. This source file contains the dispatch routines which handle:
  7. IRP_MJ_DEVICE_CONTROL
  8. IRP_MJ_SCSI
  9. Environment:
  10. kernel mode
  11. Revision History:
  12. 06-01-98 : started rewrite
  13. --*/
  14. //*****************************************************************************
  15. // I N C L U D E S
  16. //*****************************************************************************
  17. #include <ntddk.h>
  18. #include <usbdi.h>
  19. #include <usbdlib.h>
  20. #include <ntddscsi.h>
  21. #include <ntddstor.h>
  22. #include "usbmass.h"
  23. //*****************************************************************************
  24. // L O C A L F U N C T I O N P R O T O T Y P E S
  25. //*****************************************************************************
  26. NTSTATUS
  27. USBSTOR_QueryProperty (
  28. IN PDEVICE_OBJECT DeviceObject,
  29. IN PIRP Irp
  30. );
  31. NTSTATUS
  32. USBSTOR_BuildDeviceDescriptor (
  33. IN PDEVICE_OBJECT DeviceObject,
  34. IN PSTORAGE_DEVICE_DESCRIPTOR Descriptor,
  35. IN OUT PULONG DescriptorLength
  36. );
  37. NTSTATUS
  38. USBSTOR_BuildAdapterDescriptor (
  39. IN PDEVICE_OBJECT DeviceObject,
  40. IN PSTORAGE_DEVICE_DESCRIPTOR Descriptor,
  41. IN OUT PULONG DescriptorLength
  42. );
  43. NTSTATUS
  44. USBSTOR_SendPassThrough (
  45. IN PDEVICE_OBJECT DeviceObject,
  46. IN PIRP RequestIrp
  47. );
  48. VOID
  49. USBSTOR_CancelIo (
  50. IN PDEVICE_OBJECT DeviceObject,
  51. IN PIRP Irp
  52. );
  53. //
  54. // CBI (Control/Bulk/Interrupt) Routines
  55. //
  56. NTSTATUS
  57. USBSTOR_IssueClientCdb (
  58. IN PDEVICE_OBJECT DeviceObject,
  59. IN PIRP Irp
  60. );
  61. NTSTATUS
  62. USBSTOR_ClientCdbCompletion (
  63. IN PDEVICE_OBJECT DeviceObject,
  64. IN PIRP Irp,
  65. IN PVOID NotUsed
  66. );
  67. NTSTATUS
  68. USBSTOR_IssueClientBulkRequest (
  69. IN PDEVICE_OBJECT DeviceObject,
  70. IN PIRP Irp
  71. );
  72. NTSTATUS
  73. USBSTOR_ClientBulkCompletionRoutine (
  74. IN PDEVICE_OBJECT DeviceObject,
  75. IN PIRP Irp,
  76. IN PVOID NotUsed
  77. );
  78. NTSTATUS
  79. USBSTOR_IssueInterruptRequest (
  80. IN PDEVICE_OBJECT DeviceObject,
  81. IN PIRP Irp
  82. );
  83. NTSTATUS
  84. USBSTOR_InterruptDataCompletionRoutine (
  85. IN PDEVICE_OBJECT DeviceObject,
  86. IN PIRP Irp,
  87. IN PVOID NotUsed
  88. );
  89. NTSTATUS
  90. USBSTOR_IssueRequestSenseCdb (
  91. IN PDEVICE_OBJECT DeviceObject,
  92. IN PIRP Irp,
  93. IN ULONG_PTR AutoFlag
  94. );
  95. NTSTATUS
  96. USBSTOR_RequestSenseCdbCompletion (
  97. IN PDEVICE_OBJECT DeviceObject,
  98. IN PIRP Irp,
  99. IN PVOID AutoFlag
  100. );
  101. NTSTATUS
  102. USBSTOR_IssueRequestSenseBulkRequest (
  103. IN PDEVICE_OBJECT DeviceObject,
  104. IN PIRP Irp,
  105. IN ULONG_PTR AutoFlag
  106. );
  107. NTSTATUS
  108. USBSTOR_SenseDataCompletionRoutine (
  109. IN PDEVICE_OBJECT DeviceObject,
  110. IN PIRP Irp,
  111. IN PVOID AutoFlag
  112. );
  113. NTSTATUS
  114. USBSTOR_IssueRequestSenseInterruptRequest (
  115. IN PDEVICE_OBJECT DeviceObject,
  116. IN PIRP Irp,
  117. IN ULONG_PTR AutoFlag
  118. );
  119. NTSTATUS
  120. USBSTOR_RequestSenseInterruptCompletionRoutine (
  121. IN PDEVICE_OBJECT DeviceObject,
  122. IN PIRP Irp,
  123. IN PVOID AutoFlag
  124. );
  125. NTSTATUS
  126. USBSTOR_ProcessRequestSenseCompletion (
  127. IN PDEVICE_OBJECT DeviceObject,
  128. IN PIRP Irp,
  129. IN ULONG_PTR AutoFlag
  130. );
  131. VOID
  132. USBSTOR_QueueResetPipe (
  133. IN PDEVICE_OBJECT DeviceObject
  134. );
  135. VOID
  136. USBSTOR_ResetPipeWorkItem (
  137. IN PDEVICE_OBJECT DeviceObject,
  138. IN PVOID Context
  139. );
  140. //
  141. // Bulk-Only Routines
  142. //
  143. NTSTATUS
  144. USBSTOR_CbwTransfer (
  145. IN PDEVICE_OBJECT DeviceObject,
  146. IN PIRP Irp
  147. );
  148. NTSTATUS
  149. USBSTOR_CbwCompletion (
  150. IN PDEVICE_OBJECT DeviceObject,
  151. IN PIRP Irp,
  152. IN PVOID NotUsed
  153. );
  154. NTSTATUS
  155. USBSTOR_DataTransfer (
  156. IN PDEVICE_OBJECT DeviceObject,
  157. IN PIRP Irp
  158. );
  159. NTSTATUS
  160. USBSTOR_DataCompletion (
  161. IN PDEVICE_OBJECT DeviceObject,
  162. IN PIRP Irp,
  163. IN PVOID NotUsed
  164. );
  165. NTSTATUS
  166. USBSTOR_CswTransfer (
  167. IN PDEVICE_OBJECT DeviceObject,
  168. IN PIRP Irp
  169. );
  170. NTSTATUS
  171. USBSTOR_CswCompletion (
  172. IN PDEVICE_OBJECT DeviceObject,
  173. IN PIRP Irp,
  174. IN PVOID NotUsed
  175. );
  176. NTSTATUS
  177. USBSTOR_IssueRequestSense (
  178. IN PDEVICE_OBJECT DeviceObject,
  179. IN PIRP Irp
  180. );
  181. VOID
  182. USBSTOR_BulkQueueResetPipe (
  183. IN PDEVICE_OBJECT DeviceObject
  184. );
  185. VOID
  186. USBSTOR_BulkResetPipeWorkItem (
  187. IN PDEVICE_OBJECT DeviceObject,
  188. IN PVOID Context
  189. );
  190. //
  191. // CBI / Bulk-Only Common Routines
  192. //
  193. VOID
  194. USBSTOR_QueueResetDevice (
  195. IN PDEVICE_OBJECT DeviceObject
  196. );
  197. VOID
  198. USBSTOR_ResetDeviceWorkItem (
  199. IN PDEVICE_OBJECT DeviceObject,
  200. IN PVOID Context
  201. );
  202. NTSTATUS
  203. USBSTOR_IsDeviceConnected (
  204. IN PDEVICE_OBJECT DeviceObject
  205. );
  206. NTSTATUS
  207. USBSTOR_ResetDevice (
  208. IN PDEVICE_OBJECT DeviceObject
  209. );
  210. NTSTATUS
  211. USBSTOR_IssueInternalCdb (
  212. PDEVICE_OBJECT DeviceObject,
  213. PVOID DataBuffer,
  214. PULONG DataTransferLength,
  215. PCDB Cdb,
  216. UCHAR CdbLength,
  217. ULONG TimeOutValue
  218. );
  219. #ifdef ALLOC_PRAGMA
  220. #pragma alloc_text(PAGE, USBSTOR_DeviceControl)
  221. #pragma alloc_text(PAGE, USBSTOR_QueryProperty)
  222. #pragma alloc_text(PAGE, USBSTOR_BuildDeviceDescriptor)
  223. #pragma alloc_text(PAGE, USBSTOR_BuildAdapterDescriptor)
  224. #pragma alloc_text(PAGE, USBSTOR_SendPassThrough)
  225. #pragma alloc_text(PAGE, USBSTOR_IssueInternalCdb)
  226. #pragma alloc_text(PAGE, USBSTOR_GetInquiryData)
  227. #pragma alloc_text(PAGE, USBSTOR_IsFloppyDevice)
  228. #endif
  229. //******************************************************************************
  230. //
  231. // USBSTOR_DeviceControl()
  232. //
  233. // Dispatch routine which handles IRP_MJ_DEVICE_CONTROL
  234. //
  235. //******************************************************************************
  236. NTSTATUS
  237. USBSTOR_DeviceControl (
  238. IN PDEVICE_OBJECT DeviceObject,
  239. IN PIRP Irp
  240. )
  241. {
  242. PDEVICE_EXTENSION deviceExtension;
  243. PIO_STACK_LOCATION irpStack;
  244. ULONG ioControlCode;
  245. NTSTATUS ntStatus;
  246. PAGED_CODE();
  247. DBGPRINT(2, ("enter: USBSTOR_DeviceControl\n"));
  248. //LOGENTRY('IOCT', DeviceObject, Irp, 0);
  249. DBGFBRK(DBGF_BRK_IOCTL);
  250. deviceExtension = DeviceObject->DeviceExtension;
  251. // Only the PDO should handle these ioctls
  252. //
  253. if (deviceExtension->Type == USBSTOR_DO_TYPE_PDO)
  254. {
  255. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  256. fdoDeviceExtension = ((PPDO_DEVICE_EXTENSION)deviceExtension)->ParentFDO->DeviceExtension;
  257. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  258. irpStack = IoGetCurrentIrpStackLocation(Irp);
  259. ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
  260. switch (ioControlCode)
  261. {
  262. case IOCTL_STORAGE_QUERY_PROPERTY:
  263. ntStatus = USBSTOR_QueryProperty(DeviceObject, Irp);
  264. break;
  265. case IOCTL_SCSI_PASS_THROUGH:
  266. case IOCTL_SCSI_PASS_THROUGH_DIRECT:
  267. ntStatus = USBSTOR_SendPassThrough(DeviceObject, Irp);
  268. Irp->IoStatus.Status = ntStatus;
  269. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  270. break;
  271. case IOCTL_SCSI_GET_ADDRESS: // XXXXX
  272. DBGPRINT(2, ("IOCTL_SCSI_GET_ADDRESS\n"));
  273. goto IoctlNotSupported;
  274. case IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER:
  275. //
  276. // Pass the Irp down the stack
  277. //
  278. IoSkipCurrentIrpStackLocation(Irp);
  279. ntStatus = IoCallDriver(fdoDeviceExtension->StackDeviceObject,
  280. Irp);
  281. break;
  282. default:
  283. IoctlNotSupported:
  284. // Maybe we can just ignore these. Print debug info
  285. // for now so we know what IOCTLs that we've seen so
  286. // far that we fail.
  287. //
  288. DBGPRINT(2, ("ioControlCode not supported 0x%08X\n",
  289. ioControlCode));
  290. DBGFBRK(DBGF_BRK_IOCTL);
  291. ntStatus = STATUS_NOT_SUPPORTED;
  292. Irp->IoStatus.Status = ntStatus;
  293. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  294. break;
  295. }
  296. }
  297. else
  298. {
  299. ASSERT(deviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  300. DBGPRINT(2, ("ioctl not supported for FDO\n"));
  301. ntStatus = STATUS_NOT_SUPPORTED;
  302. Irp->IoStatus.Status = ntStatus;
  303. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  304. }
  305. DBGPRINT(2, ("exit: USBSTOR_DeviceControl %08X\n", ntStatus));
  306. //LOGENTRY('ioct', ntStatus, 0, 0);
  307. return ntStatus;
  308. }
  309. //******************************************************************************
  310. //
  311. // USBSTOR_QueryProperty()
  312. //
  313. // Dispatch routine which handles IRP_MJ_DEVICE_CONTROL,
  314. // IOCTL_STORAGE_QUERY_PROPERTY for the PDO
  315. //
  316. //******************************************************************************
  317. NTSTATUS
  318. USBSTOR_QueryProperty (
  319. IN PDEVICE_OBJECT DeviceObject,
  320. IN PIRP Irp
  321. )
  322. {
  323. PIO_STACK_LOCATION irpStack;
  324. PSTORAGE_PROPERTY_QUERY query;
  325. ULONG inputLength;
  326. ULONG outputLength;
  327. NTSTATUS ntStatus;
  328. PAGED_CODE();
  329. DBGPRINT(2, ("enter: USBSTOR_QueryProperty\n"));
  330. irpStack = IoGetCurrentIrpStackLocation(Irp);
  331. query = Irp->AssociatedIrp.SystemBuffer;
  332. inputLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
  333. outputLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  334. if (inputLength < sizeof(STORAGE_PROPERTY_QUERY))
  335. {
  336. ntStatus = STATUS_INVALID_PARAMETER; // Bad InputBufferLength
  337. outputLength = 0;
  338. goto USBSTOR_QueryPropertyDone;
  339. }
  340. switch (query->PropertyId)
  341. {
  342. case StorageDeviceProperty:
  343. switch (query->QueryType)
  344. {
  345. case PropertyExistsQuery:
  346. ntStatus = STATUS_SUCCESS;
  347. outputLength = 0;
  348. break;
  349. case PropertyStandardQuery:
  350. ntStatus = USBSTOR_BuildDeviceDescriptor(
  351. DeviceObject,
  352. Irp->AssociatedIrp.SystemBuffer,
  353. &outputLength);
  354. break;
  355. default:
  356. ntStatus = STATUS_INVALID_PARAMETER_2; // Bad QueryType
  357. outputLength = 0;
  358. break;
  359. }
  360. break;
  361. case StorageAdapterProperty:
  362. switch (query->QueryType)
  363. {
  364. case PropertyExistsQuery:
  365. ntStatus = STATUS_SUCCESS;
  366. outputLength = 0;
  367. break;
  368. case PropertyStandardQuery:
  369. ntStatus = USBSTOR_BuildAdapterDescriptor(
  370. DeviceObject,
  371. Irp->AssociatedIrp.SystemBuffer,
  372. &outputLength);
  373. break;
  374. default:
  375. ntStatus = STATUS_INVALID_PARAMETER_2; // Bad QueryType
  376. outputLength = 0;
  377. break;
  378. }
  379. break;
  380. default:
  381. ntStatus = STATUS_INVALID_PARAMETER_1; // Bad PropertyId
  382. outputLength = 0;
  383. break;
  384. }
  385. USBSTOR_QueryPropertyDone:
  386. Irp->IoStatus.Status = ntStatus;
  387. Irp->IoStatus.Information = outputLength;
  388. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  389. DBGPRINT(2, ("exit: USBSTOR_QueryProperty %08X\n", ntStatus));
  390. return ntStatus;
  391. }
  392. //******************************************************************************
  393. //
  394. // USBSTOR_BuildDeviceDescriptor()
  395. //
  396. //******************************************************************************
  397. NTSTATUS
  398. USBSTOR_BuildDeviceDescriptor (
  399. IN PDEVICE_OBJECT DeviceObject,
  400. IN PSTORAGE_DEVICE_DESCRIPTOR Descriptor,
  401. IN OUT PULONG DescriptorLength
  402. )
  403. {
  404. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  405. PINQUIRYDATA inquiryData;
  406. LONG inquiryLength;
  407. STORAGE_DEVICE_DESCRIPTOR localDescriptor;
  408. PUCHAR currentOffset;
  409. LONG bytesRemaining;
  410. PAGED_CODE();
  411. DBGPRINT(2, ("enter: USBSTOR_BuildDeviceDescriptor\n"));
  412. // Get a pointer to our Inquiry data
  413. //
  414. pdoDeviceExtension = DeviceObject->DeviceExtension;
  415. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  416. inquiryData = (PINQUIRYDATA)pdoDeviceExtension->InquiryDataBuffer;
  417. // inquiryLength = 5 + inquiryData->AdditionalLength;
  418. //
  419. // if (inquiryLength > INQUIRYDATABUFFERSIZE)
  420. // {
  421. // inquiryLength = INQUIRYDATABUFFERSIZE;
  422. // }
  423. //
  424. // Just return whatever we got from the device and leave it up to
  425. // whoever looks at this information to decide how much is valid.
  426. //
  427. inquiryLength = sizeof(pdoDeviceExtension->InquiryDataBuffer);
  428. // Zero initialize the output buffer
  429. //
  430. RtlZeroMemory(Descriptor, *DescriptorLength);
  431. // Build the temp local descriptor
  432. //
  433. RtlZeroMemory(&localDescriptor, sizeof(localDescriptor));
  434. localDescriptor.Version = sizeof(localDescriptor);
  435. localDescriptor.Size = FIELD_OFFSET(STORAGE_DEVICE_DESCRIPTOR,
  436. RawDeviceProperties) +
  437. inquiryLength +
  438. sizeof(inquiryData->VendorId) + 1 +
  439. sizeof(inquiryData->ProductId) + 1 +
  440. sizeof(inquiryData->ProductRevisionLevel) + 1;
  441. localDescriptor.DeviceType = inquiryData->DeviceType;
  442. localDescriptor.DeviceTypeModifier = inquiryData->DeviceTypeModifier;
  443. localDescriptor.RemovableMedia = inquiryData->RemovableMedia;
  444. localDescriptor.BusType = BusTypeUsb;
  445. // Start copying as much data as will fit in the output buffer
  446. //
  447. currentOffset = (PUCHAR)Descriptor;
  448. bytesRemaining = *DescriptorLength;
  449. // First copy the temp local descriptor
  450. //
  451. RtlCopyMemory(currentOffset,
  452. &localDescriptor,
  453. min(bytesRemaining,
  454. FIELD_OFFSET(STORAGE_DEVICE_DESCRIPTOR,
  455. RawDeviceProperties)));
  456. bytesRemaining -= FIELD_OFFSET(STORAGE_DEVICE_DESCRIPTOR,
  457. RawDeviceProperties);
  458. if (bytesRemaining <= 0)
  459. {
  460. return STATUS_SUCCESS;
  461. }
  462. // This should advance us to RawDeviceProperties[0]
  463. //
  464. currentOffset += FIELD_OFFSET(STORAGE_DEVICE_DESCRIPTOR,
  465. RawDeviceProperties);
  466. // Next copy the Inquiry data
  467. //
  468. Descriptor->RawPropertiesLength = min(bytesRemaining, inquiryLength);
  469. RtlCopyMemory(currentOffset,
  470. inquiryData,
  471. Descriptor->RawPropertiesLength);
  472. bytesRemaining -= inquiryLength;
  473. if (bytesRemaining <= 0)
  474. {
  475. return STATUS_SUCCESS;
  476. }
  477. currentOffset += inquiryLength;
  478. // Now copy the Vendor Id
  479. //
  480. RtlCopyMemory(currentOffset,
  481. inquiryData->VendorId,
  482. min(bytesRemaining, sizeof(inquiryData->VendorId)));
  483. bytesRemaining -= sizeof(inquiryData->VendorId) + 1; // include null
  484. if (bytesRemaining >= 0)
  485. {
  486. Descriptor->VendorIdOffset = (ULONG)((ULONG_PTR) currentOffset -
  487. (ULONG_PTR) Descriptor);
  488. }
  489. if (bytesRemaining <= 0)
  490. {
  491. return STATUS_SUCCESS;
  492. }
  493. currentOffset += sizeof(inquiryData->VendorId) + 1;
  494. // Now copy the Product Id
  495. //
  496. RtlCopyMemory(currentOffset,
  497. inquiryData->ProductId,
  498. min(bytesRemaining, sizeof(inquiryData->ProductId)));
  499. bytesRemaining -= sizeof(inquiryData->ProductId) + 1; // include null
  500. if (bytesRemaining >= 0)
  501. {
  502. Descriptor->ProductIdOffset = (ULONG)((ULONG_PTR) currentOffset -
  503. (ULONG_PTR) Descriptor);
  504. }
  505. if (bytesRemaining <= 0)
  506. {
  507. return STATUS_SUCCESS;
  508. }
  509. currentOffset += sizeof(inquiryData->ProductId) + 1;
  510. // And finally copy the Product Revision Level
  511. //
  512. RtlCopyMemory(currentOffset,
  513. inquiryData->ProductRevisionLevel,
  514. min(bytesRemaining, sizeof(inquiryData->ProductRevisionLevel)));
  515. bytesRemaining -= sizeof(inquiryData->ProductRevisionLevel) + 1; // include null
  516. if (bytesRemaining >= 0)
  517. {
  518. Descriptor->ProductRevisionOffset = (ULONG)((ULONG_PTR) currentOffset -
  519. (ULONG_PTR) Descriptor);
  520. }
  521. if (bytesRemaining <= 0)
  522. {
  523. return STATUS_SUCCESS;
  524. }
  525. *DescriptorLength -= bytesRemaining;
  526. return STATUS_SUCCESS;
  527. }
  528. //******************************************************************************
  529. //
  530. // USBSTOR_BuildAdapterDescriptor()
  531. //
  532. //******************************************************************************
  533. NTSTATUS
  534. USBSTOR_BuildAdapterDescriptor (
  535. IN PDEVICE_OBJECT DeviceObject,
  536. IN PSTORAGE_DEVICE_DESCRIPTOR Descriptor,
  537. IN OUT PULONG DescriptorLength
  538. )
  539. {
  540. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  541. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  542. STORAGE_ADAPTER_DESCRIPTOR localDescriptor;
  543. NTSTATUS ntStatus;
  544. PAGED_CODE();
  545. DBGPRINT(2, ("enter: USBSTOR_BuildAdapterDescriptor\n"));
  546. pdoDeviceExtension = DeviceObject->DeviceExtension;
  547. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  548. fdoDeviceExtension = pdoDeviceExtension->ParentFDO->DeviceExtension;
  549. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  550. localDescriptor.Version = sizeof(localDescriptor);
  551. localDescriptor.Size = sizeof(localDescriptor);
  552. localDescriptor.MaximumTransferLength = USBSTOR_MAX_TRANSFER_SIZE;
  553. localDescriptor.MaximumPhysicalPages = USBSTOR_MAX_TRANSFER_PAGES;
  554. localDescriptor.AlignmentMask = 0;
  555. localDescriptor.AdapterUsesPio = FALSE;
  556. localDescriptor.AdapterScansDown = FALSE;
  557. localDescriptor.CommandQueueing = FALSE;
  558. localDescriptor.AcceleratedTransfer = FALSE;
  559. localDescriptor.BusType = BusTypeUsb;
  560. localDescriptor.BusMajorVersion = fdoDeviceExtension->DeviceIsHighSpeed ?
  561. 2 : 1;
  562. localDescriptor.BusMinorVersion = 0;
  563. if (*DescriptorLength > localDescriptor.Size)
  564. {
  565. *DescriptorLength = localDescriptor.Size;
  566. }
  567. RtlCopyMemory(Descriptor,
  568. &localDescriptor,
  569. *DescriptorLength);
  570. ntStatus = STATUS_SUCCESS;
  571. DBGPRINT(2, ("exit: USBSTOR_BuildAdapterDescriptor %08X\n", ntStatus));
  572. return ntStatus;
  573. }
  574. //******************************************************************************
  575. //
  576. // USBSTOR_SendPassThrough()
  577. //
  578. // This routine handles IOCTL_SCSI_PASS_THROUGH requests.
  579. // It creates an Irp/Srb which is processed normally by the port driver.
  580. // This call is synchornous.
  581. //
  582. // (This routine borrowed from ATAPI.SYS)
  583. //
  584. //******************************************************************************
  585. NTSTATUS
  586. USBSTOR_SendPassThrough (
  587. IN PDEVICE_OBJECT DeviceObject,
  588. IN PIRP RequestIrp
  589. )
  590. {
  591. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  592. PIRP irp;
  593. PIO_STACK_LOCATION irpStack;
  594. PSCSI_PASS_THROUGH srbControl;
  595. SCSI_REQUEST_BLOCK srb;
  596. KEVENT event;
  597. LARGE_INTEGER startingOffset;
  598. IO_STATUS_BLOCK ioStatusBlock;
  599. ULONG outputLength;
  600. ULONG length;
  601. ULONG bufferOffset;
  602. PVOID buffer;
  603. PVOID endByte;
  604. PVOID senseBuffer;
  605. UCHAR majorCode;
  606. NTSTATUS status;
  607. PAGED_CODE();
  608. DBGPRINT(2, ("enter: USBSTOR_SendPassThrough\n"));
  609. pdoDeviceExtension = DeviceObject->DeviceExtension;
  610. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  611. startingOffset.QuadPart = (LONGLONG)1;
  612. // Get a pointer to the control block.
  613. //
  614. irpStack = IoGetCurrentIrpStackLocation(RequestIrp);
  615. srbControl = RequestIrp->AssociatedIrp.SystemBuffer;
  616. // Validiate the user buffer.
  617. //
  618. if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
  619. sizeof(SCSI_PASS_THROUGH))
  620. {
  621. return STATUS_INVALID_PARAMETER;
  622. }
  623. if (srbControl->Length != sizeof(SCSI_PASS_THROUGH) &&
  624. srbControl->Length != sizeof(SCSI_PASS_THROUGH_DIRECT))
  625. {
  626. return STATUS_REVISION_MISMATCH;
  627. }
  628. outputLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  629. // Validate the rest of the buffer parameters.
  630. //
  631. if (srbControl->CdbLength > 16)
  632. {
  633. return STATUS_INVALID_PARAMETER;
  634. }
  635. if (srbControl->SenseInfoLength != 0 &&
  636. (srbControl->Length > srbControl->SenseInfoOffset ||
  637. (srbControl->SenseInfoOffset + srbControl->SenseInfoLength >
  638. srbControl->DataBufferOffset && srbControl->DataTransferLength != 0)))
  639. {
  640. return STATUS_INVALID_PARAMETER;
  641. }
  642. majorCode = !srbControl->DataIn ? IRP_MJ_WRITE : IRP_MJ_READ;
  643. if (srbControl->DataTransferLength == 0)
  644. {
  645. length = 0;
  646. buffer = NULL;
  647. bufferOffset = 0;
  648. majorCode = IRP_MJ_FLUSH_BUFFERS;
  649. }
  650. else if ((srbControl->DataBufferOffset > outputLength) &&
  651. (srbControl->DataBufferOffset >
  652. irpStack->Parameters.DeviceIoControl.InputBufferLength))
  653. {
  654. // The data buffer offset is greater than system buffer. Assume this
  655. // is a user mode address.
  656. //
  657. if ((srbControl->SenseInfoOffset + srbControl->SenseInfoLength >
  658. outputLength) &&
  659. srbControl->SenseInfoLength)
  660. {
  661. return STATUS_INVALID_PARAMETER;
  662. }
  663. length = srbControl->DataTransferLength;
  664. buffer = (PCHAR) srbControl->DataBufferOffset;
  665. bufferOffset = 0;
  666. // make sure the user buffer is valid
  667. //
  668. if (RequestIrp->RequestorMode != KernelMode)
  669. {
  670. if (length)
  671. {
  672. endByte = (PVOID)((PCHAR)buffer + length - 1);
  673. if (buffer >= endByte)
  674. {
  675. return STATUS_INVALID_USER_BUFFER;
  676. }
  677. }
  678. }
  679. }
  680. else
  681. {
  682. if (srbControl->DataIn != SCSI_IOCTL_DATA_IN)
  683. {
  684. if (((srbControl->SenseInfoOffset + srbControl->SenseInfoLength >
  685. outputLength) &&
  686. srbControl->SenseInfoLength != 0) ||
  687. (srbControl->DataBufferOffset + srbControl->DataTransferLength >
  688. irpStack->Parameters.DeviceIoControl.InputBufferLength) ||
  689. (srbControl->Length > srbControl->DataBufferOffset))
  690. {
  691. return STATUS_INVALID_PARAMETER;
  692. }
  693. }
  694. if (srbControl->DataIn)
  695. {
  696. if ((srbControl->DataBufferOffset + srbControl->DataTransferLength >
  697. outputLength) ||
  698. (srbControl->Length > srbControl->DataBufferOffset))
  699. {
  700. return STATUS_INVALID_PARAMETER;
  701. }
  702. }
  703. length = (ULONG)srbControl->DataBufferOffset +
  704. srbControl->DataTransferLength;
  705. buffer = (PUCHAR) srbControl;
  706. bufferOffset = (ULONG)srbControl->DataBufferOffset;
  707. }
  708. // Validate that the request isn't too large for the miniport.
  709. //
  710. if (srbControl->DataTransferLength &&
  711. ((ADDRESS_AND_SIZE_TO_SPAN_PAGES(
  712. (PUCHAR)buffer+bufferOffset,
  713. srbControl->DataTransferLength
  714. ) > USBSTOR_MAX_TRANSFER_PAGES) ||
  715. (USBSTOR_MAX_TRANSFER_SIZE < srbControl->DataTransferLength)))
  716. {
  717. return STATUS_INVALID_PARAMETER;
  718. }
  719. if (srbControl->TimeOutValue == 0 ||
  720. srbControl->TimeOutValue > 30 * 60 * 60)
  721. {
  722. return STATUS_INVALID_PARAMETER;
  723. }
  724. //
  725. // Check for illegal command codes.
  726. //
  727. if (srbControl->Cdb[0] == SCSIOP_COPY ||
  728. srbControl->Cdb[0] == SCSIOP_COMPARE ||
  729. srbControl->Cdb[0] == SCSIOP_COPY_COMPARE)
  730. {
  731. return STATUS_INVALID_DEVICE_REQUEST;
  732. }
  733. // If this request came through a normal device control rather than from
  734. // class driver then the device must exist and be unclaimed. Class drivers
  735. // will set the minor function code for the device control. It is always
  736. // zero for a user request.
  737. //
  738. if (irpStack->MinorFunction == 0 &&
  739. pdoDeviceExtension->Claimed)
  740. {
  741. return STATUS_INVALID_PARAMETER;
  742. }
  743. // Allocate an aligned request sense buffer.
  744. //
  745. if (srbControl->SenseInfoLength != 0)
  746. {
  747. senseBuffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned,
  748. srbControl->SenseInfoLength,
  749. POOL_TAG);
  750. if (senseBuffer == NULL)
  751. {
  752. return STATUS_INSUFFICIENT_RESOURCES;
  753. }
  754. }
  755. else
  756. {
  757. senseBuffer = NULL;
  758. }
  759. //
  760. // Initialize the notification event.
  761. //
  762. KeInitializeEvent(&event,
  763. NotificationEvent,
  764. FALSE);
  765. // Build IRP for this request.
  766. // Note we do this synchronously for two reasons. If it was done
  767. // asynchonously then the completion code would have to make a special
  768. // check to deallocate the buffer. Second if a completion routine were
  769. // used then an addation stack locate would be needed.
  770. //
  771. try
  772. {
  773. irp = IoBuildSynchronousFsdRequest(
  774. majorCode,
  775. DeviceObject,
  776. buffer,
  777. length,
  778. &startingOffset,
  779. &event,
  780. &ioStatusBlock);
  781. }
  782. except(EXCEPTION_EXECUTE_HANDLER)
  783. {
  784. // An exception was incurred while attempting to probe the
  785. // caller's parameters. Dereference the file object and return
  786. // an appropriate error status code.
  787. //
  788. if (senseBuffer != NULL)
  789. {
  790. ExFreePool(senseBuffer);
  791. }
  792. return GetExceptionCode();
  793. }
  794. if (irp == NULL)
  795. {
  796. if (senseBuffer != NULL)
  797. {
  798. ExFreePool(senseBuffer);
  799. }
  800. return STATUS_INSUFFICIENT_RESOURCES;
  801. }
  802. irpStack = IoGetNextIrpStackLocation(irp);
  803. // Set major code.
  804. //
  805. irpStack->MajorFunction = IRP_MJ_SCSI;
  806. irpStack->MinorFunction = 1;
  807. // Fill in SRB fields.
  808. //
  809. irpStack->Parameters.Others.Argument1 = &srb;
  810. // Zero out the srb.
  811. //
  812. RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
  813. // Fill in the srb.
  814. //
  815. srb.Length = SCSI_REQUEST_BLOCK_SIZE;
  816. srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
  817. srb.SrbStatus = SRB_STATUS_PENDING;
  818. srb.CdbLength = srbControl->CdbLength;
  819. srb.SenseInfoBufferLength = srbControl->SenseInfoLength;
  820. switch (srbControl->DataIn)
  821. {
  822. case SCSI_IOCTL_DATA_OUT:
  823. if (srbControl->DataTransferLength)
  824. {
  825. srb.SrbFlags = SRB_FLAGS_DATA_OUT;
  826. }
  827. break;
  828. case SCSI_IOCTL_DATA_IN:
  829. if (srbControl->DataTransferLength)
  830. {
  831. srb.SrbFlags = SRB_FLAGS_DATA_IN;
  832. }
  833. break;
  834. default:
  835. srb.SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT;
  836. break;
  837. }
  838. if (srbControl->DataTransferLength == 0)
  839. {
  840. srb.SrbFlags = 0;
  841. }
  842. else
  843. {
  844. // Flush the data buffer for output. This will insure that the data is
  845. // written back to memory.
  846. //
  847. KeFlushIoBuffers(irp->MdlAddress, FALSE, TRUE);
  848. }
  849. srb.DataTransferLength = srbControl->DataTransferLength;
  850. srb.TimeOutValue = srbControl->TimeOutValue;
  851. srb.DataBuffer = (PCHAR) buffer + bufferOffset;
  852. srb.SenseInfoBuffer = senseBuffer;
  853. srb.OriginalRequest = irp;
  854. RtlCopyMemory(srb.Cdb, srbControl->Cdb, srbControl->CdbLength);
  855. // Call port driver to handle this request.
  856. //
  857. status = IoCallDriver(DeviceObject, irp);
  858. // Wait for request to complete.
  859. //
  860. if (status == STATUS_PENDING)
  861. {
  862. KeWaitForSingleObject(&event,
  863. Executive,
  864. KernelMode,
  865. FALSE,
  866. NULL);
  867. }
  868. else
  869. {
  870. ioStatusBlock.Status = status;
  871. }
  872. // Copy the returned values from the srb to the control structure.
  873. //
  874. srbControl->ScsiStatus = srb.ScsiStatus;
  875. if (srb.SrbStatus & SRB_STATUS_AUTOSENSE_VALID)
  876. {
  877. // Set the status to success so that the data is returned.
  878. //
  879. ioStatusBlock.Status = STATUS_SUCCESS;
  880. srbControl->SenseInfoLength = srb.SenseInfoBufferLength;
  881. // Copy the sense data to the system buffer.
  882. //
  883. RtlCopyMemory((PUCHAR) srbControl + srbControl->SenseInfoOffset,
  884. senseBuffer,
  885. srb.SenseInfoBufferLength);
  886. }
  887. else
  888. {
  889. srbControl->SenseInfoLength = 0;
  890. }
  891. // Free the sense buffer.
  892. //
  893. if (senseBuffer != NULL)
  894. {
  895. ExFreePool(senseBuffer);
  896. }
  897. // If the srb status is buffer underrun then set the status to success.
  898. // This insures that the data will be returned to the caller.
  899. //
  900. if (SRB_STATUS(srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN)
  901. {
  902. ioStatusBlock.Status = STATUS_SUCCESS;
  903. }
  904. srbControl->DataTransferLength = srb.DataTransferLength;
  905. // Set the information length
  906. //
  907. if (!srbControl->DataIn || bufferOffset == 0)
  908. {
  909. RequestIrp->IoStatus.Information = srbControl->SenseInfoOffset +
  910. srbControl->SenseInfoLength;
  911. }
  912. else
  913. {
  914. RequestIrp->IoStatus.Information = srbControl->DataBufferOffset +
  915. srbControl->DataTransferLength;
  916. }
  917. RequestIrp->IoStatus.Status = ioStatusBlock.Status;
  918. DBGPRINT(2, ("exit: USBSTOR_SendPassThrough %08X\n",
  919. ioStatusBlock.Status));
  920. return ioStatusBlock.Status;
  921. }
  922. //******************************************************************************
  923. //
  924. // IsRequestValid()
  925. //
  926. // Validates IRP_MJ_SCSI SRB_FUNCTION_EXECUTE_SCSI requests against
  927. // assumptions made later when processing the Srb.
  928. //
  929. //******************************************************************************
  930. BOOLEAN
  931. IsRequestValid (
  932. IN PIRP Irp
  933. )
  934. {
  935. PIO_STACK_LOCATION irpStack;
  936. PSCSI_REQUEST_BLOCK srb;
  937. BOOLEAN result;
  938. irpStack = IoGetCurrentIrpStackLocation(Irp);
  939. srb = irpStack->Parameters.Scsi.Srb;
  940. // Default return value unless a problem is found.
  941. //
  942. result = TRUE;
  943. // Note: SRB_FLAGS_UNSPECIFIED_DIRECTION is defined as
  944. // (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT)
  945. if ((srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) == 0) {
  946. // Neither SRB_FLAGS_DATA_IN nor SRB_FLAGS_DATA_IN is set.
  947. // A transfer buffer should not be specified.
  948. if (srb->DataTransferLength ||
  949. srb->DataBuffer ||
  950. Irp->MdlAddress) {
  951. result = FALSE;
  952. }
  953. } else if ((srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) ==
  954. SRB_FLAGS_UNSPECIFIED_DIRECTION) {
  955. // Both SRB_FLAGS_DATA_IN and SRB_FLAGS_DATA_IN are set.
  956. // We don't currently have a way to resolve this.
  957. result = FALSE;
  958. } else {
  959. // Either SRB_FLAGS_DATA_IN or SRB_FLAGS_DATA_IN is set.
  960. // A transfer buffer should be specified.
  961. if (!srb->DataTransferLength ||
  962. srb->DataTransferLength > USBSTOR_MAX_TRANSFER_SIZE ||
  963. //!srb->DataBuffer ||
  964. !Irp->MdlAddress) {
  965. result = FALSE;
  966. }
  967. }
  968. if (!result) {
  969. DBGPRINT(1, ("SrbFlags %08X, DataTransferLength %08X, "
  970. "DataBuffer %08X, MdlAddress %08X\n",
  971. srb->SrbFlags,
  972. srb->DataTransferLength,
  973. srb->DataBuffer,
  974. Irp->MdlAddress));
  975. DBGPRINT(1, ("Irp %08X, Srb %08X\n",
  976. Irp, srb));
  977. DBGFBRK(DBGF_BRK_INVALID_REQ);
  978. }
  979. return result;
  980. }
  981. //******************************************************************************
  982. //
  983. // USBSTOR_Scsi()
  984. //
  985. // Dispatch routine which handles IRP_MJ_SCSI
  986. //
  987. //******************************************************************************
  988. NTSTATUS
  989. USBSTOR_Scsi (
  990. IN PDEVICE_OBJECT DeviceObject,
  991. IN PIRP Irp
  992. )
  993. {
  994. PDEVICE_EXTENSION deviceExtension;
  995. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  996. PIO_STACK_LOCATION irpStack;
  997. PSCSI_REQUEST_BLOCK srb;
  998. KIRQL irql;
  999. NTSTATUS ntStatus;
  1000. DBGPRINT(3, ("enter: USBSTOR_Scsi\n"));
  1001. DBGFBRK(DBGF_BRK_SCSI);
  1002. deviceExtension = DeviceObject->DeviceExtension;
  1003. // Only the PDO should handle IRP_MJ_SCSI
  1004. //
  1005. if (deviceExtension->Type == USBSTOR_DO_TYPE_PDO)
  1006. {
  1007. pdoDeviceExtension = DeviceObject->DeviceExtension;
  1008. irpStack = IoGetCurrentIrpStackLocation(Irp);
  1009. srb = irpStack->Parameters.Scsi.Srb;
  1010. LOGENTRY('SCSI', DeviceObject, Irp, srb->Function);
  1011. switch (srb->Function)
  1012. {
  1013. case SRB_FUNCTION_EXECUTE_SCSI:
  1014. DBGPRINT(3, ("SRB_FUNCTION_EXECUTE_SCSI\n"));
  1015. // XXXXX check STOP / REMOVE flags
  1016. // XXXXX check SRB_FLAGS_BYPASS_LOCKED_QUEUE flag
  1017. if (IsRequestValid(Irp))
  1018. {
  1019. srb->SrbStatus = SRB_STATUS_PENDING;
  1020. IoMarkIrpPending(Irp);
  1021. IoStartPacket(pdoDeviceExtension->ParentFDO,
  1022. Irp,
  1023. &srb->QueueSortKey,
  1024. USBSTOR_CancelIo);
  1025. ntStatus = STATUS_PENDING;
  1026. }
  1027. else
  1028. {
  1029. ntStatus = STATUS_INVALID_PARAMETER;
  1030. }
  1031. break;
  1032. case SRB_FUNCTION_FLUSH:
  1033. DBGPRINT(2, ("SRB_FUNCTION_FLUSH\n"));
  1034. ntStatus = STATUS_SUCCESS;
  1035. srb->SrbStatus = SRB_STATUS_SUCCESS;
  1036. break;
  1037. case SRB_FUNCTION_CLAIM_DEVICE:
  1038. DBGPRINT(2, ("SRB_FUNCTION_CLAIM_DEVICE\n"));
  1039. //KeAcquireSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock,
  1040. // &irql);
  1041. {
  1042. if (pdoDeviceExtension->Claimed)
  1043. {
  1044. ntStatus = STATUS_DEVICE_BUSY;
  1045. srb->SrbStatus = SRB_STATUS_BUSY;
  1046. }
  1047. else
  1048. {
  1049. pdoDeviceExtension->Claimed = TRUE;
  1050. srb->DataBuffer = DeviceObject;
  1051. ntStatus = STATUS_SUCCESS;
  1052. srb->SrbStatus = SRB_STATUS_SUCCESS;
  1053. }
  1054. }
  1055. //KeReleaseSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock,
  1056. // irql);
  1057. break;
  1058. case SRB_FUNCTION_RELEASE_DEVICE:
  1059. DBGPRINT(2, ("SRB_FUNCTION_RELEASE_DEVICE\n"));
  1060. //KeAcquireSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock,
  1061. // &irql);
  1062. {
  1063. pdoDeviceExtension->Claimed = FALSE;
  1064. }
  1065. //KeReleaseSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock,
  1066. // irql);
  1067. ntStatus = STATUS_SUCCESS;
  1068. srb->SrbStatus = SRB_STATUS_SUCCESS;
  1069. break;
  1070. default:
  1071. DBGPRINT(2, ("Unhandled SRB function %d\n", srb->Function));
  1072. ntStatus = STATUS_NOT_SUPPORTED;
  1073. srb->SrbStatus = SRB_STATUS_ERROR;
  1074. break;
  1075. }
  1076. }
  1077. else
  1078. {
  1079. ASSERT(deviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  1080. DBGPRINT(2, ("IRP_MJ_SCSI not supported for FDO\n"));
  1081. ntStatus = STATUS_NOT_SUPPORTED;
  1082. }
  1083. if (ntStatus != STATUS_PENDING)
  1084. {
  1085. Irp->IoStatus.Status = ntStatus;
  1086. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1087. }
  1088. DBGPRINT(3, ("exit: USBSTOR_Scsi %08X\n", ntStatus));
  1089. LOGENTRY('scsi', ntStatus, 0, 0);
  1090. return ntStatus;
  1091. }
  1092. //******************************************************************************
  1093. //
  1094. // USBSTOR_TranslateCDBSubmit()
  1095. //
  1096. // Called by USBSTOR_StartIo() before a request is started.
  1097. //
  1098. //******************************************************************************
  1099. VOID
  1100. USBSTOR_TranslateCDBSubmit (
  1101. IN PDEVICE_OBJECT DeviceObject,
  1102. IN PIRP Irp,
  1103. IN PSCSI_REQUEST_BLOCK Srb
  1104. )
  1105. {
  1106. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1107. PCDB cdb;
  1108. fdoDeviceExtension = DeviceObject->DeviceExtension;
  1109. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  1110. if (fdoDeviceExtension->InterfaceDescriptor->bInterfaceSubClass ==
  1111. USBSTOR_SUBCLASS_SCSI_PASSTHROUGH)
  1112. {
  1113. return;
  1114. }
  1115. // Save the original CDB
  1116. //
  1117. cdb = (PCDB)Srb->Cdb;
  1118. RtlCopyMemory(fdoDeviceExtension->OriginalCDB, cdb, 16);
  1119. // Make sure the CDB is padded with zero bytes.
  1120. //
  1121. if (Srb->CdbLength < 16)
  1122. {
  1123. RtlZeroMemory(&Srb->Cdb[Srb->CdbLength],
  1124. 16 - Srb->CdbLength);
  1125. }
  1126. Srb->CdbLength = 12;
  1127. switch (Srb->Cdb[0])
  1128. {
  1129. // Send a SCSIOP_START_STOP_UNIT request instead of a
  1130. // SCSIOP_TEST_UNIT_READY request for selected buggy
  1131. // devices which don't otherwise update their internal
  1132. // geometry information when the media changes.
  1133. //
  1134. case SCSIOP_TEST_UNIT_READY:
  1135. if (TEST_FLAG(fdoDeviceExtension->DeviceHackFlags,
  1136. DHF_TUR_START_UNIT))
  1137. {
  1138. // Zero the new CDB
  1139. //
  1140. RtlZeroMemory(cdb, 16);
  1141. cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
  1142. cdb->START_STOP.Start = 1;
  1143. }
  1144. break;
  1145. // Convert 6-byte Mode Sense to 10-byte Mode Sense
  1146. //
  1147. case SCSIOP_MODE_SENSE:
  1148. {
  1149. UCHAR PageCode;
  1150. UCHAR Length;
  1151. // Extract the relevant params from original CDB
  1152. //
  1153. PageCode = cdb->MODE_SENSE.PageCode;
  1154. Length = cdb->MODE_SENSE.AllocationLength;
  1155. // Zero the new CDB
  1156. //
  1157. RtlZeroMemory(cdb, 16);
  1158. // Insert the relevant params into the translated CDB
  1159. //
  1160. cdb->MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10;
  1161. cdb->MODE_SENSE10.PageCode = PageCode;
  1162. cdb->MODE_SENSE10.AllocationLength[1] = Length;
  1163. }
  1164. break;
  1165. // Convert 6-byte Mode Select to 10-byte Mode Select
  1166. //
  1167. case SCSIOP_MODE_SELECT:
  1168. {
  1169. UCHAR SPBit;
  1170. UCHAR Length;
  1171. // Extract the relevant params from original CDB
  1172. //
  1173. SPBit = cdb->MODE_SELECT.SPBit;
  1174. Length = cdb->MODE_SELECT.ParameterListLength;
  1175. // Zero the new CDB
  1176. //
  1177. RtlZeroMemory(cdb, 16);
  1178. // Insert the relevant params into the translated CDB
  1179. //
  1180. cdb->MODE_SELECT10.OperationCode = SCSIOP_MODE_SELECT10;
  1181. cdb->MODE_SELECT10.SPBit = SPBit;
  1182. cdb->MODE_SELECT10.PFBit = 1;
  1183. cdb->MODE_SELECT10.ParameterListLength[1] = Length;
  1184. }
  1185. break;
  1186. }
  1187. }
  1188. //******************************************************************************
  1189. //
  1190. // USBSTOR_TranslateSrbStatus()
  1191. //
  1192. // This routine translates an srb status into an ntstatus.
  1193. //
  1194. //******************************************************************************
  1195. NTSTATUS
  1196. USBSTOR_TranslateSrbStatus(
  1197. IN PSCSI_REQUEST_BLOCK Srb
  1198. )
  1199. {
  1200. switch (SRB_STATUS(Srb->SrbStatus)) {
  1201. case SRB_STATUS_INVALID_LUN:
  1202. case SRB_STATUS_INVALID_TARGET_ID:
  1203. case SRB_STATUS_NO_DEVICE:
  1204. case SRB_STATUS_NO_HBA:
  1205. return(STATUS_DEVICE_DOES_NOT_EXIST);
  1206. case SRB_STATUS_COMMAND_TIMEOUT:
  1207. case SRB_STATUS_BUS_RESET:
  1208. case SRB_STATUS_TIMEOUT:
  1209. return(STATUS_IO_TIMEOUT);
  1210. case SRB_STATUS_SELECTION_TIMEOUT:
  1211. return(STATUS_DEVICE_NOT_CONNECTED);
  1212. case SRB_STATUS_BAD_FUNCTION:
  1213. case SRB_STATUS_BAD_SRB_BLOCK_LENGTH:
  1214. return(STATUS_INVALID_DEVICE_REQUEST);
  1215. case SRB_STATUS_DATA_OVERRUN:
  1216. return(STATUS_BUFFER_OVERFLOW);
  1217. default:
  1218. return(STATUS_IO_DEVICE_ERROR);
  1219. }
  1220. return(STATUS_IO_DEVICE_ERROR);
  1221. }
  1222. //******************************************************************************
  1223. //
  1224. // USBSTOR_TranslateCDBComplete()
  1225. //
  1226. // Called everywhere a request is completed.
  1227. //
  1228. //******************************************************************************
  1229. VOID
  1230. USBSTOR_TranslateCDBComplete (
  1231. IN PDEVICE_OBJECT DeviceObject,
  1232. IN PIRP Irp,
  1233. IN PSCSI_REQUEST_BLOCK Srb
  1234. )
  1235. {
  1236. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1237. PCDB cdb;
  1238. fdoDeviceExtension = DeviceObject->DeviceExtension;
  1239. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  1240. if (fdoDeviceExtension->InterfaceDescriptor->bInterfaceSubClass ==
  1241. USBSTOR_SUBCLASS_SCSI_PASSTHROUGH)
  1242. {
  1243. #if DBG
  1244. if ((Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) &&
  1245. (Srb->SenseInfoBufferLength >= 14))
  1246. {
  1247. PSENSE_DATA senseData;
  1248. senseData = (PSENSE_DATA)Srb->SenseInfoBuffer;
  1249. DBGPRINT(1, ("OP: %02X SenseKey %02X ASC %02X ASCQ %02X\n",
  1250. Srb->Cdb[0],
  1251. senseData->SenseKey,
  1252. senseData->AdditionalSenseCode,
  1253. senseData->AdditionalSenseCodeQualifier));
  1254. }
  1255. #endif
  1256. if (SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS)
  1257. {
  1258. Irp->IoStatus.Status = USBSTOR_TranslateSrbStatus(Srb);
  1259. }
  1260. return;
  1261. }
  1262. if (Srb->Cdb[0] != fdoDeviceExtension->OriginalCDB[0])
  1263. {
  1264. cdb = (PCDB)Srb->Cdb;
  1265. switch (Srb->Cdb[0])
  1266. {
  1267. // Convert 10-byte Mode Sense back to 6-byte Mode Sense
  1268. //
  1269. case SCSIOP_MODE_SENSE10:
  1270. {
  1271. if ((SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS ||
  1272. SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_DATA_OVERRUN) &&
  1273. Srb->DataTransferLength >= sizeof(MODE_PARAMETER_HEADER10))
  1274. {
  1275. PMODE_PARAMETER_HEADER hdr6;
  1276. PMODE_PARAMETER_HEADER10 hdr10;
  1277. hdr6 = (PMODE_PARAMETER_HEADER) Srb->DataBuffer;
  1278. hdr10 = (PMODE_PARAMETER_HEADER10)Srb->DataBuffer;
  1279. // Convert the 10-byte header to a 6-byte header
  1280. //
  1281. hdr6->ModeDataLength = hdr10->ModeDataLength[1];
  1282. hdr6->MediumType = hdr10->MediumType;
  1283. hdr6->DeviceSpecificParameter =
  1284. hdr10->DeviceSpecificParameter;
  1285. hdr6->BlockDescriptorLength =
  1286. hdr10->BlockDescriptorLength[1];
  1287. // Advance past headers
  1288. //
  1289. hdr6++;
  1290. hdr10++;
  1291. // Copy everything past the 10-byte header
  1292. //
  1293. RtlMoveMemory(hdr6,
  1294. hdr10,
  1295. (Srb->DataTransferLength -
  1296. sizeof(MODE_PARAMETER_HEADER10)));
  1297. // Adjust the return size to account for the smaller header
  1298. //
  1299. Srb->DataTransferLength -= (sizeof(MODE_PARAMETER_HEADER10) -
  1300. sizeof(MODE_PARAMETER_HEADER));
  1301. // Since we just shrunk Srb->DataTransferLength, don't
  1302. // we have SRB_STATUS_DATA_OVERRUN by definition???
  1303. //
  1304. if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID)
  1305. {
  1306. Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN |
  1307. SRB_STATUS_AUTOSENSE_VALID;
  1308. }
  1309. else
  1310. {
  1311. Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
  1312. }
  1313. }
  1314. }
  1315. break;
  1316. }
  1317. // Restore the original CDB
  1318. //
  1319. RtlCopyMemory(cdb, fdoDeviceExtension->OriginalCDB, 16);
  1320. }
  1321. #if DBG
  1322. if ((Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) &&
  1323. (Srb->SenseInfoBufferLength >= 14))
  1324. {
  1325. PSENSE_DATA senseData;
  1326. senseData = (PSENSE_DATA)Srb->SenseInfoBuffer;
  1327. DBGPRINT(1, ("OP: %02X SenseKey %02X ASC %02X ASCQ %02X\n",
  1328. Srb->Cdb[0],
  1329. senseData->SenseKey,
  1330. senseData->AdditionalSenseCode,
  1331. senseData->AdditionalSenseCodeQualifier));
  1332. }
  1333. #endif
  1334. if (SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS)
  1335. {
  1336. Irp->IoStatus.Status = USBSTOR_TranslateSrbStatus(Srb);
  1337. }
  1338. }
  1339. //******************************************************************************
  1340. //
  1341. // USBSTOR_CancelIo()
  1342. //
  1343. // This routine runs at DPC level (until the cancel spinlock is released).
  1344. //
  1345. //******************************************************************************
  1346. VOID
  1347. USBSTOR_CancelIo (
  1348. IN PDEVICE_OBJECT DeviceObject,
  1349. IN PIRP Irp
  1350. )
  1351. {
  1352. if (DeviceObject->CurrentIrp == Irp)
  1353. {
  1354. IoReleaseCancelSpinLock(Irp->CancelIrql);
  1355. LOGENTRY('CAN1', DeviceObject, Irp, 0);
  1356. DBGPRINT(1, ("USBSTOR_CancelIo cancelling CurrentIrp\n"));
  1357. }
  1358. else if (KeRemoveEntryDeviceQueue(&DeviceObject->DeviceQueue,
  1359. &Irp->Tail.Overlay.DeviceQueueEntry))
  1360. {
  1361. IoReleaseCancelSpinLock(Irp->CancelIrql);
  1362. LOGENTRY('CAN2', DeviceObject, Irp, 0);
  1363. DBGPRINT(1, ("USBSTOR_CancelIo cancelling queued Irp\n"));
  1364. Irp->IoStatus.Status = STATUS_CANCELLED;
  1365. Irp->IoStatus.Information = 0;
  1366. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1367. }
  1368. else
  1369. {
  1370. IoReleaseCancelSpinLock(Irp->CancelIrql);
  1371. }
  1372. }
  1373. //******************************************************************************
  1374. //
  1375. // USBSTOR_StartIo()
  1376. //
  1377. // This routine handles IRP_MJ_SCSI, SRB_FUNCTION_EXECUTE_SCSI requests from
  1378. // the device the queue.
  1379. //
  1380. // This routine runs at DPC level.
  1381. //
  1382. //******************************************************************************
  1383. VOID
  1384. USBSTOR_StartIo (
  1385. IN PDEVICE_OBJECT DeviceObject,
  1386. IN PIRP Irp
  1387. )
  1388. {
  1389. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1390. PIO_STACK_LOCATION irpStack;
  1391. PSCSI_REQUEST_BLOCK srb;
  1392. BOOLEAN startNext;
  1393. BOOLEAN deviceDisconnected;
  1394. BOOLEAN persistentError;
  1395. KIRQL irql;
  1396. NTSTATUS ntStatus;
  1397. LOGENTRY('STIO', DeviceObject, Irp, 0);
  1398. DBGPRINT(3, ("enter: USBSTOR_StartIo %08X %08X\n",
  1399. DeviceObject, Irp));
  1400. fdoDeviceExtension = DeviceObject->DeviceExtension;
  1401. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  1402. // Get our Irp parameters
  1403. //
  1404. irpStack = IoGetCurrentIrpStackLocation(Irp);
  1405. // Check to see if this is a power down Irp.
  1406. //
  1407. if (irpStack->MajorFunction == IRP_MJ_POWER)
  1408. {
  1409. // This is a power down Irp. Now that we know that no transfer
  1410. // requests are in progress, pass down the power Irp.
  1411. ASSERT(irpStack->MinorFunction == IRP_MN_SET_POWER);
  1412. ASSERT(irpStack->Parameters.Power.Type == DevicePowerState);
  1413. ASSERT(irpStack->Parameters.Power.State.DeviceState !=
  1414. PowerDeviceD0);
  1415. DBGPRINT(2, ("FDO Power Down Passing Down %08X %08X\n",
  1416. DeviceObject, Irp));
  1417. LOGENTRY('FPDC', DeviceObject, Irp, 0);
  1418. //
  1419. // Signal that it is time to pass the request down to the next
  1420. // lower driver
  1421. //
  1422. KeSetEvent(&fdoDeviceExtension->PowerDownEvent,
  1423. IO_NO_INCREMENT,
  1424. 0);
  1425. // Leave the device queue blocked now by simply not calling
  1426. // IoStartNextPacket(). When we want to start the device queue
  1427. // again, simply call IoStartNextPacket().
  1428. return;
  1429. }
  1430. // If the Irp is not IRP_MJ_POWER it better be IRP_MJ_SCSI
  1431. //
  1432. ASSERT(irpStack->MajorFunction == IRP_MJ_SCSI);
  1433. // Check to see if the current Irp was cancelled.
  1434. //
  1435. IoAcquireCancelSpinLock(&irql);
  1436. IoSetCancelRoutine(Irp, NULL);
  1437. if (Irp->Cancel)
  1438. {
  1439. // The current Irp was cancelled. Complete the request now, and start
  1440. // the next request, unless a reset is still in progress in which case
  1441. // the next request will be started when the reset completes.
  1442. //
  1443. KeAcquireSpinLockAtDpcLevel(&fdoDeviceExtension->ExtensionDataSpinLock);
  1444. {
  1445. startNext = !TEST_FLAG(fdoDeviceExtension->DeviceFlags,
  1446. DF_RESET_IN_PROGRESS);
  1447. }
  1448. KeReleaseSpinLockFromDpcLevel(&fdoDeviceExtension->ExtensionDataSpinLock);
  1449. IoReleaseCancelSpinLock(irql);
  1450. LOGENTRY('CAN3', DeviceObject, Irp, 0);
  1451. Irp->IoStatus.Status = STATUS_CANCELLED;
  1452. Irp->IoStatus.Information = 0;
  1453. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1454. if (startNext)
  1455. {
  1456. IoStartNextPacket(DeviceObject, TRUE);
  1457. }
  1458. return;
  1459. }
  1460. // The current Irp was not cancelled. It is no longer cancelable.
  1461. //
  1462. IoReleaseCancelSpinLock(irql);
  1463. // Get our Irp parameters
  1464. //
  1465. srb = irpStack->Parameters.Scsi.Srb;
  1466. fdoDeviceExtension->OriginalSrb = srb;
  1467. deviceDisconnected = FALSE;
  1468. persistentError = FALSE;
  1469. KeAcquireSpinLockAtDpcLevel(&fdoDeviceExtension->ExtensionDataSpinLock);
  1470. {
  1471. if (TEST_FLAG(fdoDeviceExtension->DeviceFlags, DF_DEVICE_DISCONNECTED))
  1472. {
  1473. deviceDisconnected = TRUE;
  1474. }
  1475. else
  1476. {
  1477. fdoDeviceExtension->SrbTimeout = srb->TimeOutValue;
  1478. if (TEST_FLAG(fdoDeviceExtension->DeviceFlags, DF_PERSISTENT_ERROR))
  1479. {
  1480. persistentError = TRUE;
  1481. CLEAR_FLAG(fdoDeviceExtension->DeviceFlags, DF_PERSISTENT_ERROR);
  1482. }
  1483. }
  1484. }
  1485. KeReleaseSpinLockFromDpcLevel(&fdoDeviceExtension->ExtensionDataSpinLock);
  1486. if (deviceDisconnected)
  1487. {
  1488. LOGENTRY('siod', DeviceObject, Irp, 0);
  1489. // The device is disconnected, fail this request immediately and start
  1490. // the next request.
  1491. //
  1492. srb->SrbStatus = SRB_STATUS_NO_DEVICE;
  1493. srb->DataTransferLength = 0;
  1494. ntStatus = STATUS_DEVICE_DOES_NOT_EXIST;
  1495. Irp->IoStatus.Status = ntStatus;
  1496. Irp->IoStatus.Information = 0;
  1497. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1498. IoStartNextPacket(DeviceObject, TRUE);
  1499. }
  1500. else
  1501. {
  1502. // Translate the CDB if necessary
  1503. //
  1504. USBSTOR_TranslateCDBSubmit(DeviceObject, Irp, srb);
  1505. DBGPRINT(3, ("CDB OP 0x%02X, Length %d\n", srb->Cdb[0], srb->CdbLength));
  1506. if (fdoDeviceExtension->DriverFlags == DeviceProtocolBulkOnly)
  1507. {
  1508. ntStatus = USBSTOR_CbwTransfer(DeviceObject,
  1509. Irp);
  1510. }
  1511. else
  1512. {
  1513. if (persistentError && (srb->Cdb[0] != SCSIOP_REQUEST_SENSE))
  1514. {
  1515. // There was a persistent error during the last request which
  1516. // was not cleared with an AutoSense, and this request is not
  1517. // a Request Sense, so first clear the persistent error with a
  1518. // Request Sense before issuing this request.
  1519. //
  1520. ntStatus = USBSTOR_IssueRequestSenseCdb(DeviceObject,
  1521. Irp,
  1522. NON_AUTO_SENSE);
  1523. }
  1524. else
  1525. {
  1526. // Normal case, just issue the real request.
  1527. //
  1528. ntStatus = USBSTOR_IssueClientCdb(DeviceObject,
  1529. Irp);
  1530. }
  1531. }
  1532. }
  1533. DBGPRINT(3, ("exit: USBSTOR_StartIo %08X\n", ntStatus));
  1534. return;
  1535. }
  1536. //******************************************************************************
  1537. //
  1538. // USBSTOR_CheckRequestTimeOut()
  1539. //
  1540. // Returns TRUE if the request timed out and the request should be completed.
  1541. //
  1542. //******************************************************************************
  1543. BOOLEAN
  1544. USBSTOR_CheckRequestTimeOut (
  1545. IN PDEVICE_OBJECT DeviceObject,
  1546. IN PIRP Irp,
  1547. IN PSCSI_REQUEST_BLOCK Srb,
  1548. OUT PNTSTATUS NtStatus
  1549. )
  1550. {
  1551. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1552. BOOLEAN resetStarted;
  1553. KIRQL irql;
  1554. PIO_STACK_LOCATION irpStack;
  1555. fdoDeviceExtension = DeviceObject->DeviceExtension;
  1556. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  1557. // Check to see if a reset was started while this request was in progress.
  1558. //
  1559. resetStarted = FALSE;
  1560. KeAcquireSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock, &irql);
  1561. {
  1562. CLEAR_FLAG(fdoDeviceExtension->DeviceFlags, DF_SRB_IN_PROGRESS);
  1563. if (TEST_FLAG(fdoDeviceExtension->DeviceFlags, DF_RESET_IN_PROGRESS))
  1564. {
  1565. LOGENTRY('CRT1', DeviceObject, Irp, Srb);
  1566. resetStarted = TRUE;
  1567. }
  1568. }
  1569. KeReleaseSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock, irql);
  1570. // If a timeout reset has been started, then complete this request with
  1571. // a timeout error. Well, don't actually complete the request just yet.
  1572. // Signal the cancel completion event and let USBSTOR_ResetDeviceWorkItem()
  1573. // complete the request. This allows USBSTOR_ResetDeviceWorkItem() to
  1574. // cancel the request without worrying about the request completing and
  1575. // disappearing out from underneath it.
  1576. //
  1577. if (resetStarted)
  1578. {
  1579. irpStack = IoGetCurrentIrpStackLocation(Irp);
  1580. Srb = fdoDeviceExtension->OriginalSrb;
  1581. irpStack->Parameters.Scsi.Srb = Srb;
  1582. Irp->IoStatus.Status = STATUS_IO_TIMEOUT;
  1583. Irp->IoStatus.Information = 0;
  1584. Srb->SrbStatus = SRB_STATUS_TIMEOUT;
  1585. USBSTOR_TranslateCDBComplete(DeviceObject, Irp, Srb);
  1586. *NtStatus = STATUS_MORE_PROCESSING_REQUIRED;
  1587. KeSetEvent(&fdoDeviceExtension->CancelEvent,
  1588. IO_NO_INCREMENT,
  1589. FALSE);
  1590. return TRUE;
  1591. }
  1592. else
  1593. {
  1594. fdoDeviceExtension->PendingIrp = NULL;
  1595. return FALSE;
  1596. }
  1597. }
  1598. //******************************************************************************
  1599. //
  1600. // USBSTOR_IssueControlRequest()
  1601. //
  1602. // This routine is called by USBSTOR_IssueClientCdb() and
  1603. // USBSTOR_IssueRequestSenseCdb()
  1604. //
  1605. // This routine may run at DPC level.
  1606. //
  1607. // Basic idea:
  1608. //
  1609. // Intializes the Control transfer Urb and sends it down the stack:
  1610. //
  1611. // bmRequestType = 0x21, Class specific, host to device transfer, to
  1612. // recipient interface
  1613. // bRequest = 0x00, Accept Device Specific Command
  1614. // wValue = 0x00, Not Used
  1615. // wIndex = bInterfaceNumber
  1616. // wLength = length of device specific command block
  1617. //
  1618. //******************************************************************************
  1619. NTSTATUS
  1620. USBSTOR_IssueControlRequest (
  1621. IN PDEVICE_OBJECT DeviceObject,
  1622. IN PIRP Irp,
  1623. IN ULONG TransferBufferLength,
  1624. IN PVOID TransferBuffer,
  1625. IN PIO_COMPLETION_ROUTINE CompletionRoutine,
  1626. IN PVOID Context
  1627. )
  1628. {
  1629. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1630. PIO_STACK_LOCATION nextStack;
  1631. KIRQL irql;
  1632. NTSTATUS ntStatus;
  1633. struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST *controlUrb;
  1634. DBGPRINT(3, ("enter: USBSTOR_IssueControlRequest\n"));
  1635. LOGENTRY('ICTR', DeviceObject, Irp, 0);
  1636. fdoDeviceExtension = DeviceObject->DeviceExtension;
  1637. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  1638. // Get a pointer to the Control/Bulk/Interrupt Transfer URB in our
  1639. // Device Extension
  1640. //
  1641. controlUrb = &fdoDeviceExtension->Urb.ControlUrb;
  1642. // Initialize the Control Transfer URB, all fields default to zero
  1643. //
  1644. RtlZeroMemory(controlUrb, sizeof(*controlUrb));
  1645. controlUrb->Hdr.Length = sizeof(*controlUrb);
  1646. controlUrb->Hdr.Function = URB_FUNCTION_CLASS_INTERFACE;
  1647. // controlUrb->TransferFlags is already zero
  1648. controlUrb->TransferBufferLength = TransferBufferLength;
  1649. controlUrb->TransferBuffer = TransferBuffer;
  1650. // controlUrb->TransferBufferMDL is already zero
  1651. // controlUrb->RequestTypeReservedBits is already zero
  1652. // controlUrb->Request is already zero
  1653. // controlUrb->Value is already zero
  1654. // Target the request at the proper interface on the device
  1655. //
  1656. controlUrb->Index = fdoDeviceExtension->InterfaceInfo->InterfaceNumber;
  1657. // Set the Irp parameters for the lower driver
  1658. //
  1659. nextStack = IoGetNextIrpStackLocation(Irp);
  1660. nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1661. nextStack->Parameters.DeviceIoControl.IoControlCode =
  1662. IOCTL_INTERNAL_USB_SUBMIT_URB;
  1663. nextStack->Parameters.Others.Argument1 = controlUrb;
  1664. // Set the completion routine, which will handle the next phase of the Srb
  1665. //
  1666. IoSetCompletionRoutine(Irp,
  1667. CompletionRoutine,
  1668. Context,
  1669. TRUE, // InvokeOnSuccess
  1670. TRUE, // InvokeOnError
  1671. TRUE); // InvokeOnCancel
  1672. KeAcquireSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock, &irql);
  1673. {
  1674. fdoDeviceExtension->PendingIrp = Irp;
  1675. SET_FLAG(fdoDeviceExtension->DeviceFlags, DF_SRB_IN_PROGRESS);
  1676. }
  1677. KeReleaseSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock, irql);
  1678. // Pass the Irp & Urb down the stack
  1679. //
  1680. ntStatus = IoCallDriver(fdoDeviceExtension->StackDeviceObject,
  1681. Irp);
  1682. DBGPRINT(3, ("exit: USBSTOR_IssueControlRequest %08X\n", ntStatus));
  1683. LOGENTRY('ictr', DeviceObject, Irp, ntStatus);
  1684. return ntStatus;
  1685. }
  1686. //******************************************************************************
  1687. //
  1688. // USBSTOR_IssueBulkOrInterruptRequest()
  1689. //
  1690. // This routine is called by USBSTOR_IssueClientBulkRequest(),
  1691. // USBSTOR_IssueInterruptRequest() and USBSTOR_IssueRequestSenseBulkRequest().
  1692. //
  1693. // This routine may run at DPC level.
  1694. //
  1695. // Basic idea:
  1696. //
  1697. // Initializes the Bulk or Interrupt transfer Urb and sends it down the stack
  1698. //
  1699. //******************************************************************************
  1700. NTSTATUS
  1701. USBSTOR_IssueBulkOrInterruptRequest (
  1702. IN PDEVICE_OBJECT DeviceObject,
  1703. IN PIRP Irp,
  1704. IN USBD_PIPE_HANDLE PipeHandle,
  1705. IN ULONG TransferFlags,
  1706. IN ULONG TransferBufferLength,
  1707. IN PVOID TransferBuffer,
  1708. IN PMDL TransferBufferMDL,
  1709. IN PIO_COMPLETION_ROUTINE CompletionRoutine,
  1710. IN PVOID Context
  1711. )
  1712. {
  1713. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1714. PIO_STACK_LOCATION nextStack;
  1715. KIRQL irql;
  1716. NTSTATUS ntStatus;
  1717. struct _URB_BULK_OR_INTERRUPT_TRANSFER *bulkIntrUrb;
  1718. DBGPRINT(3, ("enter: USBSTOR_IssueBulkOrInterruptRequest\n"));
  1719. LOGENTRY('IBIR', DeviceObject, Irp, 0);
  1720. fdoDeviceExtension = DeviceObject->DeviceExtension;
  1721. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  1722. // Get a pointer to the Bulk/Interrupt Transfer URB in our Device Extension
  1723. //
  1724. bulkIntrUrb = &fdoDeviceExtension->Urb.BulkIntrUrb;
  1725. // Initialize the Bulk/Interrupt Transfer URB, all fields default to zero
  1726. //
  1727. RtlZeroMemory(bulkIntrUrb, sizeof(*bulkIntrUrb));
  1728. bulkIntrUrb->Hdr.Length = sizeof(*bulkIntrUrb);
  1729. bulkIntrUrb->Hdr.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
  1730. bulkIntrUrb->PipeHandle = PipeHandle;
  1731. bulkIntrUrb->TransferFlags = TransferFlags;
  1732. bulkIntrUrb->TransferBufferLength = TransferBufferLength;
  1733. bulkIntrUrb->TransferBuffer = TransferBuffer;
  1734. bulkIntrUrb->TransferBufferMDL = TransferBufferMDL;
  1735. // Set the Irp parameters for the lower driver
  1736. //
  1737. nextStack = IoGetNextIrpStackLocation(Irp);
  1738. nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1739. nextStack->Parameters.DeviceIoControl.IoControlCode =
  1740. IOCTL_INTERNAL_USB_SUBMIT_URB;
  1741. nextStack->Parameters.Others.Argument1 = bulkIntrUrb;
  1742. // Set the completion routine, which will handle the next phase of the Srb
  1743. //
  1744. IoSetCompletionRoutine(Irp,
  1745. CompletionRoutine,
  1746. Context,
  1747. TRUE, // InvokeOnSuccess
  1748. TRUE, // InvokeOnError
  1749. TRUE); // InvokeOnCancel
  1750. KeAcquireSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock, &irql);
  1751. {
  1752. fdoDeviceExtension->PendingIrp = Irp;
  1753. SET_FLAG(fdoDeviceExtension->DeviceFlags, DF_SRB_IN_PROGRESS);
  1754. }
  1755. KeReleaseSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock, irql);
  1756. // Pass the Irp & Urb down the stack
  1757. //
  1758. ntStatus = IoCallDriver(fdoDeviceExtension->StackDeviceObject,
  1759. Irp);
  1760. DBGPRINT(3, ("exit: USBSTOR_IssueBulkOrInterruptRequest %08X\n", ntStatus));
  1761. LOGENTRY('ibir', DeviceObject, Irp, ntStatus);
  1762. return ntStatus;
  1763. }
  1764. //
  1765. // CBI (Control/Bulk/Interrupt) Routines
  1766. //
  1767. //
  1768. // Phase 1, CDB Control transfer
  1769. //
  1770. //******************************************************************************
  1771. //
  1772. // USBSTOR_IssueClientCdb()
  1773. //
  1774. // This routine is called by USBSTOR_StartIo().
  1775. //
  1776. // It runs at DPC level.
  1777. //
  1778. // Basic idea:
  1779. //
  1780. // Starts a USB transfer to write the Srb->Cdb out the control endpoint.
  1781. //
  1782. // Sets USBSTOR_ClientCdbCompletion() as the completion routine.
  1783. //
  1784. //******************************************************************************
  1785. NTSTATUS
  1786. USBSTOR_IssueClientCdb (
  1787. IN PDEVICE_OBJECT DeviceObject,
  1788. IN PIRP Irp
  1789. )
  1790. {
  1791. PIO_STACK_LOCATION irpStack;
  1792. PSCSI_REQUEST_BLOCK srb;
  1793. NTSTATUS ntStatus;
  1794. DBGPRINT(3, ("enter: USBSTOR_IssueClientCdb\n"));
  1795. LOGENTRY('ICDB', DeviceObject, Irp, 0);
  1796. // Get the client Srb
  1797. //
  1798. irpStack = IoGetCurrentIrpStackLocation(Irp);
  1799. srb = irpStack->Parameters.Scsi.Srb;
  1800. ntStatus = USBSTOR_IssueControlRequest(
  1801. DeviceObject,
  1802. Irp,
  1803. srb->CdbLength, // TransferBufferLength
  1804. srb->Cdb, // TransferBuffer
  1805. USBSTOR_ClientCdbCompletion, // CompletionRoutine
  1806. NULL); // Context
  1807. DBGPRINT(3, ("exit: USBSTOR_IssueClientCdb %08X\n", ntStatus));
  1808. LOGENTRY('icdb', DeviceObject, Irp, ntStatus);
  1809. return ntStatus;
  1810. }
  1811. //******************************************************************************
  1812. //
  1813. // USBSTOR_ClientCdbCompletion()
  1814. //
  1815. // Completion routine used by USBSTOR_IssueClientCdb()
  1816. //
  1817. // This routine may run at DPC level.
  1818. //
  1819. // Basic idea:
  1820. //
  1821. // If a timeout reset occured, complete the request.
  1822. //
  1823. // Else if the CDB USB transfer failed due to a STALL and AutoSense is not
  1824. // disabled, do not complete the request yet and start a Request Sense by
  1825. // calling USBSTOR_IssueRequestSenseCdb(AUTO_SENSE).
  1826. //
  1827. // Else if the CDB USB transfer failed due to a STALL and AutoSense is
  1828. // disabled, mark a persistant error and complete the request.
  1829. //
  1830. // Else if the CDB USB transfer failed due to some other reason, complete the
  1831. // request and start a reset by queuing USBSTOR_ResetDeviceWorkItem().
  1832. //
  1833. // Else if the CDB USB transfer succeeded and the Srb has a transfer buffer,
  1834. // do not complete the request yet and start the bulk data transfer by calling
  1835. // USBSTOR_IssueClientBulkRequest().
  1836. //
  1837. // Else if the CDB USB transfer succeeded and the Srb has no transfer buffer,
  1838. // do not complete the request yet and start the command completion interrupt
  1839. // data transfer by calling USBSTOR_IssueInterruptRequest().
  1840. //
  1841. //******************************************************************************
  1842. NTSTATUS
  1843. USBSTOR_ClientCdbCompletion (
  1844. IN PDEVICE_OBJECT DeviceObject,
  1845. IN PIRP Irp,
  1846. IN PVOID NotUsed
  1847. )
  1848. {
  1849. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  1850. PDEVICE_OBJECT fdoDeviceObject;
  1851. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1852. PIO_STACK_LOCATION irpStack;
  1853. PSCSI_REQUEST_BLOCK srb;
  1854. KIRQL irql;
  1855. NTSTATUS ntStatus;
  1856. struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST *controlUrb;
  1857. DBGPRINT(3, ("enter: USBSTOR_ClientCdbCompletion\n"));
  1858. LOGENTRY('CDBC', DeviceObject, Irp, Irp->IoStatus.Status);
  1859. pdoDeviceExtension = DeviceObject->DeviceExtension;
  1860. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  1861. fdoDeviceObject = pdoDeviceExtension->ParentFDO;
  1862. fdoDeviceExtension = fdoDeviceObject->DeviceExtension;
  1863. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  1864. // Get a pointer to the Control Transfer URB in our Device Extension
  1865. //
  1866. controlUrb = &fdoDeviceExtension->Urb.ControlUrb;
  1867. // Get our Irp parameters
  1868. //
  1869. irpStack = IoGetCurrentIrpStackLocation(Irp);
  1870. srb = irpStack->Parameters.Scsi.Srb;
  1871. // If a timeout reset occured, complete the request.
  1872. //
  1873. if (USBSTOR_CheckRequestTimeOut(fdoDeviceObject,
  1874. Irp,
  1875. srb,
  1876. &ntStatus))
  1877. {
  1878. LOGENTRY('cdb1', fdoDeviceObject, Irp, srb);
  1879. DBGPRINT(1, ("USBSTOR_ClientCdbCompletion: timeout completion\n"));
  1880. return ntStatus;
  1881. }
  1882. if (!NT_SUCCESS(Irp->IoStatus.Status))
  1883. {
  1884. // The CDB Control Transfer was not successful. Look at how the
  1885. // the transfer failed to figure out how to recover.
  1886. //
  1887. LOGENTRY('cdb2', Irp->IoStatus.Status, controlUrb->Hdr.Status, 0);
  1888. DBGPRINT(1, ("CDB transfer failed %08X %08X\n",
  1889. Irp->IoStatus.Status, controlUrb->Hdr.Status));
  1890. if (USBD_STATUS(controlUrb->Hdr.Status) ==
  1891. USBD_STATUS(USBD_STATUS_STALL_PID))
  1892. {
  1893. // The device STALLed the Control Transfer
  1894. srb->SrbStatus = SRB_STATUS_ERROR;
  1895. srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
  1896. srb->DataTransferLength = 0;
  1897. if (!(srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE) &&
  1898. (srb->SenseInfoBufferLength != 0) &&
  1899. (srb->SenseInfoBuffer != NULL))
  1900. {
  1901. LOGENTRY('cdb3', fdoDeviceObject, Irp, srb);
  1902. // AutoSense is not disabled so do not complete the request yet
  1903. // and issue a Request Sense. This request will be completed
  1904. // and the next request started when the AutoSense Request
  1905. // Sense completes later.
  1906. //
  1907. ntStatus = USBSTOR_IssueRequestSenseCdb(fdoDeviceObject,
  1908. Irp,
  1909. AUTO_SENSE);
  1910. return STATUS_MORE_PROCESSING_REQUIRED;
  1911. }
  1912. else
  1913. {
  1914. LOGENTRY('cdb4', fdoDeviceObject, Irp, srb);
  1915. // AutoSense is disabled so mark a persistent error and complete
  1916. // this request now. Also start the next request now.
  1917. //
  1918. ntStatus = STATUS_IO_DEVICE_ERROR;
  1919. Irp->IoStatus.Status = ntStatus;
  1920. Irp->IoStatus.Information = 0;
  1921. KeAcquireSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock,
  1922. &irql);
  1923. {
  1924. SET_FLAG(fdoDeviceExtension->DeviceFlags,
  1925. DF_PERSISTENT_ERROR);
  1926. }
  1927. KeReleaseSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock,
  1928. irql);
  1929. USBSTOR_TranslateCDBComplete(fdoDeviceObject, Irp, srb);
  1930. KeRaiseIrql(DISPATCH_LEVEL, &irql);
  1931. {
  1932. IoStartNextPacket(fdoDeviceObject, TRUE);
  1933. }
  1934. KeLowerIrql(irql);
  1935. return ntStatus;
  1936. }
  1937. }
  1938. else
  1939. {
  1940. LOGENTRY('cdb5', fdoDeviceObject, Irp, srb);
  1941. // Else some other strange error has occured. Maybe the device is
  1942. // unplugged, or maybe the device port was disabled, or maybe the
  1943. // request was cancelled.
  1944. //
  1945. // Complete this request now and then reset the device. The next
  1946. // request will be started when the reset completes.
  1947. //
  1948. ntStatus = STATUS_IO_DEVICE_ERROR;
  1949. Irp->IoStatus.Status = ntStatus;
  1950. Irp->IoStatus.Information = 0;
  1951. srb->SrbStatus = SRB_STATUS_BUS_RESET;
  1952. USBSTOR_TranslateCDBComplete(fdoDeviceObject, Irp, srb);
  1953. USBSTOR_QueueResetDevice(fdoDeviceObject);
  1954. DBGPRINT(1, ("USBSTOR_ClientCdbCompletion: xfer error completion\n"));
  1955. return ntStatus;
  1956. }
  1957. }
  1958. // The CDB Control Transfer was successful. Start the next phase, either
  1959. // the Data Bulk Transfer or Command Completion Interrupt Transfer, and do
  1960. // not complete the request yet (unless there is no Bulk Transfer and the
  1961. // Interrupt Transfer is not supported).
  1962. //
  1963. if (Irp->MdlAddress != NULL)
  1964. {
  1965. LOGENTRY('cdb6', fdoDeviceObject, Irp, srb);
  1966. ASSERT(srb->DataTransferLength != 0);
  1967. // The Srb has a transfer buffer, start the Data Bulk Transfer.
  1968. //
  1969. ntStatus = USBSTOR_IssueClientBulkRequest(fdoDeviceObject,
  1970. Irp);
  1971. if (NT_SUCCESS(ntStatus))
  1972. {
  1973. ntStatus = STATUS_MORE_PROCESSING_REQUIRED;
  1974. }
  1975. else
  1976. {
  1977. Irp->IoStatus.Status = ntStatus;
  1978. Irp->IoStatus.Information = 0;
  1979. srb->SrbStatus = SRB_STATUS_ERROR;
  1980. USBSTOR_TranslateCDBComplete(fdoDeviceObject, Irp, srb);
  1981. USBSTOR_QueueResetDevice(fdoDeviceObject);
  1982. }
  1983. }
  1984. else
  1985. {
  1986. ASSERT(srb->DataTransferLength == 0);
  1987. // The Srb has no transfer buffer. If the Command Completion
  1988. // Interrupt Transfer is supported, start the Command Completion
  1989. // Interrupt Transfer, else just complete the request now and
  1990. // start the next request.
  1991. //
  1992. if (fdoDeviceExtension->InterruptInPipe)
  1993. {
  1994. LOGENTRY('cdb7', fdoDeviceObject, Irp, srb);
  1995. srb->SrbStatus = SRB_STATUS_SUCCESS;
  1996. ntStatus = USBSTOR_IssueInterruptRequest(fdoDeviceObject,
  1997. Irp);
  1998. ntStatus = STATUS_MORE_PROCESSING_REQUIRED;
  1999. }
  2000. else
  2001. {
  2002. LOGENTRY('cdb8', fdoDeviceObject, Irp, srb);
  2003. ntStatus = STATUS_SUCCESS;
  2004. Irp->IoStatus.Status = ntStatus;
  2005. Irp->IoStatus.Information = 0;
  2006. srb->SrbStatus = SRB_STATUS_SUCCESS;
  2007. USBSTOR_TranslateCDBComplete(fdoDeviceObject, Irp, srb);
  2008. KeRaiseIrql(DISPATCH_LEVEL, &irql);
  2009. {
  2010. IoStartNextPacket(fdoDeviceObject, TRUE);
  2011. }
  2012. KeLowerIrql(irql);
  2013. }
  2014. }
  2015. DBGPRINT(3, ("exit: USBSTOR_ClientCdbCompletion %08X\n", ntStatus));
  2016. return ntStatus;
  2017. }
  2018. //
  2019. // Phase 2, Data Bulk transfer
  2020. //
  2021. //******************************************************************************
  2022. //
  2023. // USBSTOR_IssueClientBulkRequest()
  2024. //
  2025. // This routine is called by USBSTOR_ClientCdbCompletion().
  2026. //
  2027. // This routine may run at DPC level.
  2028. //
  2029. // Basic idea:
  2030. //
  2031. // Starts a USB transfer to read or write the Srb->DataBuffer data In or Out
  2032. // the Bulk endpoint.
  2033. //
  2034. // Sets USBSTOR_ClientBulkCompletionRoutine() as the completion routine.
  2035. //
  2036. //******************************************************************************
  2037. NTSTATUS
  2038. USBSTOR_IssueClientBulkRequest (
  2039. IN PDEVICE_OBJECT DeviceObject,
  2040. IN PIRP Irp
  2041. )
  2042. {
  2043. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  2044. PIO_STACK_LOCATION irpStack;
  2045. PSCSI_REQUEST_BLOCK srb;
  2046. PMDL mdl;
  2047. PVOID mdlVa;
  2048. USBD_PIPE_HANDLE pipeHandle;
  2049. ULONG transferFlags;
  2050. NTSTATUS ntStatus;
  2051. DBGPRINT(3, ("enter: USBSTOR_IssueClientBulkRequest\n"));
  2052. LOGENTRY('ICBK', DeviceObject, Irp, 0);
  2053. fdoDeviceExtension = DeviceObject->DeviceExtension;
  2054. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  2055. // Get our Irp parameters
  2056. //
  2057. irpStack = IoGetCurrentIrpStackLocation(Irp);
  2058. srb = irpStack->Parameters.Scsi.Srb;
  2059. // Bulk IN or Bulk OUT?
  2060. //
  2061. if ((srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) == SRB_FLAGS_DATA_IN)
  2062. {
  2063. pipeHandle = fdoDeviceExtension->BulkInPipe->PipeHandle;
  2064. transferFlags = USBD_SHORT_TRANSFER_OK;
  2065. }
  2066. else if ((srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) == SRB_FLAGS_DATA_OUT)
  2067. {
  2068. pipeHandle = fdoDeviceExtension->BulkOutPipe->PipeHandle;
  2069. transferFlags = 0;
  2070. }
  2071. else
  2072. {
  2073. // Something is wrong if we end up here.
  2074. //
  2075. ASSERT((srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) &&
  2076. ((srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) !=
  2077. SRB_FLAGS_UNSPECIFIED_DIRECTION));
  2078. return STATUS_INVALID_PARAMETER;
  2079. }
  2080. // Check to see if this request is part of a split request.
  2081. //
  2082. mdlVa = MmGetMdlVirtualAddress(Irp->MdlAddress);
  2083. if (mdlVa == (PVOID)srb->DataBuffer)
  2084. {
  2085. // Not part of a split request, use original MDL
  2086. //
  2087. mdl = Irp->MdlAddress;
  2088. }
  2089. else
  2090. {
  2091. // Part of a split request, allocate new partial MDL
  2092. //
  2093. mdl = IoAllocateMdl(srb->DataBuffer,
  2094. srb->DataTransferLength,
  2095. FALSE,
  2096. FALSE,
  2097. NULL);
  2098. if (mdl == NULL)
  2099. {
  2100. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  2101. }
  2102. else
  2103. {
  2104. IoBuildPartialMdl(Irp->MdlAddress,
  2105. mdl,
  2106. srb->DataBuffer,
  2107. srb->DataTransferLength);
  2108. }
  2109. }
  2110. if (mdl != NULL)
  2111. {
  2112. ntStatus = USBSTOR_IssueBulkOrInterruptRequest(
  2113. DeviceObject,
  2114. Irp,
  2115. pipeHandle, // PipeHandle
  2116. transferFlags, // TransferFlags
  2117. srb->DataTransferLength, // TransferBufferLen
  2118. NULL, // TransferBuffer
  2119. mdl, // TransferBufferMDL
  2120. USBSTOR_ClientBulkCompletionRoutine, // CompletionRoutine
  2121. NULL); // Context
  2122. // Just return STATUS_SUCCESS at this point. If there is an error,
  2123. // USBSTOR_ClientBulkCompletionRoutine() will handle it, not the caller
  2124. // of USBSTOR_IssueClientBulkRequest().
  2125. //
  2126. ntStatus = STATUS_SUCCESS;
  2127. }
  2128. DBGPRINT(3, ("exit: USBSTOR_IssueClientBulkRequest %08X\n", ntStatus));
  2129. LOGENTRY('icbk', DeviceObject, Irp, ntStatus);
  2130. return ntStatus;
  2131. }
  2132. //******************************************************************************
  2133. //
  2134. // USBSTOR_ClientBulkCompletionRoutine()
  2135. //
  2136. // Completion routine used by USBSTOR_IssueClientBulkRequest
  2137. //
  2138. // This routine may run at DPC level.
  2139. //
  2140. // Basic idea:
  2141. //
  2142. // If a timeout reset occured, complete the request.
  2143. //
  2144. // Else if the Bulk USB transfer failed due to a STALL and AutoSense is not
  2145. // disabled, do not complete the request yet and start a pipe reset by calling
  2146. // USBSTOR_QueueResetPipe().
  2147. //
  2148. // Else if the Bulk USB transfer failed due to a STALL and AutoSense is
  2149. // disabled, mark a persistant error and complete the request.
  2150. //
  2151. // Else if the Bulk USB transfer failed due to some other reason, complete the
  2152. // request and start a reset by queuing USBSTOR_ResetDeviceWorkItem().
  2153. //
  2154. // Else if the Bulk USB transfer succeeded, start the command completion
  2155. // interrupt data transfer by calling USBSTOR_IssueInterruptRequest().
  2156. //
  2157. //******************************************************************************
  2158. NTSTATUS
  2159. USBSTOR_ClientBulkCompletionRoutine (
  2160. IN PDEVICE_OBJECT DeviceObject,
  2161. IN PIRP Irp,
  2162. IN PVOID NotUsed
  2163. )
  2164. {
  2165. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  2166. PDEVICE_OBJECT fdoDeviceObject;
  2167. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  2168. PIO_STACK_LOCATION irpStack;
  2169. PSCSI_REQUEST_BLOCK srb;
  2170. KIRQL irql;
  2171. NTSTATUS ntStatus;
  2172. struct _URB_BULK_OR_INTERRUPT_TRANSFER *bulkUrb;
  2173. DBGPRINT(3, ("enter: USBSTOR_ClientBulkCompletionRoutine\n"));
  2174. LOGENTRY('CBKC', DeviceObject, Irp, Irp->IoStatus.Status);
  2175. pdoDeviceExtension = DeviceObject->DeviceExtension;
  2176. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  2177. fdoDeviceObject = pdoDeviceExtension->ParentFDO;
  2178. fdoDeviceExtension = fdoDeviceObject->DeviceExtension;
  2179. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  2180. // Get a pointer to the Bulk Transfer URB in our Device Extension
  2181. //
  2182. bulkUrb = &fdoDeviceExtension->Urb.BulkIntrUrb;
  2183. // Get our Irp parameters
  2184. //
  2185. irpStack = IoGetCurrentIrpStackLocation(Irp);
  2186. srb = irpStack->Parameters.Scsi.Srb;
  2187. if (bulkUrb->TransferBufferMDL != Irp->MdlAddress)
  2188. {
  2189. IoFreeMdl(bulkUrb->TransferBufferMDL);
  2190. }
  2191. // If a timeout reset occured, complete the request.
  2192. //
  2193. if (USBSTOR_CheckRequestTimeOut(fdoDeviceObject,
  2194. Irp,
  2195. srb,
  2196. &ntStatus))
  2197. {
  2198. LOGENTRY('cbk1', fdoDeviceObject, Irp, srb);
  2199. DBGPRINT(1, ("USBSTOR_ClientBulkCompletionRoutine: timeout completion\n"));
  2200. return ntStatus;
  2201. }
  2202. if (!NT_SUCCESS(Irp->IoStatus.Status))
  2203. {
  2204. // The Data Bulk Transfer was not successful. Look at how the
  2205. // the transfer failed to figure out how to recover.
  2206. //
  2207. LOGENTRY('cbk2', Irp->IoStatus.Status, bulkUrb->Hdr.Status, 0);
  2208. DBGPRINT(1, ("Client Bulk transfer failed %08X %08X\n",
  2209. Irp->IoStatus.Status, bulkUrb->Hdr.Status));
  2210. if (USBD_STATUS(bulkUrb->Hdr.Status) ==
  2211. USBD_STATUS(USBD_STATUS_STALL_PID))
  2212. {
  2213. // The device STALLed the Bulk Transfer
  2214. srb->SrbStatus = SRB_STATUS_ERROR;
  2215. srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
  2216. srb->DataTransferLength = bulkUrb->TransferBufferLength;
  2217. if (!(srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE) &&
  2218. (srb->SenseInfoBufferLength != 0) &&
  2219. (srb->SenseInfoBuffer != NULL))
  2220. {
  2221. LOGENTRY('cbk3', fdoDeviceObject, Irp, srb);
  2222. // AutoSense is not disabled so do not complete the request
  2223. // yet. Queue a bulk pipe reset. After the bulk pipe reset
  2224. // completes, a Request Sense will be issued. This request
  2225. // will be completed and the next request started when the
  2226. // AutoSense Request Sense completes later.
  2227. //
  2228. USBSTOR_QueueResetPipe(fdoDeviceObject);
  2229. return STATUS_MORE_PROCESSING_REQUIRED;
  2230. }
  2231. else
  2232. {
  2233. LOGENTRY('cbk4', fdoDeviceObject, Irp, srb);
  2234. // AutoSense is disabled so mark a persistent error and
  2235. // complete the request, but also queue a bulk pipe reset.
  2236. //
  2237. // The next request will be started when the bulk pipe
  2238. // reset completes.
  2239. //
  2240. ntStatus = STATUS_IO_DEVICE_ERROR;
  2241. Irp->IoStatus.Status = ntStatus;
  2242. Irp->IoStatus.Information = 0;
  2243. KeAcquireSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock,
  2244. &irql);
  2245. {
  2246. SET_FLAG(fdoDeviceExtension->DeviceFlags,
  2247. DF_PERSISTENT_ERROR);
  2248. }
  2249. KeReleaseSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock,
  2250. irql);
  2251. USBSTOR_TranslateCDBComplete(fdoDeviceObject, Irp, srb);
  2252. USBSTOR_QueueResetPipe(fdoDeviceObject);
  2253. return ntStatus;
  2254. }
  2255. }
  2256. else
  2257. {
  2258. LOGENTRY('cbk5', fdoDeviceObject, Irp, srb);
  2259. // Else some other strange error has occured. Maybe the device is
  2260. // unplugged, or maybe the device port was disabled, or maybe the
  2261. // request was cancelled.
  2262. //
  2263. // Complete this request now and then reset the device. The next
  2264. // request will be started when the reset completes.
  2265. //
  2266. ntStatus = STATUS_IO_DEVICE_ERROR;
  2267. Irp->IoStatus.Status = ntStatus;
  2268. Irp->IoStatus.Information = 0;
  2269. srb->SrbStatus = SRB_STATUS_BUS_RESET;
  2270. USBSTOR_TranslateCDBComplete(fdoDeviceObject, Irp, srb);
  2271. USBSTOR_QueueResetDevice(fdoDeviceObject);
  2272. DBGPRINT(1, ("USBSTOR_ClientBulkCompletionRoutine: xfer error completion\n"));
  2273. return ntStatus;
  2274. }
  2275. }
  2276. // Check for overrun
  2277. //
  2278. if (bulkUrb->TransferBufferLength < srb->DataTransferLength)
  2279. {
  2280. srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
  2281. }
  2282. else
  2283. {
  2284. srb->SrbStatus = SRB_STATUS_SUCCESS;
  2285. }
  2286. // Update the the Srb data transfer length based on the actual bulk
  2287. // transfer length.
  2288. //
  2289. srb->DataTransferLength = bulkUrb->TransferBufferLength;
  2290. // Client data Bulk Transfer successful completion. If the Command
  2291. // Completion Interrupt Transfer is supported, start the Command Completion
  2292. // Interrupt Transfer, else just complete the request now and start the
  2293. // next request.
  2294. //
  2295. if (fdoDeviceExtension->InterruptInPipe)
  2296. {
  2297. LOGENTRY('cbk6', fdoDeviceObject, Irp, bulkUrb->TransferBufferLength);
  2298. ntStatus = USBSTOR_IssueInterruptRequest(fdoDeviceObject,
  2299. Irp);
  2300. ntStatus = STATUS_MORE_PROCESSING_REQUIRED;
  2301. }
  2302. else
  2303. {
  2304. LOGENTRY('cbk7', fdoDeviceObject, Irp, bulkUrb->TransferBufferLength);
  2305. ntStatus = STATUS_SUCCESS;
  2306. Irp->IoStatus.Status = ntStatus;
  2307. USBSTOR_TranslateCDBComplete(fdoDeviceObject, Irp, srb);
  2308. Irp->IoStatus.Information = srb->DataTransferLength;
  2309. KeRaiseIrql(DISPATCH_LEVEL, &irql);
  2310. {
  2311. IoStartNextPacket(fdoDeviceObject, TRUE);
  2312. }
  2313. KeLowerIrql(irql);
  2314. }
  2315. DBGPRINT(3, ("exit: USBSTOR_ClientBulkCompletionRoutine %08X\n", ntStatus));
  2316. return ntStatus;
  2317. }
  2318. //
  2319. // Phase 3, Command completion Interrupt transfer
  2320. //
  2321. //******************************************************************************
  2322. //
  2323. // USBSTOR_IssueInterruptRequest()
  2324. //
  2325. // This routine is called by USBSTOR_ClientCdbCompletion() and
  2326. // USBSTOR_ClientBulkCompletionRoutine()
  2327. //
  2328. // This routine may run at DPC level.
  2329. //
  2330. // Basic idea:
  2331. //
  2332. // Starts a USB transfer to read the command completion interrupt data In
  2333. // the Interrupt endpoint.
  2334. //
  2335. // Sets USBSTOR_InterruptDataCompletionRoutine() as the completion routine.
  2336. //
  2337. //******************************************************************************
  2338. NTSTATUS
  2339. USBSTOR_IssueInterruptRequest (
  2340. IN PDEVICE_OBJECT DeviceObject,
  2341. IN PIRP Irp
  2342. )
  2343. {
  2344. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  2345. USBD_PIPE_HANDLE pipeHandle;
  2346. ULONG transferBufferLength;
  2347. PVOID transferBuffer;
  2348. NTSTATUS ntStatus;
  2349. DBGPRINT(3, ("enter: USBSTOR_IssueInterruptRequest\n"));
  2350. LOGENTRY('IINT', DeviceObject, Irp, 0);
  2351. fdoDeviceExtension = DeviceObject->DeviceExtension;
  2352. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  2353. pipeHandle = fdoDeviceExtension->InterruptInPipe->PipeHandle;
  2354. transferBufferLength = sizeof(fdoDeviceExtension->Cbi.InterruptData);
  2355. transferBuffer = &fdoDeviceExtension->Cbi.InterruptData;
  2356. ntStatus = USBSTOR_IssueBulkOrInterruptRequest(
  2357. DeviceObject,
  2358. Irp,
  2359. pipeHandle, // PipeHandle
  2360. 0, // TransferFlags
  2361. transferBufferLength, // TransferBufferLength
  2362. transferBuffer, // TransferBuffer
  2363. NULL, // TransferBufferMDL
  2364. USBSTOR_InterruptDataCompletionRoutine, // CompletionRoutine
  2365. NULL); // Context
  2366. DBGPRINT(3, ("exit: USBSTOR_IssueInterruptRequest %08X\n", ntStatus));
  2367. LOGENTRY('iint', DeviceObject, Irp, ntStatus);
  2368. return ntStatus;
  2369. }
  2370. //******************************************************************************
  2371. //
  2372. // USBSTOR_InterruptDataCompletionRoutine()
  2373. //
  2374. // Completion routine used by USBSTOR_IssueInterruptRequest()
  2375. //
  2376. // This routine may run at DPC level.
  2377. //
  2378. // Basic idea:
  2379. //
  2380. // If a timeout reset occured, complete the request.
  2381. //
  2382. // Else if the Interrupt USB transfer failed due to any reason, complete the
  2383. // request and start a reset by queuing USBSTOR_ResetDeviceWorkItem().
  2384. //
  2385. // Else if the Interrupt USB transfer succeeded but the completion data is
  2386. // non-zero and AutoSense is not disabled, do not complete the request yet and
  2387. // start a Request Sense by calling USBSTOR_IssueRequestSenseCdb(AUTO).
  2388. //
  2389. // Else if the Interrupt USB transfer succeeded but the completion data is
  2390. // non-zero and AutoSense is disabled, mark a persistant error and complete
  2391. // the request.
  2392. //
  2393. // Else if the Interrupt USB transfer succeeded and the completion data is
  2394. // zero, complete the request.
  2395. //
  2396. //******************************************************************************
  2397. NTSTATUS
  2398. USBSTOR_InterruptDataCompletionRoutine (
  2399. IN PDEVICE_OBJECT DeviceObject,
  2400. IN PIRP Irp,
  2401. IN PVOID NotUsed
  2402. )
  2403. {
  2404. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  2405. PDEVICE_OBJECT fdoDeviceObject;
  2406. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  2407. PIO_STACK_LOCATION irpStack;
  2408. PSCSI_REQUEST_BLOCK srb;
  2409. KIRQL irql;
  2410. NTSTATUS ntStatus;
  2411. struct _URB_BULK_OR_INTERRUPT_TRANSFER *intrUrb;
  2412. DBGPRINT(3, ("enter: USBSTOR_InterruptDataCompletionRoutine\n"));
  2413. LOGENTRY('IDCR', DeviceObject, Irp, Irp->IoStatus.Status);
  2414. pdoDeviceExtension = DeviceObject->DeviceExtension;
  2415. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  2416. fdoDeviceObject = pdoDeviceExtension->ParentFDO;
  2417. fdoDeviceExtension = fdoDeviceObject->DeviceExtension;
  2418. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  2419. // Get a pointer to the Interrupt Transfer URB in our Device Extension
  2420. //
  2421. intrUrb = &fdoDeviceExtension->Urb.BulkIntrUrb;
  2422. // Get our Irp parameters
  2423. //
  2424. irpStack = IoGetCurrentIrpStackLocation(Irp);
  2425. srb = irpStack->Parameters.Scsi.Srb;
  2426. // If a timeout reset occured, complete the request.
  2427. //
  2428. if (USBSTOR_CheckRequestTimeOut(fdoDeviceObject,
  2429. Irp,
  2430. srb,
  2431. &ntStatus))
  2432. {
  2433. LOGENTRY('idc1', fdoDeviceObject, Irp, srb);
  2434. DBGPRINT(1, ("USBSTOR_InterruptDataCompletionRoutine: timeout completion\n"));
  2435. return ntStatus;
  2436. }
  2437. if (!NT_SUCCESS(Irp->IoStatus.Status))
  2438. {
  2439. // The Interrupt CDB USB transfer failed. Complete this request
  2440. // now and then reset the device. The next request will be started
  2441. // when the reset completes.
  2442. //
  2443. LOGENTRY('idc2', Irp->IoStatus.Status, intrUrb->Hdr.Status, 0);
  2444. DBGPRINT(1, ("Interrupt transfer failed %08X %08X\n",
  2445. Irp->IoStatus.Status, intrUrb->Hdr.Status));
  2446. ntStatus = STATUS_IO_DEVICE_ERROR;
  2447. Irp->IoStatus.Status = ntStatus;
  2448. Irp->IoStatus.Information = 0;
  2449. srb->SrbStatus = SRB_STATUS_BUS_RESET;
  2450. USBSTOR_TranslateCDBComplete(fdoDeviceObject, Irp, srb);
  2451. USBSTOR_QueueResetDevice(fdoDeviceObject);
  2452. DBGPRINT(1, ("USBSTOR_InterruptDataCompletionRoutine: xfer error completion\n"));
  2453. return ntStatus;
  2454. }
  2455. if ((fdoDeviceExtension->Cbi.InterruptData != 0) &&
  2456. (srb->Cdb[0] != SCSIOP_INQUIRY) &&
  2457. (srb->Cdb[0] != SCSIOP_REQUEST_SENSE))
  2458. {
  2459. // Command completion interrupt data indicates an error. Either don't
  2460. // complete the request yet and start an AutoSense, or complete the
  2461. // request now and indicate a persistent error.
  2462. //
  2463. srb->SrbStatus = SRB_STATUS_ERROR;
  2464. srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
  2465. srb->DataTransferLength = 0; // XXXXX Leave as set by bulk completion???
  2466. if (!(srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE) &&
  2467. (srb->SenseInfoBufferLength != 0) &&
  2468. (srb->SenseInfoBuffer != NULL))
  2469. {
  2470. LOGENTRY('idc3', fdoDeviceObject, Irp, srb);
  2471. // AutoSense is not disabled so do not complete the request
  2472. // yet. Queue a bulk pipe reset. After the bulk pipe reset
  2473. // completes, a Request Sense will be issued. This request
  2474. // will be completed and the next request started when the
  2475. // AutoSense Request Sense completes later.
  2476. //
  2477. USBSTOR_QueueResetPipe(fdoDeviceObject);
  2478. return STATUS_MORE_PROCESSING_REQUIRED;
  2479. }
  2480. else
  2481. {
  2482. LOGENTRY('idc4', fdoDeviceObject, Irp, srb);
  2483. // AutoSense is disabled so mark a persistent error and
  2484. // complete the request, but also queue a bulk pipe reset.
  2485. //
  2486. // The next request will be started when the bulk pipe
  2487. // reset completes.
  2488. //
  2489. ntStatus = STATUS_IO_DEVICE_ERROR;
  2490. Irp->IoStatus.Status = ntStatus;
  2491. Irp->IoStatus.Information = 0;
  2492. KeAcquireSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock, &irql);
  2493. {
  2494. SET_FLAG(fdoDeviceExtension->DeviceFlags, DF_PERSISTENT_ERROR);
  2495. }
  2496. KeReleaseSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock, irql);
  2497. USBSTOR_TranslateCDBComplete(fdoDeviceObject, Irp, srb);
  2498. USBSTOR_QueueResetPipe(fdoDeviceObject);
  2499. return ntStatus;
  2500. }
  2501. }
  2502. // Hack for Y-E Data USB Floppy. Occasionally it will return interrupt
  2503. // data with the wrong data toggle. The interrupt data with the wrong
  2504. // toggle is silently ignored, which results in a request timeout.
  2505. // Forcing a Request Sense command between the completion of one command
  2506. // and the start of the next appears to be one way to work around this.
  2507. //
  2508. if (TEST_FLAG(fdoDeviceExtension->DeviceHackFlags, DHF_FORCE_REQUEST_SENSE))
  2509. {
  2510. KeAcquireSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock, &irql);
  2511. {
  2512. SET_FLAG(fdoDeviceExtension->DeviceFlags, DF_PERSISTENT_ERROR);
  2513. }
  2514. KeReleaseSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock, irql);
  2515. }
  2516. // The Interrupt USB transfer succeeded and the completion data is zero,
  2517. // complete this request now. Also start the next request now.
  2518. ntStatus = STATUS_SUCCESS;
  2519. Irp->IoStatus.Status = ntStatus;
  2520. ASSERT(srb->SrbStatus != SRB_STATUS_PENDING);
  2521. USBSTOR_TranslateCDBComplete(fdoDeviceObject, Irp, srb);
  2522. Irp->IoStatus.Information = srb->DataTransferLength;
  2523. LOGENTRY('idc5', fdoDeviceObject, Irp, srb);
  2524. KeRaiseIrql(DISPATCH_LEVEL, &irql);
  2525. {
  2526. IoStartNextPacket(fdoDeviceObject, TRUE);
  2527. }
  2528. KeLowerIrql(irql);
  2529. DBGPRINT(3, ("exit: USBSTOR_InterruptDataCompletionRoutine %08X\n", ntStatus));
  2530. return ntStatus;
  2531. }
  2532. //
  2533. // Phase 4, Request Sense CDB Control transfer
  2534. //
  2535. //******************************************************************************
  2536. //
  2537. // USBSTOR_IssueRequestSenseCdb()
  2538. //
  2539. // This routine can be called by USBSTOR_StartIo, USBSTOR_ClientCdbCompletion(),
  2540. // USBSTOR_InterruptDataCompletionRoutine(), and by USBSTOR_ResetPipeWorkItem().
  2541. //
  2542. // This routine may run at DPC level.
  2543. //
  2544. // Basic idea:
  2545. //
  2546. // Starts a USB transfer to write a Request Sense CDB out the control endpoint.
  2547. //
  2548. // Sets USBSTOR_RequestSenseCdbCompletion(AutoFlag) as the completion routine.
  2549. //
  2550. //******************************************************************************
  2551. NTSTATUS
  2552. USBSTOR_IssueRequestSenseCdb (
  2553. IN PDEVICE_OBJECT DeviceObject,
  2554. IN PIRP Irp,
  2555. IN ULONG_PTR AutoFlag
  2556. )
  2557. {
  2558. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  2559. PIO_STACK_LOCATION irpStack;
  2560. PSCSI_REQUEST_BLOCK srb;
  2561. ULONG transferBufferLength;
  2562. PVOID transferBuffer;
  2563. NTSTATUS ntStatus;
  2564. DBGPRINT(3, ("enter: USBSTOR_IssueRequestSenseCdb\n"));
  2565. fdoDeviceExtension = DeviceObject->DeviceExtension;
  2566. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  2567. // Get the client Srb
  2568. //
  2569. irpStack = IoGetCurrentIrpStackLocation(Irp);
  2570. srb = irpStack->Parameters.Scsi.Srb;
  2571. // The Control Transfer data buffer is our own Request Sense Cdb
  2572. //
  2573. RtlZeroMemory(fdoDeviceExtension->Cbi.RequestSenseCDB,
  2574. sizeof(fdoDeviceExtension->Cbi.RequestSenseCDB));
  2575. fdoDeviceExtension->Cbi.RequestSenseCDB[0] = SCSIOP_REQUEST_SENSE;
  2576. transferBufferLength = sizeof(fdoDeviceExtension->Cbi.RequestSenseCDB);
  2577. transferBuffer = fdoDeviceExtension->Cbi.RequestSenseCDB;
  2578. // If this is an AutoSense, we'll use the client Srb Sense Info Buffer,
  2579. // else we are doing this Request Sense to clear a persistent error and
  2580. // we'll use our own sense info buffer.
  2581. //
  2582. if (AutoFlag == AUTO_SENSE)
  2583. {
  2584. fdoDeviceExtension->Cbi.RequestSenseCDB[4] =
  2585. srb->SenseInfoBufferLength;
  2586. }
  2587. else
  2588. {
  2589. fdoDeviceExtension->Cbi.RequestSenseCDB[4] =
  2590. sizeof(fdoDeviceExtension->Cbi.SenseData);
  2591. }
  2592. ntStatus = USBSTOR_IssueControlRequest(
  2593. DeviceObject,
  2594. Irp,
  2595. transferBufferLength, // TransferBufferLength
  2596. transferBuffer, // TransferBuffer
  2597. USBSTOR_RequestSenseCdbCompletion, // CompletionRoutine
  2598. (PVOID)AutoFlag); // Context
  2599. DBGPRINT(3, ("exit: USBSTOR_IssueRequestSenseCdb %08X\n", ntStatus));
  2600. return ntStatus;
  2601. }
  2602. //******************************************************************************
  2603. //
  2604. // USBSTOR_RequestSenseCdbCompletion()
  2605. //
  2606. // Completion routine used by USBSTOR_IssueRequestSenseCdb
  2607. //
  2608. // This routine may run at DPC level.
  2609. //
  2610. // Basic idea:
  2611. //
  2612. // If a timeout reset occured, complete the request.
  2613. //
  2614. // Else if the Request Sense CDB USB transfer failed, complete the request and
  2615. // start a reset by queuing USBSTOR_ResetDeviceWorkItem().
  2616. //
  2617. // Else if the Request Sense CDB USB transfer succeeded, do not complete the
  2618. // request yet and start the Request Sense Bulk USB data transfer by calling
  2619. // USBSTOR_IssueRequestSenseBulkRequest(AutoFlag)
  2620. //
  2621. //******************************************************************************
  2622. NTSTATUS
  2623. USBSTOR_RequestSenseCdbCompletion (
  2624. IN PDEVICE_OBJECT DeviceObject,
  2625. IN PIRP Irp,
  2626. IN PVOID AutoFlag
  2627. )
  2628. {
  2629. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  2630. PDEVICE_OBJECT fdoDeviceObject;
  2631. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  2632. PIO_STACK_LOCATION irpStack;
  2633. PSCSI_REQUEST_BLOCK srb;
  2634. NTSTATUS ntStatus;
  2635. struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST *controlUrb;
  2636. DBGPRINT(3, ("enter: USBSTOR_RequestSenseCdbCompletion\n"));
  2637. LOGENTRY('RSCC', DeviceObject, Irp, Irp->IoStatus.Status);
  2638. pdoDeviceExtension = DeviceObject->DeviceExtension;
  2639. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  2640. fdoDeviceObject = pdoDeviceExtension->ParentFDO;
  2641. fdoDeviceExtension = fdoDeviceObject->DeviceExtension;
  2642. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  2643. // Get a pointer to the Control/Bulk/Interrupt Transfer URB in our Device
  2644. // Extension
  2645. //
  2646. controlUrb = &fdoDeviceExtension->Urb.ControlUrb;
  2647. // Get our Irp parameters
  2648. //
  2649. irpStack = IoGetCurrentIrpStackLocation(Irp);
  2650. srb = irpStack->Parameters.Scsi.Srb;
  2651. // If a timeout reset occured, complete the request.
  2652. //
  2653. if (USBSTOR_CheckRequestTimeOut(fdoDeviceObject,
  2654. Irp,
  2655. srb,
  2656. &ntStatus))
  2657. {
  2658. LOGENTRY('rsc1', fdoDeviceObject, Irp, srb);
  2659. DBGPRINT(1, ("USBSTOR_RequestSenseCdbCompletion: timeout completion\n"));
  2660. return ntStatus;
  2661. }
  2662. if (!NT_SUCCESS(Irp->IoStatus.Status))
  2663. {
  2664. LOGENTRY('rsc2', Irp->IoStatus.Status, controlUrb->Hdr.Status, 0);
  2665. DBGPRINT(1, ("Request Sense CDB transfer failed %08X %08X\n",
  2666. Irp->IoStatus.Status, controlUrb->Hdr.Status));
  2667. // The Request Sense CDB USB transfer failed. Complete this request
  2668. // now and then reset the device. The next request will be started
  2669. // when the reset completes.
  2670. //
  2671. ntStatus = STATUS_IO_DEVICE_ERROR;
  2672. Irp->IoStatus.Status = ntStatus;
  2673. Irp->IoStatus.Information = 0;
  2674. srb->SrbStatus = SRB_STATUS_BUS_RESET;
  2675. USBSTOR_TranslateCDBComplete(fdoDeviceObject, Irp, srb);
  2676. USBSTOR_QueueResetDevice(fdoDeviceObject);
  2677. DBGPRINT(1, ("USBSTOR_RequestSenseCdbCompletion: xfer error completion\n"));
  2678. return ntStatus;
  2679. }
  2680. LOGENTRY('rsc3', Irp->IoStatus.Status, controlUrb->Hdr.Status, 0);
  2681. // The Request Sense CDB USB transfer succeeded, do not complete the request
  2682. // yet and start the Request Sense Bulk USB data transfer.
  2683. //
  2684. ntStatus = USBSTOR_IssueRequestSenseBulkRequest(fdoDeviceObject,
  2685. Irp,
  2686. (ULONG_PTR)AutoFlag);
  2687. DBGPRINT(3, ("exit: USBSTOR_RequestSenseCdbCompletion %08X\n", ntStatus));
  2688. return STATUS_MORE_PROCESSING_REQUIRED;
  2689. }
  2690. //
  2691. // Phase 5, Request Sense Bulk transfer
  2692. //
  2693. //******************************************************************************
  2694. //
  2695. // USBSTOR_IssueRequestSenseBulkRequest()
  2696. //
  2697. // This routine is called by USBSTOR_RequestSenseCdbCompletion().
  2698. //
  2699. // This routine may run at DPC level.
  2700. //
  2701. // Basic idea:
  2702. //
  2703. // Starts a USB transfer to read the Requese Sense data in the bulk endpoint.
  2704. //
  2705. // If AutoFlag==AUTO, transfer buffer = Srb->SenseInfoBuffer.
  2706. //
  2707. // Else if AutoFlag==NON_AUTO, transfer buffer = bit bucket
  2708. //
  2709. // Sets USBSTOR_SenseDataCompletionRoutine(AutoFlag) as the completion routine.
  2710. //
  2711. //******************************************************************************
  2712. NTSTATUS
  2713. USBSTOR_IssueRequestSenseBulkRequest (
  2714. IN PDEVICE_OBJECT DeviceObject,
  2715. IN PIRP Irp,
  2716. IN ULONG_PTR AutoFlag
  2717. )
  2718. {
  2719. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  2720. PIO_STACK_LOCATION irpStack;
  2721. PSCSI_REQUEST_BLOCK srb;
  2722. USBD_PIPE_HANDLE pipeHandle;
  2723. ULONG transferBufferLength;
  2724. PVOID transferBuffer;
  2725. NTSTATUS ntStatus;
  2726. fdoDeviceExtension = DeviceObject->DeviceExtension;
  2727. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  2728. // Get our Irp parameters
  2729. //
  2730. irpStack = IoGetCurrentIrpStackLocation(Irp);
  2731. srb = irpStack->Parameters.Scsi.Srb;
  2732. pipeHandle = fdoDeviceExtension->BulkInPipe->PipeHandle;
  2733. // If this is an AutoSense, we'll use the client Srb Sense Info Buffer,
  2734. // else we are doing this Request Sense to clear a persistent error and
  2735. // we'll use our own sense info buffer.
  2736. //
  2737. if (AutoFlag == AUTO_SENSE)
  2738. {
  2739. transferBufferLength = srb->SenseInfoBufferLength;
  2740. transferBuffer = srb->SenseInfoBuffer;
  2741. }
  2742. else
  2743. {
  2744. transferBufferLength = sizeof(fdoDeviceExtension->Cbi.SenseData);
  2745. transferBuffer = &fdoDeviceExtension->Cbi.SenseData;
  2746. }
  2747. RtlZeroMemory(&fdoDeviceExtension->Cbi.SenseData,
  2748. sizeof(fdoDeviceExtension->Cbi.SenseData));
  2749. ntStatus = USBSTOR_IssueBulkOrInterruptRequest(
  2750. DeviceObject,
  2751. Irp,
  2752. pipeHandle, // PipeHandle
  2753. USBD_SHORT_TRANSFER_OK, // TransferFlags
  2754. transferBufferLength, // TransferBufferLength
  2755. transferBuffer, // TransferBuffer
  2756. NULL, // TransferBufferMDL
  2757. USBSTOR_SenseDataCompletionRoutine, // CompletionRoutine
  2758. (PVOID)AutoFlag); // Context
  2759. return ntStatus;
  2760. }
  2761. //******************************************************************************
  2762. //
  2763. // USBSTOR_SenseDataCompletionRoutine()
  2764. //
  2765. // Completion routine used by USBSTOR_IssueRequestSenseBulkRequest()
  2766. //
  2767. // This routine may run at DPC level.
  2768. //
  2769. // Basic idea:
  2770. //
  2771. // If a timeout reset occured, complete the request.
  2772. //
  2773. // Else if the Request Sense Bulk USB transfer failed due to any reason,
  2774. // complete the request and start a reset by queuing a call to
  2775. // USBSTOR_ResetDeviceWorkItem().
  2776. //
  2777. // Else if the Request Sense Bulk USB transfer succeeded and the device
  2778. // does support the command completion interrupt, start the command completion
  2779. // interrupt transfer by calling USBSTOR_IssueRequestSenseInterruptRequest().
  2780. //
  2781. // Else if the Request Sense Bulk USB transfer succeeded and the device
  2782. // does not support the command completion interrupt, complete the request
  2783. // by calling USBSTOR_ProcessRequestSenseCompletion().
  2784. //
  2785. //******************************************************************************
  2786. NTSTATUS
  2787. USBSTOR_SenseDataCompletionRoutine (
  2788. IN PDEVICE_OBJECT DeviceObject,
  2789. IN PIRP Irp,
  2790. IN PVOID AutoFlag
  2791. )
  2792. {
  2793. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  2794. PDEVICE_OBJECT fdoDeviceObject;
  2795. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  2796. PIO_STACK_LOCATION irpStack;
  2797. PSCSI_REQUEST_BLOCK srb;
  2798. NTSTATUS ntStatus;
  2799. struct _URB_BULK_OR_INTERRUPT_TRANSFER *bulkUrb;
  2800. DBGPRINT(3, ("enter: USBSTOR_SenseDataCompletionRoutine\n"));
  2801. LOGENTRY('SDCR', DeviceObject, Irp, Irp->IoStatus.Status);
  2802. pdoDeviceExtension = DeviceObject->DeviceExtension;
  2803. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  2804. fdoDeviceObject = pdoDeviceExtension->ParentFDO;
  2805. fdoDeviceExtension = fdoDeviceObject->DeviceExtension;
  2806. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  2807. // Get a pointer to the Bulk Transfer URB in our Device Extension
  2808. //
  2809. bulkUrb = &fdoDeviceExtension->Urb.BulkIntrUrb;
  2810. // Get our Irp parameters
  2811. //
  2812. irpStack = IoGetCurrentIrpStackLocation(Irp);
  2813. srb = irpStack->Parameters.Scsi.Srb;
  2814. // If a timeout reset occured, complete the request.
  2815. //
  2816. if (USBSTOR_CheckRequestTimeOut(fdoDeviceObject,
  2817. Irp,
  2818. srb,
  2819. &ntStatus))
  2820. {
  2821. LOGENTRY('sdc1', fdoDeviceObject, Irp, srb);
  2822. DBGPRINT(1, ("USBSTOR_SenseDataCompletionRoutine: timeout completion\n"));
  2823. return ntStatus;
  2824. }
  2825. if (!NT_SUCCESS(Irp->IoStatus.Status))
  2826. {
  2827. LOGENTRY('sdc2', Irp->IoStatus.Status, bulkUrb->Hdr.Status, 0);
  2828. DBGPRINT(1, ("BULK sense data transfer failed %08X %08X\n",
  2829. Irp->IoStatus.Status, bulkUrb->Hdr.Status));
  2830. // The Request Sense Bulk USB transfer failed. Complete this request
  2831. // now and then reset the device. The next request will be started
  2832. // when the reset completes.
  2833. //
  2834. ntStatus = STATUS_IO_DEVICE_ERROR;
  2835. Irp->IoStatus.Status = ntStatus;
  2836. Irp->IoStatus.Information = 0;
  2837. srb->SrbStatus = SRB_STATUS_BUS_RESET;
  2838. USBSTOR_TranslateCDBComplete(fdoDeviceObject, Irp, srb);
  2839. USBSTOR_QueueResetDevice(fdoDeviceObject);
  2840. DBGPRINT(1, ("USBSTOR_SenseDataCompletionRoutine: xfer error completion\n"));
  2841. return ntStatus;
  2842. }
  2843. // The Request Sense Bulk transfer completed successfully.
  2844. LOGENTRY('sdc3', Irp->IoStatus.Status, bulkUrb->Hdr.Status,
  2845. bulkUrb->TransferBufferLength);
  2846. // Save the sense data so we can look at it after the command
  2847. // completion interrupt transfer completes.
  2848. //
  2849. if ((ULONG_PTR)AutoFlag == AUTO_SENSE)
  2850. {
  2851. RtlCopyMemory(&fdoDeviceExtension->Cbi.SenseData,
  2852. bulkUrb->TransferBuffer,
  2853. min(bulkUrb->TransferBufferLength,
  2854. sizeof(fdoDeviceExtension->Cbi.SenseData)));
  2855. // Update the SRB with the length of the sense data that was
  2856. // actually returned.
  2857. //
  2858. srb->SenseInfoBufferLength = (UCHAR)bulkUrb->TransferBufferLength;
  2859. }
  2860. DBGPRINT(2, ("Sense Data: 0x%02X 0x%02X 0x%02X\n",
  2861. fdoDeviceExtension->Cbi.SenseData.SenseKey,
  2862. fdoDeviceExtension->Cbi.SenseData.AdditionalSenseCode,
  2863. fdoDeviceExtension->Cbi.SenseData.AdditionalSenseCodeQualifier));
  2864. if (fdoDeviceExtension->InterruptInPipe)
  2865. {
  2866. // Command completion interrupt supported. Do not complete the
  2867. // request yet. Start the Request Sense command completion interrupt
  2868. // transfer.
  2869. //
  2870. ntStatus = USBSTOR_IssueRequestSenseInterruptRequest(
  2871. fdoDeviceObject,
  2872. Irp,
  2873. (ULONG_PTR)AutoFlag);
  2874. ntStatus = STATUS_MORE_PROCESSING_REQUIRED;
  2875. }
  2876. else
  2877. {
  2878. // Command completion interrupt not supported. Complete the request
  2879. // now.
  2880. //
  2881. ntStatus = USBSTOR_ProcessRequestSenseCompletion(
  2882. fdoDeviceObject,
  2883. Irp,
  2884. (ULONG_PTR)AutoFlag);
  2885. }
  2886. DBGPRINT(3, ("exit: USBSTOR_SenseDataCompletionRoutine %08X\n", ntStatus));
  2887. return ntStatus;
  2888. }
  2889. //
  2890. // Phase 6, Request Sense Command completion Interrupt transfer
  2891. //
  2892. //******************************************************************************
  2893. //
  2894. // USBSTOR_IssueRequestSenseInterruptRequest()
  2895. //
  2896. // This routine is called USBSTOR_SenseDataCompletionRoutine()
  2897. //
  2898. // This routine may run at DPC level.
  2899. //
  2900. // Basic idea:
  2901. //
  2902. // Starts a USB transfer to read the command completion interrupt data In
  2903. // the Interrupt endpoint.
  2904. //
  2905. // Sets USBSTOR_RequestSenseInterruptCompletionRoutine() as the completion
  2906. // routine.
  2907. //
  2908. //******************************************************************************
  2909. NTSTATUS
  2910. USBSTOR_IssueRequestSenseInterruptRequest (
  2911. IN PDEVICE_OBJECT DeviceObject,
  2912. IN PIRP Irp,
  2913. IN ULONG_PTR AutoFlag
  2914. )
  2915. {
  2916. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  2917. USBD_PIPE_HANDLE pipeHandle;
  2918. ULONG transferBufferLength;
  2919. PVOID transferBuffer;
  2920. NTSTATUS ntStatus;
  2921. DBGPRINT(3, ("enter: USBSTOR_IssueRequestSenseInterruptRequest\n"));
  2922. LOGENTRY('IRSI', DeviceObject, Irp, 0);
  2923. fdoDeviceExtension = DeviceObject->DeviceExtension;
  2924. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  2925. pipeHandle = fdoDeviceExtension->InterruptInPipe->PipeHandle;
  2926. transferBufferLength = sizeof(fdoDeviceExtension->Cbi.InterruptData);
  2927. transferBuffer = &fdoDeviceExtension->Cbi.InterruptData;
  2928. ntStatus = USBSTOR_IssueBulkOrInterruptRequest(
  2929. DeviceObject,
  2930. Irp,
  2931. pipeHandle, // PipeHandle
  2932. 0, // TransferFlags
  2933. transferBufferLength, // TransferBufferLength
  2934. transferBuffer, // TransferBuffer
  2935. NULL, // TransferBufferMDL
  2936. USBSTOR_RequestSenseInterruptCompletionRoutine, // CompletionRoutine
  2937. (PVOID)AutoFlag); // Context
  2938. DBGPRINT(3, ("exit: USBSTOR_IssueRequestSenseInterruptRequest %08X\n",
  2939. ntStatus));
  2940. LOGENTRY('irsi', DeviceObject, Irp, ntStatus);
  2941. return ntStatus;
  2942. }
  2943. //******************************************************************************
  2944. //
  2945. // USBSTOR_RequestSenseInterruptCompletionRoutine()
  2946. //
  2947. // Completion routine used by USBSTOR_IssueRequestSenseInterruptRequest()
  2948. //
  2949. // This routine may run at DPC level.
  2950. //
  2951. // Basic idea:
  2952. //
  2953. // If a timeout reset occured, complete the request.
  2954. //
  2955. // Else if the Interrupt USB transfer failed due to any reason, complete the
  2956. // request and start a reset by queuing USBSTOR_ResetDeviceWorkItem().
  2957. //
  2958. // Else if the Interrupt USB transfer succeeded but the completion data is
  2959. // non-zero and AutoSense is not disabled, do not complete the request yet and
  2960. // start a Request Sense by calling USBSTOR_IssueRequestSenseCdb(AUTO).
  2961. //
  2962. // Else if the Interrupt USB transfer succeeded, ignore the interrupt data
  2963. // and complete the request by calling USBSTOR_ProcessRequestSenseCompletion().
  2964. //
  2965. //******************************************************************************
  2966. NTSTATUS
  2967. USBSTOR_RequestSenseInterruptCompletionRoutine (
  2968. IN PDEVICE_OBJECT DeviceObject,
  2969. IN PIRP Irp,
  2970. IN PVOID AutoFlag
  2971. )
  2972. {
  2973. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  2974. PDEVICE_OBJECT fdoDeviceObject;
  2975. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  2976. PIO_STACK_LOCATION irpStack;
  2977. PSCSI_REQUEST_BLOCK srb;
  2978. NTSTATUS ntStatus;
  2979. struct _URB_BULK_OR_INTERRUPT_TRANSFER *intrUrb;
  2980. DBGPRINT(3, ("enter: USBSTOR_RequestSenseInterruptCompletionRoutine\n"));
  2981. LOGENTRY('RSIC', DeviceObject, Irp, Irp->IoStatus.Status);
  2982. pdoDeviceExtension = DeviceObject->DeviceExtension;
  2983. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  2984. fdoDeviceObject = pdoDeviceExtension->ParentFDO;
  2985. fdoDeviceExtension = fdoDeviceObject->DeviceExtension;
  2986. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  2987. // Get a pointer to the Interrupt Transfer URB in our Device Extension
  2988. //
  2989. intrUrb = &fdoDeviceExtension->Urb.BulkIntrUrb;
  2990. // Get our Irp parameters
  2991. //
  2992. irpStack = IoGetCurrentIrpStackLocation(Irp);
  2993. srb = irpStack->Parameters.Scsi.Srb;
  2994. // If a timeout reset occured, complete the request.
  2995. //
  2996. if (USBSTOR_CheckRequestTimeOut(fdoDeviceObject,
  2997. Irp,
  2998. srb,
  2999. &ntStatus))
  3000. {
  3001. LOGENTRY('rsi1', fdoDeviceObject, Irp, srb);
  3002. DBGPRINT(1, ("USBSTOR_RequestSenseInterruptCompletionRoutine: timeout completion\n"));
  3003. return ntStatus;
  3004. }
  3005. if (!NT_SUCCESS(Irp->IoStatus.Status))
  3006. {
  3007. // The command completion Interrupt USB transfer failed. Complete
  3008. // this request now and then reset the device. The next request will
  3009. // be started when the reset completes.
  3010. //
  3011. LOGENTRY('rsi2', Irp->IoStatus.Status, intrUrb->Hdr.Status, 0);
  3012. DBGPRINT(1, ("Interrupt transfer failed %08X %08X\n",
  3013. Irp->IoStatus.Status, intrUrb->Hdr.Status));
  3014. ntStatus = STATUS_IO_DEVICE_ERROR;
  3015. Irp->IoStatus.Status = ntStatus;
  3016. Irp->IoStatus.Information = 0;
  3017. srb->SrbStatus = SRB_STATUS_BUS_RESET;
  3018. USBSTOR_TranslateCDBComplete(fdoDeviceObject, Irp, srb);
  3019. USBSTOR_QueueResetDevice(fdoDeviceObject);
  3020. DBGPRINT(1, ("USBSTOR_RequestSenseInterruptCompletionRoutine: xfer error completion\n"));
  3021. return ntStatus;
  3022. }
  3023. // Request Sense Command Completion Interrupt tranfer completed successfully.
  3024. LOGENTRY('rsi3', Irp->IoStatus.Status, intrUrb->Hdr.Status,
  3025. intrUrb->TransferBufferLength);
  3026. ntStatus = USBSTOR_ProcessRequestSenseCompletion(
  3027. fdoDeviceObject,
  3028. Irp,
  3029. (ULONG_PTR)AutoFlag);
  3030. DBGPRINT(3, ("exit: USBSTOR_RequestSenseInterruptCompletionRoutine %08X\n", ntStatus));
  3031. return ntStatus;
  3032. }
  3033. //******************************************************************************
  3034. //
  3035. // USBSTOR_ProcessRequestSenseCompletion()
  3036. //
  3037. // This routine handles completion for USBSTOR_SenseDataCompletionRoutine()
  3038. // and USBSTOR_RequestSenseInterruptCompletionRoutine(). It basically just
  3039. // handles a couple of special cases.
  3040. //
  3041. // This routine may run at DPC level.
  3042. //
  3043. //******************************************************************************
  3044. NTSTATUS
  3045. USBSTOR_ProcessRequestSenseCompletion (
  3046. IN PDEVICE_OBJECT DeviceObject,
  3047. IN PIRP Irp,
  3048. IN ULONG_PTR AutoFlag
  3049. )
  3050. {
  3051. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  3052. PIO_STACK_LOCATION irpStack;
  3053. PSCSI_REQUEST_BLOCK srb;
  3054. KIRQL irql;
  3055. NTSTATUS ntStatus;
  3056. LOGENTRY('PRSC', DeviceObject, Irp, 0);
  3057. fdoDeviceExtension = DeviceObject->DeviceExtension;
  3058. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  3059. // Get our Irp parameters
  3060. //
  3061. irpStack = IoGetCurrentIrpStackLocation(Irp);
  3062. srb = irpStack->Parameters.Scsi.Srb;
  3063. if (AutoFlag == NON_AUTO_SENSE)
  3064. {
  3065. LOGENTRY('prs1', DeviceObject, Irp, srb);
  3066. if ((fdoDeviceExtension->Cbi.SenseData.SenseKey ==
  3067. SCSI_SENSE_UNIT_ATTENTION)
  3068. &&
  3069. (fdoDeviceExtension->Cbi.SenseData.AdditionalSenseCode ==
  3070. SCSI_ADSENSE_BUS_RESET))
  3071. {
  3072. fdoDeviceExtension->LastSenseWasReset = TRUE;
  3073. }
  3074. // Just cleared the persistent error from the previous request,
  3075. // now issue the real request.
  3076. //
  3077. ntStatus = USBSTOR_IssueClientCdb(DeviceObject,
  3078. Irp);
  3079. return STATUS_MORE_PROCESSING_REQUIRED;
  3080. }
  3081. // SrbStatus and DataTransferLength were already set in
  3082. // USBSTOR_ClientCdbCompletion(), USBSTOR_ClientBulkCompletionRoutine(), or in
  3083. // or USBSTOR_InterruptDataCompletionRoutine() before we got here.
  3084. //
  3085. srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
  3086. USBSTOR_TranslateCDBComplete(DeviceObject, Irp, srb);
  3087. Irp->IoStatus.Information = srb->DataTransferLength;
  3088. ntStatus = Irp->IoStatus.Status;
  3089. // Disgusting hack for Y-E Data USB Floppy. On Medium Changed it doesn't
  3090. // automatically update the Write Protect status that you get back in
  3091. // the Mode Parameter Header on a Mode Sense. Supposedly a Start Unit
  3092. // request after a Medium Changed should cause it to update the Write
  3093. // Protect status, but that does not seem to be the case. A good old
  3094. // bus reset gets its attention though and updates the Write Protect
  3095. // status. Don't do this if the last status was a Bus Reset or that
  3096. // will cause a loop.
  3097. //
  3098. if ((fdoDeviceExtension->Cbi.SenseData.SenseKey ==
  3099. SCSI_SENSE_UNIT_ATTENTION)
  3100. &&
  3101. (fdoDeviceExtension->Cbi.SenseData.AdditionalSenseCode ==
  3102. SCSI_ADSENSE_MEDIUM_CHANGED)
  3103. &&
  3104. !fdoDeviceExtension->LastSenseWasReset
  3105. &&
  3106. TEST_FLAG(fdoDeviceExtension->DeviceHackFlags, DHF_MEDIUM_CHANGE_RESET))
  3107. {
  3108. LOGENTRY('prs2', DeviceObject, Irp, srb);
  3109. USBSTOR_QueueResetDevice(DeviceObject);
  3110. }
  3111. else
  3112. {
  3113. if ((fdoDeviceExtension->Cbi.SenseData.SenseKey ==
  3114. SCSI_SENSE_UNIT_ATTENTION)
  3115. &&
  3116. (fdoDeviceExtension->Cbi.SenseData.AdditionalSenseCode ==
  3117. SCSI_ADSENSE_BUS_RESET))
  3118. {
  3119. LOGENTRY('prs3', DeviceObject, Irp, srb);
  3120. fdoDeviceExtension->LastSenseWasReset = TRUE;
  3121. }
  3122. else
  3123. {
  3124. LOGENTRY('prs4', DeviceObject, Irp, srb);
  3125. fdoDeviceExtension->LastSenseWasReset = FALSE;
  3126. }
  3127. KeRaiseIrql(DISPATCH_LEVEL, &irql);
  3128. {
  3129. IoStartNextPacket(DeviceObject, TRUE);
  3130. }
  3131. KeLowerIrql(irql);
  3132. }
  3133. return ntStatus;
  3134. }
  3135. //******************************************************************************
  3136. //
  3137. // USBSTOR_QueueResetPipe()
  3138. //
  3139. // Called by USBSTOR_BulkCompletionRoutine() to clear the STALL on the bulk
  3140. // endpoints.
  3141. //
  3142. //******************************************************************************
  3143. VOID
  3144. USBSTOR_QueueResetPipe (
  3145. IN PDEVICE_OBJECT DeviceObject
  3146. )
  3147. {
  3148. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  3149. LOGENTRY('QRSP', DeviceObject, 0, 0);
  3150. fdoDeviceExtension = DeviceObject->DeviceExtension;
  3151. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  3152. INCREMENT_PENDING_IO_COUNT(fdoDeviceExtension);
  3153. IoQueueWorkItem(fdoDeviceExtension->IoWorkItem,
  3154. USBSTOR_ResetPipeWorkItem,
  3155. CriticalWorkQueue,
  3156. NULL);
  3157. }
  3158. //******************************************************************************
  3159. //
  3160. // USBSTOR_ResetPipeWorkItem()
  3161. //
  3162. // WorkItem routine used by USBSTOR_ResetPipe()
  3163. //
  3164. // This routine runs at PASSIVE level.
  3165. //
  3166. // Basic idea:
  3167. //
  3168. // Issue a Reset Pipe request to clear the Bulk endpoint STALL and reset
  3169. // the data toggle to Data0.
  3170. //
  3171. // If AutoSense is not disabled, do not complete the request yet and start
  3172. // a Request Sense by calling USBSTOR_IssueRequestSenseCdb(AUTO).
  3173. //
  3174. // Else if AutoSense is disabled, complete the request.
  3175. //
  3176. //******************************************************************************
  3177. VOID
  3178. USBSTOR_ResetPipeWorkItem (
  3179. IN PDEVICE_OBJECT DeviceObject,
  3180. IN PVOID Context
  3181. )
  3182. {
  3183. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  3184. BOOLEAN persistentError;
  3185. KIRQL irql;
  3186. NTSTATUS ntStatus;
  3187. LOGENTRY('RSPW', DeviceObject, 0, 0);
  3188. DBGPRINT(2, ("enter: USBSTOR_ResetPipeWorkItem\n"));
  3189. fdoDeviceExtension = DeviceObject->DeviceExtension;
  3190. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  3191. // Reset the Bulk Endpoint. This clears the endpoint halt on the
  3192. // host side, resets the host side data toggle to Data0, and issues
  3193. // the Clear_Feature Endpoint_Stall request to the device.
  3194. //
  3195. ntStatus = USBSTOR_ResetPipe((PDEVICE_OBJECT)DeviceObject,
  3196. fdoDeviceExtension->BulkInPipe->PipeHandle);
  3197. ntStatus = USBSTOR_ResetPipe((PDEVICE_OBJECT)DeviceObject,
  3198. fdoDeviceExtension->BulkOutPipe->PipeHandle);
  3199. persistentError = FALSE;
  3200. KeAcquireSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock, &irql);
  3201. {
  3202. if (TEST_FLAG(fdoDeviceExtension->DeviceFlags, DF_PERSISTENT_ERROR))
  3203. {
  3204. persistentError = TRUE;
  3205. }
  3206. }
  3207. KeReleaseSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock, irql);
  3208. if (persistentError)
  3209. {
  3210. // We are not doing an AutoSense, start the next packet.
  3211. //
  3212. KeRaiseIrql(DISPATCH_LEVEL, &irql);
  3213. {
  3214. IoStartNextPacket(DeviceObject, TRUE);
  3215. }
  3216. KeLowerIrql(irql);
  3217. }
  3218. else
  3219. {
  3220. // We are doing an AutoSense, send the REQUEST_SENSE Cdb to the device.
  3221. //
  3222. ntStatus = USBSTOR_IssueRequestSenseCdb(
  3223. (PDEVICE_OBJECT)DeviceObject,
  3224. ((PDEVICE_OBJECT)DeviceObject)->CurrentIrp,
  3225. AUTO_SENSE);
  3226. }
  3227. DBGPRINT(2, ("exit: USBSTOR_ResetPipeWorkItem\n"));
  3228. DECREMENT_PENDING_IO_COUNT(fdoDeviceExtension);
  3229. }
  3230. //
  3231. // Bulk-Only Routines
  3232. //
  3233. //
  3234. // Phase 1, CBW Transfer
  3235. //
  3236. //******************************************************************************
  3237. //
  3238. // USBSTOR_CbwTransfer()
  3239. //
  3240. // This routine is called by USBSTOR_StartIo().
  3241. //
  3242. // It runs at DPC level.
  3243. //
  3244. // Basic idea:
  3245. //
  3246. // Starts a USB transfer to write the Srb->Cdb wrapped inside a CBW out
  3247. // the Bulk OUT endpoint.
  3248. //
  3249. // Sets USBSTOR_CbwCompletion() as the completion routine.
  3250. //
  3251. //******************************************************************************
  3252. NTSTATUS
  3253. USBSTOR_CbwTransfer (
  3254. IN PDEVICE_OBJECT DeviceObject,
  3255. IN PIRP Irp
  3256. )
  3257. {
  3258. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  3259. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  3260. PIO_STACK_LOCATION irpStack;
  3261. PSCSI_REQUEST_BLOCK srb;
  3262. PCBW cbw;
  3263. USBD_PIPE_HANDLE pipeHandle;
  3264. NTSTATUS ntStatus;
  3265. DBGPRINT(3, ("enter: USBSTOR_CbwTransfer\n"));
  3266. LOGENTRY('ICBW', DeviceObject, Irp, 0);
  3267. fdoDeviceExtension = DeviceObject->DeviceExtension;
  3268. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  3269. fdoDeviceExtension->BulkOnly.StallCount = 0;
  3270. irpStack = IoGetCurrentIrpStackLocation(Irp);
  3271. // Get the PDO extension from the PDO which was saved in the current
  3272. // stack location when the Irp was originally sent to the PDO.
  3273. //
  3274. pdoDeviceExtension = irpStack->DeviceObject->DeviceExtension;
  3275. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  3276. LOGENTRY('icbl', DeviceObject, irpStack->DeviceObject,
  3277. pdoDeviceExtension->LUN);
  3278. // Get the client Srb
  3279. //
  3280. srb = irpStack->Parameters.Scsi.Srb;
  3281. // Initialize the Command Block Wrapper
  3282. //
  3283. cbw = &fdoDeviceExtension->BulkOnly.CbwCsw.Cbw;
  3284. cbw->dCBWSignature = CBW_SIGNATURE;
  3285. cbw->dCBWTag = PtrToUlong(Irp);
  3286. cbw->dCBWDataTransferLength = srb->DataTransferLength;
  3287. cbw->bCBWFlags = (srb->SrbFlags & SRB_FLAGS_DATA_IN) ?
  3288. CBW_FLAGS_DATA_IN : CBW_FLAGS_DATA_OUT;
  3289. cbw->bCBWLUN = pdoDeviceExtension->LUN;
  3290. cbw->bCDBLength = srb->CdbLength;
  3291. RtlCopyMemory(cbw->CBWCDB, srb->Cdb, 16);
  3292. pipeHandle = fdoDeviceExtension->BulkOutPipe->PipeHandle;
  3293. ntStatus = USBSTOR_IssueBulkOrInterruptRequest(
  3294. DeviceObject,
  3295. Irp,
  3296. pipeHandle, // PipeHandle
  3297. 0, // TransferFlags
  3298. sizeof(CBW), // TransferBufferLength
  3299. cbw, // TransferBuffer
  3300. NULL, // TransferBufferMDL
  3301. USBSTOR_CbwCompletion, // CompletionRoutine
  3302. NULL); // Context
  3303. DBGPRINT(3, ("exit: USBSTOR_CbwTransfer %08X\n", ntStatus));
  3304. LOGENTRY('icbw', DeviceObject, Irp, ntStatus);
  3305. return ntStatus;
  3306. }
  3307. //******************************************************************************
  3308. //
  3309. // USBSTOR_CbwCompletion()
  3310. //
  3311. // Completion routine used by USBSTOR_CbwTransfer()
  3312. //
  3313. // This routine may run at DPC level.
  3314. //
  3315. // Basic idea:
  3316. //
  3317. // If a timeout reset occured, complete the request.
  3318. //
  3319. // Else if the CBW USB transfer failed due to any reason, complete the
  3320. // request and start a reset by queuing USBSTOR_ResetDeviceWorkItem().
  3321. //
  3322. // Else if the CBW USB transfer succeeded and the Srb has a transfer buffer,
  3323. // do not complete the request yet and start the bulk data transfer by calling
  3324. // USBSTOR_DataTransfer().
  3325. //
  3326. // Else if the CBW USB transfer succeeded and the Srb has no transfer buffer,
  3327. // do not complete the request yet and start the CSW bulk transfer by calling
  3328. // USBSTOR_CswTransfer().
  3329. //
  3330. //******************************************************************************
  3331. NTSTATUS
  3332. USBSTOR_CbwCompletion (
  3333. IN PDEVICE_OBJECT DeviceObject,
  3334. IN PIRP Irp,
  3335. IN PVOID NotUsed
  3336. )
  3337. {
  3338. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  3339. PDEVICE_OBJECT fdoDeviceObject;
  3340. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  3341. PIO_STACK_LOCATION irpStack;
  3342. PSCSI_REQUEST_BLOCK srb;
  3343. NTSTATUS ntStatus;
  3344. struct _URB_BULK_OR_INTERRUPT_TRANSFER *bulkUrb;
  3345. DBGPRINT(3, ("enter: USBSTOR_CbwCompletion\n"));
  3346. LOGENTRY('CBWC', DeviceObject, Irp, Irp->IoStatus.Status);
  3347. pdoDeviceExtension = DeviceObject->DeviceExtension;
  3348. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  3349. fdoDeviceObject = pdoDeviceExtension->ParentFDO;
  3350. fdoDeviceExtension = fdoDeviceObject->DeviceExtension;
  3351. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  3352. // Get a pointer to the Bulk Transfer URB in our Device Extension
  3353. //
  3354. bulkUrb = &fdoDeviceExtension->Urb.BulkIntrUrb;
  3355. // Get our Irp parameters
  3356. //
  3357. irpStack = IoGetCurrentIrpStackLocation(Irp);
  3358. srb = irpStack->Parameters.Scsi.Srb;
  3359. // If a timeout reset occured, complete the request.
  3360. //
  3361. if (USBSTOR_CheckRequestTimeOut(fdoDeviceObject,
  3362. Irp,
  3363. srb,
  3364. &ntStatus))
  3365. {
  3366. LOGENTRY('cbw1', fdoDeviceObject, Irp, srb);
  3367. DBGPRINT(1, ("USBSTOR_CbwCompletion: timeout completion\n"));
  3368. return ntStatus;
  3369. }
  3370. if (!NT_SUCCESS(Irp->IoStatus.Status))
  3371. {
  3372. // The CBW Bulk Transfer was not successful.
  3373. //
  3374. LOGENTRY('cbw2', Irp->IoStatus.Status, bulkUrb->Hdr.Status, 0);
  3375. DBGPRINT(1, ("CBW transfer failed %08X %08X\n",
  3376. Irp->IoStatus.Status, bulkUrb->Hdr.Status));
  3377. srb = fdoDeviceExtension->OriginalSrb;
  3378. irpStack->Parameters.Scsi.Srb = srb;
  3379. // Complete this request now and then reset the device. The next
  3380. // request will be started when the reset completes.
  3381. //
  3382. ntStatus = STATUS_IO_DEVICE_ERROR;
  3383. Irp->IoStatus.Status = ntStatus;
  3384. Irp->IoStatus.Information = 0;
  3385. srb->SrbStatus = SRB_STATUS_BUS_RESET;
  3386. USBSTOR_TranslateCDBComplete(fdoDeviceObject, Irp, srb);
  3387. USBSTOR_QueueResetDevice(fdoDeviceObject);
  3388. DBGPRINT(1, ("USBSTOR_CbwCompletion: xfer error completion\n"));
  3389. return ntStatus;
  3390. }
  3391. // The CBW Bulk Transfer was successful. Start the next phase, either
  3392. // the Data Bulk Transfer or CSW Bulk Transfer, and do not complete the
  3393. // request yet.
  3394. //
  3395. if (Irp->MdlAddress != NULL ||
  3396. srb != fdoDeviceExtension->OriginalSrb)
  3397. {
  3398. // The Srb has a transfer buffer, start the Data Bulk Transfer.
  3399. //
  3400. LOGENTRY('cbw3', fdoDeviceObject, Irp, srb);
  3401. ASSERT(srb->DataTransferLength != 0);
  3402. ntStatus = USBSTOR_DataTransfer(fdoDeviceObject,
  3403. Irp);
  3404. if (NT_SUCCESS(ntStatus))
  3405. {
  3406. ntStatus = STATUS_MORE_PROCESSING_REQUIRED;
  3407. }
  3408. else
  3409. {
  3410. srb = fdoDeviceExtension->OriginalSrb;
  3411. irpStack->Parameters.Scsi.Srb = srb;
  3412. Irp->IoStatus.Status = ntStatus;
  3413. Irp->IoStatus.Information = 0;
  3414. srb->SrbStatus = SRB_STATUS_ERROR;
  3415. USBSTOR_TranslateCDBComplete(fdoDeviceObject, Irp, srb);
  3416. USBSTOR_QueueResetDevice(fdoDeviceObject);
  3417. }
  3418. }
  3419. else
  3420. {
  3421. // The Srb has no transfer buffer. Start the CSW Bulk Transfer.
  3422. //
  3423. LOGENTRY('cbw4', fdoDeviceObject, Irp, srb);
  3424. ASSERT(srb->DataTransferLength == 0);
  3425. srb->SrbStatus = SRB_STATUS_SUCCESS;
  3426. ntStatus = USBSTOR_CswTransfer(fdoDeviceObject,
  3427. Irp);
  3428. ntStatus = STATUS_MORE_PROCESSING_REQUIRED;
  3429. }
  3430. DBGPRINT(3, ("exit: USBSTOR_CbwCompletion %08X\n", ntStatus));
  3431. return ntStatus;
  3432. }
  3433. //
  3434. // Phase 2, Data Transfer
  3435. //
  3436. //******************************************************************************
  3437. //
  3438. // USBSTOR_DataTransfer()
  3439. //
  3440. // This routine is called by USBSTOR_ClientCdbCompletion().
  3441. //
  3442. // This routine may run at DPC level.
  3443. //
  3444. // Basic idea:
  3445. //
  3446. // Starts a USB transfer to read or write the Srb->DataBuffer data In or Out
  3447. // the Bulk endpoint.
  3448. //
  3449. // Sets USBSTOR_DataCompletion() as the completion routine.
  3450. //
  3451. //******************************************************************************
  3452. NTSTATUS
  3453. USBSTOR_DataTransfer (
  3454. IN PDEVICE_OBJECT DeviceObject,
  3455. IN PIRP Irp
  3456. )
  3457. {
  3458. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  3459. PIO_STACK_LOCATION irpStack;
  3460. PSCSI_REQUEST_BLOCK srb;
  3461. PMDL mdl;
  3462. PVOID mdlVa;
  3463. PVOID transferBuffer;
  3464. USBD_PIPE_HANDLE pipeHandle;
  3465. ULONG transferFlags;
  3466. NTSTATUS ntStatus;
  3467. DBGPRINT(3, ("enter: USBSTOR_DataTransfer\n"));
  3468. LOGENTRY('IBKD', DeviceObject, Irp, 0);
  3469. fdoDeviceExtension = DeviceObject->DeviceExtension;
  3470. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  3471. // Get our Irp parameters
  3472. //
  3473. irpStack = IoGetCurrentIrpStackLocation(Irp);
  3474. srb = irpStack->Parameters.Scsi.Srb;
  3475. // Bulk IN or Bulk OUT?
  3476. //
  3477. if ((srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) == SRB_FLAGS_DATA_IN)
  3478. {
  3479. pipeHandle = fdoDeviceExtension->BulkInPipe->PipeHandle;
  3480. transferFlags = USBD_SHORT_TRANSFER_OK;
  3481. }
  3482. else if ((srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) == SRB_FLAGS_DATA_OUT)
  3483. {
  3484. pipeHandle = fdoDeviceExtension->BulkOutPipe->PipeHandle;
  3485. transferFlags = 0;
  3486. }
  3487. else
  3488. {
  3489. // Something is wrong if we end up here.
  3490. //
  3491. ASSERT((srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) &&
  3492. ((srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) !=
  3493. SRB_FLAGS_UNSPECIFIED_DIRECTION));
  3494. return STATUS_INVALID_PARAMETER;
  3495. }
  3496. mdl = NULL;
  3497. transferBuffer = NULL;
  3498. if (srb == fdoDeviceExtension->OriginalSrb)
  3499. {
  3500. // Check to see if this request is part of a split request.
  3501. //
  3502. mdlVa = MmGetMdlVirtualAddress(Irp->MdlAddress);
  3503. if (mdlVa == (PVOID)srb->DataBuffer)
  3504. {
  3505. // Not part of a split request, use original MDL
  3506. //
  3507. mdl = Irp->MdlAddress;
  3508. }
  3509. else
  3510. {
  3511. // Part of a split request, allocate new partial MDL
  3512. //
  3513. mdl = IoAllocateMdl(srb->DataBuffer,
  3514. srb->DataTransferLength,
  3515. FALSE,
  3516. FALSE,
  3517. NULL);
  3518. if (mdl == NULL)
  3519. {
  3520. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3521. }
  3522. else
  3523. {
  3524. IoBuildPartialMdl(Irp->MdlAddress,
  3525. mdl,
  3526. srb->DataBuffer,
  3527. srb->DataTransferLength);
  3528. }
  3529. }
  3530. }
  3531. else
  3532. {
  3533. transferBuffer = srb->DataBuffer;
  3534. // If (srb != fdoDeviceExtension->OriginalSrb) then
  3535. // srb->DataBuffer should equal OriginalSrb->SenseInfoBuffer,
  3536. // which should not be NULL if we end up here.
  3537. //
  3538. ASSERT(transferBuffer);
  3539. if (!transferBuffer) {
  3540. // just in case
  3541. ntStatus = STATUS_INVALID_PARAMETER;
  3542. }
  3543. }
  3544. if (mdl != NULL || transferBuffer != NULL)
  3545. {
  3546. ntStatus = USBSTOR_IssueBulkOrInterruptRequest(
  3547. DeviceObject,
  3548. Irp,
  3549. pipeHandle, // PipeHandle
  3550. transferFlags, // TransferFlags
  3551. srb->DataTransferLength, // TransferBufferLength
  3552. transferBuffer, // TransferBuffer
  3553. mdl, // TransferBufferMDL
  3554. USBSTOR_DataCompletion, // CompletionRoutine
  3555. NULL); // Context
  3556. // Just return STATUS_SUCCESS at this point. If there is an error,
  3557. // USBSTOR_DataCompletion() will handle it, not the caller of
  3558. // USBSTOR_DataTransfer().
  3559. //
  3560. ntStatus = STATUS_SUCCESS;
  3561. }
  3562. DBGPRINT(3, ("exit: USBSTOR_DataTransfer %08X\n", ntStatus));
  3563. LOGENTRY('ibkd', DeviceObject, Irp, ntStatus);
  3564. return ntStatus;
  3565. }
  3566. //******************************************************************************
  3567. //
  3568. // USBSTOR_DataCompletion()
  3569. //
  3570. // Completion routine used by USBSTOR_DataTransfer
  3571. //
  3572. // This routine may run at DPC level.
  3573. //
  3574. // Basic idea:
  3575. //
  3576. // If a timeout reset occured, complete the request.
  3577. //
  3578. // Else if the Bulk USB transfer failed due to a STALL do not complete the
  3579. // request yet and start a pipe reset by calling USBSTOR_BulkQueueResetPipe().
  3580. //
  3581. // Else if the Bulk USB transfer failed due to some other reason, complete the
  3582. // request and start a reset by queuing USBSTOR_ResetDeviceWorkItem().
  3583. //
  3584. // Else if the Bulk USB transfer succeeded, start CSW transfer by calling
  3585. // USBSTOR_CswTransfer().
  3586. //
  3587. //******************************************************************************
  3588. NTSTATUS
  3589. USBSTOR_DataCompletion (
  3590. IN PDEVICE_OBJECT DeviceObject,
  3591. IN PIRP Irp,
  3592. IN PVOID NotUsed
  3593. )
  3594. {
  3595. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  3596. PDEVICE_OBJECT fdoDeviceObject;
  3597. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  3598. PIO_STACK_LOCATION irpStack;
  3599. PSCSI_REQUEST_BLOCK srb;
  3600. NTSTATUS ntStatus;
  3601. struct _URB_BULK_OR_INTERRUPT_TRANSFER *bulkUrb;
  3602. DBGPRINT(3, ("enter: USBSTOR_DataCompletion\n"));
  3603. LOGENTRY('BKDC', DeviceObject, Irp, Irp->IoStatus.Status);
  3604. pdoDeviceExtension = DeviceObject->DeviceExtension;
  3605. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  3606. fdoDeviceObject = pdoDeviceExtension->ParentFDO;
  3607. fdoDeviceExtension = fdoDeviceObject->DeviceExtension;
  3608. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  3609. // Get a pointer to the Bulk Transfer URB in our Device Extension
  3610. //
  3611. bulkUrb = &fdoDeviceExtension->Urb.BulkIntrUrb;
  3612. // Get our Irp parameters
  3613. //
  3614. irpStack = IoGetCurrentIrpStackLocation(Irp);
  3615. srb = irpStack->Parameters.Scsi.Srb;
  3616. if (srb == fdoDeviceExtension->OriginalSrb &&
  3617. bulkUrb->TransferBufferMDL != Irp->MdlAddress)
  3618. {
  3619. IoFreeMdl(bulkUrb->TransferBufferMDL);
  3620. }
  3621. // If a timeout reset occured, complete the request.
  3622. //
  3623. if (USBSTOR_CheckRequestTimeOut(fdoDeviceObject,
  3624. Irp,
  3625. srb,
  3626. &ntStatus))
  3627. {
  3628. LOGENTRY('bkd1', fdoDeviceObject, Irp, srb);
  3629. DBGPRINT(1, ("USBSTOR_DataCompletion: timeout completion\n"));
  3630. return ntStatus;
  3631. }
  3632. if (!NT_SUCCESS(Irp->IoStatus.Status))
  3633. {
  3634. // The Data Bulk Transfer was not successful. Look at how the
  3635. // the transfer failed to figure out how to recover.
  3636. //
  3637. LOGENTRY('bkd2', Irp->IoStatus.Status, bulkUrb->Hdr.Status, 0);
  3638. DBGPRINT(1, ("Data transfer failed %08X %08X\n",
  3639. Irp->IoStatus.Status, bulkUrb->Hdr.Status));
  3640. if (USBD_STATUS(bulkUrb->Hdr.Status) ==
  3641. USBD_STATUS(USBD_STATUS_STALL_PID))
  3642. {
  3643. // The device STALLed the Data Bulk Transfer
  3644. //
  3645. fdoDeviceExtension->BulkOnly.StallCount++;
  3646. // A STALL during the Data Bulk Transfer does not necessarily
  3647. // indicate an error. Accept the data that was actually
  3648. // transferred. If a STALL was seen it must have been seen
  3649. // before the requested amount of data was transferred.
  3650. //
  3651. ASSERT(bulkUrb->TransferBufferLength < srb->DataTransferLength);
  3652. srb->DataTransferLength = bulkUrb->TransferBufferLength;
  3653. srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
  3654. LOGENTRY('bkd3', fdoDeviceObject, Irp, srb);
  3655. // Queue a bulk pipe reset. After the bulk pipe reset
  3656. // completes, a CSW transfer will be started.
  3657. //
  3658. USBSTOR_BulkQueueResetPipe(fdoDeviceObject);
  3659. return STATUS_MORE_PROCESSING_REQUIRED;
  3660. }
  3661. else
  3662. {
  3663. LOGENTRY('bkd4', fdoDeviceObject, Irp, srb);
  3664. // Else some other strange error has occured. Maybe the device is
  3665. // unplugged, or maybe the device port was disabled, or maybe the
  3666. // request was cancelled.
  3667. //
  3668. // Complete this request now and then reset the device. The next
  3669. // request will be started when the reset completes.
  3670. //
  3671. srb = fdoDeviceExtension->OriginalSrb;
  3672. irpStack->Parameters.Scsi.Srb = srb;
  3673. ntStatus = STATUS_IO_DEVICE_ERROR;
  3674. Irp->IoStatus.Status = ntStatus;
  3675. Irp->IoStatus.Information = 0;
  3676. srb->SrbStatus = SRB_STATUS_BUS_RESET;
  3677. USBSTOR_TranslateCDBComplete(fdoDeviceObject, Irp, srb);
  3678. USBSTOR_QueueResetDevice(fdoDeviceObject);
  3679. DBGPRINT(1, ("USBSTOR_DataCompletion: xfer error completion\n"));
  3680. return ntStatus;
  3681. }
  3682. }
  3683. // Check for overrun
  3684. //
  3685. if (bulkUrb->TransferBufferLength < srb->DataTransferLength)
  3686. {
  3687. srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
  3688. }
  3689. else
  3690. {
  3691. srb->SrbStatus = SRB_STATUS_SUCCESS;
  3692. }
  3693. // Update the the Srb data transfer length based on the actual bulk
  3694. // transfer length.
  3695. //
  3696. srb->DataTransferLength = bulkUrb->TransferBufferLength;
  3697. // Client data Bulk Transfer successful completion. Start the CSW transfer.
  3698. //
  3699. LOGENTRY('bkd5', fdoDeviceObject, Irp, bulkUrb->TransferBufferLength);
  3700. ntStatus = USBSTOR_CswTransfer(fdoDeviceObject,
  3701. Irp);
  3702. ntStatus = STATUS_MORE_PROCESSING_REQUIRED;
  3703. DBGPRINT(3, ("exit: USBSTOR_DataCompletion %08X\n", ntStatus));
  3704. return ntStatus;
  3705. }
  3706. //******************************************************************************
  3707. //
  3708. // USBSTOR_CswTransfer()
  3709. //
  3710. // This routine is called by USBSTOR_CbwCompletion() and
  3711. // USBSTOR_DataCompletion()
  3712. //
  3713. // This routine may run at DPC level.
  3714. //
  3715. // Basic idea:
  3716. //
  3717. // Starts a USB transfer to read the CSW in the Bulk IN endpoint.
  3718. //
  3719. // Sets USBSTOR_CswCompletion() as the completion routine.
  3720. //
  3721. //******************************************************************************
  3722. NTSTATUS
  3723. USBSTOR_CswTransfer (
  3724. IN PDEVICE_OBJECT DeviceObject,
  3725. IN PIRP Irp
  3726. )
  3727. {
  3728. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  3729. PCSW csw;
  3730. USBD_PIPE_HANDLE pipeHandle;
  3731. ULONG transferFlags;
  3732. ULONG transferBufferLength;
  3733. NTSTATUS ntStatus;
  3734. DBGPRINT(3, ("enter: USBSTOR_CswTransfer\n"));
  3735. LOGENTRY('ICSW', DeviceObject, Irp, 0);
  3736. fdoDeviceExtension = DeviceObject->DeviceExtension;
  3737. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  3738. csw = &fdoDeviceExtension->BulkOnly.CbwCsw.Csw;
  3739. pipeHandle = fdoDeviceExtension->BulkInPipe->PipeHandle;
  3740. // Workaround for USB 2.0 controller Data Toggle / Babble bug
  3741. //
  3742. if (fdoDeviceExtension->BulkInPipe->MaximumPacketSize ==
  3743. sizeof(fdoDeviceExtension->BulkOnly.CbwCsw.MaxPacketSize))
  3744. {
  3745. transferFlags = USBD_SHORT_TRANSFER_OK;
  3746. transferBufferLength =
  3747. sizeof(fdoDeviceExtension->BulkOnly.CbwCsw.MaxPacketSize);
  3748. }
  3749. else
  3750. {
  3751. transferFlags = 0;
  3752. transferBufferLength = sizeof(CSW);
  3753. }
  3754. ntStatus = USBSTOR_IssueBulkOrInterruptRequest(
  3755. DeviceObject,
  3756. Irp,
  3757. pipeHandle, // PipeHandle
  3758. transferFlags, // TransferFlags
  3759. transferBufferLength, // TransferBufferLength
  3760. csw, // TransferBuffer
  3761. NULL, // TransferBufferMDL
  3762. USBSTOR_CswCompletion, // CompletionRoutine
  3763. NULL); // Context
  3764. DBGPRINT(3, ("exit: USBSTOR_CswTransfer %08X\n", ntStatus));
  3765. LOGENTRY('icsw', DeviceObject, Irp, ntStatus);
  3766. return ntStatus;
  3767. }
  3768. //******************************************************************************
  3769. //
  3770. // USBSTOR_CswCompletion()
  3771. //
  3772. // Completion routine used by USBSTOR_CswTransfer()
  3773. //
  3774. // This routine may run at DPC level.
  3775. //
  3776. // Basic idea:
  3777. //
  3778. // If a timeout reset occured, complete the request.
  3779. //
  3780. //******************************************************************************
  3781. NTSTATUS
  3782. USBSTOR_CswCompletion (
  3783. IN PDEVICE_OBJECT DeviceObject,
  3784. IN PIRP Irp,
  3785. IN PVOID NotUsed
  3786. )
  3787. {
  3788. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  3789. PDEVICE_OBJECT fdoDeviceObject;
  3790. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  3791. PIO_STACK_LOCATION irpStack;
  3792. PSCSI_REQUEST_BLOCK srb;
  3793. PCSW csw;
  3794. KIRQL irql;
  3795. NTSTATUS ntStatus;
  3796. struct _URB_BULK_OR_INTERRUPT_TRANSFER *bulkUrb;
  3797. DBGPRINT(3, ("enter: USBSTOR_CswCompletion\n"));
  3798. LOGENTRY('CSWC', DeviceObject, Irp, Irp->IoStatus.Status);
  3799. pdoDeviceExtension = DeviceObject->DeviceExtension;
  3800. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  3801. fdoDeviceObject = pdoDeviceExtension->ParentFDO;
  3802. fdoDeviceExtension = fdoDeviceObject->DeviceExtension;
  3803. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  3804. // Get a pointer to the Bulk Transfer URB in our Device Extension
  3805. //
  3806. bulkUrb = &fdoDeviceExtension->Urb.BulkIntrUrb;
  3807. // Get our Irp parameters
  3808. //
  3809. irpStack = IoGetCurrentIrpStackLocation(Irp);
  3810. srb = irpStack->Parameters.Scsi.Srb;
  3811. csw = &fdoDeviceExtension->BulkOnly.CbwCsw.Csw;
  3812. // If a timeout reset occured, complete the request.
  3813. //
  3814. if (USBSTOR_CheckRequestTimeOut(fdoDeviceObject,
  3815. Irp,
  3816. srb,
  3817. &ntStatus))
  3818. {
  3819. LOGENTRY('csw1', fdoDeviceObject, Irp, srb);
  3820. DBGPRINT(1, ("USBSTOR_CswCompletion: timeout completion\n"));
  3821. return ntStatus;
  3822. }
  3823. if (!NT_SUCCESS(Irp->IoStatus.Status))
  3824. {
  3825. // The Data Bulk Transfer was not successful. Look at how the
  3826. // the transfer failed to figure out how to recover.
  3827. //
  3828. LOGENTRY('csw2', Irp->IoStatus.Status, bulkUrb->Hdr.Status, 0);
  3829. DBGPRINT(1, ("CSW transfer failed %08X %08X\n",
  3830. Irp->IoStatus.Status, bulkUrb->Hdr.Status));
  3831. if (USBD_STATUS(bulkUrb->Hdr.Status) ==
  3832. USBD_STATUS(USBD_STATUS_STALL_PID) &&
  3833. fdoDeviceExtension->BulkOnly.StallCount < 2)
  3834. {
  3835. // The device STALLed the CSW Bulk Transfer
  3836. //
  3837. fdoDeviceExtension->BulkOnly.StallCount++;
  3838. LOGENTRY('csw3', fdoDeviceObject, Irp, srb);
  3839. // Queue a bulk pipe reset. After the bulk pipe reset
  3840. // completes, a CSW transfer will be started.
  3841. //
  3842. USBSTOR_BulkQueueResetPipe(fdoDeviceObject);
  3843. return STATUS_MORE_PROCESSING_REQUIRED;
  3844. }
  3845. else
  3846. {
  3847. LOGENTRY('csw4', fdoDeviceObject, Irp, srb);
  3848. // Else some other strange error has occured. Maybe the device is
  3849. // unplugged, or maybe the device port was disabled, or maybe the
  3850. // request was cancelled.
  3851. //
  3852. // Complete this request now and then reset the device. The next
  3853. // request will be started when the reset completes.
  3854. //
  3855. srb = fdoDeviceExtension->OriginalSrb;
  3856. irpStack->Parameters.Scsi.Srb = srb;
  3857. ntStatus = STATUS_IO_DEVICE_ERROR;
  3858. Irp->IoStatus.Status = ntStatus;
  3859. Irp->IoStatus.Information = 0;
  3860. srb->SrbStatus = SRB_STATUS_BUS_RESET;
  3861. USBSTOR_TranslateCDBComplete(fdoDeviceObject, Irp, srb);
  3862. USBSTOR_QueueResetDevice(fdoDeviceObject);
  3863. DBGPRINT(1, ("USBSTOR_DataCompletion: xfer error completion\n"));
  3864. return ntStatus;
  3865. }
  3866. }
  3867. if (csw->bCSWStatus == CSW_STATUS_GOOD)
  3868. {
  3869. // Complete this request now. Also start the next request now.
  3870. //
  3871. // SrbStatus should have been set in USBSTOR_DataCompletion()
  3872. //
  3873. ASSERT(srb->SrbStatus != SRB_STATUS_PENDING);
  3874. if (srb != fdoDeviceExtension->OriginalSrb)
  3875. {
  3876. // Update the original SRB with the length of the sense data that
  3877. // was actually returned.
  3878. //
  3879. fdoDeviceExtension->OriginalSrb->SenseInfoBufferLength =
  3880. (UCHAR)srb->DataTransferLength;
  3881. srb = fdoDeviceExtension->OriginalSrb;
  3882. irpStack->Parameters.Scsi.Srb = srb;
  3883. srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
  3884. }
  3885. ntStatus = STATUS_SUCCESS;
  3886. Irp->IoStatus.Status = ntStatus;
  3887. USBSTOR_TranslateCDBComplete(fdoDeviceObject, Irp, srb);
  3888. Irp->IoStatus.Information = srb->DataTransferLength;
  3889. LOGENTRY('csw5', fdoDeviceObject, Irp, srb);
  3890. KeRaiseIrql(DISPATCH_LEVEL, &irql);
  3891. {
  3892. IoStartNextPacket(fdoDeviceObject, TRUE);
  3893. }
  3894. KeLowerIrql(irql);
  3895. }
  3896. else if (csw->bCSWStatus == CSW_STATUS_FAILED &&
  3897. srb == fdoDeviceExtension->OriginalSrb)
  3898. {
  3899. LOGENTRY('csw6', fdoDeviceObject, Irp, srb);
  3900. srb->SrbStatus = SRB_STATUS_ERROR;
  3901. srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
  3902. srb->DataTransferLength = 0; // XXXXX Leave as set by bulk completion???
  3903. if (!(srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE) &&
  3904. (srb->SenseInfoBufferLength != 0) &&
  3905. (srb->SenseInfoBuffer != NULL))
  3906. {
  3907. // Start the Request Sense thing
  3908. //
  3909. ntStatus = USBSTOR_IssueRequestSense(fdoDeviceObject,
  3910. Irp);
  3911. ntStatus = STATUS_MORE_PROCESSING_REQUIRED;
  3912. }
  3913. else
  3914. {
  3915. ntStatus = STATUS_IO_DEVICE_ERROR; // XXXXX
  3916. Irp->IoStatus.Status = ntStatus; // XXXXX
  3917. Irp->IoStatus.Information = 0; // XXXXX
  3918. USBSTOR_TranslateCDBComplete(fdoDeviceObject, Irp, srb);
  3919. KeRaiseIrql(DISPATCH_LEVEL, &irql);
  3920. {
  3921. IoStartNextPacket(fdoDeviceObject, TRUE);
  3922. }
  3923. KeLowerIrql(irql);
  3924. }
  3925. }
  3926. else
  3927. {
  3928. LOGENTRY('csw7', fdoDeviceObject, Irp, srb);
  3929. // PHASE ERROR or Unknown Status
  3930. //
  3931. // Complete this request now and then reset the device. The next
  3932. // request will be started when the reset completes.
  3933. //
  3934. srb = fdoDeviceExtension->OriginalSrb;
  3935. irpStack->Parameters.Scsi.Srb = srb;
  3936. ntStatus = STATUS_IO_DEVICE_ERROR;
  3937. Irp->IoStatus.Status = ntStatus;
  3938. Irp->IoStatus.Information = 0;
  3939. srb->SrbStatus = SRB_STATUS_BUS_RESET;
  3940. USBSTOR_TranslateCDBComplete(fdoDeviceObject, Irp, srb);
  3941. USBSTOR_QueueResetDevice(fdoDeviceObject);
  3942. }
  3943. DBGPRINT(3, ("exit: USBSTOR_CswCompletion %08X\n", ntStatus));
  3944. return ntStatus;
  3945. }
  3946. //******************************************************************************
  3947. //
  3948. // USBSTOR_IssueRequestSense()
  3949. //
  3950. //******************************************************************************
  3951. NTSTATUS
  3952. USBSTOR_IssueRequestSense (
  3953. IN PDEVICE_OBJECT DeviceObject,
  3954. IN PIRP Irp
  3955. )
  3956. {
  3957. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  3958. PIO_STACK_LOCATION irpStack;
  3959. PSCSI_REQUEST_BLOCK srb;
  3960. NTSTATUS ntStatus;
  3961. DBGPRINT(3, ("enter: USBSTOR_IssueRequestSense\n"));
  3962. fdoDeviceExtension = DeviceObject->DeviceExtension;
  3963. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  3964. // Get the current Srb
  3965. //
  3966. irpStack = IoGetCurrentIrpStackLocation(Irp);
  3967. srb = irpStack->Parameters.Scsi.Srb;
  3968. // Get a pointer to the internal Srb.
  3969. //
  3970. srb = &fdoDeviceExtension->BulkOnly.InternalSrb;
  3971. irpStack->Parameters.Scsi.Srb = srb;
  3972. // Initialize SRB & CDB to all ZERO
  3973. //
  3974. RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
  3975. // Initialize SRB
  3976. //
  3977. srb->Length = sizeof(SCSI_REQUEST_BLOCK);
  3978. srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
  3979. srb->CdbLength = 12;
  3980. srb->SrbFlags = SRB_FLAGS_DATA_IN |
  3981. SRB_FLAGS_DISABLE_AUTOSENSE;
  3982. srb->DataTransferLength = fdoDeviceExtension->OriginalSrb->SenseInfoBufferLength;
  3983. srb->DataBuffer = fdoDeviceExtension->OriginalSrb->SenseInfoBuffer;
  3984. // Initialize CDB
  3985. //
  3986. srb->Cdb[0] = SCSIOP_REQUEST_SENSE;
  3987. srb->Cdb[4] = fdoDeviceExtension->OriginalSrb->SenseInfoBufferLength;
  3988. ntStatus = USBSTOR_CbwTransfer(DeviceObject,
  3989. Irp);
  3990. return ntStatus;
  3991. DBGPRINT(3, ("exit: USBSTOR_IssueRequestSense %08X\n", ntStatus));
  3992. }
  3993. //******************************************************************************
  3994. //
  3995. // USBSTOR_BulkQueueResetPipe()
  3996. //
  3997. // Called by USBSTOR_DataCompletion() and USBSTOR_CswCompletion() to clear the
  3998. // STALL on the bulk endpoints.
  3999. //
  4000. //******************************************************************************
  4001. VOID
  4002. USBSTOR_BulkQueueResetPipe (
  4003. IN PDEVICE_OBJECT DeviceObject
  4004. )
  4005. {
  4006. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  4007. LOGENTRY('QRSP', DeviceObject, 0, 0);
  4008. DBGFBRK(DBGF_BRK_RESETPIPE);
  4009. fdoDeviceExtension = DeviceObject->DeviceExtension;
  4010. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  4011. INCREMENT_PENDING_IO_COUNT(fdoDeviceExtension);
  4012. IoQueueWorkItem(fdoDeviceExtension->IoWorkItem,
  4013. USBSTOR_BulkResetPipeWorkItem,
  4014. CriticalWorkQueue,
  4015. NULL);
  4016. }
  4017. //******************************************************************************
  4018. //
  4019. // USBSTOR_BulkResetPipeWorkItem()
  4020. //
  4021. // WorkItem routine used by USBSTOR_BulkQueueResetPipe()
  4022. //
  4023. // This routine runs at PASSIVE level.
  4024. //
  4025. // Basic idea:
  4026. //
  4027. // Issue a Reset Pipe request to clear the Bulk endpoint STALL and reset
  4028. // the data toggle to Data0.
  4029. //
  4030. // Then start the CSW transfer.
  4031. //
  4032. //******************************************************************************
  4033. VOID
  4034. USBSTOR_BulkResetPipeWorkItem (
  4035. IN PDEVICE_OBJECT DeviceObject,
  4036. IN PVOID Context
  4037. )
  4038. {
  4039. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  4040. NTSTATUS ntStatus;
  4041. struct _URB_BULK_OR_INTERRUPT_TRANSFER *bulkUrb;
  4042. LOGENTRY('RSPW', DeviceObject, 0, 0);
  4043. DBGPRINT(2, ("enter: USBSTOR_BulkResetPipeWorkItem\n"));
  4044. fdoDeviceExtension = DeviceObject->DeviceExtension;
  4045. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  4046. // Get a pointer to the Bulk Transfer URB in our Device Extension.
  4047. // We'll pull the appropriate Bulk Endpoint pipe handle out of the URB.
  4048. //
  4049. // NOTE: This assumes that the URB in our Device Extension has
  4050. // not been touched since USBSTOR_DataCompletion() or
  4051. // USBSTOR_CswCompletion() called USBSTOR_BulkQueueResetPipe().
  4052. //
  4053. bulkUrb = &fdoDeviceExtension->Urb.BulkIntrUrb;
  4054. // Reset the Bulk Endpoint. This clears the endpoint halt on the
  4055. // host side, resets the host side data toggle to Data0, and issues
  4056. // the Clear_Feature Endpoint_Stall request to the device.
  4057. //
  4058. ntStatus = USBSTOR_ResetPipe((PDEVICE_OBJECT)DeviceObject,
  4059. bulkUrb->PipeHandle);
  4060. ntStatus = USBSTOR_CswTransfer(
  4061. (PDEVICE_OBJECT)DeviceObject,
  4062. ((PDEVICE_OBJECT)DeviceObject)->CurrentIrp);
  4063. DBGPRINT(2, ("exit: USBSTOR_BulkResetPipeWorkItem\n"));
  4064. DECREMENT_PENDING_IO_COUNT(fdoDeviceExtension);
  4065. }
  4066. //
  4067. // CBI / Bulk-Only Common Routines
  4068. //
  4069. //******************************************************************************
  4070. //
  4071. // USBSTOR_TimerTick()
  4072. //
  4073. // Called once per second at DISPATCH_LEVEL after the device has been started.
  4074. // Checks to see if there is an active Srb which has timed out, and if so,
  4075. // kicks off the reset recovery process.
  4076. //
  4077. //******************************************************************************
  4078. VOID
  4079. USBSTOR_TimerTick (
  4080. IN PDEVICE_OBJECT DeviceObject,
  4081. IN PVOID NotUsed
  4082. )
  4083. {
  4084. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  4085. BOOLEAN reset;
  4086. fdoDeviceExtension = DeviceObject->DeviceExtension;
  4087. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  4088. reset = FALSE;
  4089. KeAcquireSpinLockAtDpcLevel(&fdoDeviceExtension->ExtensionDataSpinLock);
  4090. {
  4091. if (!TEST_FLAG(fdoDeviceExtension->DeviceFlags, DF_RESET_IN_PROGRESS) &&
  4092. TEST_FLAG(fdoDeviceExtension->DeviceFlags, DF_SRB_IN_PROGRESS))
  4093. {
  4094. // There is no reset in progress and there is an Srb in progress.
  4095. // Decrement the timeout of the Srb. If it reaches zero, then we
  4096. // will reset the device.
  4097. //
  4098. if (--fdoDeviceExtension->SrbTimeout == 0)
  4099. {
  4100. SET_FLAG(fdoDeviceExtension->DeviceFlags, DF_RESET_IN_PROGRESS);
  4101. reset = TRUE;
  4102. }
  4103. }
  4104. }
  4105. KeReleaseSpinLockFromDpcLevel(&fdoDeviceExtension->ExtensionDataSpinLock);
  4106. if (reset)
  4107. {
  4108. LOGENTRY('TIMR', DeviceObject, 0, 0);
  4109. DBGPRINT(2, ("queuing USBSTOR_ResetDeviceWorkItem\n"));
  4110. // Queue WorkItem to reset the device
  4111. //
  4112. INCREMENT_PENDING_IO_COUNT(fdoDeviceExtension);
  4113. IoQueueWorkItem(fdoDeviceExtension->IoWorkItem,
  4114. USBSTOR_ResetDeviceWorkItem,
  4115. CriticalWorkQueue,
  4116. NULL);
  4117. }
  4118. }
  4119. //******************************************************************************
  4120. //
  4121. // USBSTOR_QueueResetDevice()
  4122. //
  4123. //******************************************************************************
  4124. VOID
  4125. USBSTOR_QueueResetDevice (
  4126. IN PDEVICE_OBJECT DeviceObject
  4127. )
  4128. {
  4129. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  4130. KIRQL irql;
  4131. LOGENTRY('QRSD', DeviceObject, 0, 0);
  4132. fdoDeviceExtension = DeviceObject->DeviceExtension;
  4133. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  4134. KeAcquireSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock, &irql);
  4135. {
  4136. SET_FLAG(fdoDeviceExtension->DeviceFlags, DF_RESET_IN_PROGRESS);
  4137. }
  4138. KeReleaseSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock, irql);
  4139. // Queue WorkItem to reset the device
  4140. //
  4141. INCREMENT_PENDING_IO_COUNT(fdoDeviceExtension);
  4142. IoQueueWorkItem(fdoDeviceExtension->IoWorkItem,
  4143. USBSTOR_ResetDeviceWorkItem,
  4144. CriticalWorkQueue,
  4145. NULL);
  4146. }
  4147. //******************************************************************************
  4148. //
  4149. // USBSTOR_ResetDeviceWorkItem()
  4150. //
  4151. // Work item which runs at PASSIVE_LEVEL in the context of a system thread.
  4152. // This routine first checks to see if the device is still attached, and if
  4153. // it is, the device is reset.
  4154. //
  4155. //******************************************************************************
  4156. VOID
  4157. USBSTOR_ResetDeviceWorkItem (
  4158. IN PDEVICE_OBJECT DeviceObject,
  4159. IN PVOID Context
  4160. )
  4161. {
  4162. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  4163. KIRQL irql;
  4164. ULONG retryCount;
  4165. NTSTATUS ntStatus;
  4166. LOGENTRY('RSDW', DeviceObject, 0, 0);
  4167. DBGFBRK(DBGF_BRK_RESET);
  4168. DBGPRINT(2, ("enter: USBSTOR_ResetDeviceWorkItem\n"));
  4169. fdoDeviceExtension = DeviceObject->DeviceExtension;
  4170. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  4171. // If the we timed out a request and it is still pending, cancel
  4172. // it and then wait for the cancel to finish, and then complete
  4173. // the request.
  4174. //
  4175. if (fdoDeviceExtension->PendingIrp)
  4176. {
  4177. LOGENTRY('rsd1', DeviceObject, fdoDeviceExtension->PendingIrp, 0);
  4178. IoCancelIrp(fdoDeviceExtension->PendingIrp);
  4179. LOGENTRY('rsd2', DeviceObject, fdoDeviceExtension->PendingIrp, 0);
  4180. KeWaitForSingleObject(&fdoDeviceExtension->CancelEvent,
  4181. Executive,
  4182. KernelMode,
  4183. FALSE,
  4184. NULL);
  4185. LOGENTRY('rsd3', DeviceObject, fdoDeviceExtension->PendingIrp, 0);
  4186. // Some storage drivers (e.g. CDROM.SYS) assume that requests complete
  4187. // at DISPATCH_LEVEL.
  4188. //
  4189. KeRaiseIrql(DISPATCH_LEVEL, &irql);
  4190. {
  4191. IoCompleteRequest(fdoDeviceExtension->PendingIrp, IO_NO_INCREMENT);
  4192. }
  4193. KeLowerIrql(irql);
  4194. fdoDeviceExtension->PendingIrp = NULL;
  4195. }
  4196. // Try the reset up to 3 times
  4197. //
  4198. for (retryCount = 0; retryCount < 3; retryCount++)
  4199. {
  4200. //
  4201. // First figure out if the device is still connected.
  4202. //
  4203. ntStatus = USBSTOR_IsDeviceConnected(DeviceObject);
  4204. if (!NT_SUCCESS(ntStatus))
  4205. {
  4206. // Give up if the device is no longer connected.
  4207. break;
  4208. }
  4209. //
  4210. // The device is still connected, now reset the device.
  4211. //
  4212. DBGPRINT(1, ("Reseting Device %d\n", retryCount));
  4213. ntStatus = USBSTOR_ResetDevice(DeviceObject);
  4214. if (NT_SUCCESS(ntStatus))
  4215. {
  4216. // Reset was successful!
  4217. break;
  4218. }
  4219. }
  4220. KeAcquireSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock, &irql);
  4221. {
  4222. CLEAR_FLAG(fdoDeviceExtension->DeviceFlags, DF_RESET_IN_PROGRESS);
  4223. // If the reset failed, then abandon all hope and mark the device as
  4224. // disconnected.
  4225. //
  4226. if (!NT_SUCCESS(ntStatus))
  4227. {
  4228. SET_FLAG(fdoDeviceExtension->DeviceFlags, DF_DEVICE_DISCONNECTED);
  4229. }
  4230. }
  4231. KeReleaseSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock, irql);
  4232. // A request has failed in a bad way or timed out if we are reseting the
  4233. // device. If the protocol was not specified then the default protocol
  4234. // was DeviceProtocolCB. Let's try DeviceProtocolBulkOnly now and see if
  4235. // we have any better luck. (Note that if a DeviceProtocolCB device fails
  4236. // the first request in a bad way then will we retry the first request as
  4237. // a DeviceProtocolBulkOnly device, which will then also fail and we will
  4238. // not recover from that situation).
  4239. //
  4240. if (fdoDeviceExtension->DriverFlags == DeviceProtocolUnspecified)
  4241. {
  4242. DBGPRINT(1, ("Setting Unspecified device to BulkOnly\n"));
  4243. fdoDeviceExtension->DriverFlags = DeviceProtocolBulkOnly;
  4244. }
  4245. KeRaiseIrql(DISPATCH_LEVEL, &irql);
  4246. {
  4247. IoStartNextPacket(DeviceObject, TRUE);
  4248. }
  4249. KeLowerIrql(irql);
  4250. DECREMENT_PENDING_IO_COUNT(fdoDeviceExtension);
  4251. DBGPRINT(2, ("exit: USBSTOR_ResetDeviceWorkItem %08X\n", ntStatus));
  4252. }
  4253. //******************************************************************************
  4254. //
  4255. // USBSTOR_IsDeviceConnected()
  4256. //
  4257. // This routine checks to see if the device is still attached.
  4258. //
  4259. // This routine runs at PASSIVE level.
  4260. //
  4261. //******************************************************************************
  4262. NTSTATUS
  4263. USBSTOR_IsDeviceConnected (
  4264. IN PDEVICE_OBJECT DeviceObject
  4265. )
  4266. {
  4267. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  4268. PIRP irp;
  4269. KEVENT localevent;
  4270. PIO_STACK_LOCATION nextStack;
  4271. ULONG portStatus;
  4272. NTSTATUS ntStatus;
  4273. DBGPRINT(1, ("enter: USBSTOR_IsDeviceConnected\n"));
  4274. fdoDeviceExtension = DeviceObject->DeviceExtension;
  4275. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  4276. // Allocate the Irp
  4277. //
  4278. irp = IoAllocateIrp((CCHAR)(fdoDeviceExtension->StackDeviceObject->StackSize),
  4279. FALSE);
  4280. if (irp == NULL)
  4281. {
  4282. return STATUS_INSUFFICIENT_RESOURCES;
  4283. }
  4284. // Initialize the event we'll wait on.
  4285. //
  4286. KeInitializeEvent(&localevent,
  4287. SynchronizationEvent,
  4288. FALSE);
  4289. // Set the Irp parameters
  4290. //
  4291. nextStack = IoGetNextIrpStackLocation(irp);
  4292. nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  4293. nextStack->Parameters.DeviceIoControl.IoControlCode =
  4294. IOCTL_INTERNAL_USB_GET_PORT_STATUS;
  4295. nextStack->Parameters.Others.Argument1 = &portStatus;
  4296. // Set the completion routine, which will signal the event
  4297. //
  4298. IoSetCompletionRoutineEx(DeviceObject,
  4299. irp,
  4300. USBSTOR_SyncCompletionRoutine,
  4301. &localevent,
  4302. TRUE, // InvokeOnSuccess
  4303. TRUE, // InvokeOnError
  4304. TRUE); // InvokeOnCancel
  4305. // Pass the Irp down the stack
  4306. //
  4307. ntStatus = IoCallDriver(fdoDeviceExtension->StackDeviceObject,
  4308. irp);
  4309. // If the request is pending, block until it completes
  4310. //
  4311. if (ntStatus == STATUS_PENDING)
  4312. {
  4313. KeWaitForSingleObject(&localevent,
  4314. Executive,
  4315. KernelMode,
  4316. FALSE,
  4317. NULL);
  4318. ntStatus = irp->IoStatus.Status;
  4319. }
  4320. IoFreeIrp(irp);
  4321. if (NT_SUCCESS(ntStatus) && !(portStatus & USBD_PORT_CONNECTED))
  4322. {
  4323. ntStatus = STATUS_DEVICE_DOES_NOT_EXIST;
  4324. }
  4325. DBGPRINT(1, ("exit: USBSTOR_IsDeviceConnected %08X\n", ntStatus));
  4326. return ntStatus;
  4327. }
  4328. //******************************************************************************
  4329. //
  4330. // USBSTOR_ResetDevice()
  4331. //
  4332. // This routine resets the device (actually it resets the port to which the
  4333. // device is attached).
  4334. //
  4335. // This routine runs at PASSIVE level.
  4336. //
  4337. //******************************************************************************
  4338. NTSTATUS
  4339. USBSTOR_ResetDevice (
  4340. IN PDEVICE_OBJECT DeviceObject
  4341. )
  4342. {
  4343. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  4344. PIRP irp;
  4345. KEVENT localevent;
  4346. PIO_STACK_LOCATION nextStack;
  4347. ULONG portStatus;
  4348. NTSTATUS ntStatus;
  4349. DBGPRINT(1, ("enter: USBSTOR_ResetDevice\n"));
  4350. fdoDeviceExtension = DeviceObject->DeviceExtension;
  4351. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  4352. // Allocate the Irp
  4353. //
  4354. irp = IoAllocateIrp((CCHAR)(fdoDeviceExtension->StackDeviceObject->StackSize),
  4355. FALSE);
  4356. if (irp == NULL)
  4357. {
  4358. return STATUS_INSUFFICIENT_RESOURCES;
  4359. }
  4360. // Initialize the event we'll wait on.
  4361. //
  4362. KeInitializeEvent(&localevent,
  4363. SynchronizationEvent,
  4364. FALSE);
  4365. // Set the Irp parameters
  4366. //
  4367. nextStack = IoGetNextIrpStackLocation(irp);
  4368. nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  4369. nextStack->Parameters.DeviceIoControl.IoControlCode =
  4370. IOCTL_INTERNAL_USB_RESET_PORT;
  4371. // Set the completion routine, which will signal the event
  4372. //
  4373. IoSetCompletionRoutineEx(DeviceObject,
  4374. irp,
  4375. USBSTOR_SyncCompletionRoutine,
  4376. &localevent,
  4377. TRUE, // InvokeOnSuccess
  4378. TRUE, // InvokeOnError
  4379. TRUE); // InvokeOnCancel
  4380. // Pass the Irp & Urb down the stack
  4381. //
  4382. ntStatus = IoCallDriver(fdoDeviceExtension->StackDeviceObject,
  4383. irp);
  4384. // If the request is pending, block until it completes
  4385. //
  4386. if (ntStatus == STATUS_PENDING)
  4387. {
  4388. KeWaitForSingleObject(&localevent,
  4389. Executive,
  4390. KernelMode,
  4391. FALSE,
  4392. NULL);
  4393. ntStatus = irp->IoStatus.Status;
  4394. }
  4395. IoFreeIrp(irp);
  4396. DBGPRINT(1, ("exit: USBSTOR_ResetDevice %08X\n", ntStatus));
  4397. return ntStatus;
  4398. }
  4399. //******************************************************************************
  4400. //
  4401. // USBSTOR_IssueInternalCdb()
  4402. //
  4403. //******************************************************************************
  4404. NTSTATUS
  4405. USBSTOR_IssueInternalCdb (
  4406. PDEVICE_OBJECT DeviceObject,
  4407. PVOID DataBuffer,
  4408. PULONG DataTransferLength,
  4409. PCDB Cdb,
  4410. UCHAR CdbLength,
  4411. ULONG TimeOutValue
  4412. )
  4413. {
  4414. PIRP irp;
  4415. PIO_STACK_LOCATION nextStack;
  4416. PSCSI_REQUEST_BLOCK srb;
  4417. PSENSE_DATA senseInfoBuffer;
  4418. PMDL mdl;
  4419. ULONG retryCount;
  4420. KEVENT localevent;
  4421. NTSTATUS ntStatus;
  4422. PAGED_CODE();
  4423. DBGPRINT(2, ("enter: USBSTOR_IssueInternalCdb\n"));
  4424. // Initialize these so we can bail early if an allocation fails
  4425. //
  4426. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  4427. irp = NULL;
  4428. srb = NULL;
  4429. senseInfoBuffer = NULL;
  4430. mdl = NULL;
  4431. // Allocate the Srb
  4432. //
  4433. srb = ExAllocatePoolWithTag(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK),
  4434. POOL_TAG);
  4435. if (srb == NULL)
  4436. {
  4437. goto USBSTOR_GetInquiryData_Exit;
  4438. }
  4439. // Allocate the sense buffer
  4440. //
  4441. senseInfoBuffer = ExAllocatePoolWithTag(NonPagedPool, SENSE_BUFFER_SIZE,
  4442. POOL_TAG);
  4443. if (senseInfoBuffer == NULL)
  4444. {
  4445. goto USBSTOR_GetInquiryData_Exit;
  4446. }
  4447. // Try the request up to 3 times
  4448. //
  4449. for (retryCount = 0; retryCount < 3; retryCount++)
  4450. {
  4451. // Allocate an Irp including a stack location for a completion routine
  4452. //
  4453. irp = IoAllocateIrp((CCHAR)(DeviceObject->StackSize), FALSE);
  4454. if (irp == NULL)
  4455. {
  4456. break;
  4457. }
  4458. nextStack = IoGetNextIrpStackLocation(irp);
  4459. nextStack->MajorFunction = IRP_MJ_SCSI;
  4460. nextStack->Parameters.Scsi.Srb = srb;
  4461. // (Re)Initialize the Srb
  4462. //
  4463. RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK)); // SRB & CDB all ZERO
  4464. srb->Length = sizeof(SCSI_REQUEST_BLOCK);
  4465. srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
  4466. srb->CdbLength = CdbLength;
  4467. srb->SrbFlags = SRB_FLAGS_DATA_IN;
  4468. srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
  4469. srb->SenseInfoBuffer = senseInfoBuffer;
  4470. srb->DataTransferLength = *DataTransferLength;
  4471. srb->DataBuffer = DataBuffer;
  4472. srb->TimeOutValue = TimeOutValue;
  4473. // (Re)Initialize the Cdb
  4474. //
  4475. RtlCopyMemory(srb->Cdb, Cdb, CdbLength);
  4476. // Initialize the MDL (first time only)
  4477. //
  4478. if (retryCount == 0)
  4479. {
  4480. mdl = IoAllocateMdl(DataBuffer,
  4481. *DataTransferLength,
  4482. FALSE,
  4483. FALSE,
  4484. NULL);
  4485. if (!mdl)
  4486. {
  4487. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  4488. goto USBSTOR_GetInquiryData_Exit;
  4489. }
  4490. MmBuildMdlForNonPagedPool(mdl);
  4491. }
  4492. irp->MdlAddress = mdl;
  4493. // Initialize the event we'll wait on
  4494. //
  4495. KeInitializeEvent(&localevent,
  4496. SynchronizationEvent,
  4497. FALSE);
  4498. // Set the completion routine, which will signal the event
  4499. //
  4500. IoSetCompletionRoutine(irp,
  4501. USBSTOR_SyncCompletionRoutine,
  4502. &localevent,
  4503. TRUE, // InvokeOnSuccess
  4504. TRUE, // InvokeOnError
  4505. TRUE); // InvokeOnCancel
  4506. // Pass the Irp & Srb down the stack
  4507. //
  4508. ntStatus = IoCallDriver(DeviceObject, irp);
  4509. // If the request is pending, block until it completes
  4510. //
  4511. if (ntStatus == STATUS_PENDING)
  4512. {
  4513. KeWaitForSingleObject(&localevent,
  4514. Executive,
  4515. KernelMode,
  4516. FALSE,
  4517. NULL);
  4518. // Get final completion status
  4519. //
  4520. ntStatus = irp->IoStatus.Status;
  4521. }
  4522. DBGPRINT(2, ("USBSTOR_IssueInternalCdb %d %08X %08X\n",
  4523. retryCount, ntStatus, srb->SrbStatus));
  4524. if ((SRB_STATUS(srb->SrbStatus) == SRB_STATUS_SUCCESS) ||
  4525. (SRB_STATUS(srb->SrbStatus) == SRB_STATUS_DATA_OVERRUN))
  4526. {
  4527. ntStatus = STATUS_SUCCESS;
  4528. *DataTransferLength = srb->DataTransferLength;
  4529. break;
  4530. }
  4531. else
  4532. {
  4533. ntStatus = STATUS_UNSUCCESSFUL;
  4534. }
  4535. // Free the Irp. A new one will be allocated the next time around.
  4536. //
  4537. IoFreeIrp(irp);
  4538. irp = NULL;
  4539. }
  4540. USBSTOR_GetInquiryData_Exit:
  4541. if (mdl != NULL)
  4542. {
  4543. IoFreeMdl(mdl);
  4544. }
  4545. if (senseInfoBuffer != NULL)
  4546. {
  4547. ExFreePool(senseInfoBuffer);
  4548. }
  4549. if (srb != NULL)
  4550. {
  4551. ExFreePool(srb);
  4552. }
  4553. if (irp != NULL)
  4554. {
  4555. IoFreeIrp(irp);
  4556. }
  4557. DBGPRINT(2, ("exit: USBSTOR_IssueInternalCdb %08X\n", ntStatus));
  4558. return ntStatus;
  4559. }
  4560. //******************************************************************************
  4561. //
  4562. // USBSTOR_GetInquiryData()
  4563. //
  4564. //******************************************************************************
  4565. NTSTATUS
  4566. USBSTOR_GetInquiryData (
  4567. PDEVICE_OBJECT DeviceObject
  4568. )
  4569. {
  4570. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  4571. PDEVICE_OBJECT fdoDeviceObject;
  4572. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  4573. PVOID dataBuffer;
  4574. ULONG dataTransferLength;
  4575. CDB cdb;
  4576. NTSTATUS ntStatus;
  4577. PAGED_CODE();
  4578. DBGPRINT(2, ("enter: USBSTOR_GetInquiryData\n"));
  4579. pdoDeviceExtension = DeviceObject->DeviceExtension;
  4580. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  4581. fdoDeviceObject = pdoDeviceExtension->ParentFDO;
  4582. fdoDeviceExtension = fdoDeviceObject->DeviceExtension;
  4583. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  4584. dataBuffer = pdoDeviceExtension->InquiryDataBuffer;
  4585. dataTransferLength = sizeof(pdoDeviceExtension->InquiryDataBuffer);
  4586. RtlZeroMemory(&cdb, sizeof(CDB));
  4587. cdb.CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
  4588. cdb.CDB6INQUIRY.AllocationLength = (UCHAR)dataTransferLength;
  4589. ntStatus = USBSTOR_IssueInternalCdb(DeviceObject,
  4590. dataBuffer,
  4591. &dataTransferLength,
  4592. &cdb,
  4593. sizeof(cdb.CDB6INQUIRY),
  4594. 20);
  4595. if (NT_SUCCESS(ntStatus) &&
  4596. fdoDeviceExtension->DriverFlags == DeviceProtocolUnspecified)
  4597. {
  4598. // The Inquiry request is the first request we send to the device. If
  4599. // the first request was successful and the protocol was not specified,
  4600. // set it to the default protocol, which is DeviceProtocolCB.
  4601. //
  4602. DBGPRINT(1, ("Setting Unspecified device to CB\n"));
  4603. fdoDeviceExtension->DriverFlags = DeviceProtocolCB;
  4604. }
  4605. DBGPRINT(2, ("exit: USBSTOR_GetInquiryData %08X\n", ntStatus));
  4606. return ntStatus;
  4607. }
  4608. //******************************************************************************
  4609. //
  4610. // USBSTOR_IsFloppyDevice()
  4611. //
  4612. // This routine issues a SCSIOP_READ_FORMATTED_CAPACITY request and looks
  4613. // at the returned Format Capacity Descriptor list to see if the device
  4614. // supports any of the known floppy capacities. If the device does support
  4615. // a known floppy capacity, it is assumed that the device is a floppy.
  4616. //
  4617. //******************************************************************************
  4618. typedef struct _FORMATTED_CAPACITY
  4619. {
  4620. ULONG NumberOfBlocks;
  4621. ULONG BlockLength;
  4622. } FORMATTED_CAPACITY, *PFORMATTED_CAPACITY;
  4623. FORMATTED_CAPACITY FloppyCapacities[] =
  4624. {
  4625. // Blocks BlockLen H T B/S S/T
  4626. {0x00000500, 0x000200}, // 2 80 512 8 640 KB F5_640_512
  4627. {0x000005A0, 0x000200}, // 2 80 512 9 720 KB F3_720_512
  4628. {0x00000960, 0x000200}, // 2 80 512 15 1.20 MB F3_1Pt2_512 (Toshiba)
  4629. {0x000004D0, 0x000400}, // 2 77 1024 8 1.23 MB F3_1Pt23_1024 (NEC)
  4630. {0x00000B40, 0x000200}, // 2 80 512 18 1.44 MB F3_1Pt44_512
  4631. {0x0003C300, 0x000200}, // 8 963 512 32 120 MB F3_120M_512
  4632. {0x000600A4, 0x000200} //13 890 512 34 200 MB HiFD
  4633. };
  4634. #define FLOPPY_CAPACITIES (sizeof(FloppyCapacities)/sizeof(FloppyCapacities[0]))
  4635. BOOLEAN
  4636. USBSTOR_IsFloppyDevice (
  4637. PDEVICE_OBJECT DeviceObject
  4638. )
  4639. {
  4640. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  4641. BOOLEAN isFloppy;
  4642. struct _READ_FORMATTED_CAPACITIES cdb;
  4643. PFORMATTED_CAPACITY_LIST capList;
  4644. PVOID dataBuffer;
  4645. ULONG dataTransferLength;
  4646. NTSTATUS ntStatus;
  4647. PAGED_CODE();
  4648. DBGPRINT(1, ("enter: USBSTOR_IsFloppyDevice\n"));
  4649. pdoDeviceExtension = DeviceObject->DeviceExtension;
  4650. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  4651. isFloppy = FALSE;
  4652. // Allocate a transfer buffer for the SCSIOP_READ_FORMATTED_CAPACITY request
  4653. // The length of the returned descriptor array is limited to a byte field
  4654. // in the capacity list header.
  4655. //
  4656. dataTransferLength = sizeof(FORMATTED_CAPACITY_LIST) +
  4657. 31 * sizeof(FORMATTED_CAPACITY_DESCRIPTOR);
  4658. ASSERT(dataTransferLength < 0x100);
  4659. dataBuffer = ExAllocatePoolWithTag(NonPagedPool,
  4660. dataTransferLength,
  4661. POOL_TAG);
  4662. if (dataBuffer)
  4663. {
  4664. RtlZeroMemory(dataBuffer, dataTransferLength);
  4665. RtlZeroMemory(&cdb, sizeof(cdb));
  4666. cdb.OperationCode = SCSIOP_READ_FORMATTED_CAPACITY;
  4667. cdb.AllocationLength[1] = (UCHAR)dataTransferLength;
  4668. capList = (PFORMATTED_CAPACITY_LIST)dataBuffer;
  4669. ntStatus = USBSTOR_IssueInternalCdb(DeviceObject,
  4670. dataBuffer,
  4671. &dataTransferLength,
  4672. (PCDB)&cdb,
  4673. sizeof(cdb),
  4674. 20);
  4675. DBGPRINT(1, ("%08X %08X %02X\n",
  4676. ntStatus, dataTransferLength, capList->CapacityListLength));
  4677. if (NT_SUCCESS(ntStatus) &&
  4678. dataTransferLength >= sizeof(FORMATTED_CAPACITY_LIST) &&
  4679. capList->CapacityListLength &&
  4680. capList->CapacityListLength % sizeof(FORMATTED_CAPACITY_DESCRIPTOR) == 0)
  4681. {
  4682. ULONG NumberOfBlocks;
  4683. ULONG BlockLength;
  4684. ULONG i, j, count;
  4685. // Subtract the size of the Capacity List Header to get
  4686. // just the size of the Capacity List Descriptor array.
  4687. //
  4688. dataTransferLength -= sizeof(FORMATTED_CAPACITY_LIST);
  4689. // Only look at the Capacity List Descriptors that were
  4690. // actually returned.
  4691. //
  4692. if (dataTransferLength < capList->CapacityListLength)
  4693. {
  4694. count = dataTransferLength /
  4695. sizeof(FORMATTED_CAPACITY_DESCRIPTOR);
  4696. }
  4697. else
  4698. {
  4699. count = capList->CapacityListLength /
  4700. sizeof(FORMATTED_CAPACITY_DESCRIPTOR);
  4701. }
  4702. for (i=0; i<count; i++)
  4703. {
  4704. NumberOfBlocks = (capList->Descriptors[i].NumberOfBlocks[0] << 24) +
  4705. (capList->Descriptors[i].NumberOfBlocks[1] << 16) +
  4706. (capList->Descriptors[i].NumberOfBlocks[2] << 8) +
  4707. capList->Descriptors[i].NumberOfBlocks[3];
  4708. BlockLength = (capList->Descriptors[i].BlockLength[0] << 16) +
  4709. (capList->Descriptors[i].BlockLength[1] << 8) +
  4710. capList->Descriptors[i].BlockLength[2];
  4711. DBGPRINT(1, ("Capacity[%d] %08X %06X %d%d\n",
  4712. i,
  4713. NumberOfBlocks,
  4714. BlockLength,
  4715. capList->Descriptors[i].Valid,
  4716. capList->Descriptors[i].Maximum));
  4717. for (j=0; j<FLOPPY_CAPACITIES; j++)
  4718. {
  4719. if (NumberOfBlocks == FloppyCapacities[j].NumberOfBlocks &&
  4720. BlockLength == FloppyCapacities[j].BlockLength)
  4721. {
  4722. isFloppy = TRUE;
  4723. }
  4724. }
  4725. }
  4726. }
  4727. ExFreePool(dataBuffer);
  4728. }
  4729. DBGPRINT(1, ("exit: USBSTOR_IsFloppyDevice %d\n", isFloppy));
  4730. return isFloppy;
  4731. }