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

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