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

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