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.

2471 lines
67 KiB

  1. /*++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name :
  4. read.c
  5. Abstract:
  6. This driver implements a state machine which polls for USB read data.
  7. It pends a single private read irp to USBD as soon as it starts up (StartDevice)
  8. if there is no interrupt endpoint.
  9. We have only 1 USB read buffer of some configured size.
  10. When the USB read irp completes then we copy the data into any pending user read buffer,
  11. and resubmit the Usb UsbReadIrp to USBD, *IF OUR BUFFER* is emptied. This implements
  12. simple flow ctrl. There is an optional ring-buffer implementation, which will not bind USB reads
  13. to application reads.
  14. Timeouts are set from the app via serial ioctls.
  15. An alternative to this muck is to create a driver thread to do the polling
  16. for USB read data. This has it's own caveats & requires the thread to be scheduled,
  17. so take time to investigate beforehand.
  18. Author:
  19. Jeff Midkiff (jeffmi) 07-16-99
  20. --*/
  21. #if defined (USE_RING_BUFF)
  22. #define min(a,b) (((a) < (b)) ? (a) : (b))
  23. #else
  24. #include <stdlib.h>
  25. #endif
  26. #include "wceusbsh.h"
  27. //
  28. // called with control held
  29. //
  30. #if defined (USE_RING_BUFF)
  31. #define START_ANOTHER_USBREAD( _PDevExt ) \
  32. ( (IRP_STATE_COMPLETE == _PDevExt->UsbReadState) && \
  33. CanAcceptIoRequests(_PDevExt->DeviceObject, FALSE, TRUE) \
  34. )
  35. #else
  36. #define START_ANOTHER_USBREAD( _PDevExt ) \
  37. ( (IRP_STATE_COMPLETE == _PDevExt->UsbReadState) && \
  38. (0 == _PDevExt->UsbReadBuffChars) && \
  39. CanAcceptIoRequests(_PDevExt->DeviceObject, FALSE, TRUE) \
  40. )
  41. #endif
  42. NTSTATUS
  43. UsbReadCompletion(
  44. IN PDEVICE_OBJECT DeviceObject,
  45. IN PIRP Irp,
  46. IN PVOID Context
  47. );
  48. __inline
  49. ULONG
  50. GetUserData(
  51. IN PDEVICE_EXTENSION PDevExt,
  52. IN PCHAR PDestBuff,
  53. IN ULONG RequestedLen,
  54. IN OUT PULONG PBytesCopied
  55. );
  56. __inline
  57. VOID
  58. PutUserData(
  59. IN PDEVICE_EXTENSION PDevExt,
  60. IN ULONG Count
  61. );
  62. __inline
  63. VOID
  64. CheckForQueuedUserReads(
  65. IN PDEVICE_EXTENSION PDevExt,
  66. IN KIRQL Irql
  67. );
  68. VOID
  69. CancelQueuedIrp(
  70. IN PDEVICE_OBJECT PDevObj,
  71. IN PIRP PIrp
  72. );
  73. VOID
  74. CancelUsbReadWorkItem(
  75. IN PWCE_WORK_ITEM PWorkItem
  76. );
  77. VOID
  78. StartUsbReadWorkItem(
  79. IN PWCE_WORK_ITEM PWorkItem
  80. );
  81. NTSTATUS
  82. StartUserRead(
  83. IN PDEVICE_EXTENSION PDevExt
  84. );
  85. VOID
  86. UsbReadTimeout(
  87. IN PKDPC PDpc,
  88. IN PVOID DeferredContext,
  89. IN PVOID SystemContext1,
  90. IN PVOID SystemContext2
  91. );
  92. VOID
  93. CancelCurrentRead(
  94. IN PDEVICE_OBJECT PDevObj,
  95. IN PIRP PIrp
  96. );
  97. NTSTATUS
  98. StartOrQueueIrp(
  99. IN PDEVICE_EXTENSION PDevExt,
  100. IN PIRP PIrp,
  101. IN PLIST_ENTRY PIrpQueue,
  102. IN PIRP *PPCurrentIrp,
  103. IN PSTART_ROUTINE StartRoutine
  104. );
  105. VOID
  106. GetNextUserIrp(
  107. IN PIRP *PpCurrentOpIrp,
  108. IN PLIST_ENTRY PQueueToProcess,
  109. OUT PIRP *PpNextIrp,
  110. IN BOOLEAN CompleteCurrent,
  111. IN PDEVICE_EXTENSION PDevExt
  112. );
  113. ///////////////////////////////////////////////////////////////////
  114. //
  115. // USB read section
  116. //
  117. //
  118. //
  119. // This function allocates a single Irp & Urb to be continously submitted
  120. // to USBD for buffered reads.
  121. // It is called from StartDevice.
  122. // The Irp & Urb are finally freed in StopDevice.
  123. //
  124. NTSTATUS
  125. AllocUsbRead(
  126. IN PDEVICE_EXTENSION PDevExt
  127. )
  128. {
  129. NTSTATUS status = STATUS_SUCCESS;
  130. PIRP pIrp;
  131. DbgDump(DBG_READ, (">AllocUsbRead(%p)\n", PDevExt->DeviceObject));
  132. ASSERT( PDevExt );
  133. ASSERT( NULL == PDevExt->UsbReadIrp );
  134. pIrp = IoAllocateIrp( (CCHAR)(PDevExt->NextDevice->StackSize + 1), FALSE);
  135. if ( pIrp ) {
  136. DbgDump(DBG_READ, ("UsbReadIrp: %p\n", pIrp ));
  137. //
  138. // fixup irp so we can pass to ourself,
  139. // and to USBD
  140. //
  141. FIXUP_RAW_IRP( pIrp, PDevExt->DeviceObject );
  142. //
  143. // setup read state
  144. //
  145. KeInitializeEvent( &PDevExt->UsbReadCancelEvent,
  146. SynchronizationEvent,
  147. FALSE);
  148. PDevExt->UsbReadIrp = pIrp;
  149. ASSERT( PDevExt->UsbReadBuff );
  150. PDevExt->UsbReadBuffChars = 0;
  151. PDevExt->UsbReadBuffIndex = 0;
  152. ASSERT( 0 == PDevExt->PendingReadCount );
  153. InterlockedExchange(&PDevExt->UsbReadState, IRP_STATE_COMPLETE);
  154. } else {
  155. //
  156. // this is a fatal err since we can't post reads to USBD
  157. //
  158. TEST_TRAP();
  159. status = STATUS_INSUFFICIENT_RESOURCES;
  160. DbgDump(DBG_ERR, ("AllocUsbRead: 0x%x\n", status ));
  161. }
  162. DbgDump(DBG_READ, ("<AllocUsbRead 0x%x\n", status ));
  163. return status;
  164. }
  165. //
  166. // Work item queued from read completion or read timeout.
  167. // Starts another USB read if there is not one already in progress
  168. //
  169. VOID
  170. StartUsbReadWorkItem(
  171. IN PWCE_WORK_ITEM PWorkItem
  172. )
  173. {
  174. PDEVICE_OBJECT pDevObj = PWorkItem->DeviceObject;
  175. PDEVICE_EXTENSION pDevExt = pDevObj->DeviceExtension;
  176. NTSTATUS status = STATUS_DELETE_PENDING;
  177. PERF_ENTRY( PERF_StartUsbReadWorkItem );
  178. DbgDump(DBG_READ|DBG_WORK_ITEMS, (">StartUsbReadWorkItem(%p)\n", pDevObj ));
  179. if ( InterlockedCompareExchange(&pDevExt->AcceptingRequests, TRUE, TRUE) ) {
  180. status = UsbRead( pDevExt, FALSE );
  181. }
  182. DequeueWorkItem( pDevObj, PWorkItem );
  183. DbgDump(DBG_READ|DBG_WORK_ITEMS, ("<StartUsbReadWorkItem 0x%x\n", status ));
  184. PAGED_CODE(); // we must exit at passive level
  185. PERF_EXIT( PERF_StartUsbReadWorkItem );
  186. return;
  187. }
  188. //
  189. // This routine takes the device's current USB UsbReadIrp and submits it to USBD.
  190. // When the Irp is completed by USBD our completion routine fires.
  191. //
  192. // An optional Timeout value sets a timer on the USB Read Irp,
  193. // so USBD won't queue the read Irp indefinetly.
  194. // If there is a device error then USB returns the Irp.
  195. //
  196. // Return: successful return value is STATUS_SUCCESS, or
  197. // STATUS_PENDING - which means the I/O is pending in the USB stack.
  198. //
  199. NTSTATUS
  200. UsbRead(
  201. IN PDEVICE_EXTENSION PDevExt,
  202. IN BOOLEAN UseTimeout
  203. )
  204. {
  205. NTSTATUS status;
  206. KIRQL irql;
  207. LARGE_INTEGER noTimeout = {0,0};
  208. PERF_ENTRY( PERF_UsbRead );
  209. DbgDump(DBG_READ, (">UsbRead(%p, %d)\n", PDevExt->DeviceObject, UseTimeout));
  210. do {
  211. //
  212. // check our USB read state
  213. //
  214. KeAcquireSpinLock(&PDevExt->ControlLock, &irql);
  215. if ( !PDevExt->UsbReadIrp ) {
  216. status = STATUS_UNSUCCESSFUL;
  217. DbgDump(DBG_ERR, ("UsbRead NO READ IRP\n"));
  218. KeReleaseSpinLock(&PDevExt->ControlLock, irql);
  219. PERF_EXIT( PERF_UsbRead );
  220. break;
  221. }
  222. if ( !CanAcceptIoRequests(PDevExt->DeviceObject, FALSE, TRUE)) {
  223. status = STATUS_DELETE_PENDING;
  224. DbgDump(DBG_ERR, ("UsbRead: 0x%x\n", status ));
  225. KeReleaseSpinLock(&PDevExt->ControlLock, irql);
  226. PERF_EXIT( PERF_UsbRead );
  227. break;
  228. }
  229. //
  230. // we post our read irp to USB if it has been completed (not cancelled),
  231. // and our read bufer is driained (if not using a ring-buffer)
  232. // and the device is accepting requests
  233. //
  234. if ( START_ANOTHER_USBREAD( PDevExt ) ) {
  235. status = AcquireRemoveLock(&PDevExt->RemoveLock, PDevExt->UsbReadIrp);
  236. if ( !NT_SUCCESS(status) ) {
  237. DbgDump(DBG_ERR, ("UsbRead: 0x%x\n", status ));
  238. KeReleaseSpinLock(&PDevExt->ControlLock, irql);
  239. PERF_EXIT( PERF_UsbRead );
  240. break;
  241. }
  242. ASSERT( IRP_STATE_COMPLETE == PDevExt->UsbReadState);
  243. InterlockedExchange(&PDevExt->UsbReadState, IRP_STATE_PENDING);
  244. KeClearEvent( &PDevExt->PendingDataInEvent );
  245. KeClearEvent( &PDevExt->UsbReadCancelEvent );
  246. RecycleIrp( PDevExt->DeviceObject, PDevExt->UsbReadIrp );
  247. //
  248. // bump ttl request count
  249. //
  250. PDevExt->TtlUSBReadRequests++;
  251. KeReleaseSpinLock(&PDevExt->ControlLock, irql);
  252. #if DBG
  253. if (UseTimeout) {
  254. DbgDump(DBG_INT, ("INT Read Timeout due in %d msec\n", (PDevExt->IntReadTimeOut.QuadPart/10000) ));
  255. KeQuerySystemTime(&PDevExt->LastIntReadTime);
  256. }
  257. #endif
  258. status = UsbReadWritePacket( PDevExt,
  259. PDevExt->UsbReadIrp,
  260. UsbReadCompletion, // Irp completion routine
  261. UseTimeout ? PDevExt->IntReadTimeOut : noTimeout,
  262. UseTimeout ? UsbReadTimeout : NULL, // Timeout routine
  263. TRUE ); // Read
  264. if ( (STATUS_SUCCESS != status) && (STATUS_PENDING != status) ) {
  265. //
  266. // We can end up here after our completion routine runs
  267. // for an error condition i.e., when we have an
  268. // invalid parameter, or when user pulls the plug, etc.
  269. //
  270. DbgDump(DBG_ERR, ("UsbReadWritePacket: 0x%x\n", status));
  271. }
  272. } else {
  273. //
  274. // we did not post a Read, but this is not an error condition
  275. //
  276. status = STATUS_SUCCESS;
  277. DbgDump(DBG_READ, ("!UsbRead RE(2): (0x%x,0x%x)\n", PDevExt->UsbReadState, PDevExt->UsbReadBuffChars ));
  278. KeReleaseSpinLock(&PDevExt->ControlLock, irql);
  279. }
  280. } while (0);
  281. DbgDump(DBG_READ, ("<UsbRead 0x%x\n", status ));
  282. PERF_EXIT( PERF_UsbRead );
  283. return status;
  284. }
  285. //
  286. // This completion routine fires when our USB read completes our UsbReadIrp
  287. // Note: we allocated the Irp, and recycle it.
  288. // Always return STATUS_MORE_PROCESSING_REQUIRED to retain the Irp.
  289. // This routine runs at DPC_LEVEL.
  290. //
  291. NTSTATUS
  292. UsbReadCompletion(
  293. IN PDEVICE_OBJECT PDevObj,
  294. IN PIRP Irp,
  295. IN PUSB_PACKET PPacket // Context
  296. )
  297. {
  298. PDEVICE_EXTENSION pDevExt = PPacket->DeviceExtension;
  299. PDEVICE_OBJECT pDevObj = pDevExt->DeviceObject;
  300. PURB pUrb;
  301. ULONG count;
  302. KIRQL irql;
  303. NTSTATUS irpStatus;
  304. NTSTATUS workStatus;
  305. USBD_STATUS urbStatus;
  306. PERF_ENTRY( PERF_UsbReadCompletion );
  307. UNREFERENCED_PARAMETER( PDevObj );
  308. DbgDump(DBG_READ, (">UsbReadCompletion (%p)\n", Irp));
  309. KeAcquireSpinLock(&pDevExt->ControlLock, &irql);
  310. //
  311. // cancel the Packet Timer
  312. //
  313. if ( PPacket->Timeout.QuadPart != 0 ) {
  314. if (KeCancelTimer( &PPacket->TimerObj ) ) {
  315. //
  316. // the packet's timer was successfully removed from the system
  317. //
  318. DbgDump(DBG_READ|DBG_INT, ("Read PacketTimer: Canceled\n"));
  319. } else {
  320. //
  321. // the timer
  322. // a) already completed, in which case the Irp is being cancelled, or
  323. // b) it's spinning on the control lock, so tell it we took the Irp.
  324. //
  325. PPacket->Status = STATUS_ALERTED;
  326. DbgDump(DBG_READ|DBG_INT, ("Read PacketTimer: Alerted\n"));
  327. }
  328. }
  329. //
  330. // get everything we need out of the packet
  331. // and put it back on the list
  332. //
  333. // ensure the Irp is the same one as in our DevExt
  334. ASSERT( pDevExt->UsbReadIrp == Irp );
  335. // ensure the Packet's Irp is the same one as in our DevExt
  336. ASSERT( PPacket->Irp == Irp );
  337. pUrb = pDevExt->UsbReadUrb;
  338. // ensure the Packet's Urb is the same one as in our DevExt
  339. ASSERT( pUrb == &PPacket->Urb );
  340. count = pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength;
  341. RemoveEntryList( &PPacket->ListEntry );
  342. //
  343. // Our read state should be either pending or cancelled at this point.
  344. // If it pending then USB is completing the Irp normally.
  345. // If it is cancelled then our CancelUsbReadIrp set it,
  346. // in which case USB can complete the irp normally or as cancelled
  347. // depending on where it was in processing. If the read state is cancelled
  348. // then do NOT set to complete, else the read Irp will
  349. // go back down to USB and you are hosed.
  350. //
  351. ASSERT( (IRP_STATE_PENDING == pDevExt->UsbReadState)
  352. || (IRP_STATE_CANCELLED== pDevExt->UsbReadState) );
  353. if (IRP_STATE_PENDING == pDevExt->UsbReadState) {
  354. InterlockedExchange(&pDevExt->UsbReadState, IRP_STATE_COMPLETE);
  355. }
  356. //
  357. // Put the pacet back in packet pool
  358. //
  359. ExFreeToNPagedLookasideList( &pDevExt->PacketPool, // Lookaside,
  360. PPacket // Entry
  361. );
  362. //
  363. // signal everyone if this is the last IRP
  364. //
  365. if ( 0 == InterlockedDecrement(&pDevExt->PendingReadCount) ) {
  366. DbgDump(DBG_READ, ("PendingReadCount(1) = 0\n"));
  367. // when we drop back to passive level they will get signalled
  368. KeSetEvent(&pDevExt->PendingDataInEvent, IO_SERIAL_INCREMENT, FALSE);
  369. }
  370. irpStatus = Irp->IoStatus.Status;
  371. DbgDump(DBG_READ, ("Irp->IoStatus.Status 0x%x\n", irpStatus));
  372. urbStatus = pUrb->UrbHeader.Status;
  373. DbgDump(DBG_READ, ("pUrb->UrbHeader.Status 0x%x\n", urbStatus ));
  374. switch (irpStatus) {
  375. case STATUS_SUCCESS: {
  376. //
  377. // save the read transfer info
  378. //
  379. ASSERT( USBD_STATUS_SUCCESS == urbStatus );
  380. DbgDump(DBG_READ_LENGTH, ("USB Read indication: %d\n", count));
  381. //
  382. // store read data
  383. //
  384. PutUserData( pDevExt, count );
  385. //
  386. // clear pipe error count
  387. //
  388. InterlockedExchange( &pDevExt->ReadDeviceErrors, 0);
  389. //
  390. // bump ttl byte counter
  391. //
  392. pDevExt->TtlUSBReadBytes += count;
  393. //
  394. // We have some USB read data in our local buffer,
  395. // let's see if we can satisfy any queued user read requests.
  396. // This f() releases the control lock.
  397. //
  398. CheckForQueuedUserReads(pDevExt, irql);
  399. //
  400. // kick off another USB read
  401. //
  402. UsbRead( pDevExt,
  403. (BOOLEAN)(pDevExt->IntPipe.hPipe ? TRUE : FALSE) );
  404. }
  405. break;
  406. case STATUS_CANCELLED: {
  407. DbgDump(DBG_WRN|DBG_READ|DBG_IRP, ("Read: STATUS_CANCELLED\n"));
  408. KeReleaseSpinLock(&pDevExt->ControlLock, irql);
  409. //
  410. // If it was cancelled, it may have timed out.
  411. // We can tell by looking at the packet attached to it.
  412. //
  413. if ( STATUS_TIMEOUT == PPacket->Status ) {
  414. //
  415. // no read data available from USBD
  416. //
  417. DbgDump(DBG_WRN|DBG_READ|DBG_IRP, ("Read: STATUS_TIMEOUT\n"));
  418. ASSERT( USBD_STATUS_CANCELED == urbStatus);
  419. //
  420. // We need to kick off another USB read when we are out of reads,
  421. // or have an error condition.
  422. //
  423. if ( !pDevExt->IntPipe.hPipe ) {
  424. workStatus = QueueWorkItem( pDevObj,
  425. StartUsbReadWorkItem,
  426. NULL,
  427. 0 );
  428. } else {
  429. workStatus = STATUS_UNSUCCESSFUL;
  430. }
  431. }
  432. //
  433. // signal anyone who cancelled this or is waiting for it to stop
  434. //
  435. KeSetEvent(&pDevExt->UsbReadCancelEvent, IO_SERIAL_INCREMENT, FALSE);
  436. }
  437. break;
  438. case STATUS_DEVICE_DATA_ERROR: {
  439. //
  440. // generic device error set by USBD.
  441. //
  442. DbgDump(DBG_ERR, ("ReadPipe STATUS_DEVICE_DATA_ERROR: 0x%x\n", urbStatus ));
  443. KeReleaseSpinLock(&pDevExt->ControlLock, irql);
  444. //
  445. // bump pipe error count
  446. //
  447. InterlockedIncrement( &pDevExt->ReadDeviceErrors);
  448. //
  449. // is the endpoint is stalled?
  450. //
  451. if ( USBD_HALTED(pUrb->UrbHeader.Status) ) {
  452. if ( USBD_STATUS_BUFFER_OVERRUN == pUrb->UrbHeader.Status) {
  453. pDevExt->TtlUSBReadBuffOverruns++;
  454. }
  455. //
  456. // queue a reset request,
  457. // which also starts another read
  458. //
  459. workStatus = QueueWorkItem( pDevObj,
  460. UsbResetOrAbortPipeWorkItem,
  461. (PVOID)((LONG_PTR)urbStatus),
  462. WORK_ITEM_RESET_READ_PIPE );
  463. } else {
  464. //
  465. // kick start another USB read
  466. //
  467. workStatus = QueueWorkItem( PDevObj,
  468. StartUsbReadWorkItem,
  469. NULL,
  470. 0 );
  471. }
  472. }
  473. break;
  474. case STATUS_INVALID_PARAMETER: {
  475. //
  476. // This means that our (TransferBufferSize > PipeInfo->MaxTransferSize)
  477. // we need to either break up requests or reject the Irp from the start.
  478. //
  479. DbgDump(DBG_WRN, ("STATUS_INVALID_PARAMETER\n"));
  480. ASSERT(USBD_STATUS_INVALID_PARAMETER == urbStatus);
  481. KeReleaseSpinLock(&pDevExt->ControlLock, irql);
  482. TEST_TRAP();
  483. }
  484. break;
  485. default: {
  486. DbgDump(DBG_ERR, ("READ: Unhandled Irp status: 0x%x\n", irpStatus));
  487. KeReleaseSpinLock(&pDevExt->ControlLock, irql);
  488. }
  489. break;
  490. }
  491. ReleaseRemoveLock(&pDevExt->RemoveLock, pDevExt->UsbReadIrp);
  492. DbgDump(DBG_READ, ("<UsbReadCompletion\n"));
  493. PERF_EXIT( PERF_UsbReadCompletion );
  494. return STATUS_MORE_PROCESSING_REQUIRED;
  495. }
  496. //
  497. // This routine is called from the UsbReadCompletion routine
  498. // when our USB UsbReadIrp has completed successfully.
  499. // See if we have any queued user read Irps that we can satisfy.
  500. // It is called with the control lock held (as an optimization)
  501. // and must release the lock upon return.
  502. //
  503. __inline
  504. VOID
  505. CheckForQueuedUserReads(
  506. IN PDEVICE_EXTENSION PDevExt,
  507. IN KIRQL Irql
  508. )
  509. {
  510. PERF_ENTRY( PERF_CheckForQueuedUserReads );
  511. DbgDump(DBG_READ, (">CheckForQueuedUserReads(%p)\n", PDevExt->DeviceObject));
  512. //
  513. // is there a user read pending?
  514. //
  515. if ( (PDevExt->UserReadIrp != NULL) &&
  516. (IRP_REFERENCE_COUNT(PDevExt->UserReadIrp) & IRP_REF_RX_BUFFER)) {
  517. //
  518. // copy our USB read data into user's irp buffer
  519. //
  520. #if DBG
  521. ULONG charsRead =
  522. #endif
  523. GetUserData( PDevExt,
  524. ((PUCHAR)(PDevExt->UserReadIrp->AssociatedIrp.SystemBuffer))
  525. + (IoGetCurrentIrpStackLocation(PDevExt->UserReadIrp))->Parameters.Read.Length
  526. - PDevExt->NumberNeededForRead,
  527. PDevExt->NumberNeededForRead,
  528. (PULONG)&PDevExt->UserReadIrp->IoStatus.Information );
  529. if ( !PDevExt->UserReadIrp ) {
  530. //
  531. // it's (no longer) possible to have completed the read Irp
  532. // in the above GetUserData cycle.
  533. //
  534. DbgDump(DBG_READ, ("UsbReadIrp already completed(2)\n"));
  535. TEST_TRAP();
  536. } else if (PDevExt->NumberNeededForRead == 0) {
  537. //
  538. // Mark the user's read Irp as completed,
  539. // and try to get and service the next user read irp
  540. //
  541. ASSERT( PDevExt->UserReadIrp );
  542. PDevExt->UserReadIrp->IoStatus.Status = STATUS_SUCCESS;
  543. // signals the interval timer this read is complete
  544. PDevExt->CountOnLastRead = SERIAL_COMPLETE_READ_COMPLETE;
  545. #if DBG
  546. if ( DebugLevel & DBG_READ_LENGTH) {
  547. ULONG count;
  548. if (PDevExt->UserReadIrp->IoStatus.Status == STATUS_SUCCESS) {
  549. count = (ULONG)PDevExt->UserReadIrp->IoStatus.Information;
  550. } else {
  551. count = 0;
  552. }
  553. KdPrint(("RD2: RL(%d) C(%d) I(%p)\n",
  554. IoGetCurrentIrpStackLocation(PDevExt->UserReadIrp)->Parameters.Read.Length,
  555. count,
  556. PDevExt->UserReadIrp));
  557. }
  558. #endif
  559. TryToCompleteCurrentIrp( PDevExt,
  560. STATUS_SUCCESS,
  561. &PDevExt->UserReadIrp,
  562. &PDevExt->UserReadQueue,
  563. &PDevExt->ReadRequestIntervalTimer,
  564. &PDevExt->ReadRequestTotalTimer,
  565. StartUserRead,
  566. GetNextUserIrp,
  567. IRP_REF_RX_BUFFER,
  568. TRUE,
  569. Irql );
  570. } else {
  571. //
  572. // we could get here if we did not staisfy the user's read
  573. // but have drained our read buffer. This requires another
  574. // USB read post.
  575. //
  576. ASSERT( PDevExt->UserReadIrp );
  577. ASSERT( PDevExt->NumberNeededForRead );
  578. DbgDump(DBG_READ|DBG_READ_LENGTH, ("Pending Irp (%p) has %d bytes to satisfy\n",
  579. PDevExt->UserReadIrp, PDevExt->NumberNeededForRead));
  580. KeReleaseSpinLock( &PDevExt->ControlLock, Irql);
  581. // TEST_TRAP();
  582. }
  583. } else {
  584. //
  585. // Q: should we:
  586. // 1.) copy the data into a local ring-buffer and post another read to USBD, - or -
  587. // 2.) leave the data in the FIFO & let the device stall/NAK so that:
  588. // a) we dont lose any data if the user is not posting reads,
  589. // b) lets the other end know to stop sending data via NAKs
  590. //
  591. // ...Currently choose #2. If we were to add a ring-buffer then here is where you should do the
  592. // local copy.
  593. //
  594. // Note: we could get here before an app even opens this device
  595. // if the there is data coming in on the other side of the FIFO.
  596. //
  597. DbgDump(DBG_READ|DBG_READ_LENGTH, ("No pending user Reads\n"));
  598. KeReleaseSpinLock( &PDevExt->ControlLock, Irql);
  599. //TEST_TRAP();
  600. }
  601. //
  602. // process serial Rx wait masks
  603. //
  604. ProcessSerialWaits(PDevExt);
  605. DbgDump(DBG_READ, ("<CheckForQueuedUserReads\n"));
  606. PERF_EXIT( PERF_CheckForQueuedUserReads );
  607. return;
  608. }
  609. #if !defined (USE_RING_BUFF)
  610. //
  611. // We have no ring-buffer.
  612. // Simply copy data from our USB read buffer into user's buffer.
  613. // Called with the control lock held.
  614. //
  615. // Returns the number of bytes copied.
  616. //
  617. __inline
  618. ULONG
  619. GetUserData(
  620. IN PDEVICE_EXTENSION PDevExt,
  621. IN PCHAR PDestBuff,
  622. IN ULONG RequestedLen,
  623. IN OUT PULONG PBytesCopied
  624. )
  625. {
  626. ULONG count;
  627. PERF_ENTRY( PERF_GetUserData );
  628. DbgDump(DBG_READ, (">GetUserData (%p)\n", PDevExt->DeviceObject ));
  629. count = min(PDevExt->UsbReadBuffChars, RequestedLen);
  630. if (count) {
  631. memcpy( PDestBuff, &PDevExt->UsbReadBuff[PDevExt->UsbReadBuffIndex], count);
  632. PDevExt->UsbReadBuffIndex += count;
  633. PDevExt->UsbReadBuffChars -= count;
  634. PDevExt->NumberNeededForRead -= count;
  635. *PBytesCopied += count;
  636. PDevExt->ReadByIsr += count;
  637. }
  638. #if DBG
  639. // temp hack to debug iPAQ 'CLIENT' indications
  640. if ((DebugLevel & DBG_DUMP_READS) && (count <= 6))
  641. {
  642. ULONG i;
  643. KdPrint(("RD1(%d): ", count));
  644. for (i = 0; i < count; i++) {
  645. KdPrint(("%02x ", PDestBuff[i] & 0xFF));
  646. }
  647. KdPrint(("\n"));
  648. }
  649. #endif
  650. DbgDump(DBG_READ, ("<GetUserData 0x%x\n", count ));
  651. PERF_EXIT( PERF_GetUserData );
  652. return count;
  653. }
  654. /*
  655. We have no ring buffer.
  656. Simply update the USB read buffer's count & index
  657. and process serial chars.
  658. Called with the ControlLock held.
  659. */
  660. __inline
  661. VOID
  662. PutUserData(
  663. IN PDEVICE_EXTENSION PDevExt,
  664. IN ULONG Count
  665. )
  666. {
  667. PERF_ENTRY( PERF_PutUserData );
  668. ASSERT( PDevExt );
  669. DbgDump(DBG_READ, (">PutUserData %d\n", Count ));
  670. PDevExt->UsbReadBuffChars = Count;
  671. PDevExt->UsbReadBuffIndex = 0;
  672. ASSERT_SERIAL_PORT(PDevExt->SerialPort);
  673. PDevExt->SerialPort.HistoryMask |= SERIAL_EV_RXCHAR;
  674. // We have no concept of 80% full. If we blindly set it
  675. // then serial apps may go into flow handlers.
  676. // | SERIAL_EV_RX80FULL;
  677. //
  678. // Scan for RXFLAG char if needed
  679. //
  680. if (PDevExt->SerialPort.WaitMask & SERIAL_EV_RXFLAG) {
  681. ULONG i;
  682. for (i = 0; i < Count; i++) {
  683. if ( *((PUCHAR)&PDevExt->UsbReadBuff[PDevExt->UsbReadBuffIndex] + i)
  684. == PDevExt->SerialPort.SpecialChars.EventChar) {
  685. PDevExt->SerialPort.HistoryMask |= SERIAL_EV_RXFLAG;
  686. DbgDump(DBG_READ|DBG_EVENTS, ("Found SpecialChar: %x\n", PDevExt->SerialPort.SpecialChars.EventChar ));
  687. break;
  688. }
  689. }
  690. }
  691. DbgDump(DBG_READ, ("<PutUserData\n"));
  692. PERF_EXIT( PERF_PutUserData );
  693. return;
  694. }
  695. #else
  696. /*
  697. Ring-buffer version
  698. Copy the ring-buffer data into the user's buffer while checking for wrap around.
  699. Also must check if we exhaust the read buffer.
  700. Called with the ControlLock held.
  701. */
  702. __inline
  703. ULONG
  704. GetUserData(
  705. IN PDEVICE_EXTENSION PDevExt,
  706. IN PCHAR PDestBuff,
  707. IN ULONG RequestedLen,
  708. IN OUT PULONG PBytesCopied
  709. )
  710. {
  711. ULONG i, count;
  712. PERF_ENTRY( PERF_GetUserData );
  713. DbgDump(DBG_READ, (">GetUserData (%p)\n", PDevExt->DeviceObject ));
  714. count = min(PDevExt->RingBuff.CharsInBuff, RequestedLen);
  715. if (count) {
  716. for ( i = 0; i< count; i++) {
  717. // copy the ring buffer data into user's buffer
  718. PDestBuff[i] = *PDevExt->RingBuff.pHead;
  719. // bump head checking for wrap
  720. PDevExt->RingBuff.pHead = PDevExt->RingBuff.pBase + ((ULONG)(PDevExt->RingBuff.pHead + 1) % RINGBUFF_SIZE);
  721. }
  722. PDevExt->RingBuff.CharsInBuff -= count;
  723. PDevExt->NumberNeededForRead -= count;
  724. *PBytesCopied += count;
  725. PDevExt->ReadByIsr += count;
  726. }
  727. #if DBG
  728. if (DebugLevel & DBG_DUMP_READS)
  729. {
  730. ULONG i;
  731. KdPrint(("RD1(%d): ", count));
  732. for (i = 0; i < count; i++) {
  733. KdPrint(("%02x ", PDestBuff[i] & 0xFF));
  734. }
  735. KdPrint(("\n"));
  736. }
  737. #endif
  738. DbgDump(DBG_READ, ("<GetUserData 0x%x\n", count ));
  739. PERF_EXIT( PERF_GetUserData );
  740. return count;
  741. }
  742. /*
  743. Ring-buffer version
  744. Copy the USB Read buffer into the ring-buffer while checking for wrap around.
  745. The ring buffer is assummed to be at least the same size as the USB read buffer.
  746. This is a simple ring where writes occur at the tail, which can eventually overwrite the start of
  747. the user read buffer location at the head, if user is not consuming the data. If we overwrite the
  748. head then we must reset the head to be where we started the current write.
  749. Note: the USB read buffer is a simple char array, with it's current index = 0.
  750. Note: SerialPort ownership assummed.
  751. Called with the ControlLock held.
  752. Q: Should write an error log if an app has an open handle and we overrun the buffer?
  753. */
  754. __inline
  755. VOID
  756. PutUserData(
  757. IN PDEVICE_EXTENSION PDevExt,
  758. IN ULONG Count
  759. )
  760. {
  761. ULONG i;
  762. PUCHAR pPrevTail;
  763. PERF_ENTRY( PERF_PutUserData );
  764. ASSERT( PDevExt );
  765. ASSERT( PDevExt->RingBuff.pBase );
  766. ASSERT( PDevExt->RingBuff.pHead );
  767. ASSERT( PDevExt->RingBuff.pTail );
  768. ASSERT( PDevExt->RingBuff.Size >= PDevExt->UsbReadBuffSize );
  769. ASSERT_SERIAL_PORT(PDevExt->SerialPort);
  770. DbgDump(DBG_READ, (">PutUserData %d\n", Count ));
  771. pPrevTail = PDevExt->RingBuff.pTail;
  772. for ( i = 0; i < Count; i++) {
  773. // copy the USB data
  774. *PDevExt->RingBuff.pTail = PDevExt->UsbReadBuff[i];
  775. // check EV_RXFLAG while we are here
  776. if ( (PDevExt->SerialPort.WaitMask & SERIAL_EV_RXFLAG) &&
  777. (*PDevExt->RingBuff.pTail == PDevExt->SerialPort.SpecialChars.EventChar)) {
  778. PDevExt->SerialPort.HistoryMask |= SERIAL_EV_RXFLAG;
  779. DbgDump(DBG_READ|DBG_SERIAL, ("Found SpecialChar: %x\n", PDevExt->SerialPort.SpecialChars.EventChar ));
  780. }
  781. // bump tail checking for wrap
  782. PDevExt->RingBuff.pTail = PDevExt->RingBuff.pBase + ((ULONG)(PDevExt->RingBuff.pTail + 1) % PDevExt->RingBuff.Size);
  783. }
  784. //
  785. // bump count
  786. //
  787. if ( (PDevExt->RingBuff.CharsInBuff + Count) <= PDevExt->RingBuff.Size ) {
  788. PDevExt->RingBuff.CharsInBuff += Count;
  789. } else {
  790. //
  791. // Overrun condition. We could check for this first to save the above copy process,
  792. // but it's the unusual case. We could also optimize the above copy a bit, but still need
  793. // to check for EV_RXFLAG.
  794. //
  795. PDevExt->RingBuff.CharsInBuff = Count;
  796. PDevExt->RingBuff.pHead = pPrevTail;
  797. #if PERFORMANCE
  798. PDevExt->TtlRingBuffOverruns.QuadPart ++;
  799. #endif
  800. }
  801. PDevExt->SerialPort.HistoryMask |= SERIAL_EV_RXCHAR;
  802. //
  803. // Check for 80% full.
  804. // We currently signal this at 50% since we run at a raised IRQL and serial apps are slow.
  805. //
  806. if ( PDevExt->RingBuff.CharsInBuff > RINGBUFF_HIGHWATER_MARK ) {
  807. DbgDump(DBG_READ|DBG_READ_LENGTH|DBG_SERIAL|DBG_WRN, ("SERIAL_EV_RX80FULL\n"));
  808. PDevExt->SerialPort.HistoryMask |= SERIAL_EV_RX80FULL;
  809. }
  810. DbgDump(DBG_READ, ("<PutUserData\n"));
  811. PERF_EXIT( PERF_PutUserData );
  812. return;
  813. }
  814. #endif // USE_RING_BUFF
  815. //
  816. // This routine requests USB to cancel our USB Read Irp.
  817. //
  818. // Note: it is the responsibility of the caller to
  819. // reset the read state to IRP_STATE_COMPLETE and restart USB reads
  820. // when this routine completes. Else, no more reads will get posted.
  821. // Note: when the USB Read Irp is cancelled the pending USB read packet
  822. // is cancelled via the USB Read completion routine.
  823. // Note: must be called at PASSIVE_LEVEL.
  824. //
  825. NTSTATUS
  826. CancelUsbReadIrp(
  827. IN PDEVICE_OBJECT PDevObj
  828. )
  829. {
  830. PDEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  831. NTSTATUS status = STATUS_SUCCESS;
  832. NTSTATUS wait_status;
  833. KIRQL irql;
  834. PERF_ENTRY( PERF_CancelUsbReadIrp );
  835. DbgDump(DBG_READ|DBG_IRP, (">CancelUsbReadIrp\n"));
  836. KeAcquireSpinLock(&pDevExt->ControlLock, &irql);
  837. if ( pDevExt->UsbReadIrp ) {
  838. switch (pDevExt->UsbReadState) {
  839. //case IRP_STATE_START:
  840. case IRP_STATE_PENDING:
  841. {
  842. //
  843. // the Irp is pending somewhere down the USB stack...
  844. //
  845. PVOID Objects[2] = { &pDevExt->PendingDataInEvent,
  846. &pDevExt->UsbReadCancelEvent };
  847. //
  848. // signal we need to cancel the Irp
  849. //
  850. pDevExt->UsbReadState = IRP_STATE_CANCELLED;
  851. KeReleaseSpinLock(&pDevExt->ControlLock, irql);
  852. if ( !IoCancelIrp( pDevExt->UsbReadIrp ) ) {
  853. //
  854. // This means USB has the UsbReadIrp in a non-canceable state.
  855. // We still need to wait for either the pending read event, or the cancel event.
  856. //
  857. DbgDump(DBG_READ|DBG_IRP, ("Irp (%p) was not cancelled\n", pDevExt->UsbReadIrp ));
  858. // TEST_TRAP();
  859. }
  860. DbgDump(DBG_READ|DBG_IRP, ("Waiting for pending UsbReadIrp (%p) to cancel...\n", pDevExt->UsbReadIrp ));
  861. PAGED_CODE();
  862. wait_status = KeWaitForMultipleObjects(
  863. 2,
  864. Objects,
  865. WaitAny,
  866. Executive,
  867. KernelMode,
  868. FALSE,
  869. NULL,
  870. NULL );
  871. DbgDump(DBG_READ|DBG_IRP, ("...UsbReadIrp (%p) signalled by: %d\n", pDevExt->UsbReadIrp, wait_status ));
  872. //
  873. // At this point the read packet is back on our list
  874. // and we have the Irp back from USB
  875. //
  876. }
  877. break;
  878. case IRP_STATE_COMPLETE:
  879. pDevExt->UsbReadState = IRP_STATE_CANCELLED;
  880. KeReleaseSpinLock(&pDevExt->ControlLock, irql);
  881. break;
  882. default:
  883. DbgDump(DBG_ERR, ("CancelUsbReadIrp - Invalid UsbReadState: 0x%x\n", pDevExt->UsbReadState ));
  884. TEST_TRAP();
  885. KeReleaseSpinLock(&pDevExt->ControlLock, irql);
  886. break;
  887. }
  888. if ( (IRP_STATE_CANCELLED != pDevExt->UsbReadState) ||
  889. (0 != pDevExt->PendingReadCount) ) {
  890. DbgDump(DBG_ERR, ("CancelUsbReadIrp error: UsbReadState: 0x%x \tPendingReadCount: 0x%x\n", pDevExt->UsbReadState, pDevExt->PendingReadCount ));
  891. //TEST_TRAP();
  892. }
  893. } else {
  894. status = STATUS_UNSUCCESSFUL;
  895. DbgDump(DBG_ERR, ("No Read Irp\n" ));
  896. KeReleaseSpinLock(&pDevExt->ControlLock, irql);
  897. // TEST_TRAP();
  898. }
  899. DbgDump(DBG_READ|DBG_IRP, ("<CancelUsbReadIrp\n"));
  900. PERF_EXIT( PERF_CancelUsbReadIrp );
  901. return status;
  902. }
  903. //
  904. // Work item queued from USB read timeout
  905. // to Cancel the USB read irp pending in the USB stack
  906. //
  907. VOID
  908. CancelUsbReadWorkItem(
  909. IN PWCE_WORK_ITEM PWorkItem
  910. )
  911. {
  912. PDEVICE_OBJECT pDevObj = PWorkItem->DeviceObject;
  913. PDEVICE_EXTENSION pDevExt = pDevObj->DeviceExtension;
  914. NTSTATUS status = STATUS_DELETE_PENDING;
  915. KIRQL irql;
  916. PERF_ENTRY( PERF_CancelUsbReadWorkItem );
  917. DbgDump(DBG_INT|DBG_READ|DBG_WORK_ITEMS, (">CancelUsbReadWorkItem(%p)\n", pDevObj ));
  918. KeAcquireSpinLock( &pDevExt->ControlLock, &irql);
  919. if (IRP_STATE_PENDING == pDevExt->UsbReadState) {
  920. KeReleaseSpinLock( &pDevExt->ControlLock, irql);
  921. status = CancelUsbReadIrp( pDevObj );
  922. InterlockedExchange(&pDevExt->UsbReadState, IRP_STATE_COMPLETE);
  923. } else {
  924. KeReleaseSpinLock( &pDevExt->ControlLock, irql);
  925. }
  926. DequeueWorkItem( pDevObj, PWorkItem );
  927. DbgDump(DBG_INT|DBG_READ|DBG_WORK_ITEMS, ("<CancelUsbReadWorkItem 0x%x\n", status ));
  928. PAGED_CODE(); // we must exit at passive level
  929. PERF_EXIT( PERF_CancelUsbReadWorkItem );
  930. return;
  931. }
  932. //
  933. // USB read timeout set on a read packet in UsbRead.
  934. // Runs at DISPATCH_LEVEL.
  935. //
  936. VOID
  937. UsbReadTimeout(
  938. IN PKDPC PDpc,
  939. IN PVOID DeferredContext,
  940. IN PVOID SystemContext1,
  941. IN PVOID SystemContext2
  942. )
  943. {
  944. PUSB_PACKET pPacket = (PUSB_PACKET)DeferredContext;
  945. PDEVICE_EXTENSION pDevExt = pPacket->DeviceExtension;
  946. PDEVICE_OBJECT pDevObj = pDevExt->DeviceObject;
  947. NTSTATUS status; // = STATUS_TIMEOUT;
  948. KIRQL irql;
  949. #if DBG
  950. LARGE_INTEGER currentTime;
  951. #endif
  952. UNREFERENCED_PARAMETER( PDpc );
  953. UNREFERENCED_PARAMETER( SystemContext1 );
  954. UNREFERENCED_PARAMETER( SystemContext2 );
  955. DbgDump(DBG_INT|DBG_READ, (">UsbReadTimeout\n"));
  956. if (pPacket && pDevExt && pDevObj) {
  957. //
  958. // sync with completion routine putting packet back on list
  959. //
  960. KeAcquireSpinLock( &pDevExt->ControlLock, &irql);
  961. if ( !pPacket || !pPacket->Irp ||
  962. (STATUS_ALERTED == pPacket->Status) ) {
  963. status = STATUS_ALERTED;
  964. DbgDump(DBG_INT|DBG_READ, ("STATUS_ALERTED\n" ));
  965. KeReleaseSpinLock( &pDevExt->ControlLock, irql );
  966. } else {
  967. //
  968. // queue a passive work item to cancel the USB read irp
  969. //
  970. KeReleaseSpinLock( &pDevExt->ControlLock, irql );
  971. #if DBG
  972. KeQuerySystemTime(&currentTime);
  973. DbgDump(DBG_INT, ("INT Read Timeout occured in < %I64d msec\n", ((currentTime.QuadPart - pDevExt->LastIntReadTime.QuadPart)/(LONGLONG)10000) ));
  974. #endif
  975. status = QueueWorkItem( pDevObj,
  976. CancelUsbReadWorkItem,
  977. NULL,
  978. 0);
  979. }
  980. } else {
  981. status = STATUS_INVALID_PARAMETER;
  982. DbgDump(DBG_ERR, ("UsbReadTimeout: 0x%x\n", status ));
  983. TEST_TRAP();
  984. }
  985. DbgDump(DBG_INT|DBG_READ, ("<UsbReadTimeout (0x%x)\n", status ));
  986. return;
  987. }
  988. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  989. //
  990. // User read section
  991. //
  992. NTSTATUS
  993. Read(
  994. IN PDEVICE_OBJECT PDevObj,
  995. IN PIRP PIrp)
  996. {
  997. PDEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  998. NTSTATUS status = STATUS_SUCCESS;
  999. PIO_STACK_LOCATION pIrpSp;
  1000. PERF_ENTRY( PERF_Read );
  1001. DbgDump(DBG_READ|DBG_TRACE, (">Read (%p, %p)\n", PDevObj, PIrp ));
  1002. if ( !CanAcceptIoRequests( pDevExt->DeviceObject, TRUE, TRUE) ) {
  1003. status = PIrp->IoStatus.Status = STATUS_DELETE_PENDING;
  1004. IoCompleteRequest (PIrp, IO_SERIAL_INCREMENT );
  1005. DbgDump(DBG_ERR, ("Read: 0x%x\n", status ));
  1006. PERF_EXIT( PERF_Read );
  1007. return status;
  1008. }
  1009. //
  1010. // set return values to something known
  1011. //
  1012. PIrp->IoStatus.Information = 0;
  1013. pIrpSp = IoGetCurrentIrpStackLocation(PIrp);
  1014. if (pIrpSp->Parameters.Read.Length != 0) {
  1015. status = AcquireRemoveLock(&pDevExt->RemoveLock, PIrp);
  1016. if ( !NT_SUCCESS(status) ) {
  1017. DbgDump(DBG_ERR, ("Read:(0x%x)\n", status));
  1018. PIrp->IoStatus.Status = status;
  1019. IoCompleteRequest(PIrp, IO_NO_INCREMENT);
  1020. return status;
  1021. }
  1022. DbgDump(DBG_READ_LENGTH, ("User Read (%p) length: %d\n", PIrp, pIrpSp->Parameters.Read.Length ));
  1023. status = StartOrQueueIrp( pDevExt,
  1024. PIrp,
  1025. &pDevExt->UserReadQueue,
  1026. &pDevExt->UserReadIrp,
  1027. StartUserRead);
  1028. } else {
  1029. PIrp->IoStatus.Status = status = STATUS_SUCCESS;
  1030. PIrp->IoStatus.Information = 0;
  1031. IoCompleteRequest(PIrp, IO_SERIAL_INCREMENT);
  1032. }
  1033. DbgDump(DBG_READ|DBG_TRACE, ("<Read 0x%x\n", status));
  1034. PERF_EXIT( PERF_Read );
  1035. return status;
  1036. }
  1037. NTSTATUS
  1038. StartOrQueueIrp(
  1039. IN PDEVICE_EXTENSION PDevExt,
  1040. IN PIRP PIrp,
  1041. IN PLIST_ENTRY PQueue,
  1042. IN PIRP *PPCurrentIrp,
  1043. IN PSTART_ROUTINE Starter)
  1044. /*++
  1045. Routine Description:
  1046. This function is used to either start processing an I/O request or to
  1047. queue it on the appropriate queue if a request is already pending or
  1048. requests may not be started.
  1049. Arguments:
  1050. PDevExt - A pointer to the DeviceExtension.
  1051. PIrp - A pointer to the IRP that is being started or queued.
  1052. PQueue - A pointer to the queue to place the IRP on if necessary.
  1053. PPCurrentIrp - A pointer to the pointer to the currently active I/O IRP.
  1054. Starter - Function to call if we decide to start this IRP.
  1055. Return Value:
  1056. NTSTATUS
  1057. --*/
  1058. {
  1059. KIRQL irql;
  1060. NTSTATUS status;
  1061. PERF_ENTRY( PERF_StartOrQueueIrp );
  1062. DbgDump(DBG_READ|DBG_TRACE, (">StartOrQueueIrp (%p, %p)\n", PDevExt->DeviceObject, PIrp ));
  1063. //
  1064. // Make sure the device is accepting request
  1065. //
  1066. if ( !CanAcceptIoRequests( PDevExt->DeviceObject, TRUE, TRUE) ) {
  1067. status = PIrp->IoStatus.Status = STATUS_DELETE_PENDING;
  1068. ReleaseRemoveLock(&PDevExt->RemoveLock, PIrp);
  1069. IoCompleteRequest (PIrp, IO_SERIAL_INCREMENT );
  1070. DbgDump(DBG_ERR, ("StartOrQueueIrp 0x%x\n", status ));
  1071. PERF_EXIT( PERF_StartOrQueueIrp );
  1072. return status;
  1073. }
  1074. KeAcquireSpinLock( &PDevExt->ControlLock, &irql );
  1075. //
  1076. // if nothing is pending then start this new irp
  1077. //
  1078. if (IsListEmpty(PQueue) && (NULL == *PPCurrentIrp)) {
  1079. *PPCurrentIrp = PIrp;
  1080. KeReleaseSpinLock( &PDevExt->ControlLock, irql );
  1081. status = Starter(PDevExt);
  1082. DbgDump(DBG_READ, ("<StartOrQueueIrp 0x%x\n", status ));
  1083. PERF_EXIT( PERF_StartOrQueueIrp );
  1084. return status;
  1085. }
  1086. //
  1087. // We're queueing the irp, so we need a cancel routine -- make sure
  1088. // the irp hasn't already been cancelled.
  1089. //
  1090. if (PIrp->Cancel) {
  1091. //
  1092. // The IRP was apparently cancelled. Complete it.
  1093. //
  1094. KeReleaseSpinLock( &PDevExt->ControlLock, irql );
  1095. PIrp->IoStatus.Status = STATUS_CANCELLED;
  1096. ReleaseRemoveLock(&PDevExt->RemoveLock, PIrp);
  1097. IoCompleteRequest(PIrp, IO_SERIAL_INCREMENT);
  1098. DbgDump(DBG_READ|DBG_TRACE, ("<StartOrQueueIrp 0x%x\n", STATUS_CANCELLED ));
  1099. PERF_EXIT( PERF_StartOrQueueIrp );
  1100. return STATUS_CANCELLED;
  1101. }
  1102. //
  1103. // Mark as pending, attach our cancel routine, put on our wait list
  1104. //
  1105. PIrp->IoStatus.Status = STATUS_PENDING;
  1106. IoMarkIrpPending(PIrp);
  1107. InsertTailList(PQueue, &PIrp->Tail.Overlay.ListEntry);
  1108. ASSERT ( !PIrp->CancelRoutine );
  1109. IoSetCancelRoutine(PIrp, CancelQueuedIrp);
  1110. KeReleaseSpinLock( &PDevExt->ControlLock, irql );
  1111. DbgDump(DBG_READ, ("<StartOrQueueIrp 0x%x\n", STATUS_PENDING ));
  1112. PERF_EXIT( PERF_StartOrQueueIrp );
  1113. return STATUS_PENDING;
  1114. }
  1115. NTSTATUS
  1116. StartUserRead(
  1117. IN PDEVICE_EXTENSION PDevExt
  1118. )
  1119. /*++
  1120. Routine Description:
  1121. This routine processes the active user read request by initializing any timers,
  1122. doing the initial submission to the read state machine, etc.
  1123. Arguments:
  1124. PDevExt - Pointer to the device extension for the device to start a read on
  1125. Return Value:
  1126. NTSTATUS
  1127. --*/
  1128. {
  1129. NTSTATUS status = STATUS_SUCCESS;
  1130. BOOLEAN bSetStatus = FALSE;
  1131. KIRQL irql;
  1132. PIRP newIrp = NULL;
  1133. ULONG readLen;
  1134. ULONG multiplierVal = 0;
  1135. ULONG constantVal = 0;
  1136. ULONG ulNumberNeededForRead = 0;
  1137. BOOLEAN useTotalTimer = FALSE;
  1138. BOOLEAN returnWithWhatsPresent = FALSE;
  1139. BOOLEAN os2ssreturn = FALSE;
  1140. BOOLEAN crunchDownToOne = FALSE;
  1141. BOOLEAN useIntervalTimer = FALSE;
  1142. SERIAL_TIMEOUTS timeoutsForIrp;
  1143. LARGE_INTEGER totalTime = {0,0};
  1144. BOOLEAN bControlLockReleased = FALSE;
  1145. PERF_ENTRY( PERF_StartUserRead );
  1146. do {
  1147. if ( !PDevExt || !PDevExt->DeviceObject ) {
  1148. DbgDump(DBG_ERR, ("StartUserRead: NO Extension\n"));
  1149. status = STATUS_UNSUCCESSFUL;
  1150. TEST_TRAP();
  1151. break;
  1152. }
  1153. DbgDump(DBG_READ, (">StartUserRead (%p, %p)\n", PDevExt->DeviceObject, PDevExt->UserReadIrp ));
  1154. //
  1155. // get user's read request parameters
  1156. //
  1157. bControlLockReleased = FALSE;
  1158. KeAcquireSpinLock(&PDevExt->ControlLock, &irql);
  1159. // ensure we have a user Irp to play with
  1160. if ( !PDevExt->UserReadIrp ) {
  1161. DbgDump(DBG_ERR, ("StartUserRead: NO UserReadIrp!!\n"));
  1162. KeReleaseSpinLock( &PDevExt->ControlLock, irql);
  1163. status = STATUS_UNSUCCESSFUL;
  1164. TEST_TRAP();
  1165. break;
  1166. }
  1167. // ensure the timers were removed from an earilier read
  1168. if ( KeCancelTimer(&PDevExt->ReadRequestTotalTimer) ||
  1169. KeCancelTimer(&PDevExt->ReadRequestIntervalTimer) )
  1170. {
  1171. DbgDump(DBG_ERR, ("StartUserRead: Timer not cancelled !!\n"));
  1172. TEST_TRAP();
  1173. }
  1174. //
  1175. // Always initialize the timer objects so that the
  1176. // completion code can tell when it attempts to
  1177. // cancel the timers whether the timers had ever
  1178. // been Set.
  1179. //
  1180. KeInitializeTimer(&PDevExt->ReadRequestTotalTimer);
  1181. KeInitializeTimer(&PDevExt->ReadRequestIntervalTimer);
  1182. IRP_SET_REFERENCE(PDevExt->UserReadIrp, IRP_REF_RX_BUFFER);
  1183. readLen = IoGetCurrentIrpStackLocation(PDevExt->UserReadIrp)->Parameters.Read.Length;
  1184. PDevExt->NumberNeededForRead = readLen;
  1185. PDevExt->ReadByIsr = 0;
  1186. DbgDump(DBG_READ|DBG_TIME, ("NumberNeededForRead: %d\n", PDevExt->NumberNeededForRead ));
  1187. DbgDump(DBG_READ|DBG_TIME, ("ReadByIsr: %d\n", PDevExt->ReadByIsr ));
  1188. ASSERT_SERIAL_PORT( PDevExt->SerialPort );
  1189. timeoutsForIrp = PDevExt->SerialPort.Timeouts;
  1190. PDevExt->CountOnLastRead = 0;
  1191. //
  1192. // determine which timeouts we need to calculate for the read
  1193. //
  1194. if (timeoutsForIrp.ReadIntervalTimeout
  1195. && (timeoutsForIrp.ReadIntervalTimeout != MAXULONG)) {
  1196. useIntervalTimer = TRUE;
  1197. }
  1198. if (timeoutsForIrp.ReadIntervalTimeout == MAXULONG) {
  1199. //
  1200. // We need to do special return quickly stuff here.
  1201. //
  1202. //
  1203. // 1) If both constant and multiplier are
  1204. // 0 then we return immediately with whatever
  1205. // we've got, even if it was zero.
  1206. //
  1207. if (!timeoutsForIrp.ReadTotalTimeoutConstant
  1208. && !timeoutsForIrp.ReadTotalTimeoutMultiplier) {
  1209. returnWithWhatsPresent = TRUE;
  1210. }
  1211. //
  1212. // 2) If constant and multiplier are not MAXULONG
  1213. // then return immediately if any characters
  1214. // are present, but if nothing is there, then
  1215. // use the timeouts as specified.
  1216. //
  1217. else if ((timeoutsForIrp.ReadTotalTimeoutConstant != MAXULONG)
  1218. && (timeoutsForIrp.ReadTotalTimeoutMultiplier
  1219. != MAXULONG)) {
  1220. useTotalTimer = TRUE;
  1221. os2ssreturn = TRUE;
  1222. multiplierVal = timeoutsForIrp.ReadTotalTimeoutMultiplier;
  1223. constantVal = timeoutsForIrp.ReadTotalTimeoutConstant;
  1224. }
  1225. //
  1226. // 3) If multiplier is MAXULONG then do as in
  1227. // "2" but return when the first character
  1228. // arrives.
  1229. //
  1230. else if ((timeoutsForIrp.ReadTotalTimeoutConstant != MAXULONG)
  1231. && (timeoutsForIrp.ReadTotalTimeoutMultiplier
  1232. == MAXULONG)) {
  1233. useTotalTimer = TRUE;
  1234. os2ssreturn = TRUE;
  1235. crunchDownToOne = TRUE;
  1236. multiplierVal = 0;
  1237. constantVal = timeoutsForIrp.ReadTotalTimeoutConstant;
  1238. }
  1239. } else {
  1240. //
  1241. // If both the multiplier and the constant are
  1242. // zero then don't do any total timeout processing.
  1243. //
  1244. if (timeoutsForIrp.ReadTotalTimeoutMultiplier
  1245. || timeoutsForIrp.ReadTotalTimeoutConstant) {
  1246. //
  1247. // We have some timer values to calculate
  1248. //
  1249. useTotalTimer = TRUE;
  1250. multiplierVal = timeoutsForIrp.ReadTotalTimeoutMultiplier;
  1251. constantVal = timeoutsForIrp.ReadTotalTimeoutConstant;
  1252. }
  1253. }
  1254. if (useTotalTimer) {
  1255. ulNumberNeededForRead = PDevExt->NumberNeededForRead;
  1256. }
  1257. // bump total request count
  1258. PDevExt->TtlReadRequests++;
  1259. //
  1260. // see if we have any read data already available
  1261. //
  1262. #if defined (USE_RING_BUFF)
  1263. if (PDevExt->RingBuff.CharsInBuff) {
  1264. #else
  1265. if (PDevExt->UsbReadBuffChars) {
  1266. #endif
  1267. #if DBG
  1268. ULONG charsRead =
  1269. #endif
  1270. GetUserData( PDevExt,
  1271. ((PUCHAR)(PDevExt->UserReadIrp->AssociatedIrp.SystemBuffer))
  1272. + readLen - PDevExt->NumberNeededForRead,
  1273. PDevExt->NumberNeededForRead,
  1274. (PULONG)&PDevExt->UserReadIrp->IoStatus.Information );
  1275. } else {
  1276. DbgDump(DBG_READ|DBG_READ_LENGTH, ("No immediate Read data\n"));
  1277. }
  1278. //
  1279. // Try to kick start another USB read.
  1280. //
  1281. if ( START_ANOTHER_USBREAD(PDevExt) ) {
  1282. KeReleaseSpinLock(&PDevExt->ControlLock, irql);
  1283. UsbRead( PDevExt,
  1284. (BOOLEAN)(PDevExt->IntPipe.hPipe ? TRUE : FALSE) );
  1285. bControlLockReleased = FALSE;
  1286. KeAcquireSpinLock(&PDevExt->ControlLock, &irql);
  1287. }
  1288. if ( !PDevExt->UserReadIrp ) {
  1289. //
  1290. // it's possible that we completed the read Irp already
  1291. // in the above cycle
  1292. //
  1293. DbgDump(DBG_READ, ("UsbReadIrp already completed(1)\n"));
  1294. } else if (returnWithWhatsPresent || (PDevExt->NumberNeededForRead == 0)
  1295. || (os2ssreturn && PDevExt->UsbReadIrp->IoStatus.Information)) {
  1296. //
  1297. // See if this read is complete
  1298. //
  1299. ASSERT( PDevExt->UserReadIrp );
  1300. #if DBG
  1301. if ( DebugLevel & DBG_READ_LENGTH)
  1302. {
  1303. ULONG count;
  1304. if (PDevExt->UserReadIrp->IoStatus.Status == STATUS_SUCCESS) {
  1305. count = (ULONG)PDevExt->UserReadIrp->IoStatus.Information;
  1306. } else {
  1307. count = 0;
  1308. }
  1309. KdPrint(("RD3: RL(%d) C(%d) I(%p)\n",
  1310. IoGetCurrentIrpStackLocation(PDevExt->UserReadIrp)->Parameters.Read.Length,
  1311. count,
  1312. PDevExt->UserReadIrp));
  1313. }
  1314. #endif
  1315. //
  1316. // Update the amount of chars left in the ring buffer
  1317. //
  1318. PDevExt->UserReadIrp->IoStatus.Status = STATUS_SUCCESS;
  1319. if (!bSetStatus) {
  1320. status = STATUS_SUCCESS;
  1321. bSetStatus = TRUE;
  1322. }
  1323. } else {
  1324. //
  1325. // The irp has the chance to timeout
  1326. //
  1327. IRP_INIT_REFERENCE(PDevExt->UserReadIrp);
  1328. //
  1329. // Check to see if it needs to be cancelled
  1330. //
  1331. if (PDevExt->UserReadIrp->Cancel) {
  1332. PDevExt->UserReadIrp->IoStatus.Status = STATUS_CANCELLED;
  1333. PDevExt->UserReadIrp->IoStatus.Information = 0;
  1334. if (!bSetStatus) {
  1335. bSetStatus = TRUE;
  1336. status = STATUS_CANCELLED;
  1337. }
  1338. } else {
  1339. //
  1340. // If we are supposed to crunch the read down to
  1341. // one character, then update the read length
  1342. // in the irp and truncate the number needed for
  1343. // read down to one. Note that if we are doing
  1344. // this crunching, then the information must be
  1345. // zero (or we would have completed above) and
  1346. // the number needed for the read must still be
  1347. /// equal to the read length.
  1348. //
  1349. if (crunchDownToOne) {
  1350. PDevExt->NumberNeededForRead = 1;
  1351. IoGetCurrentIrpStackLocation(PDevExt->UserReadIrp)->Parameters.Read.Length = 1;
  1352. }
  1353. IRP_SET_REFERENCE(PDevExt->UserReadIrp, IRP_REF_RX_BUFFER);
  1354. IRP_SET_REFERENCE(PDevExt->UserReadIrp, IRP_REF_CANCEL);
  1355. if (useTotalTimer) {
  1356. CalculateTimeout( &totalTime,
  1357. ulNumberNeededForRead,
  1358. multiplierVal,
  1359. constantVal );
  1360. IRP_SET_REFERENCE(PDevExt->UserReadIrp, IRP_REF_TOTAL_TIMER);
  1361. DbgDump(DBG_READ|DBG_TIME, ("TotalReadTimeout for Irp %p due in %d msec\n", PDevExt->UserReadIrp, (totalTime.QuadPart/10000) ));
  1362. KeSetTimer(&PDevExt->ReadRequestTotalTimer,
  1363. totalTime,
  1364. &PDevExt->TotalReadTimeoutDpc);
  1365. }
  1366. if (useIntervalTimer) {
  1367. // relative time. Note we could lose the high order bit here
  1368. PDevExt->IntervalTime.QuadPart = MILLISEC_TO_100NANOSEC( (signed)timeoutsForIrp.ReadIntervalTimeout );
  1369. IRP_SET_REFERENCE(PDevExt->UserReadIrp, IRP_REF_INTERVAL_TIMER);
  1370. KeQuerySystemTime(&PDevExt->LastReadTime);
  1371. DbgDump(DBG_READ|DBG_TIME, ("ReadIntervalTimeout for Irp %p due in %d msec\n", PDevExt->UserReadIrp, (PDevExt->IntervalTime.QuadPart/10000) ));
  1372. KeSetTimer(&PDevExt->ReadRequestIntervalTimer,
  1373. PDevExt->IntervalTime,
  1374. &PDevExt->IntervalReadTimeoutDpc);
  1375. }
  1376. //
  1377. // Mark IRP as cancellable
  1378. //
  1379. ASSERT( PDevExt->UserReadIrp );
  1380. IoSetCancelRoutine( PDevExt->UserReadIrp,
  1381. CancelCurrentRead );
  1382. ASSERT( PDevExt->UserReadIrp );
  1383. IoMarkIrpPending( PDevExt->UserReadIrp );
  1384. bControlLockReleased = TRUE;
  1385. KeReleaseSpinLock(&PDevExt->ControlLock, irql);
  1386. if (!bSetStatus) {
  1387. //
  1388. // At this point the USB Read irp pending as the PDevExt->UsbReadIrp.
  1389. // Either a read timer will fire to complete or cancel the Read,
  1390. // or we hang indefinetly.
  1391. //
  1392. status = STATUS_PENDING;
  1393. }
  1394. }
  1395. DbgDump(DBG_READ, ("<StartUserRead (1) 0x%x\n", status ));
  1396. PERF_EXIT( PERF_StartUserRead );
  1397. return status;
  1398. }
  1399. //
  1400. // kick start the next queued user Read Irp
  1401. //
  1402. bControlLockReleased = TRUE;
  1403. KeReleaseSpinLock(&PDevExt->ControlLock, irql);
  1404. GetNextUserIrp( &PDevExt->UserReadIrp,
  1405. &PDevExt->UserReadQueue,
  1406. &newIrp,
  1407. TRUE,
  1408. PDevExt);
  1409. } while (newIrp != NULL);
  1410. DbgDump(DBG_READ, ("<StartUserRead (2) 0x%x\n", status ));
  1411. PERF_EXIT( PERF_StartUserRead );
  1412. return status;
  1413. }
  1414. VOID
  1415. GetNextUserIrp(
  1416. IN PIRP *PpCurrentOpIrp,
  1417. IN PLIST_ENTRY PQueueToProcess,
  1418. OUT PIRP *PpNextIrp,
  1419. IN BOOLEAN CompleteCurrent,
  1420. IN PDEVICE_EXTENSION PDevExt
  1421. )
  1422. /*++
  1423. Routine Description:
  1424. This function gets the next IRP off a queue, marks it as current,
  1425. and possibly completes the current IRP.
  1426. Arguments:
  1427. PpCurrentOpIrp - A pointer to the pointer to the current IRP.
  1428. PQueueToProcess - A pointer to the queue to get the next IRP from.
  1429. PpNextIrp - A pointer to the pointer to the next IRP to process.
  1430. CompleteCurrent - TRUE if we should complete the IRP that is current at
  1431. the time we are called.
  1432. PDevExt - A pointer to the device extension.
  1433. Return Value:
  1434. NTSTATUS
  1435. --*/
  1436. {
  1437. KIRQL irql;
  1438. PIRP pOldIrp;
  1439. PERF_ENTRY( PERF_GetNextUserIrp );
  1440. if ( !PpCurrentOpIrp || !PQueueToProcess || !PpNextIrp || !PDevExt ) {
  1441. DbgDump(DBG_ERR, ("GetNextUserIrp: missing parameter\n" ));
  1442. PERF_EXIT( PERF_GetNextUserIrp );
  1443. TEST_TRAP();
  1444. return;
  1445. }
  1446. DbgDump(DBG_IRP|DBG_READ, (">GetNextUserIrp (%p)\n", PDevExt->DeviceObject ));
  1447. KeAcquireSpinLock(&PDevExt->ControlLock, &irql);
  1448. pOldIrp = *PpCurrentOpIrp;
  1449. //
  1450. // Check to see if there is a new irp to start up
  1451. //
  1452. if ( !IsListEmpty(PQueueToProcess) ) {
  1453. PLIST_ENTRY pHeadOfList;
  1454. pHeadOfList = RemoveHeadList(PQueueToProcess);
  1455. *PpCurrentOpIrp = CONTAINING_RECORD(pHeadOfList, IRP,
  1456. Tail.Overlay.ListEntry);
  1457. IoSetCancelRoutine(*PpCurrentOpIrp, NULL);
  1458. } else {
  1459. *PpCurrentOpIrp = NULL;
  1460. }
  1461. *PpNextIrp = *PpCurrentOpIrp;
  1462. //
  1463. // Complete the current one if so requested
  1464. //
  1465. if ( pOldIrp && CompleteCurrent ) {
  1466. ASSERT(NULL == pOldIrp->CancelRoutine);
  1467. DbgDump(DBG_IRP|DBG_READ|DBG_READ_LENGTH|DBG_TRACE, ("IoCompleteRequest(1, %p) Status: 0x%x Btyes: %d\n",
  1468. pOldIrp, pOldIrp->IoStatus.Status, pOldIrp->IoStatus.Information ));
  1469. //
  1470. // bump ttl byte counter
  1471. //
  1472. PDevExt->TtlReadBytes += (ULONG)pOldIrp->IoStatus.Information;
  1473. ReleaseRemoveLock(&PDevExt->RemoveLock, pOldIrp);
  1474. KeReleaseSpinLock(&PDevExt->ControlLock, irql);
  1475. IoCompleteRequest(pOldIrp, IO_NO_INCREMENT );
  1476. } else {
  1477. KeReleaseSpinLock(&PDevExt->ControlLock, irql);
  1478. }
  1479. DbgDump(DBG_IRP|DBG_READ, ("Next Irp: %p\n", *PpNextIrp ));
  1480. DbgDump(DBG_IRP|DBG_READ|DBG_TRACE, ("<GetNextUserIrp\n" ));
  1481. PERF_EXIT( PERF_GetNextUserIrp );
  1482. return;
  1483. }
  1484. VOID
  1485. CancelCurrentRead(
  1486. IN PDEVICE_OBJECT PDevObj,
  1487. IN PIRP PIrp
  1488. )
  1489. /*++
  1490. Routine Description:
  1491. This routine is used to cancel the User's current read Irp.
  1492. Arguments:
  1493. PDevObj - Pointer to the device object for this device
  1494. PIrp - Pointer to the IRP to be canceled.
  1495. Return Value:
  1496. None.
  1497. --*/
  1498. {
  1499. PDEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  1500. KIRQL irql;
  1501. PERF_ENTRY( PERF_CancelCurrentRead );
  1502. DbgDump(DBG_READ|DBG_IRP, (">CancelCurrentRead (%p)\n", PDevObj ));
  1503. //
  1504. // we manage our own Irp queue, so release this ASAP
  1505. //
  1506. IoReleaseCancelSpinLock( PIrp->CancelIrql );
  1507. //
  1508. // We set this to indicate to the interval timer
  1509. // that the read has encountered a cancel.
  1510. //
  1511. // Recall that the interval timer dpc can be lurking in some
  1512. // DPC queue.
  1513. //
  1514. KeAcquireSpinLock(&pDevExt->ControlLock, &irql);
  1515. pDevExt->CountOnLastRead = SERIAL_COMPLETE_READ_CANCEL;
  1516. if ( pDevExt->UserReadIrp ) {
  1517. // grab the read irp
  1518. IRP_CLEAR_REFERENCE(pDevExt->UserReadIrp, IRP_REF_RX_BUFFER);
  1519. TryToCompleteCurrentIrp( pDevExt,
  1520. STATUS_CANCELLED,
  1521. &pDevExt->UserReadIrp,
  1522. &pDevExt->UserReadQueue,
  1523. &pDevExt->ReadRequestIntervalTimer,
  1524. &pDevExt->ReadRequestTotalTimer,
  1525. StartUserRead,
  1526. GetNextUserIrp,
  1527. IRP_REF_CANCEL,
  1528. TRUE,
  1529. irql );
  1530. } else {
  1531. //
  1532. // it is already gone
  1533. //
  1534. DbgDump( DBG_ERR, ("UserReadIrp already gone!\n" ));
  1535. KeReleaseSpinLock(&pDevExt->ControlLock, irql);
  1536. TEST_TRAP();
  1537. }
  1538. DbgDump(DBG_READ|DBG_IRP, ("<CancelCurrentRead\n" ));
  1539. PERF_EXIT( PERF_CancelCurrentRead );
  1540. return;
  1541. }
  1542. VOID
  1543. CancelQueuedIrp(
  1544. IN PDEVICE_OBJECT PDevObj,
  1545. IN PIRP PIrp
  1546. )
  1547. /*++
  1548. Routine Description:
  1549. This function is used as a cancel routine for queued irps.
  1550. Basically for us this means the user's Read IRPs.
  1551. Arguments:
  1552. PDevObj - A pointer to the serial device object.
  1553. PIrp - A pointer to the IRP that is being cancelled
  1554. Return Value:
  1555. VOID
  1556. --*/
  1557. {
  1558. PDEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  1559. PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(PIrp);
  1560. KIRQL irql;
  1561. PERF_ENTRY( PERF_CancelQueuedIrp );
  1562. DbgDump(DBG_READ|DBG_IRP|DBG_TRACE, (">CancelQueuedIrp (%p)\n", PDevObj ));
  1563. //
  1564. // we manage our own Irp queue, so release this ASAP
  1565. //
  1566. IoReleaseCancelSpinLock(PIrp->CancelIrql);
  1567. //
  1568. // The irp was cancelled -- remove it from the queue
  1569. //
  1570. KeAcquireSpinLock(&pDevExt->ControlLock, &irql);
  1571. PIrp->IoStatus.Status = STATUS_CANCELLED;
  1572. PIrp->IoStatus.Information = 0;
  1573. RemoveEntryList(&PIrp->Tail.Overlay.ListEntry);
  1574. ReleaseRemoveLock(&pDevExt->RemoveLock, PIrp);
  1575. KeReleaseSpinLock(&pDevExt->ControlLock, irql);
  1576. IoCompleteRequest(PIrp, IO_SERIAL_INCREMENT);
  1577. DbgDump(DBG_READ|DBG_IRP|DBG_TRACE, ("<CancelQueuedIrp\n" ));
  1578. PERF_EXIT( PERF_CancelQueuedIrp );
  1579. return;
  1580. }
  1581. VOID
  1582. ReadTimeout(
  1583. IN PKDPC PDpc,
  1584. IN PVOID DeferredContext,
  1585. IN PVOID SystemContext1,
  1586. IN PVOID SystemContext2
  1587. )
  1588. /*++
  1589. Routine Description:
  1590. This routine is used to complete a read because its total
  1591. timer has expired.
  1592. Arguments:
  1593. PDpc - Not Used.
  1594. DeferredContext - Really points to the device extension.
  1595. SystemContext1 - Not Used.
  1596. SystemContext2 - Not Used.
  1597. Return Value:
  1598. None.
  1599. --*/
  1600. {
  1601. PDEVICE_EXTENSION pDevExt = DeferredContext;
  1602. KIRQL oldIrql;
  1603. PERF_ENTRY( PERF_ReadTimeout );
  1604. UNREFERENCED_PARAMETER(PDpc);
  1605. UNREFERENCED_PARAMETER(SystemContext1);
  1606. UNREFERENCED_PARAMETER(SystemContext2);
  1607. DbgDump(DBG_TIME, (">ReadTimeout (%p)\n", pDevExt->DeviceObject ));
  1608. KeAcquireSpinLock(&pDevExt->ControlLock, &oldIrql);
  1609. if ( !CanAcceptIoRequests(pDevExt->DeviceObject, FALSE, TRUE) ) {
  1610. TEST_TRAP();
  1611. IRP_CLEAR_REFERENCE( pDevExt->UserReadIrp, IRP_REF_TOTAL_TIMER);
  1612. // manually set the cancel routine
  1613. IoSetCancelRoutine( pDevExt->UserReadIrp,
  1614. CancelCurrentRead );
  1615. KeReleaseSpinLock(&pDevExt->ControlLock, oldIrql);
  1616. IoCancelIrp(pDevExt->UserReadIrp);
  1617. PERF_EXIT( PERF_ReadTimeout );
  1618. return;
  1619. }
  1620. //
  1621. // We set this to indicate to the interval timer
  1622. // that the read has completed due to total timeout.
  1623. //
  1624. // Recall that the interval timer dpc can be lurking in some
  1625. // DPC queue.
  1626. //
  1627. pDevExt->CountOnLastRead = SERIAL_COMPLETE_READ_TOTAL;
  1628. // grab the read irp
  1629. IRP_CLEAR_REFERENCE(pDevExt->UserReadIrp, IRP_REF_RX_BUFFER);
  1630. DbgDump(DBG_TIME|DBG_READ_LENGTH, ("TotalReadTimeout for (%p)\n", pDevExt->UserReadIrp ));
  1631. TryToCompleteCurrentIrp( pDevExt,
  1632. STATUS_TIMEOUT,
  1633. &pDevExt->UserReadIrp,
  1634. &pDevExt->UserReadQueue,
  1635. &pDevExt->ReadRequestIntervalTimer,
  1636. &pDevExt->ReadRequestTotalTimer,
  1637. StartUserRead,
  1638. GetNextUserIrp,
  1639. IRP_REF_TOTAL_TIMER,
  1640. TRUE,
  1641. oldIrql );
  1642. DbgDump(DBG_TIME, ("<ReadTimeout\n"));
  1643. PERF_EXIT( PERF_ReadTimeout );
  1644. return;
  1645. }
  1646. VOID
  1647. IntervalReadTimeout(
  1648. IN PKDPC PDpc,
  1649. IN PVOID DeferredContext,
  1650. IN PVOID SystemContext1,
  1651. IN PVOID SystemContext2
  1652. )
  1653. /*++
  1654. Routine Description:
  1655. This routine is used timeout the request if the time between
  1656. characters exceed the interval time. A global is kept in
  1657. the device extension that records the count of characters read
  1658. the last the last time this routine was invoked (This dpc
  1659. will resubmit the timer if the count has changed). If the
  1660. count has not changed then this routine will attempt to complete
  1661. the irp. Note the special case of the last count being zero.
  1662. The timer isn't really in effect until the first character is
  1663. read.
  1664. Arguments:
  1665. PDpc - Not Used.
  1666. DeferredContext - Really points to the device extension.
  1667. SystemContext1 - Not Used.
  1668. SystemContext2 - Not Used.
  1669. Return Value:
  1670. None.
  1671. --*/
  1672. {
  1673. PDEVICE_EXTENSION pDevExt = DeferredContext;
  1674. KIRQL irql;
  1675. PERF_ENTRY( PERF_IntervalReadTimeout );
  1676. UNREFERENCED_PARAMETER(PDpc);
  1677. UNREFERENCED_PARAMETER(SystemContext1);
  1678. UNREFERENCED_PARAMETER(SystemContext2);
  1679. DbgDump(DBG_TIME, (">IntervalReadTimeout (%p)\n", pDevExt->DeviceObject ));
  1680. KeAcquireSpinLock(&pDevExt->ControlLock, &irql);
  1681. if ( !pDevExt->UserReadIrp ||
  1682. (IRP_REFERENCE_COUNT(pDevExt->UserReadIrp) & IRP_REF_INTERVAL_TIMER) == 0 ) {
  1683. //
  1684. // we already completed the read irp so just exit
  1685. //
  1686. DbgDump(DBG_TIME|DBG_IRP, ("Already completed User's Read Irp\n"));
  1687. KeReleaseSpinLock(&pDevExt->ControlLock, irql);
  1688. PERF_EXIT( PERF_IntervalReadTimeout );
  1689. return;
  1690. }
  1691. if ( !CanAcceptIoRequests(pDevExt->DeviceObject, FALSE, TRUE) ) {
  1692. IRP_CLEAR_REFERENCE( pDevExt->UserReadIrp, IRP_REF_INTERVAL_TIMER);
  1693. // manually set the cancel routine
  1694. IoSetCancelRoutine( pDevExt->UserReadIrp,
  1695. CancelCurrentRead );
  1696. KeReleaseSpinLock(&pDevExt->ControlLock, irql);
  1697. IoCancelIrp(pDevExt->UserReadIrp);
  1698. PERF_EXIT( PERF_IntervalReadTimeout );
  1699. return;
  1700. }
  1701. if (pDevExt->CountOnLastRead == SERIAL_COMPLETE_READ_TOTAL) {
  1702. //
  1703. // This value is only set by the total
  1704. // timer to indicate that it has fired.
  1705. // If so, then we should simply try to complete.
  1706. //
  1707. DbgDump(DBG_TIME, ("SERIAL_COMPLETE_READ_TOTAL\n"));
  1708. // grab the read irp
  1709. IRP_CLEAR_REFERENCE(pDevExt->UserReadIrp, IRP_REF_RX_BUFFER);
  1710. pDevExt->CountOnLastRead = 0;
  1711. TryToCompleteCurrentIrp( pDevExt,
  1712. STATUS_TIMEOUT,
  1713. &pDevExt->UserReadIrp,
  1714. &pDevExt->UserReadQueue,
  1715. &pDevExt->ReadRequestIntervalTimer,
  1716. &pDevExt->ReadRequestTotalTimer,
  1717. StartUserRead,
  1718. GetNextUserIrp,
  1719. IRP_REF_INTERVAL_TIMER,
  1720. TRUE,
  1721. irql );
  1722. } else if (pDevExt->CountOnLastRead == SERIAL_COMPLETE_READ_COMPLETE) {
  1723. //
  1724. // This value is only set by the regular completion routine.
  1725. // If so, then we should simply try to complete.
  1726. //
  1727. DbgDump(DBG_TIME|DBG_READ_LENGTH, ("SERIAL_COMPLETE_READ_COMPLETE\n"));
  1728. // grab the read irp
  1729. IRP_CLEAR_REFERENCE(pDevExt->UserReadIrp, IRP_REF_RX_BUFFER);
  1730. pDevExt->CountOnLastRead = 0;
  1731. TryToCompleteCurrentIrp( pDevExt,
  1732. STATUS_SUCCESS,
  1733. &pDevExt->UserReadIrp,
  1734. &pDevExt->UserReadQueue,
  1735. &pDevExt->ReadRequestIntervalTimer,
  1736. &pDevExt->ReadRequestTotalTimer,
  1737. StartUserRead,
  1738. GetNextUserIrp,
  1739. IRP_REF_INTERVAL_TIMER,
  1740. TRUE,
  1741. irql );
  1742. } else if (pDevExt->CountOnLastRead == SERIAL_COMPLETE_READ_CANCEL) {
  1743. //
  1744. // This value is only set by the cancel
  1745. // read routine.
  1746. //
  1747. // If so, then we should simply try to complete.
  1748. //
  1749. DbgDump(DBG_TIME, ("SERIAL_COMPLETE_READ_CANCEL\n"));
  1750. // grab the read irp
  1751. IRP_CLEAR_REFERENCE(pDevExt->UserReadIrp, IRP_REF_RX_BUFFER);
  1752. pDevExt->CountOnLastRead = 0;
  1753. TryToCompleteCurrentIrp( pDevExt,
  1754. STATUS_CANCELLED,
  1755. &pDevExt->UserReadIrp,
  1756. &pDevExt->UserReadQueue,
  1757. &pDevExt->ReadRequestIntervalTimer,
  1758. &pDevExt->ReadRequestTotalTimer,
  1759. StartUserRead,
  1760. GetNextUserIrp,
  1761. IRP_REF_INTERVAL_TIMER,
  1762. TRUE,
  1763. irql );
  1764. } else if (pDevExt->CountOnLastRead || pDevExt->ReadByIsr) {
  1765. //
  1766. // Something has happened since we last came here. We
  1767. // check to see if the ISR has read in any more characters.
  1768. // If it did then we should update the isr's read count
  1769. // and resubmit the timer.
  1770. //
  1771. if (pDevExt->ReadByIsr) {
  1772. DbgDump(DBG_TIME, ("ReadByIsr %d\n", pDevExt->ReadByIsr));
  1773. pDevExt->CountOnLastRead = pDevExt->ReadByIsr;
  1774. pDevExt->ReadByIsr = 0;
  1775. //
  1776. // Save off the "last" time something was read.
  1777. // As we come back to this routine we will compare
  1778. // the current time to the "last" time. If the
  1779. // difference is ever larger then the interval
  1780. // requested by the user, then time out the request.
  1781. //
  1782. KeQuerySystemTime(&pDevExt->LastReadTime);
  1783. DbgDump(DBG_TIME, ("ReadIntervalTimeout for Irp %p due in %d msec\n", pDevExt->UsbReadIrp, pDevExt->IntervalTime.QuadPart/10000 ));
  1784. KeSetTimer(&pDevExt->ReadRequestIntervalTimer,
  1785. pDevExt->IntervalTime,
  1786. &pDevExt->IntervalReadTimeoutDpc);
  1787. KeReleaseSpinLock(&pDevExt->ControlLock, irql);
  1788. } else {
  1789. //
  1790. // Take the difference between the current time
  1791. // and the last time we had characters and
  1792. // see if it is greater then the interval time.
  1793. // if it is, then time out the request. Otherwise
  1794. // restart the timer.
  1795. //
  1796. //
  1797. // No characters read in the interval time. Kill
  1798. // this read.
  1799. //
  1800. LARGE_INTEGER currentTime;
  1801. KeQuerySystemTime(&currentTime);
  1802. if ((currentTime.QuadPart - pDevExt->LastReadTime.QuadPart) >=
  1803. -(pDevExt->IntervalTime.QuadPart) ) { // absolute time
  1804. DbgDump(DBG_TIME, ("TIMEOUT - CountOnLastRead=%d ReadByIsr=%d\n", pDevExt->CountOnLastRead, pDevExt->ReadByIsr));
  1805. #if DBG
  1806. if (pDevExt->ReadByIsr > pDevExt->NumberNeededForRead ) {
  1807. // did we we forgot to clear ReadByIsr
  1808. TEST_TRAP();
  1809. }
  1810. #endif
  1811. // grab the read irp
  1812. IRP_CLEAR_REFERENCE(pDevExt->UserReadIrp, IRP_REF_RX_BUFFER);
  1813. pDevExt->CountOnLastRead = pDevExt->ReadByIsr = 0;
  1814. // return any chars read up to this point
  1815. TryToCompleteCurrentIrp( pDevExt,
  1816. STATUS_TIMEOUT,
  1817. &pDevExt->UserReadIrp,
  1818. &pDevExt->UserReadQueue,
  1819. &pDevExt->ReadRequestIntervalTimer,
  1820. &pDevExt->ReadRequestTotalTimer,
  1821. StartUserRead,
  1822. GetNextUserIrp,
  1823. IRP_REF_INTERVAL_TIMER,
  1824. TRUE,
  1825. irql );
  1826. } else {
  1827. DbgDump(DBG_TIME, ("ReadIntervalTimeout for Irp %p due in %d msec\n", pDevExt->UsbReadIrp, pDevExt->IntervalTime.QuadPart/10000 ));
  1828. KeSetTimer(&pDevExt->ReadRequestIntervalTimer,
  1829. pDevExt->IntervalTime,
  1830. &pDevExt->IntervalReadTimeoutDpc);
  1831. KeReleaseSpinLock(&pDevExt->ControlLock, irql);
  1832. }
  1833. }
  1834. } else {
  1835. //
  1836. // Timer doesn't really start until the first character.
  1837. // So we should simply resubmit ourselves.
  1838. //
  1839. DbgDump(DBG_TIME, ("ReadIntervalTimeout for Irp %p due in %d msec\n", pDevExt->UsbReadIrp, pDevExt->IntervalTime.QuadPart/10000 ));
  1840. KeSetTimer(&pDevExt->ReadRequestIntervalTimer,
  1841. pDevExt->IntervalTime,
  1842. &pDevExt->IntervalReadTimeoutDpc);
  1843. KeReleaseSpinLock(&pDevExt->ControlLock, irql);
  1844. }
  1845. DbgDump(DBG_TIME, ("<IntervalReadTimeout\n"));
  1846. PERF_EXIT( PERF_IntervalReadTimeout );
  1847. return;
  1848. }
  1849. // EOF