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

1430 lines
34 KiB

  1. /*++
  2. Copyright (C) 1992-9 Microsoft Corporation
  3. Module Name:
  4. print.c
  5. Abstract:
  6. The printer class driver tranlates IRPs to SRBs with embedded CDBs
  7. and sends them to its devices through the port driver.
  8. Author:
  9. Mike Glass (mglass)
  10. Environment:
  11. kernel mode only
  12. Notes:
  13. Revision History:
  14. georgioc - Made into a pnp class driver independent of the underlying storage bus
  15. using the new storage/classpnp
  16. dankn, 22-Jul-99 : Added ability to block & resubmit failed writes for
  17. 1394 printers to behave more like other print stacks
  18. (i.e. USB) and therefore keep USBMON.DLL (the Win2k
  19. port monitor) happy. USBMON does not deal well
  20. with failed writes.
  21. --*/
  22. #include "printpnp.h"
  23. #include "ntddser.h"
  24. NTSTATUS
  25. PrinterOpenClose(
  26. IN PDEVICE_OBJECT Fdo,
  27. IN PIRP Irp
  28. )
  29. /*++
  30. Routine Description:
  31. This routine is called to establish a connection to the printer
  32. class driver. It does no more than return STATUS_SUCCESS.
  33. Arguments:
  34. DeviceObject - Device object for a printer.
  35. Irp - Open or Close request packet
  36. Return Value:
  37. NT Status - STATUS_SUCCESS
  38. --*/
  39. {
  40. PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
  41. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  42. //
  43. // Set status in Irp.
  44. //
  45. Irp->IoStatus.Status = STATUS_SUCCESS;
  46. //
  47. // forward irp.
  48. //
  49. ClassReleaseRemoveLock (Fdo, Irp);
  50. IoCopyCurrentIrpStackLocationToNext(Irp);
  51. return IoCallDriver(fdoExtension->CommonExtension.LowerDeviceObject, Irp);
  52. } // end PrinterOpenClose()
  53. NTSTATUS
  54. BuildPrintRequest(
  55. PDEVICE_OBJECT Fdo,
  56. PIRP Irp
  57. )
  58. /*++
  59. Routine Description:
  60. Build SRB and CDB requests to scsi printer.
  61. Arguments:
  62. DeviceObject - Device object representing this printer device.
  63. Irp - System IO request packet.
  64. Return Value:
  65. None.
  66. --*/
  67. {
  68. PFUNCTIONAL_DEVICE_EXTENSION deviceExtension = Fdo->DeviceExtension;
  69. PIO_COMPLETION_ROUTINE completionRoutine;
  70. PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
  71. PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
  72. PSCSI_REQUEST_BLOCK srb;
  73. PCDB cdb;
  74. ULONG transferLength;
  75. //
  76. // Allocate Srb from nonpaged pool.
  77. // This call must succeed.
  78. //
  79. srb = ExAllocatePool(NonPagedPool, SCSI_REQUEST_BLOCK_SIZE);
  80. if (srb == NULL) {
  81. return STATUS_INSUFFICIENT_RESOURCES;
  82. }
  83. srb->SrbFlags = 0;
  84. //
  85. // Write length to SRB.
  86. //
  87. srb->Length = SCSI_REQUEST_BLOCK_SIZE;
  88. //
  89. // Set up IRP Address.
  90. //
  91. srb->OriginalRequest = Irp;
  92. //
  93. // Set up target id and logical unit number.
  94. //
  95. srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
  96. srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
  97. //
  98. // Save byte count of transfer in SRB Extension.
  99. //
  100. srb->DataTransferLength = currentIrpStack->Parameters.Write.Length;
  101. //
  102. // Transfer length should never be greater than MAX_PRINT_XFER
  103. //
  104. ASSERT(srb->DataTransferLength <= MAX_PRINT_XFER);
  105. //
  106. // Initialize the queue actions field.
  107. //
  108. srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
  109. //
  110. // Queue sort key is not used.
  111. //
  112. srb->QueueSortKey = 0;
  113. //
  114. // Indicate auto request sense by specifying buffer and size.
  115. //
  116. srb->SenseInfoBuffer = deviceExtension->SenseData;
  117. srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
  118. //
  119. // Set timeout value in seconds.
  120. //
  121. srb->TimeOutValue = deviceExtension->TimeOutValue;
  122. //
  123. // Zero statuses.
  124. //
  125. srb->SrbStatus = srb->ScsiStatus = 0;
  126. srb->NextSrb = 0;
  127. //
  128. // Get number of bytes to transfer.
  129. //
  130. transferLength = currentIrpStack->Parameters.Write.Length;
  131. //
  132. // Get pointer to CDB in SRB.
  133. //
  134. cdb = (PCDB) srb->Cdb;
  135. //
  136. // Init 10-byte READ CDB's for reads (per scanner device READ spec
  137. // in SCSI-2), and 6-byte PRINT CDB's for writes
  138. //
  139. if (currentIrpStack->MajorFunction == IRP_MJ_READ) {
  140. srb->CdbLength = 10;
  141. srb->SrbFlags = SRB_FLAGS_DATA_IN;
  142. RtlZeroMemory (cdb, 10);
  143. cdb->CDB10.OperationCode = SCSIOP_READ;
  144. //
  145. // Move little endian values into CDB in big endian format.
  146. //
  147. cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE) &transferLength)->Byte0;
  148. cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE) &transferLength)->Byte1;
  149. cdb->CDB10.Reserved2 = ((PFOUR_BYTE) &transferLength)->Byte2;
  150. //
  151. // For read's we always use the ClassIoComplete completion routine
  152. //
  153. completionRoutine = ClassIoComplete;
  154. } else {
  155. srb->CdbLength = 6;
  156. srb->SrbFlags = SRB_FLAGS_DATA_OUT;
  157. cdb->PRINT.OperationCode = SCSIOP_PRINT;
  158. cdb->PRINT.Reserved = 0;
  159. cdb->PRINT.LogicalUnitNumber = 0;
  160. //
  161. // Move little endian values into CDB in big endian format.
  162. //
  163. cdb->PRINT.TransferLength[2] = ((PFOUR_BYTE) &transferLength)->Byte0;
  164. cdb->PRINT.TransferLength[1] = ((PFOUR_BYTE) &transferLength)->Byte1;
  165. cdb->PRINT.TransferLength[0] = ((PFOUR_BYTE) &transferLength)->Byte2;
  166. cdb->PRINT.Control = 0;
  167. //
  168. // Set the appropriate write/print completion routine
  169. //
  170. completionRoutine = ((PPRINTER_DATA) deviceExtension->
  171. CommonExtension.DriverData)->WriteCompletionRoutine;
  172. }
  173. //
  174. // Or in the default flags from the device object.
  175. //
  176. srb->SrbFlags |= deviceExtension->SrbFlags;
  177. //
  178. // Set up major SCSI function.
  179. //
  180. nextIrpStack->MajorFunction = IRP_MJ_SCSI;
  181. //
  182. // Save SRB address in next stack for port driver.
  183. //
  184. nextIrpStack->Parameters.Scsi.Srb = srb;
  185. //
  186. // Save retry count in current IRP stack.
  187. //
  188. currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
  189. //
  190. // Set up IoCompletion routine address.
  191. //
  192. IoSetCompletionRoutine(Irp, completionRoutine, srb, TRUE, TRUE, TRUE);
  193. return STATUS_SUCCESS;
  194. } // end BuildPrintRequest()
  195. NTSTATUS
  196. PrinterReadWrite(
  197. IN PDEVICE_OBJECT Fdo,
  198. IN PIRP Irp
  199. )
  200. /*++
  201. Routine Description:
  202. This is the entry called by the I/O system for print requests.
  203. It builds the SRB and sends it to the port driver.
  204. Arguments:
  205. DeviceObject - the system object for the device.
  206. Irp - IRP involved.
  207. Return Value:
  208. NT Status
  209. --*/
  210. {
  211. PFUNCTIONAL_DEVICE_EXTENSION deviceExtension = Fdo->DeviceExtension;
  212. PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
  213. ULONG transferByteCount = currentIrpStack->Parameters.Write.Length;
  214. ULONG maximumTransferLength;
  215. ULONG transferPages;
  216. NTSTATUS Status;
  217. DEBUGPRINT3(("PrinterReadWrite: Enter routine\n"));
  218. if (deviceExtension->AdapterDescriptor == NULL) {
  219. //
  220. // device removed..
  221. //
  222. DEBUGPRINT3(("PrinterReadWrite: Device removed(!!)\n"));
  223. Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
  224. Irp->IoStatus.Information = 0;
  225. return STATUS_DEVICE_DOES_NOT_EXIST;
  226. }
  227. maximumTransferLength = deviceExtension->AdapterDescriptor->MaximumTransferLength;
  228. //
  229. // Calculate number of pages in this transfer.
  230. //
  231. transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(
  232. MmGetMdlVirtualAddress(Irp->MdlAddress),
  233. currentIrpStack->Parameters.Write.Length);
  234. //
  235. // Check if hardware maximum transfer length is larger than SCSI
  236. // print command can handle. If so, lower the maximum allowed to
  237. // the SCSI print maximum.
  238. //
  239. if (maximumTransferLength > MAX_PRINT_XFER)
  240. maximumTransferLength = MAX_PRINT_XFER;
  241. //
  242. // Check if request length is greater than the maximum number of
  243. // bytes that the hardware can transfer.
  244. //
  245. if (currentIrpStack->Parameters.Write.Length > maximumTransferLength ||
  246. transferPages > deviceExtension->AdapterDescriptor->MaximumPhysicalPages) {
  247. transferPages =
  248. deviceExtension->AdapterDescriptor->MaximumPhysicalPages - 1;
  249. if (maximumTransferLength > transferPages << PAGE_SHIFT ) {
  250. maximumTransferLength = transferPages << PAGE_SHIFT;
  251. }
  252. //
  253. // Check that maximum transfer size is not zero.
  254. //
  255. if (maximumTransferLength == 0) {
  256. maximumTransferLength = PAGE_SIZE;
  257. }
  258. //
  259. // Mark IRP with status pending.
  260. //
  261. IoMarkIrpPending(Irp);
  262. //
  263. // Request greater than port driver maximum.
  264. // Break up into smaller routines.
  265. //
  266. SplitRequest(Fdo,
  267. Irp,
  268. maximumTransferLength);
  269. return STATUS_PENDING;
  270. }
  271. //
  272. // Build SRB and CDB for this IRP.
  273. //
  274. Status = BuildPrintRequest(Fdo, Irp);
  275. if (!NT_SUCCESS (Status)) {
  276. return Status;
  277. }
  278. //
  279. // Return the results of the call to the port driver.
  280. //
  281. return IoCallDriver(deviceExtension->CommonExtension.LowerDeviceObject, Irp);
  282. } // end ScsiPrinterWrite()
  283. NTSTATUS
  284. PrinterDeviceControl(
  285. IN PDEVICE_OBJECT Fdo,
  286. IN PIRP Irp
  287. )
  288. /*++
  289. Routine Description:
  290. This is the NT device control handler for Printers.
  291. Arguments:
  292. DeviceObject - for this Printer
  293. Irp - IO Request packet
  294. Return Value:
  295. NTSTATUS
  296. --*/
  297. {
  298. PVOID buffer = Irp->AssociatedIrp.SystemBuffer;
  299. NTSTATUS status;
  300. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  301. PFUNCTIONAL_DEVICE_EXTENSION deviceExtension = Fdo->DeviceExtension;
  302. DEBUGPRINT2 (("PrinterDeviceControl: enter, Fdo=x%p, Ioctl=", Fdo));
  303. //
  304. // Zero CDB in SRB on stack.
  305. //
  306. switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
  307. case IOCTL_SERIAL_SET_TIMEOUTS: {
  308. PSERIAL_TIMEOUTS newTimeouts = ((PSERIAL_TIMEOUTS) buffer);
  309. DEBUGPRINT2 (("SET_TIMEOUTS\n"));
  310. if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
  311. sizeof(SERIAL_TIMEOUTS)) {
  312. status = STATUS_BUFFER_TOO_SMALL;
  313. } else if (newTimeouts->WriteTotalTimeoutConstant < 2000) {
  314. status = STATUS_INVALID_PARAMETER;
  315. } else {
  316. deviceExtension->TimeOutValue =
  317. newTimeouts->WriteTotalTimeoutConstant / 1000;
  318. status = STATUS_SUCCESS;
  319. }
  320. break;
  321. }
  322. case IOCTL_SERIAL_GET_TIMEOUTS:
  323. DEBUGPRINT2(("GET_TIMEOUTS\n"));
  324. if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
  325. sizeof(SERIAL_TIMEOUTS)) {
  326. status = STATUS_BUFFER_TOO_SMALL;
  327. } else {
  328. RtlZeroMemory (buffer, sizeof (SERIAL_TIMEOUTS));
  329. Irp->IoStatus.Information = sizeof(SERIAL_TIMEOUTS);
  330. ((PSERIAL_TIMEOUTS) buffer)->WriteTotalTimeoutConstant =
  331. deviceExtension->TimeOutValue * 1000;
  332. status = STATUS_SUCCESS;
  333. }
  334. break;
  335. case IOCTL_USBPRINT_GET_LPT_STATUS:
  336. //
  337. // We support this ioctl for USBMON.DLL's sake. Other print
  338. // stacks will block failed writes, and eventually USBMON
  339. // will send them this ioctl to see if the printer is out
  340. // of paper, which will be indicated by the state of the
  341. // 0x20 bit in the returned UCHAR value.
  342. //
  343. if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
  344. sizeof(UCHAR)) {
  345. status = STATUS_BUFFER_TOO_SMALL;
  346. } else if (deviceExtension->AdapterDescriptor->BusType !=
  347. BusType1394) {
  348. status = STATUS_INVALID_PARAMETER;
  349. } else {
  350. PPRINTER_DATA printerData;
  351. printerData = (PPRINTER_DATA)
  352. deviceExtension->CommonExtension.DriverData;
  353. Irp->IoStatus.Information = sizeof (UCHAR);
  354. *((UCHAR *) buffer) = (printerData->LastWriteStatus ==
  355. STATUS_NO_MEDIA_IN_DEVICE ? 0x20 : 0);
  356. DEBUGPRINT2((
  357. "GET_LPT_STATUS (=x%x)\n",
  358. (ULONG) *((UCHAR *) buffer)
  359. ));
  360. status = STATUS_SUCCESS;
  361. }
  362. break;
  363. case IOCTL_SCSIPRNT_1394_BLOCKING_WRITE:
  364. //
  365. // This ioctl en/disables the blocking write functionality
  366. // (for failed writes) on 1394 devices. By default we
  367. // block writes which fail on 1394 devices (until the write
  368. // finally succeeds or is cancelled), but a smart port
  369. // monitor could send this ioctl down to disable blocking
  370. // so it would get write error notifications asap.
  371. //
  372. if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
  373. sizeof(UCHAR)) {
  374. status = STATUS_BUFFER_TOO_SMALL;
  375. } else if (deviceExtension->AdapterDescriptor->BusType !=
  376. BusType1394) {
  377. status = STATUS_INVALID_PARAMETER;
  378. } else {
  379. PPRINTER_DATA printerData;
  380. printerData = (PPRINTER_DATA)
  381. deviceExtension->CommonExtension.DriverData;
  382. printerData->WriteCompletionRoutine = (*((UCHAR *) buffer) ?
  383. PrinterWriteComplete : ClassIoComplete);
  384. status = STATUS_SUCCESS;
  385. }
  386. break;
  387. default:
  388. //
  389. // Pass the request to the common device control routine.
  390. //
  391. DEBUGPRINT2((
  392. "x%x\n",
  393. irpStack->Parameters.DeviceIoControl.IoControlCode
  394. ));
  395. return(ClassDeviceControl(Fdo, Irp));
  396. break;
  397. } // end switch()
  398. //
  399. // Update IRP with completion status.
  400. //
  401. Irp->IoStatus.Status = status;
  402. //
  403. // Complete the request.
  404. //
  405. IoCompleteRequest(Irp, IO_DISK_INCREMENT);
  406. //
  407. // Release the remove lock (which ClassDeviceControl does)
  408. //
  409. ClassReleaseRemoveLock(Fdo, Irp);
  410. DEBUGPRINT2(( "PrinterDeviceControl: Status is %lx\n", status));
  411. return status;
  412. } // end ScsiPrinterDeviceControl()
  413. VOID
  414. SplitRequest(
  415. IN PDEVICE_OBJECT Fdo,
  416. IN PIRP Irp,
  417. IN ULONG MaximumBytes
  418. )
  419. /*++
  420. Routine Description:
  421. Break request into smaller requests. Each new request will be the
  422. maximum transfer size that the port driver can handle or if it
  423. is the final request, it may be the residual size.
  424. The number of IRPs required to process this request is written in the
  425. current stack of the original IRP. Then as each new IRP completes
  426. the count in the original IRP is decremented. When the count goes to
  427. zero, the original IRP is completed.
  428. Arguments:
  429. DeviceObject - Pointer to the class device object to be addressed.
  430. Irp - Pointer to Irp the orginal request.
  431. Return Value:
  432. None.
  433. --*/
  434. {
  435. PFUNCTIONAL_DEVICE_EXTENSION deviceExtension = Fdo->DeviceExtension;
  436. PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
  437. PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
  438. ULONG transferByteCount = currentIrpStack->Parameters.Read.Length;
  439. LARGE_INTEGER startingOffset = currentIrpStack->Parameters.Read.ByteOffset;
  440. PVOID dataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
  441. ULONG dataLength = MaximumBytes;
  442. ULONG irpCount = (transferByteCount + MaximumBytes - 1) / MaximumBytes;
  443. PSCSI_REQUEST_BLOCK srb;
  444. ULONG i;
  445. NTSTATUS Status;
  446. DEBUGPRINT2(( "SplitRequest: Requires %d IRPs\n", irpCount));
  447. DEBUGPRINT2(( "SplitRequest: Original IRP %p\n", Irp));
  448. //
  449. // If all partial transfers complete successfully then the status and
  450. // bytes transferred are already set up. Failing a partial-transfer IRP
  451. // will set status to error and bytes transferred to 0 during
  452. // IoCompletion. Setting bytes transferred to 0 if an IRP fails allows
  453. // asynchronous partial transfers. This is an optimization for the
  454. // successful case.
  455. //
  456. Irp->IoStatus.Status = STATUS_SUCCESS;
  457. Irp->IoStatus.Information = transferByteCount;
  458. //
  459. // Save number of IRPs to complete count on current stack
  460. // of original IRP.
  461. //
  462. nextIrpStack->Parameters.Others.Argument1 = ULongToPtr( irpCount );
  463. for (i = 0; i < irpCount; i++) {
  464. PIRP newIrp;
  465. PIO_STACK_LOCATION newIrpStack;
  466. //
  467. // Allocate new IRP.
  468. //
  469. newIrp = IoAllocateIrp(Fdo->StackSize, FALSE);
  470. if (newIrp == NULL) {
  471. DEBUGPRINT1(("SplitRequest: Can't allocate Irp\n"));
  472. //
  473. // If an Irp can't be allocated then the orginal request cannot
  474. // be executed. If this is the first request then just fail the
  475. // orginal request; otherwise just return. When the pending
  476. // requests complete, they will complete the original request.
  477. // In either case set the IRP status to failure.
  478. //
  479. Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  480. Irp->IoStatus.Information = 0;
  481. if (i == 0) {
  482. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  483. }
  484. return;
  485. }
  486. DEBUGPRINT2(( "SplitRequest: New IRP %p\n", newIrp));
  487. //
  488. // Write MDL address to new IRP. In the port driver the SRB data
  489. // buffer field is used as an offset into the MDL, so the same MDL
  490. // can be used for each partial transfer. This saves having to build
  491. // a new MDL for each partial transfer.
  492. //
  493. newIrp->MdlAddress = Irp->MdlAddress;
  494. //
  495. // At this point there is no current stack. IoSetNextIrpStackLocation
  496. // will make the first stack location the current stack so that the
  497. // SRB address can be written there.
  498. //
  499. IoSetNextIrpStackLocation(newIrp);
  500. newIrpStack = IoGetCurrentIrpStackLocation(newIrp);
  501. newIrpStack->MajorFunction = currentIrpStack->MajorFunction;
  502. newIrpStack->Parameters.Read.Length = dataLength;
  503. newIrpStack->Parameters.Read.ByteOffset = startingOffset;
  504. newIrpStack->DeviceObject = Fdo;
  505. //
  506. // Build SRB and CDB.
  507. //
  508. Status = BuildPrintRequest(Fdo, newIrp);
  509. if (!NT_SUCCESS (Status)) {
  510. IoFreeIrp (newIrp);
  511. Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  512. Irp->IoStatus.Information = 0;
  513. if (i == 0) {
  514. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  515. }
  516. return;
  517. }
  518. //
  519. // Adjust SRB for this partial transfer.
  520. //
  521. newIrpStack = IoGetNextIrpStackLocation(newIrp);
  522. srb = newIrpStack->Parameters.Others.Argument1;
  523. srb->DataBuffer = dataBuffer;
  524. //
  525. // Write original IRP address to new IRP.
  526. //
  527. newIrp->AssociatedIrp.MasterIrp = Irp;
  528. //
  529. // Set the completion routine to ScsiClassIoCompleteAssociated.
  530. //
  531. IoSetCompletionRoutine(newIrp,
  532. ClassIoCompleteAssociated,
  533. srb,
  534. TRUE,
  535. TRUE,
  536. TRUE);
  537. //
  538. // Call port driver with new request.
  539. //
  540. IoCallDriver(deviceExtension->CommonExtension.LowerDeviceObject, newIrp);
  541. //
  542. // Set up for next request.
  543. //
  544. dataBuffer = (PCHAR)dataBuffer + MaximumBytes;
  545. transferByteCount -= MaximumBytes;
  546. if (transferByteCount > MaximumBytes) {
  547. dataLength = MaximumBytes;
  548. } else {
  549. dataLength = transferByteCount;
  550. }
  551. //
  552. // Adjust disk byte offset.
  553. //
  554. startingOffset.QuadPart = startingOffset.QuadPart + MaximumBytes;
  555. }
  556. return;
  557. } // end SplitRequest()
  558. NTSTATUS
  559. PrinterWriteComplete(
  560. IN PDEVICE_OBJECT Fdo,
  561. IN PIRP Irp,
  562. IN PVOID Context
  563. )
  564. /*++
  565. Routine Description:
  566. Ideally we should be should be able to use ClassIoComplete for
  567. all write completion notifications, but alas...
  568. (Code borrowed from classpnp!ClassIoComplete)
  569. This is the special, 1394 bus-specific write completion routine
  570. required to keep USBMON.DLL happy in the case of failed write
  571. requests. The other stacks that USBMON talks to all pend
  572. unsuccessful writes forever, rather than simply completing them
  573. with an error. When a write blocks for a long time USBMON will
  574. issue a sideband ioctl, namely IOCTL_USBPRINT_GET_LPT_STATUS,
  575. to determine if the printer is out of paper or not. Eventually
  576. USBMON may cancel a blocked write. However, it simply doesn't
  577. expect writes to just fail, so we have to fake out the behavior
  578. of the other stacks to keep it happy. We'll retry blocked
  579. writes every so often, & mark the irp as cancellable in between
  580. retries.
  581. At least USBMON will only send down one 10k (or so) write at a
  582. time, so we don't have to worry about queue-ing >1 write at a
  583. time for a device, nor do we have to deal with handling failed
  584. sub-requests of a split write.
  585. Arguments:
  586. Fdo - Supplies the device object which represents the logical unit.
  587. Irp - Supplies the Irp which has completed.
  588. Context - Supplies a pointer to the SRB.
  589. Return Value:
  590. NT status
  591. --*/
  592. {
  593. ULONG retryInterval;
  594. KIRQL oldIrql;
  595. BOOLEAN retry;
  596. PPRINTER_DATA printerData;
  597. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation (Irp);
  598. PSCSI_REQUEST_BLOCK srb = Context;
  599. PCOMMON_DEVICE_EXTENSION extension = Fdo->DeviceExtension;
  600. ASSERT(extension->IsFdo);
  601. if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) {
  602. DEBUGPRINT3 (("PrinterWriteCompl: Fdo=x%p, Irp=x%p, ", Fdo, Irp));
  603. if (((PFUNCTIONAL_DEVICE_EXTENSION) extension)->AdapterDescriptor ==
  604. NULL) {
  605. //
  606. // Device removed..
  607. //
  608. DEBUGPRINT3(("device removed(\n"));
  609. Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
  610. Irp->IoStatus.Information = 0;
  611. ClassReleaseRemoveLock (Fdo, Irp);
  612. return STATUS_DEVICE_DOES_NOT_EXIST;
  613. }
  614. if (Irp->Cancel) {
  615. //
  616. // Someone tried to cancel the irp after it was passed
  617. // down the stack (where, as of win2k, there is no cancel
  618. // support), so bail out now
  619. //
  620. DEBUGPRINT3 (("irp cancelled\n"));
  621. Irp->IoStatus.Status = STATUS_CANCELLED;
  622. Irp->IoStatus.Information = 0;
  623. ClassReleaseRemoveLock (Fdo, Irp);
  624. return STATUS_CANCELLED;
  625. }
  626. printerData = (PPRINTER_DATA) extension->DriverData;
  627. //
  628. // Note that ClassInterpretSenseInfo will return (retry=)
  629. // FALSE if it determines there's no media in device
  630. //
  631. retry = ClassInterpretSenseInfo(
  632. Fdo,
  633. srb,
  634. irpStack->MajorFunction,
  635. 0,
  636. MAXIMUM_RETRIES - ((ULONG)(ULONG_PTR)
  637. irpStack->Parameters.Others.Argument4),
  638. &printerData->LastWriteStatus,
  639. &retryInterval
  640. );
  641. if (retry &&
  642. ((ULONG)(ULONG_PTR)irpStack->Parameters.Others.Argument4)--) {
  643. DEBUGPRINT3 (("retry write\n"));
  644. PrinterRetryRequest (Fdo, Irp, srb);
  645. } else {
  646. if (printerData->LastWriteStatus == STATUS_NO_MEDIA_IN_DEVICE) {
  647. //
  648. // At the current time Epson is returning
  649. // SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED for both
  650. // the out-of-paper & offline cases. The EndOfMedia
  651. // bit wil be set if the printer is truly out of paper,
  652. // but if it's not then we want to change the
  653. // LastWriteStatus so that we won't set the out-of-paper
  654. // bit in the IOCTL_USBPRINT_GET_LPT_STATUS handler.
  655. //
  656. PSENSE_DATA senseBuffer = srb->SenseInfoBuffer;
  657. if (senseBuffer->AdditionalSenseCodeQualifier ==
  658. SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED &&
  659. !senseBuffer->EndOfMedia) {
  660. printerData->LastWriteStatus = STATUS_IO_DEVICE_ERROR;
  661. }
  662. }
  663. printerData->DueTime.HighPart = -1;
  664. printerData->DueTime.LowPart =
  665. BLOCKED_WRITE_TIMEOUT * (-10 * 1000 * 1000);
  666. KeAcquireSpinLock (&printerData->SplitRequestSpinLock, &oldIrql);
  667. ASSERT (printerData->WriteIrp == NULL);
  668. if (printerData->WriteIrp == NULL ||
  669. printerData->WriteIrp == Irp) {
  670. printerData->WriteIrp = Irp;
  671. } else {
  672. //
  673. // We assume that if we're in blocking write mode then
  674. // the client is USBMON who will only submit 1 write
  675. // at a time (other clients should use
  676. // IOCTL_SCSIPRNT_1394_BLOCKING_WRITE to disable blocking
  677. // writes if they don't want this behavior).
  678. //
  679. // Since we don't handle >1 blocked write at a time we'll
  680. // just complete this 2nd write, so we don't lose track of
  681. // (and fail to complete) any irps.
  682. //
  683. KeReleaseSpinLock (&printerData->SplitRequestSpinLock, oldIrql);
  684. return ClassIoComplete (Fdo, Irp, Context);
  685. }
  686. KeReleaseSpinLock (&printerData->SplitRequestSpinLock, oldIrql);
  687. IoSetCancelRoutine (Irp, PrinterCancel);
  688. KeSetTimer(
  689. &printerData->Timer,
  690. printerData->DueTime,
  691. &printerData->TimerDpc
  692. );
  693. DEBUGPRINT3 ((
  694. "Sts=x%x, pend write\n",
  695. printerData->LastWriteStatus
  696. ));
  697. }
  698. return STATUS_MORE_PROCESSING_REQUIRED;
  699. }
  700. return ClassIoComplete (Fdo, Irp, Context);
  701. } // end PrinterWriteComplete()
  702. VOID
  703. PrinterRetryRequest(
  704. PDEVICE_OBJECT DeviceObject,
  705. PIRP Irp,
  706. PSCSI_REQUEST_BLOCK Srb
  707. )
  708. /*++
  709. Routine Description:
  710. (Code borrowed from classpnp!ClassIoComplete, since we need to
  711. set a different completion routine)
  712. This routine reinitalizes the necessary fields, and sends the request
  713. to the lower driver.
  714. Arguments:
  715. DeviceObject - Supplies the device object associated with this request.
  716. Irp - Supplies the request to be retried.
  717. Srb - Supplies a Pointer to the SCSI request block to be retied.
  718. Return Value:
  719. None
  720. --*/
  721. {
  722. ULONG transferByteCount;
  723. PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
  724. PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
  725. PCOMMON_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
  726. //
  727. // Determine the transfer count of the request. If this is a read or a
  728. // write then the transfer count is in the Irp stack. Otherwise assume
  729. // the MDL contains the correct length. If there is no MDL then the
  730. // transfer length must be zero.
  731. //
  732. if (currentIrpStack->MajorFunction == IRP_MJ_READ ||
  733. currentIrpStack->MajorFunction == IRP_MJ_WRITE) {
  734. transferByteCount = currentIrpStack->Parameters.Read.Length;
  735. } else if (Irp->MdlAddress != NULL) {
  736. //
  737. // Note this assumes that only read and write requests are spilt and
  738. // other request do not need to be. If the data buffer address in
  739. // the MDL and the SRB don't match then transfer length is most
  740. // likely incorrect.
  741. //
  742. ASSERT(Srb->DataBuffer == MmGetMdlVirtualAddress(Irp->MdlAddress));
  743. transferByteCount = Irp->MdlAddress->ByteCount;
  744. } else {
  745. transferByteCount = 0;
  746. }
  747. //
  748. // Reset byte count of transfer in SRB Extension.
  749. //
  750. Srb->DataTransferLength = transferByteCount;
  751. //
  752. // Zero SRB statuses.
  753. //
  754. Srb->SrbStatus = Srb->ScsiStatus = 0;
  755. //
  756. // Set the no disconnect flag, disable synchronous data transfers and
  757. // disable tagged queuing. This fixes some errors.
  758. //
  759. Srb->SrbFlags |= SRB_FLAGS_DISABLE_DISCONNECT |
  760. SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
  761. Srb->SrbFlags &= ~SRB_FLAGS_QUEUE_ACTION_ENABLE;
  762. Srb->QueueTag = SP_UNTAGGED;
  763. //
  764. // Set up major SCSI function.
  765. //
  766. nextIrpStack->MajorFunction = IRP_MJ_SCSI;
  767. //
  768. // Save SRB address in next stack for port driver.
  769. //
  770. nextIrpStack->Parameters.Scsi.Srb = Srb;
  771. //
  772. // Set up IoCompletion routine address.
  773. //
  774. IoSetCompletionRoutine (Irp, PrinterWriteComplete, Srb, TRUE, TRUE, TRUE);
  775. //
  776. // Pass the request to the port driver.
  777. //
  778. IoCallDriver (extension->LowerDeviceObject, Irp);
  779. return;
  780. } // end PrinterRetryRequest()
  781. VOID
  782. PrinterWriteTimeoutDpc(
  783. IN PKDPC Dpc,
  784. IN PCOMMON_DEVICE_EXTENSION Extension,
  785. IN PVOID SystemArgument1,
  786. IN PVOID SystemArgument2
  787. )
  788. /*++
  789. Routine Description:
  790. Gets called when the blocking-write timer expires. Allocates &
  791. queues a low-priority work item (to resubmit the write) if
  792. there's an outstanding write, & if the allocation fails justs
  793. resets the time to try again later. (We're running at raised
  794. irql here, when it's not necesarily safe to re-submit the write,
  795. hence the work item which gets processed later at passive level.)
  796. Arguments:
  797. Dpc -
  798. Extension -
  799. SystemArgument1 -
  800. SystemArgument2 -
  801. Return Value:
  802. None
  803. --*/
  804. {
  805. PIO_WORKITEM workItem;
  806. PPRINTER_DATA printerData = (PPRINTER_DATA) Extension->DriverData;
  807. DEBUGPRINT3((
  808. "PrinterWriteTimeoutDpc: enter, Fdo=x%p, Irp=x%p\n",
  809. Extension->DeviceObject,
  810. printerData->WriteIrp
  811. ));
  812. if (printerData->WriteIrp) {
  813. workItem = IoAllocateWorkItem (Extension->DeviceObject);
  814. if (workItem) {
  815. IoQueueWorkItem(
  816. workItem,
  817. PrinterResubmitWrite,
  818. DelayedWorkQueue, // not time critical
  819. workItem
  820. );
  821. } else {
  822. printerData->DueTime.HighPart = -1;
  823. printerData->DueTime.LowPart =
  824. BLOCKED_WRITE_TIMEOUT * (-10 * 1000 * 1000);
  825. KeSetTimer(
  826. &printerData->Timer,
  827. printerData->DueTime,
  828. &printerData->TimerDpc
  829. );
  830. }
  831. }
  832. } // end PrinterWriteTimeoutDpc
  833. VOID
  834. PrinterResubmitWrite(
  835. PDEVICE_OBJECT DeviceObject,
  836. PVOID Context
  837. )
  838. /*++
  839. Routine Description:
  840. Work item handler routine, gets called at passive level in an
  841. arbitrary thread context. Simply resubmits an outstanding write,
  842. if any.
  843. Arguments:
  844. DeviceObject -
  845. Context - pointer to the IO_WORKITEM
  846. Return Value:
  847. None
  848. --*/
  849. {
  850. PIRP irp;
  851. KIRQL oldIrql;
  852. PPRINTER_DATA printerData;
  853. DEBUGPRINT3 (("PrinterResubmitWrite: enter, Fdo=x%p, ", DeviceObject));
  854. IoFreeWorkItem ((PIO_WORKITEM) Context);
  855. printerData = (PPRINTER_DATA)
  856. ((PCOMMON_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->DriverData;
  857. //
  858. // See if there's still an outstanding write irp, & if so NULL-ify
  859. // the cancel routine since we'll be passing the irp down the stack
  860. //
  861. KeAcquireSpinLock (&printerData->SplitRequestSpinLock, &oldIrql);
  862. irp = printerData->WriteIrp;
  863. if (irp) {
  864. if (IoSetCancelRoutine (irp, NULL) == NULL) {
  865. DEBUGPRINT3 (("write cancelled\n"));
  866. irp = NULL;
  867. } else {
  868. printerData->WriteIrp = NULL;
  869. }
  870. } else {
  871. DEBUGPRINT3 (("no pending write\n"));
  872. }
  873. KeReleaseSpinLock (&printerData->SplitRequestSpinLock, oldIrql);
  874. //
  875. // Rebsubmit an outstanding write irp
  876. //
  877. if (irp) {
  878. PFUNCTIONAL_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
  879. if (extension->AdapterDescriptor) {
  880. DEBUGPRINT3 (("Irp=x%p\n", irp));
  881. PrinterReadWrite (DeviceObject, irp);
  882. } else {
  883. DEBUGPRINT3((" RMV!, fail Irp=x%p\n", irp));
  884. IoMarkIrpPending (irp);
  885. irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
  886. irp->IoStatus.Information = 0;
  887. IoCompleteRequest (irp, IO_NO_INCREMENT);
  888. ClassReleaseRemoveLock (DeviceObject, irp);
  889. }
  890. }
  891. } // end PrinterWriteTimeoutDpc
  892. VOID
  893. PrinterCancel(
  894. PDEVICE_OBJECT DeviceObject,
  895. PIRP Irp
  896. )
  897. /*++
  898. Routine Description:
  899. Cancels a blocked write irp
  900. Arguments:
  901. DeviceObject -
  902. Irp - irp to cancel
  903. Return Value:
  904. None
  905. --*/
  906. {
  907. KIRQL oldIrql;
  908. PPRINTER_DATA printerData;
  909. PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
  910. PSCSI_REQUEST_BLOCK srb;
  911. DEBUGPRINT2((
  912. "\nPrinterCancel: enter, DevObj=x%p, Irp=x%p\n\n",
  913. DeviceObject,
  914. Irp
  915. ));
  916. printerData = (PPRINTER_DATA)
  917. ((PCOMMON_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->DriverData;
  918. IoReleaseCancelSpinLock (Irp->CancelIrql);
  919. KeCancelTimer (&printerData->Timer);
  920. KeAcquireSpinLock (&printerData->SplitRequestSpinLock, &oldIrql);
  921. ASSERT (Irp == printerData->WriteIrp);
  922. printerData->WriteIrp = NULL;
  923. KeReleaseSpinLock (&printerData->SplitRequestSpinLock, oldIrql);
  924. // see if this is a SCSI Irp we sent down
  925. if(currentIrpStack->MajorFunction == IRP_MJ_SCSI)
  926. {
  927. // the associated SRB never got freed, so do it before we complete this request
  928. srb = currentIrpStack->Parameters.Scsi.Srb;
  929. if (srb)
  930. {
  931. currentIrpStack->Parameters.Scsi.Srb = NULL;
  932. ExFreePool(srb);
  933. }
  934. }
  935. Irp->IoStatus.Status = STATUS_CANCELLED;
  936. Irp->IoStatus.Information = 0;
  937. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  938. } // end PrinterCancel