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.

1343 lines
35 KiB

  1. /*++
  2. Module Name:
  3. read.c
  4. Environment:
  5. Kernel mode
  6. Revision History :
  7. --*/
  8. #include "precomp.h"
  9. NTSTATUS
  10. MoxaRead(
  11. IN PDEVICE_OBJECT DeviceObject,
  12. IN PIRP Irp
  13. )
  14. {
  15. NTSTATUS status;
  16. PMOXA_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
  17. if ((extension->ControlDevice == TRUE)||
  18. (extension->DeviceIsOpened == FALSE) ||
  19. (extension->PowerState != PowerDeviceD0) ) {
  20. Irp->IoStatus.Status = STATUS_CANCELLED;
  21. Irp->IoStatus.Information=0L;
  22. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  23. return STATUS_CANCELLED;
  24. }
  25. // MoxaKdPrint(MX_DBG_TRACE,("Enter MoxaRead\n"));
  26. if ((status = MoxaIRPPrologue(Irp, extension)) != STATUS_SUCCESS) {
  27. MoxaCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  28. return status;
  29. }
  30. if (MoxaCompleteIfError(
  31. DeviceObject,
  32. Irp
  33. ) != STATUS_SUCCESS) {
  34. return STATUS_CANCELLED;
  35. }
  36. Irp->IoStatus.Information = 0L;
  37. //
  38. // Quick check for a zero length read. If it is zero length
  39. // then we are already done!
  40. //
  41. if (IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length) {
  42. //
  43. // Well it looks like we actually have to do some
  44. // work. Put the read on the queue so that we can
  45. // process it when our previous reads are done.
  46. //
  47. return MoxaStartOrQueue(
  48. extension,
  49. Irp,
  50. &extension->ReadQueue,
  51. &extension->CurrentReadIrp,
  52. MoxaStartRead
  53. );
  54. } else {
  55. Irp->IoStatus.Status = STATUS_SUCCESS;
  56. MoxaCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  57. return STATUS_SUCCESS;
  58. }
  59. }
  60. BOOLEAN
  61. MoxaLineInput(
  62. IN PVOID Context
  63. )
  64. {
  65. PMOXA_DEVICE_EXTENSION extension = Context;
  66. PIO_STACK_LOCATION irpSp;
  67. irpSp = IoGetCurrentIrpStackLocation(extension->CurrentReadIrp);
  68. LIterminater = *(PUCHAR)extension->CurrentReadIrp->AssociatedIrp.SystemBuffer;
  69. LIbufferSize = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
  70. LIdataBuffer = (PUCHAR)extension->CurrentReadIrp->AssociatedIrp.SystemBuffer;
  71. LIbase = extension->PortBase;
  72. LIofs = extension->PortOfs;
  73. LIbuff = LIbase + DynPage_addr;
  74. LIrptr = (PUSHORT)(LIofs + RXrptr);
  75. LIwptr = (PUSHORT)(LIofs + RXwptr);
  76. LIrxMask = *(PUSHORT)(LIofs + RX_mask);
  77. LIspage = *(PUSHORT)(LIofs + Page_rxb);
  78. LIepage = *(PUSHORT)(LIofs + EndPage_rxb);
  79. LIhead = *LIrptr;
  80. LItail = *LIwptr;
  81. LIcount = (LItail >= LIhead) ? (LItail - LIhead)
  82. : (LItail - LIhead + LIrxMask + 1);
  83. if (!LIcount) /* Rx buffer no data! */
  84. return FALSE;
  85. if (LIspage == LIepage) {
  86. LIbufHead = *(PUSHORT)(LIofs + Ofs_rxb);
  87. *(LIbase + Control_reg) = (UCHAR)LIspage;
  88. LIi = 0;
  89. do {
  90. LIi++;
  91. *LIdataBuffer = LIbuff[LIbufHead+LIhead++];
  92. LIhead &= LIrxMask;
  93. if (*LIdataBuffer == LIterminater)
  94. break;
  95. LIdataBuffer++;
  96. // if (LIhead == *LIwptr)
  97. if ( (LIhead == *LIwptr) && (LIi < LIbufferSize) )
  98. return FALSE;
  99. } while (LIi < LIbufferSize);
  100. }
  101. else {
  102. LIpageNo = LIspage + (LIhead >> 13);
  103. LIpageOfs = LIhead & Page_mask;
  104. *(LIbase + Control_reg) = (UCHAR)LIpageNo;
  105. LIi = 0;
  106. do {
  107. LIi++;
  108. *LIdataBuffer = LIbuff[LIpageOfs++];
  109. LIhead++;
  110. LIhead &= LIrxMask;
  111. if (*LIdataBuffer == LIterminater)
  112. break;
  113. LIdataBuffer++;
  114. // if (LIhead == *LIwptr)
  115. if ( (LIhead == *LIwptr) && (LIi < LIbufferSize) )
  116. return FALSE;
  117. if (LIpageOfs == Page_size) {
  118. if (++LIpageNo == LIepage)
  119. LIpageNo = LIspage;
  120. *(LIbase + Control_reg) = (UCHAR)LIpageNo;
  121. LIpageOfs = 0;
  122. }
  123. } while (LIi < LIbufferSize);
  124. }
  125. *LIrptr = LIhead;
  126. extension->CurrentReadIrp->IoStatus.Information = LIi;
  127. extension->PerfStats.ReceivedCount += LIi;
  128. if (*(LIofs + FlagStat) & Rx_xoff) {
  129. LIcount = (*LIwptr >= *LIrptr) ? (*LIwptr - *LIrptr)
  130. : (*LIwptr - *LIrptr + LIrxMask + 1);
  131. if (LIcount < extension->HandFlow.XonLimit)
  132. MoxaFuncWithDumbWait(LIofs, FC_SendXon, 0);
  133. }
  134. return FALSE;
  135. }
  136. BOOLEAN
  137. MoxaView(
  138. IN PVOID Context
  139. )
  140. {
  141. PMOXA_DEVICE_EXTENSION extension = Context;
  142. PIO_STACK_LOCATION irpSp;
  143. irpSp = IoGetCurrentIrpStackLocation(extension->CurrentReadIrp);
  144. LIbufferSize = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
  145. LIdataBuffer = (PUCHAR)extension->CurrentReadIrp->AssociatedIrp.SystemBuffer;
  146. LIbase = extension->PortBase;
  147. LIofs = extension->PortOfs;
  148. LIbuff = LIbase + DynPage_addr;
  149. LIrptr = (PUSHORT)(LIofs + RXrptr);
  150. LIwptr = (PUSHORT)(LIofs + RXwptr);
  151. LIrxMask = *(PUSHORT)(LIofs + RX_mask);
  152. LIspage = *(PUSHORT)(LIofs + Page_rxb);
  153. LIepage = *(PUSHORT)(LIofs + EndPage_rxb);
  154. LIhead = *LIrptr;
  155. LItail = *LIwptr;
  156. LIcount = (LItail >= LIhead) ? (LItail - LIhead)
  157. : (LItail - LIhead + LIrxMask + 1);
  158. if (!LIcount) /* Rx buffer no data! */
  159. return FALSE;
  160. if (LIcount > LIbufferSize)
  161. LIcount = (USHORT)LIbufferSize;
  162. LIlen = (USHORT)LIcount;
  163. if (LIspage == LIepage) {
  164. LIbufHead = *(PUSHORT)(LIofs + Ofs_rxb);
  165. *(LIbase + Control_reg) = (UCHAR)LIspage;
  166. if (LIhead & 1) {
  167. *LIdataBuffer++ = LIbuff[LIbufHead+LIhead++];
  168. LIhead &= LIrxMask;
  169. LIcount--;
  170. }
  171. LIcount2 = LIcount >> 1;
  172. while (LIcount2--) {
  173. *((PUSHORT)LIdataBuffer)++ = *(PUSHORT)&(LIbuff[LIbufHead+LIhead]);
  174. LIhead += 2;
  175. LIhead &= LIrxMask;
  176. }
  177. if (LIcount & 1) {
  178. *LIdataBuffer++ = LIbuff[LIbufHead+LIhead++];
  179. LIhead &= LIrxMask;
  180. }
  181. }
  182. else {
  183. LIpageNo = LIspage + (LIhead >> 13);
  184. LIpageOfs = LIhead & Page_mask;
  185. do {
  186. LIcnt = Page_size - LIpageOfs;
  187. if (LIcnt > LIcount)
  188. LIcnt = LIcount;
  189. LIcount -= LIcnt;
  190. if (LIcnt) {
  191. *(LIbase + Control_reg) = (UCHAR)LIpageNo;
  192. if (LIpageOfs & 1) {
  193. *LIdataBuffer++ = LIbuff[LIpageOfs++];
  194. LIcnt--;
  195. }
  196. LIcount2 = LIcnt >> 1;
  197. while (LIcount2--) {
  198. *((PUSHORT)LIdataBuffer)++ = *(PUSHORT)&(LIbuff[LIpageOfs]);
  199. LIpageOfs += 2;
  200. }
  201. if (LIcnt & 1)
  202. *LIdataBuffer++ = LIbuff[LIpageOfs++];
  203. }
  204. if (LIcount == 0)
  205. break;
  206. if (++LIpageNo == LIepage)
  207. LIpageNo = LIspage;
  208. LIpageOfs = 0;
  209. } while (TRUE);
  210. }
  211. extension->CurrentReadIrp->IoStatus.Information = LIlen;
  212. return FALSE;
  213. }
  214. BOOLEAN
  215. MoxaIn(
  216. IN PVOID Context
  217. )
  218. {
  219. PMOXA_DEVICE_EXTENSION extension = Context;
  220. extension->ReadCurrentChar = extension->CurrentReadIrp->AssociatedIrp.SystemBuffer;
  221. MoxaGetData(extension);
  222. return FALSE;
  223. }
  224. VOID
  225. MoxaGetData(
  226. IN PMOXA_DEVICE_EXTENSION Extension
  227. )
  228. {
  229. //KdPrint(("In MoxaGetData\n"));
  230. GDbase = Extension->PortBase;
  231. GDofs = Extension->PortOfs;
  232. GDbuff = GDbase + DynPage_addr;
  233. GDrptr = (PUSHORT)(GDofs + RXrptr);
  234. GDwptr = (PUSHORT)(GDofs + RXwptr);
  235. GDrxMask = *(PUSHORT)(GDofs + RX_mask);
  236. GDspage = *(PUSHORT)(GDofs + Page_rxb);
  237. GDepage = *(PUSHORT)(GDofs + EndPage_rxb);
  238. GDhead = *GDrptr;
  239. GDtail = *GDwptr;
  240. GDdataLen = Extension->NumberNeededForRead;
  241. GDreadChar = Extension->ReadCurrentChar;
  242. GDcount = (GDtail >= GDhead) ? (GDtail - GDhead)
  243. : (GDtail - GDhead + GDrxMask + 1);
  244. if (!GDcount) /* Rx buffer no data! */
  245. return;
  246. if (GDspage == GDepage) {
  247. GDbufHead = *(PUSHORT)(GDofs + Ofs_rxb);
  248. if (GDcount > GDdataLen)
  249. GDcount = (USHORT)GDdataLen;
  250. GDdataLen -= GDcount;
  251. GDlen = GDcount;
  252. *(GDbase + Control_reg) = (UCHAR)GDspage;
  253. if (GDhead & 1) {
  254. *GDreadChar++ = GDbuff[GDbufHead+GDhead++];
  255. GDhead &= GDrxMask;
  256. GDcount--;
  257. }
  258. GDcount2 = GDcount >> 1;
  259. while (GDcount2--) {
  260. *((PUSHORT)GDreadChar)++ = *(PUSHORT)&(GDbuff[GDbufHead+GDhead]);
  261. GDhead += 2;
  262. GDhead &= GDrxMask;
  263. }
  264. if (GDcount & 1) {
  265. *GDreadChar++ = GDbuff[GDbufHead+GDhead++];
  266. GDhead &= GDrxMask;
  267. }
  268. *GDrptr = GDhead;
  269. }
  270. else {
  271. if (GDcount > GDdataLen)
  272. GDcount = (USHORT)GDdataLen;
  273. GDdataLen -= GDcount;
  274. GDlen = GDcount;
  275. GDpageNo = GDspage + (GDhead >> 13);
  276. GDpageOfs = GDhead & Page_mask;
  277. do {
  278. GDcnt = Page_size - GDpageOfs;
  279. if (GDcnt > GDcount)
  280. GDcnt = GDcount;
  281. GDcount -= GDcnt;
  282. if (GDcnt) {
  283. *(GDbase + Control_reg) = (UCHAR)GDpageNo;
  284. if (GDpageOfs & 1) {
  285. *GDreadChar++ = GDbuff[GDpageOfs++];
  286. GDcnt--;
  287. }
  288. GDcount2 = GDcnt >> 1;
  289. while (GDcount2--) {
  290. *((PUSHORT)GDreadChar)++ = *(PUSHORT)&(GDbuff[GDpageOfs]);
  291. GDpageOfs += 2;
  292. }
  293. if (GDcnt & 1)
  294. *GDreadChar++ = GDbuff[GDpageOfs++];
  295. }
  296. if (GDcount == 0)
  297. break;
  298. if (++GDpageNo == GDepage)
  299. GDpageNo = GDspage;
  300. GDpageOfs = 0;
  301. } while (TRUE);
  302. *GDrptr = (GDhead + GDlen) & GDrxMask;
  303. }
  304. Extension->NumberNeededForRead = GDdataLen;
  305. Extension->ReadCurrentChar = GDreadChar;
  306. Extension->CurrentReadIrp->IoStatus.Information += GDlen;
  307. Extension->PerfStats.ReceivedCount += GDlen;
  308. if (*(GDofs + FlagStat) & Rx_xoff) {
  309. GDcount = (*GDwptr >= *GDrptr) ? (*GDwptr - *GDrptr)
  310. : (*GDwptr - *GDrptr + GDrxMask + 1);
  311. if (GDcount < Extension->HandFlow.XonLimit)
  312. MoxaFuncWithDumbWait(GDofs, FC_SendXon, 0);
  313. }
  314. }
  315. BOOLEAN
  316. MoxaInSwitchToUser(
  317. IN PVOID Context
  318. )
  319. {
  320. PMOXA_DEVICE_EXTENSION extension = Context;
  321. USHORT max;
  322. *(PUSHORT)(extension->PortOfs + Rx_trigger) = 1;
  323. *(PUSHORT)(extension->PortOfs + HostStat) |= WakeupRxTrigger;
  324. MoxaGetData(extension);
  325. extension->ReadLength = extension->NumberNeededForRead;
  326. if (extension->NumberNeededForRead) {
  327. /* 8-14-01 by William
  328. max = *(PUSHORT)(extension->PortOfs + RX_mask) - 128;
  329. */
  330. max = *(PUSHORT)(extension->PortOfs + RX_mask) - RX_offset;
  331. if (extension->NumberNeededForRead > max)
  332. *(PUSHORT)(extension->PortOfs + Rx_trigger) = max;
  333. else
  334. *(PUSHORT)(extension->PortOfs + Rx_trigger) = (USHORT)extension->NumberNeededForRead;
  335. MOXA_INC_REFERENCE(extension->CurrentReadIrp);
  336. extension->CountOnLastRead =
  337. extension->CurrentReadIrp->IoStatus.Information;
  338. extension->ReadByIsr = 0;
  339. IoSetCancelRoutine(
  340. extension->CurrentReadIrp,
  341. MoxaCancelCurrentRead
  342. );
  343. MOXA_INC_REFERENCE(extension->CurrentReadIrp);
  344. }
  345. else
  346. *(PSHORT)(extension->PortOfs + HostStat) &= ~WakeupRxTrigger;
  347. return FALSE;
  348. }
  349. NTSTATUS
  350. MoxaStartRead(
  351. IN PMOXA_DEVICE_EXTENSION Extension
  352. )
  353. {
  354. PIO_STACK_LOCATION irpSp;
  355. PIRP newIrp;
  356. KIRQL oldIrql;
  357. KIRQL controlIrql;
  358. BOOLEAN returnWithWhatsPresent;
  359. BOOLEAN os2ssreturn;
  360. BOOLEAN crunchDownToOne;
  361. BOOLEAN useTotalTimer;
  362. BOOLEAN useIntervalTimer;
  363. ULONG ioControlCode;
  364. ULONG multiplierVal;
  365. ULONG constantVal;
  366. LARGE_INTEGER totalTime;
  367. SERIAL_TIMEOUTS timeoutsForIrp;
  368. BOOLEAN setFirstStatus = FALSE;
  369. NTSTATUS firstStatus;
  370. do {
  371. irpSp = IoGetCurrentIrpStackLocation(Extension->CurrentReadIrp);
  372. //
  373. // Check if MOXA_IOCTL_xxx request
  374. //
  375. if (irpSp->MajorFunction != IRP_MJ_READ) {
  376. KeAcquireSpinLock(
  377. &Extension->ControlLock,
  378. &controlIrql
  379. );
  380. IoAcquireCancelSpinLock(&oldIrql);
  381. if (Extension->CurrentReadIrp->Cancel) {
  382. Extension->CurrentReadIrp->IoStatus.Status =
  383. STATUS_CANCELLED;
  384. IoReleaseCancelSpinLock(oldIrql);
  385. KeReleaseSpinLock(
  386. &Extension->ControlLock,
  387. controlIrql
  388. );
  389. if (!setFirstStatus) {
  390. firstStatus = STATUS_CANCELLED;
  391. setFirstStatus = TRUE;
  392. }
  393. }
  394. else {
  395. ioControlCode =
  396. irpSp->Parameters.DeviceIoControl.IoControlCode;
  397. if (ioControlCode == IOCTL_MOXA_LineInput)
  398. KeSynchronizeExecution(
  399. Extension->Interrupt,
  400. MoxaLineInput,
  401. Extension
  402. );
  403. else
  404. KeSynchronizeExecution(
  405. Extension->Interrupt,
  406. MoxaView,
  407. Extension
  408. );
  409. Extension->CurrentReadIrp->IoStatus.Status = STATUS_SUCCESS;
  410. IoReleaseCancelSpinLock(oldIrql);
  411. KeReleaseSpinLock(
  412. &Extension->ControlLock,
  413. controlIrql
  414. );
  415. if (!setFirstStatus) {
  416. firstStatus = STATUS_SUCCESS;
  417. setFirstStatus = TRUE;
  418. }
  419. }
  420. }
  421. else {
  422. Extension->NumberNeededForRead =
  423. IoGetCurrentIrpStackLocation(Extension->CurrentReadIrp)
  424. ->Parameters.Read.Length;
  425. useTotalTimer = FALSE;
  426. returnWithWhatsPresent = FALSE;
  427. os2ssreturn = FALSE;
  428. crunchDownToOne = FALSE;
  429. useIntervalTimer = FALSE;
  430. KeAcquireSpinLock(
  431. &Extension->ControlLock,
  432. &controlIrql
  433. );
  434. timeoutsForIrp = Extension->Timeouts;
  435. KeReleaseSpinLock(
  436. &Extension->ControlLock,
  437. controlIrql
  438. );
  439. //
  440. // Calculate the interval timeout for the read.
  441. //
  442. if (timeoutsForIrp.ReadIntervalTimeout &&
  443. (timeoutsForIrp.ReadIntervalTimeout !=
  444. MAXULONG)) {
  445. useIntervalTimer = TRUE;
  446. Extension->IntervalTime.QuadPart =
  447. UInt32x32To64(
  448. timeoutsForIrp.ReadIntervalTimeout,
  449. 10000
  450. );
  451. if (Extension->IntervalTime.QuadPart >=
  452. Extension->CutOverAmount.QuadPart) {
  453. Extension->IntervalTimeToUse =
  454. &Extension->LongIntervalAmount;
  455. } else {
  456. Extension->IntervalTimeToUse =
  457. &Extension->ShortIntervalAmount;
  458. }
  459. }
  460. if (timeoutsForIrp.ReadIntervalTimeout == MAXULONG) {
  461. //
  462. // We need to do special return quickly stuff here.
  463. //
  464. // 1) If both constant and multiplier are
  465. // 0 then we return immediately with whatever
  466. // we've got, even if it was zero.
  467. //
  468. // 2) If constant and multiplier are not MAXULONG
  469. // then return immediately if any characters
  470. // are present, but if nothing is there, then
  471. // use the timeouts as specified.
  472. //
  473. // 3) If multiplier is MAXULONG then do as in
  474. // "2" but return when the first character
  475. // arrives.
  476. //
  477. if (!timeoutsForIrp.ReadTotalTimeoutConstant &&
  478. !timeoutsForIrp.ReadTotalTimeoutMultiplier) {
  479. returnWithWhatsPresent = TRUE;
  480. } else if ((timeoutsForIrp.ReadTotalTimeoutConstant != MAXULONG)
  481. &&
  482. (timeoutsForIrp.ReadTotalTimeoutMultiplier
  483. != MAXULONG)) {
  484. useTotalTimer = TRUE;
  485. os2ssreturn = TRUE;
  486. multiplierVal = timeoutsForIrp.ReadTotalTimeoutMultiplier;
  487. constantVal = timeoutsForIrp.ReadTotalTimeoutConstant;
  488. } else if ((timeoutsForIrp.ReadTotalTimeoutConstant != MAXULONG)
  489. &&
  490. (timeoutsForIrp.ReadTotalTimeoutMultiplier
  491. == MAXULONG)) {
  492. useTotalTimer = TRUE;
  493. os2ssreturn = TRUE;
  494. crunchDownToOne = TRUE;
  495. multiplierVal = 0;
  496. constantVal = timeoutsForIrp.ReadTotalTimeoutConstant;
  497. }
  498. } else {
  499. //
  500. // If both the multiplier and the constant are
  501. // zero then don't do any total timeout processing.
  502. //
  503. if (timeoutsForIrp.ReadTotalTimeoutMultiplier ||
  504. timeoutsForIrp.ReadTotalTimeoutConstant) {
  505. //
  506. // We have some timer values to calculate.
  507. //
  508. useTotalTimer = TRUE;
  509. multiplierVal = timeoutsForIrp.ReadTotalTimeoutMultiplier;
  510. constantVal = timeoutsForIrp.ReadTotalTimeoutConstant;
  511. }
  512. }
  513. if (useTotalTimer) {
  514. totalTime.QuadPart = ((LONGLONG)(UInt32x32To64(
  515. Extension->NumberNeededForRead,
  516. multiplierVal
  517. )
  518. + constantVal))
  519. * -10000;
  520. }
  521. KeAcquireSpinLock(
  522. &Extension->ControlLock,
  523. &controlIrql
  524. );
  525. MOXA_INIT_REFERENCE(Extension->CurrentReadIrp);
  526. IoAcquireCancelSpinLock(&oldIrql);
  527. if (Extension->CurrentReadIrp->Cancel) {
  528. Extension->CurrentReadIrp->IoStatus.Status =
  529. STATUS_CANCELLED;
  530. Extension->CurrentReadIrp->IoStatus.Information = 0;
  531. IoReleaseCancelSpinLock(oldIrql);
  532. KeReleaseSpinLock(
  533. &Extension->ControlLock,
  534. controlIrql
  535. );
  536. if (!setFirstStatus) {
  537. firstStatus = STATUS_CANCELLED;
  538. setFirstStatus = TRUE;
  539. }
  540. }
  541. else {
  542. KeSynchronizeExecution(
  543. Extension->Interrupt,
  544. MoxaIn,
  545. Extension
  546. );
  547. if (returnWithWhatsPresent || (!Extension->NumberNeededForRead) ||
  548. (os2ssreturn &&
  549. Extension->CurrentReadIrp->IoStatus.Information)) {
  550. //
  551. // We got all we needed for this read.
  552. //
  553. Extension->CurrentReadIrp->IoStatus.Status = STATUS_SUCCESS;
  554. IoReleaseCancelSpinLock(oldIrql);
  555. KeReleaseSpinLock(
  556. &Extension->ControlLock,
  557. controlIrql
  558. );
  559. if (!setFirstStatus) {
  560. firstStatus = STATUS_SUCCESS;
  561. setFirstStatus = TRUE;
  562. }
  563. }
  564. else {
  565. //
  566. // If we are supposed to crunch the read down to
  567. // one character, then update the read length
  568. // in the irp and truncate the number needed for
  569. // read down to one. Note that if we are doing
  570. // this crunching, then the information must be
  571. // zero (or we would have completed above) and
  572. // the number needed for the read must still be
  573. // equal to the read length.
  574. //
  575. if (crunchDownToOne) {
  576. Extension->NumberNeededForRead = 1;
  577. IoGetCurrentIrpStackLocation(
  578. Extension->CurrentReadIrp
  579. )->Parameters.Read.Length = 1;
  580. }
  581. KeSynchronizeExecution(
  582. Extension->Interrupt,
  583. MoxaInSwitchToUser,
  584. Extension
  585. );
  586. if (Extension->NumberNeededForRead) {
  587. if (useTotalTimer) {
  588. MOXA_INC_REFERENCE(Extension->CurrentReadIrp);
  589. MoxaSetTimer(
  590. &Extension->ReadRequestTotalTimer,
  591. totalTime,
  592. &Extension->TotalReadTimeoutDpc,
  593. Extension
  594. );
  595. }
  596. if (useIntervalTimer) {
  597. MOXA_INC_REFERENCE(Extension->CurrentReadIrp);
  598. KeQuerySystemTime(
  599. &Extension->LastReadTime
  600. );
  601. MoxaSetTimer(
  602. &Extension->ReadRequestIntervalTimer,
  603. *Extension->IntervalTimeToUse,
  604. &Extension->IntervalReadTimeoutDpc,
  605. Extension
  606. );
  607. }
  608. IoMarkIrpPending(Extension->CurrentReadIrp);
  609. IoReleaseCancelSpinLock(oldIrql);
  610. KeReleaseSpinLock(
  611. &Extension->ControlLock,
  612. controlIrql
  613. );
  614. if (!setFirstStatus) {
  615. firstStatus = STATUS_PENDING;
  616. }
  617. return firstStatus;
  618. } else {
  619. Extension->CurrentReadIrp->IoStatus.Status =
  620. STATUS_SUCCESS;
  621. IoReleaseCancelSpinLock(oldIrql);
  622. KeReleaseSpinLock(
  623. &Extension->ControlLock,
  624. controlIrql
  625. );
  626. if (!setFirstStatus) {
  627. firstStatus = STATUS_SUCCESS;
  628. setFirstStatus = TRUE;
  629. }
  630. }
  631. }
  632. }
  633. }
  634. //
  635. // Well the operation is complete.
  636. //
  637. MoxaGetNextIrp(
  638. &Extension->CurrentReadIrp,
  639. &Extension->ReadQueue,
  640. &newIrp,
  641. TRUE,
  642. Extension
  643. );
  644. } while (newIrp);
  645. return firstStatus;
  646. }
  647. VOID
  648. MoxaCancelCurrentRead(
  649. PDEVICE_OBJECT DeviceObject,
  650. PIRP Irp
  651. )
  652. {
  653. PMOXA_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
  654. extension->CountOnLastRead = MOXA_COMPLETE_READ_CANCEL;
  655. MoxaTryToCompleteCurrent(
  656. extension,
  657. MoxaGrabReadFromIsr,
  658. Irp->CancelIrql,
  659. STATUS_CANCELLED,
  660. &extension->CurrentReadIrp,
  661. &extension->ReadQueue,
  662. &extension->ReadRequestIntervalTimer,
  663. &extension->ReadRequestTotalTimer,
  664. MoxaStartRead,
  665. MoxaGetNextIrp
  666. );
  667. }
  668. BOOLEAN
  669. MoxaGrabReadFromIsr(
  670. IN PVOID Context
  671. )
  672. {
  673. PMOXA_DEVICE_EXTENSION extension = Context;
  674. if (extension->ReadLength) {
  675. extension->CurrentReadIrp->IoStatus.Information =
  676. IoGetCurrentIrpStackLocation(
  677. extension->CurrentReadIrp
  678. )->Parameters.Read.Length -
  679. extension->ReadLength;
  680. *(PSHORT)(extension->PortOfs + HostStat) &= ~WakeupRxTrigger;
  681. extension->ReadLength = 0;
  682. MOXA_DEC_REFERENCE(extension->CurrentReadIrp);
  683. }
  684. return FALSE;
  685. }
  686. VOID
  687. MoxaCompleteRead(
  688. IN PKDPC Dpc,
  689. IN PVOID DeferredContext,
  690. IN PVOID SystemContext1,
  691. IN PVOID SystemContext2
  692. )
  693. {
  694. PMOXA_DEVICE_EXTENSION extension = DeferredContext;
  695. KIRQL oldIrql;
  696. IoAcquireCancelSpinLock(&oldIrql);
  697. extension->CountOnLastRead = MOXA_COMPLETE_READ_COMPLETE;
  698. MoxaTryToCompleteCurrent(
  699. extension,
  700. NULL,
  701. oldIrql,
  702. STATUS_SUCCESS,
  703. &extension->CurrentReadIrp,
  704. &extension->ReadQueue,
  705. &extension->ReadRequestIntervalTimer,
  706. &extension->ReadRequestTotalTimer,
  707. MoxaStartRead,
  708. MoxaGetNextIrp
  709. );
  710. MoxaDpcEpilogue(extension, Dpc);
  711. }
  712. VOID
  713. MoxaReadTimeout(
  714. IN PKDPC Dpc,
  715. IN PVOID DeferredContext,
  716. IN PVOID SystemContext1,
  717. IN PVOID SystemContext2
  718. )
  719. {
  720. PMOXA_DEVICE_EXTENSION extension = DeferredContext;
  721. KIRQL oldIrql;
  722. IoAcquireCancelSpinLock(&oldIrql);
  723. if (extension->CountOnLastRead == MOXA_COMPLETE_READ_COMPLETE) {
  724. MoxaTryToCompleteCurrent(
  725. extension,
  726. NULL,
  727. oldIrql,
  728. STATUS_SUCCESS,
  729. &extension->CurrentReadIrp,
  730. &extension->ReadQueue,
  731. &extension->ReadRequestIntervalTimer,
  732. &extension->ReadRequestTotalTimer,
  733. MoxaStartRead,
  734. MoxaGetNextIrp
  735. );
  736. MoxaDpcEpilogue(extension, Dpc);
  737. return;
  738. }
  739. if (MoxaCheckInQueue(extension)) {
  740. KeSynchronizeExecution(
  741. extension->Interrupt,
  742. MoxaPollGetData,
  743. extension
  744. );
  745. if (!extension->ReadLength) {
  746. extension->CountOnLastRead = MOXA_COMPLETE_READ_COMPLETE;
  747. MOXA_DEC_REFERENCE(extension->CurrentReadIrp);
  748. MoxaTryToCompleteCurrent(
  749. extension,
  750. NULL,
  751. oldIrql,
  752. STATUS_SUCCESS,
  753. &extension->CurrentReadIrp,
  754. &extension->ReadQueue,
  755. &extension->ReadRequestIntervalTimer,
  756. &extension->ReadRequestTotalTimer,
  757. MoxaStartRead,
  758. MoxaGetNextIrp
  759. );
  760. MoxaDpcEpilogue(extension, Dpc);
  761. return;
  762. }
  763. }
  764. extension->CountOnLastRead = MOXA_COMPLETE_READ_TOTAL;
  765. MoxaTryToCompleteCurrent(
  766. extension,
  767. MoxaGrabReadFromIsr,
  768. oldIrql,
  769. STATUS_TIMEOUT,
  770. &extension->CurrentReadIrp,
  771. &extension->ReadQueue,
  772. &extension->ReadRequestIntervalTimer,
  773. &extension->ReadRequestTotalTimer,
  774. MoxaStartRead,
  775. MoxaGetNextIrp
  776. );
  777. MoxaDpcEpilogue(extension, Dpc);
  778. }
  779. VOID
  780. MoxaIntervalReadTimeout(
  781. IN PKDPC Dpc,
  782. IN PVOID DeferredContext,
  783. IN PVOID SystemContext1,
  784. IN PVOID SystemContext2
  785. )
  786. {
  787. PMOXA_DEVICE_EXTENSION extension = DeferredContext;
  788. KIRQL oldIrql;
  789. USHORT count;
  790. /*
  791. PUCHAR base;
  792. base = extension->PortBase;
  793. */
  794. IoAcquireCancelSpinLock(&oldIrql);
  795. if (extension->CountOnLastRead == MOXA_COMPLETE_READ_TOTAL) {
  796. MoxaTryToCompleteCurrent(
  797. extension,
  798. MoxaGrabReadFromIsr,
  799. oldIrql,
  800. STATUS_TIMEOUT,
  801. &extension->CurrentReadIrp,
  802. &extension->ReadQueue,
  803. &extension->ReadRequestIntervalTimer,
  804. &extension->ReadRequestTotalTimer,
  805. MoxaStartRead,
  806. MoxaGetNextIrp
  807. );
  808. }
  809. else if (extension->CountOnLastRead == MOXA_COMPLETE_READ_COMPLETE) {
  810. MoxaTryToCompleteCurrent(
  811. extension,
  812. NULL,
  813. oldIrql,
  814. STATUS_SUCCESS,
  815. &extension->CurrentReadIrp,
  816. &extension->ReadQueue,
  817. &extension->ReadRequestIntervalTimer,
  818. &extension->ReadRequestTotalTimer,
  819. MoxaStartRead,
  820. MoxaGetNextIrp
  821. );
  822. }
  823. else if (extension->CountOnLastRead == MOXA_COMPLETE_READ_CANCEL) {
  824. MoxaTryToCompleteCurrent(
  825. extension,
  826. MoxaGrabReadFromIsr,
  827. oldIrql,
  828. STATUS_CANCELLED,
  829. &extension->CurrentReadIrp,
  830. &extension->ReadQueue,
  831. &extension->ReadRequestIntervalTimer,
  832. &extension->ReadRequestTotalTimer,
  833. MoxaStartRead,
  834. MoxaGetNextIrp
  835. );
  836. }
  837. else {
  838. if (extension->CountOnLastRead) {
  839. //base[0x300]++;
  840. IRTofs = extension->PortOfs;
  841. IRTrptr = (PUSHORT)(IRTofs + RXrptr);
  842. IRTwptr = (PUSHORT)(IRTofs + RXwptr);
  843. IRTrxMask = *(PUSHORT)(IRTofs + RX_mask);
  844. count = (*IRTwptr >= *IRTrptr) ? (*IRTwptr - *IRTrptr)
  845. : (*IRTwptr - *IRTrptr + IRTrxMask + 1);
  846. if (count > extension->ReadByIsr) {
  847. //base[0x301]++;
  848. extension->ReadByIsr = count;
  849. KeQuerySystemTime(
  850. &extension->LastReadTime
  851. );
  852. MoxaSetTimer(
  853. &extension->ReadRequestIntervalTimer,
  854. *extension->IntervalTimeToUse,
  855. &extension->IntervalReadTimeoutDpc,
  856. extension
  857. );
  858. IoReleaseCancelSpinLock(oldIrql);
  859. }
  860. else {
  861. LARGE_INTEGER currentTime;
  862. //base[0x302]++;
  863. KeQuerySystemTime(
  864. &currentTime
  865. );
  866. if ((currentTime.QuadPart - extension->LastReadTime.QuadPart) >=
  867. extension->IntervalTime.QuadPart) {
  868. //base[0x303]++;
  869. if (MoxaCheckInQueue(extension)) {
  870. //base[0x304]++;
  871. KeSynchronizeExecution(
  872. extension->Interrupt,
  873. MoxaPollGetData,
  874. extension
  875. );
  876. if (!extension->ReadLength) {
  877. //base[0x305]++;
  878. extension->CountOnLastRead =
  879. MOXA_COMPLETE_READ_COMPLETE;
  880. MOXA_DEC_REFERENCE(extension->CurrentReadIrp);
  881. MoxaTryToCompleteCurrent(
  882. extension,
  883. NULL,
  884. oldIrql,
  885. STATUS_SUCCESS,
  886. &extension->CurrentReadIrp,
  887. &extension->ReadQueue,
  888. &extension->ReadRequestIntervalTimer,
  889. &extension->ReadRequestTotalTimer,
  890. MoxaStartRead,
  891. MoxaGetNextIrp
  892. );
  893. MoxaDpcEpilogue(extension, Dpc);
  894. return;
  895. }
  896. }
  897. //base[0x306]++;
  898. MoxaTryToCompleteCurrent(
  899. extension,
  900. MoxaGrabReadFromIsr,
  901. oldIrql,
  902. STATUS_TIMEOUT,
  903. &extension->CurrentReadIrp,
  904. &extension->ReadQueue,
  905. &extension->ReadRequestIntervalTimer,
  906. &extension->ReadRequestTotalTimer,
  907. MoxaStartRead,
  908. MoxaGetNextIrp
  909. );
  910. }
  911. else {
  912. //base[0x307]++;
  913. MoxaSetTimer(
  914. &extension->ReadRequestIntervalTimer,
  915. *extension->IntervalTimeToUse,
  916. &extension->IntervalReadTimeoutDpc,
  917. extension
  918. );
  919. IoReleaseCancelSpinLock(oldIrql);
  920. }
  921. }
  922. }
  923. else {
  924. //base[0x308]++;
  925. IRTofs = extension->PortOfs;
  926. IRTrptr = (PUSHORT)(IRTofs + RXrptr);
  927. IRTwptr = (PUSHORT)(IRTofs + RXwptr);
  928. IRTrxMask = *(PUSHORT)(IRTofs + RX_mask);
  929. count = (*IRTwptr >= *IRTrptr) ? (*IRTwptr - *IRTrptr)
  930. : (*IRTwptr - *IRTrptr + IRTrxMask + 1);
  931. if (count) {
  932. //base[0x309]++;
  933. extension->CountOnLastRead = count;
  934. extension->ReadByIsr = count;
  935. KeQuerySystemTime(
  936. &extension->LastReadTime
  937. );
  938. }
  939. MoxaSetTimer(
  940. &extension->ReadRequestIntervalTimer,
  941. *extension->IntervalTimeToUse,
  942. &extension->IntervalReadTimeoutDpc,
  943. extension
  944. );
  945. IoReleaseCancelSpinLock(oldIrql);
  946. }
  947. }
  948. MoxaDpcEpilogue(extension, Dpc);
  949. }
  950. BOOLEAN
  951. MoxaCheckInQueue(
  952. IN PMOXA_DEVICE_EXTENSION Extension
  953. )
  954. {
  955. PUCHAR ofs;
  956. PUSHORT rptr, wptr;
  957. ofs = Extension->PortOfs;
  958. GDrptr = (PUSHORT)(ofs + RXrptr);
  959. GDwptr = (PUSHORT)(ofs + RXwptr);
  960. if (*GDrptr != *GDwptr)
  961. return TRUE;
  962. else
  963. return FALSE;
  964. }
  965. BOOLEAN
  966. MoxaPollGetData(
  967. IN PVOID Context
  968. )
  969. {
  970. PMOXA_DEVICE_EXTENSION extension = Context;
  971. PIO_STACK_LOCATION irpSp;
  972. MoxaGetData(extension);
  973. extension->ReadLength = extension->NumberNeededForRead;
  974. if (!extension->ReadLength) {
  975. *(PSHORT)(extension->PortOfs + HostStat) &= ~WakeupRxTrigger;
  976. irpSp = IoGetCurrentIrpStackLocation(
  977. extension->CurrentReadIrp);
  978. extension->CurrentReadIrp->IoStatus.Information =
  979. irpSp->Parameters.Read.Length;
  980. }
  981. return FALSE;
  982. }