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.

1599 lines
55 KiB

  1. /*--------------------------------------------------------------------------
  2. *
  3. * Copyright (C) Cyclades Corporation, 1997-2001.
  4. * All rights reserved.
  5. *
  6. * Cyclades-Z Port Driver
  7. *
  8. * This file: cyzpoll.c
  9. *
  10. * Description: This module contains the code related to the polling
  11. * of the hardware. It replaces the ISR.
  12. *
  13. * Notes: This code supports Windows 2000 and Windows XP,
  14. * x86 and IA64 processors.
  15. *
  16. * Complies with Cyclades SW Coding Standard rev 1.3.
  17. *
  18. *--------------------------------------------------------------------------
  19. */
  20. /*-------------------------------------------------------------------------
  21. *
  22. * Change History
  23. *
  24. *--------------------------------------------------------------------------
  25. *
  26. *
  27. *--------------------------------------------------------------------------
  28. */
  29. #include "precomp.h"
  30. #ifdef ALLOC_PRAGMA
  31. #pragma alloc_text(PAGESER,CyzPutChar)
  32. #pragma alloc_text(PAGESER,CyzProcessLSR)
  33. #pragma alloc_text(PAGESER,CyzTxStart)
  34. #pragma alloc_text(PAGESER,CyzQueueCompleteWrite)
  35. #endif
  36. static const PHYSICAL_ADDRESS CyzPhysicalZero = {0};
  37. VOID
  38. CyzPollingDpc(
  39. IN PKDPC Dpc,
  40. IN PVOID DeferredContext,
  41. IN PVOID SystemContext1,
  42. IN PVOID SystemContext2
  43. )
  44. /*--------------------------------------------------------------------------
  45. Routine Description:
  46. This is the polling routine for the Cyclades-Z driver. It replaces
  47. the ISR, as we are not enabling interrupts.
  48. Arguments:
  49. Dpc - Not Used.
  50. DeferredContext - Really points to the device extention.
  51. SystemContext1 - Not used.
  52. SystemContext2 - Not used.
  53. Return Value:
  54. None.
  55. --------------------------------------------------------------------------*/
  56. {
  57. PCYZ_DISPATCH Dispatch = DeferredContext;
  58. PCYZ_DEVICE_EXTENSION Extension, dbExtension; //Note: db=doorbell
  59. struct INT_QUEUE *pt_zf_int_queue;
  60. struct BUF_CTRL *buf_ctrl;
  61. ULONG qu_get, qu_put;
  62. ULONG channel, dbChannel; //Note: db=doorbell
  63. ULONG fwcmd_param;
  64. ULONG rx_bufsize, rx_get, rx_put;
  65. UCHAR loc_doorbell;
  66. UCHAR rxchar;
  67. UNREFERENCED_PARAMETER(Dpc);
  68. UNREFERENCED_PARAMETER(SystemContext1);
  69. UNREFERENCED_PARAMETER(SystemContext2);
  70. KeAcquireSpinLockAtDpcLevel(&Dispatch->PollingLock);
  71. if (!Dispatch->PollingStarted) {
  72. Dispatch->PollingDrained = TRUE;
  73. KeSetEvent(&Dispatch->PendingDpcEvent, IO_NO_INCREMENT, FALSE);
  74. goto EndDpc;
  75. }
  76. for (channel=0; channel<Dispatch->NChannels; channel++) {
  77. Extension = Dispatch->Extensions[channel];
  78. if (Extension == NULL) {
  79. continue;
  80. }
  81. pt_zf_int_queue = Extension->PtZfIntQueue;
  82. if (pt_zf_int_queue == NULL) {
  83. continue;
  84. }
  85. qu_get = CYZ_READ_ULONG(&pt_zf_int_queue->get);
  86. qu_put = CYZ_READ_ULONG(&pt_zf_int_queue->put);
  87. while (qu_get != qu_put) {
  88. if (qu_get >= QUEUE_SIZE) {
  89. // bad value, reset qu_get
  90. qu_get = 0;
  91. break;
  92. }
  93. if (qu_put >= QUEUE_SIZE) {
  94. // bad value
  95. break;
  96. }
  97. loc_doorbell = CYZ_READ_UCHAR(&pt_zf_int_queue->intr_code[qu_get]);
  98. dbChannel = CYZ_READ_ULONG(&pt_zf_int_queue->channel[qu_get]);
  99. if (dbChannel >= Dispatch->NChannels) {
  100. break;
  101. }
  102. // so far, only DCD status is sent on the fwcmd_param.
  103. fwcmd_param = CYZ_READ_ULONG(&pt_zf_int_queue->param[qu_get]);
  104. dbExtension = Dispatch->Extensions[dbChannel];
  105. if (!dbExtension) {
  106. goto NextQueueGet;
  107. }
  108. KeAcquireSpinLockAtDpcLevel(&dbExtension->PollLock);
  109. //-- Error Injection
  110. //loc_doorbell = C_CM_FATAL;
  111. //loc_doorbell = C_CM_CMDERROR;
  112. //----
  113. switch (loc_doorbell) {
  114. case C_CM_IOCTLW:
  115. //CyzDump (CYZDIAG5,("CyzPollingDpc C_CM_IOCTLW\n"));
  116. dbExtension->IoctlwProcessed = TRUE;
  117. break;
  118. case C_CM_CMD_DONE:
  119. //CyzDump (CYZDIAG5,("CyzPollingDpc C_CM_CMD_DONE\n"));
  120. break;
  121. case C_CM_RXHIWM: // Reception above high watermark
  122. case C_CM_RXNNDT: // Timeout without receiving more chars.
  123. case C_CM_INTBACK2: // Not used in polling mode.
  124. //CyzDump (CYZERRORS,
  125. // ("CyzPollingDpc C_CM_RXHIWM,C_CM_RXNNDT,C_CM_INTBACK2\n"));
  126. break;
  127. case C_CM_TXBEMPTY: // Firmware buffer empty
  128. //dbExtension->HoldingEmpty = TRUE;
  129. //CyzDump (CYZDIAG5,("CyzPollingDpc C_CM_TXBEMPTY\n"));
  130. break;
  131. case C_CM_TXFEMPTY: // Hardware FIFO empty
  132. dbExtension->HoldingEmpty = TRUE;
  133. //CyzDump (CYZDIAG5,("CyzPollingDpc C_CM_TXFEMPTY\n"));
  134. break;
  135. case C_CM_INTBACK: // New transmission
  136. //CyzDump(CYZBUGCHECK,
  137. // ("C_CM_INTBACK! We should not receive this...\n"));
  138. break;
  139. case C_CM_TXLOWWM:
  140. //CyzDump (CYZBUGCHECK,("CyzPollingDpc C_CM_TXLOWN\n"));
  141. break;
  142. case C_CM_MDCD: // Modem
  143. dbExtension->DCDstatus = fwcmd_param;
  144. case C_CM_MDSR:
  145. case C_CM_MRI:
  146. case C_CM_MCTS:
  147. //CyzDump(CYZDIAG5,
  148. // ("doorbell %x port%d\n",loc_doorbell,dbExtension->PortIndex+1));
  149. if (dbExtension->DeviceIsOpened) {
  150. CyzHandleModemUpdate(dbExtension,FALSE,loc_doorbell);
  151. }
  152. break;
  153. case C_CM_RXBRK:
  154. //CyzDump (CYZERRORS,("CyzPollingDpc C_CM_RXBRK\n"));
  155. if (dbExtension->DeviceIsOpened) {
  156. CyzProcessLSR(dbExtension,SERIAL_LSR_BI);
  157. }
  158. break;
  159. case C_CM_PR_ERROR:
  160. //dbExtension->PerfStats.ParityErrorCount++;
  161. //dbExtension->ErrorWord |= SERIAL_ERROR_PARITY;
  162. if (dbExtension->DeviceIsOpened) {
  163. CyzProcessLSR(dbExtension,SERIAL_LSR_PE);
  164. }
  165. break;
  166. case C_CM_FR_ERROR:
  167. //dbExtension->PerfStats.FrameErrorCount++;
  168. //dbExtension->ErrorWord |= SERIAL_ERROR_FRAMING;
  169. if (dbExtension->DeviceIsOpened) {
  170. CyzProcessLSR(dbExtension,SERIAL_LSR_FE);
  171. }
  172. break;
  173. case C_CM_OVR_ERROR:
  174. //dbExtension->PerfStats.SerialOverrunErrorCount++;
  175. //dbExtension->ErrorWord |= SERIAL_ERROR_OVERRUN;
  176. if (dbExtension->DeviceIsOpened) {
  177. CyzProcessLSR(dbExtension,SERIAL_LSR_OE);
  178. }
  179. break;
  180. case C_CM_RXOFL:
  181. //dbExtension->PerfStats.SerialOverrunErrorCount++;
  182. //dbExtension->ErrorWord |= SERIAL_ERROR_OVERRUN;
  183. if (dbExtension->DeviceIsOpened) {
  184. CyzProcessLSR(dbExtension,SERIAL_LSR_OE);
  185. }
  186. break;
  187. case C_CM_CMDERROR:
  188. //CyzDump (CYZBUGCHECK,("CyzPollingDpc C_CM_CMDERROR\n"));
  189. CyzLogError( dbExtension->DriverObject,dbExtension->DeviceObject,
  190. dbExtension->OriginalBoardMemory,CyzPhysicalZero,
  191. 0,0,0,dbExtension->PortIndex+1,STATUS_SUCCESS,
  192. CYZ_FIRMWARE_CMDERROR,0,NULL,0,NULL);
  193. break;
  194. case C_CM_FATAL:
  195. //CyzDump (CYZBUGCHECK,("CyzPollingDpc C_CM_FATAL\n"));
  196. CyzLogError( dbExtension->DriverObject,dbExtension->DeviceObject,
  197. dbExtension->OriginalBoardMemory,CyzPhysicalZero,
  198. 0,0,0,dbExtension->PortIndex+1,STATUS_SUCCESS,
  199. CYZ_FIRMWARE_FATAL,0,NULL,0,NULL);
  200. break;
  201. } // end switch
  202. KeReleaseSpinLockFromDpcLevel(&dbExtension->PollLock);
  203. NextQueueGet:
  204. if (qu_get == QUEUE_SIZE-1) {
  205. qu_get = 0;
  206. } else {
  207. qu_get++;
  208. }
  209. } // end while (qu_get != qu_put)
  210. CYZ_WRITE_ULONG(&pt_zf_int_queue->get,qu_get);
  211. KeAcquireSpinLockAtDpcLevel(&Extension->PollLock);
  212. // Reception
  213. buf_ctrl = Extension->BufCtrl;
  214. rx_put = CYZ_READ_ULONG(&buf_ctrl->rx_put);
  215. rx_get = CYZ_READ_ULONG(&buf_ctrl->rx_get);
  216. rx_bufsize = Extension->RxBufsize;
  217. if ((rx_put >= rx_bufsize) || (rx_get >= rx_bufsize)) {
  218. CYZ_WRITE_ULONG(&buf_ctrl->rx_get,rx_get);
  219. KeReleaseSpinLockFromDpcLevel(&Extension->PollLock);
  220. continue;
  221. }
  222. if (rx_put != rx_get) {
  223. if (Extension->DeviceIsOpened) {
  224. ULONG pppflag = 0;
  225. while ((rx_get != rx_put) &&
  226. (Extension->CharsInInterruptBuffer <
  227. Extension->BufferSize) ){
  228. rxchar = CYZ_READ_UCHAR(&Extension->RxBufaddr[rx_get]);
  229. Extension->PerfStats.ReceivedCount++;
  230. Extension->WmiPerfData.ReceivedCount++;
  231. rxchar &= Extension->ValidDataMask;
  232. if (!rxchar && // NULL stripping
  233. (Extension->HandFlow.FlowReplace &
  234. SERIAL_NULL_STRIPPING)) {
  235. goto nextchar1;
  236. }
  237. if((Extension->HandFlow.FlowReplace & SERIAL_AUTO_TRANSMIT)
  238. && ((rxchar == Extension->SpecialChars.XonChar) ||
  239. (rxchar == Extension->SpecialChars.XoffChar))) {
  240. if (rxchar == Extension->SpecialChars.XoffChar) {
  241. Extension->TXHolding |= CYZ_TX_XOFF;
  242. if ((Extension->HandFlow.FlowReplace &
  243. SERIAL_RTS_MASK) ==
  244. SERIAL_TRANSMIT_TOGGLE) {
  245. CyzInsertQueueDpc(
  246. &Extension->StartTimerLowerRTSDpc,
  247. NULL,
  248. NULL,
  249. Extension
  250. )?Extension->CountOfTryingToLowerRTS++:0;
  251. }
  252. } else {
  253. if (Extension->TXHolding & CYZ_TX_XOFF) {
  254. Extension->TXHolding &= ~CYZ_TX_XOFF;
  255. }
  256. }
  257. goto nextchar1;
  258. }
  259. // Check to see if we should note the receive
  260. // character or special character event.
  261. if (Extension->IsrWaitMask) {
  262. if (Extension->IsrWaitMask & SERIAL_EV_RXCHAR) {
  263. Extension->HistoryMask |= SERIAL_EV_RXCHAR;
  264. }
  265. if ((Extension->IsrWaitMask & SERIAL_EV_RXFLAG) &&
  266. (Extension->SpecialChars.EventChar == rxchar)) {
  267. Extension->HistoryMask |= SERIAL_EV_RXFLAG;
  268. if (rxchar == 0x7e){ //Optimized for RAS PPP
  269. if (Extension->PPPaware) {
  270. if (pppflag == 0){
  271. pppflag = 1;
  272. } else {
  273. pppflag = 2;
  274. }
  275. }
  276. }
  277. }
  278. if (Extension->IrpMaskLocation &&
  279. Extension->HistoryMask) {
  280. *Extension->IrpMaskLocation =
  281. Extension->HistoryMask;
  282. Extension->IrpMaskLocation = NULL;
  283. Extension->HistoryMask = 0;
  284. Extension->CurrentWaitIrp->IoStatus.Information =
  285. sizeof(ULONG);
  286. CyzInsertQueueDpc(&Extension->CommWaitDpc,NULL,NULL,Extension);
  287. }
  288. }
  289. CyzPutChar(Extension,rxchar);
  290. // If we're doing line status and modem
  291. // status insertion then we need to insert
  292. // a zero following the character we just
  293. // placed into the buffer to mark that this
  294. // was reception of what we are using to
  295. // escape.
  296. if (Extension->EscapeChar &&
  297. (Extension->EscapeChar == rxchar)) {
  298. CyzPutChar(Extension,SERIAL_LSRMST_ESCAPE);
  299. }
  300. nextchar1:;
  301. if (rx_get == rx_bufsize-1)
  302. rx_get = 0;
  303. else
  304. rx_get++;
  305. if (pppflag == 2) //Optimized for NT RAS PPP
  306. break;
  307. } // end while
  308. } else { // device is being closed, discard rx chars
  309. rx_get = rx_put;
  310. }
  311. CYZ_WRITE_ULONG(&buf_ctrl->rx_get,rx_get);
  312. } // end if (rx_put != rx_get)
  313. // Transmission
  314. if (Extension->DeviceIsOpened) {
  315. if (Extension->ReturnStatusAfterFwEmpty) {
  316. if (Extension->ReturnWriteStatus && Extension->WriteLength) {
  317. if (!CyzAmountInTxBuffer(Extension)) {
  318. //txfempty Extension->HoldingEmpty = TRUE;
  319. Extension->WriteLength = 0;
  320. Extension->ReturnWriteStatus = FALSE;
  321. CyzQueueCompleteWrite(Extension);
  322. }
  323. } else {
  324. CyzTxStart(Extension);
  325. }
  326. } else { // We don't wait for the firmware buff empty to tx
  327. CyzTxStart(Extension);
  328. }
  329. }
  330. KeReleaseSpinLockFromDpcLevel(&Extension->PollLock);
  331. } // end for (channel=0;channel<Dispatch->NChannels;channel++);
  332. //KeSetTimer(&Dispatch->PollingTimer,Dispatch->PollingTime,&Dispatch->PollingDpc);
  333. EndDpc:
  334. KeReleaseSpinLockFromDpcLevel(&Dispatch->PollingLock);
  335. }
  336. VOID
  337. CyzPutChar(
  338. IN PCYZ_DEVICE_EXTENSION Extension,
  339. IN UCHAR CharToPut
  340. )
  341. /*--------------------------------------------------------------------------
  342. CyzPutChar()
  343. Routine Description: This routine, which only runs at device level,
  344. takes care of placing a character into the typeahead (receive) buffer.
  345. Arguments:
  346. Extension - The serial device extension.
  347. Return Value: None.
  348. --------------------------------------------------------------------------*/
  349. {
  350. CYZ_LOCKED_PAGED_CODE();
  351. // If we have dsr sensitivity enabled then
  352. // we need to check the modem status register
  353. // to see if it has changed.
  354. if (Extension->HandFlow.ControlHandShake & SERIAL_DSR_SENSITIVITY) {
  355. CyzHandleModemUpdate(Extension,FALSE,0);
  356. if (Extension->RXHolding & CYZ_RX_DSR) {
  357. // We simply act as if we haven't seen the character if
  358. // dsr line is low.
  359. return;
  360. }
  361. }
  362. // If the xoff counter is non-zero then decrement it.
  363. // If the counter then goes to zero, complete that irp.
  364. if (Extension->CountSinceXoff) {
  365. Extension->CountSinceXoff--;
  366. if (!Extension->CountSinceXoff) {
  367. Extension->CurrentXoffIrp->IoStatus.Status = STATUS_SUCCESS;
  368. Extension->CurrentXoffIrp->IoStatus.Information = 0;
  369. CyzInsertQueueDpc(&Extension->XoffCountCompleteDpc,NULL,NULL,Extension);
  370. }
  371. }
  372. // Check to see if we are copying into the
  373. // users buffer or into the interrupt buffer.
  374. //
  375. // If we are copying into the user buffer
  376. // then we know there is always room for one more.
  377. // (We know this because if there wasn't room
  378. // then that read would have completed and we
  379. // would be using the interrupt buffer.)
  380. //
  381. // If we are copying into the interrupt buffer
  382. // then we will need to check if we have enough
  383. // room.
  384. if (Extension->ReadBufferBase != Extension->InterruptReadBuffer) {
  385. // Increment the following value so
  386. // that the interval timer (if one exists
  387. // for this read) can know that a character
  388. // has been read.
  389. Extension->ReadByIsr++;
  390. // We are in the user buffer. Place the character into the buffer.
  391. // See if the read is complete.
  392. *Extension->CurrentCharSlot = CharToPut;
  393. if (Extension->CurrentCharSlot == Extension->LastCharSlot) {
  394. // We've filled up the users buffer.
  395. // Switch back to the interrupt buffer
  396. // and send off a DPC to Complete the read.
  397. //
  398. // It is inherent that when we were using
  399. // a user buffer that the interrupt buffer
  400. // was empty.
  401. Extension->ReadBufferBase = Extension->InterruptReadBuffer;
  402. Extension->CurrentCharSlot = Extension->InterruptReadBuffer;
  403. Extension->FirstReadableChar = Extension->InterruptReadBuffer;
  404. Extension->LastCharSlot = Extension->InterruptReadBuffer +
  405. (Extension->BufferSize - 1);
  406. Extension->CharsInInterruptBuffer = 0;
  407. Extension->CurrentReadIrp->IoStatus.Information =
  408. IoGetCurrentIrpStackLocation(
  409. Extension->CurrentReadIrp
  410. )->Parameters.Read.Length;
  411. CyzInsertQueueDpc(&Extension->CompleteReadDpc,NULL,NULL,Extension);
  412. } else {
  413. // Not done with the users read.
  414. Extension->CurrentCharSlot++;
  415. }
  416. } else {
  417. // We need to see if we reached our flow
  418. // control threshold. If we have then
  419. // we turn on whatever flow control the
  420. // owner has specified. If no flow
  421. // control was specified, well..., we keep
  422. // trying to receive characters and hope that
  423. // we have enough room. Note that no matter
  424. // what flow control protocol we are using, it
  425. // will not prevent us from reading whatever
  426. // characters are available.
  427. if ((Extension->HandFlow.ControlHandShake
  428. & SERIAL_DTR_MASK) ==
  429. SERIAL_DTR_HANDSHAKE) {
  430. // If we are already doing a
  431. // dtr hold then we don't have
  432. // to do anything else.
  433. if (!(Extension->RXHolding &
  434. CYZ_RX_DTR)) {
  435. if ((Extension->BufferSize -
  436. Extension->HandFlow.XoffLimit)
  437. <= (Extension->CharsInInterruptBuffer+1)) {
  438. Extension->RXHolding |= CYZ_RX_DTR;
  439. #ifndef FIRMWARE_HANDSHAKE
  440. CyzClrDTR(Extension);
  441. #endif
  442. }
  443. }
  444. }
  445. if ((Extension->HandFlow.FlowReplace
  446. & SERIAL_RTS_MASK) ==
  447. SERIAL_RTS_HANDSHAKE) {
  448. // If we are already doing a
  449. // rts hold then we don't have
  450. // to do anything else.
  451. if (!(Extension->RXHolding & CYZ_RX_RTS)) {
  452. if ((Extension->BufferSize -
  453. Extension->HandFlow.XoffLimit)
  454. <= (Extension->CharsInInterruptBuffer+1)) {
  455. Extension->RXHolding |= CYZ_RX_RTS;
  456. #ifndef FIRMWARE_HANDSHAKE
  457. CyzClrRTS(Extension);
  458. #endif
  459. }
  460. }
  461. }
  462. if (Extension->HandFlow.FlowReplace & SERIAL_AUTO_RECEIVE) {
  463. // If we are already doing a
  464. // xoff hold then we don't have
  465. // to do anything else.
  466. if (!(Extension->RXHolding & CYZ_RX_XOFF)) {
  467. if ((Extension->BufferSize -
  468. Extension->HandFlow.XoffLimit)
  469. <= (Extension->CharsInInterruptBuffer+1)) {
  470. Extension->RXHolding |= CYZ_RX_XOFF;
  471. // If necessary cause an
  472. // off to be sent.
  473. CyzProdXonXoff(Extension,FALSE);
  474. }
  475. }
  476. }
  477. if (Extension->CharsInInterruptBuffer < Extension->BufferSize) {
  478. *Extension->CurrentCharSlot = CharToPut;
  479. Extension->CharsInInterruptBuffer++;
  480. // If we've become 80% full on this character
  481. // and this is an interesting event, note it.
  482. if (Extension->CharsInInterruptBuffer == Extension->BufferSizePt8) {
  483. if (Extension->IsrWaitMask & SERIAL_EV_RX80FULL) {
  484. Extension->HistoryMask |= SERIAL_EV_RX80FULL;
  485. if (Extension->IrpMaskLocation) {
  486. *Extension->IrpMaskLocation = Extension->HistoryMask;
  487. Extension->IrpMaskLocation = NULL;
  488. Extension->HistoryMask = 0;
  489. Extension->CurrentWaitIrp->IoStatus.Information = sizeof(ULONG);
  490. CyzInsertQueueDpc(&Extension->CommWaitDpc,NULL,NULL,Extension);
  491. }
  492. }
  493. }
  494. // Point to the next available space
  495. // for a received character. Make sure
  496. // that we wrap around to the beginning
  497. // of the buffer if this last character
  498. // received was placed at the last slot
  499. // in the buffer.
  500. if (Extension->CurrentCharSlot == Extension->LastCharSlot) {
  501. Extension->CurrentCharSlot = Extension->InterruptReadBuffer;
  502. } else {
  503. Extension->CurrentCharSlot++;
  504. }
  505. } else {
  506. // We have a new character but no room for it.
  507. Extension->PerfStats.BufferOverrunErrorCount++;
  508. Extension->WmiPerfData.BufferOverrunErrorCount++;
  509. Extension->ErrorWord |= SERIAL_ERROR_QUEUEOVERRUN;
  510. if (Extension->HandFlow.FlowReplace & SERIAL_ERROR_CHAR) {
  511. // Place the error character into the last
  512. // valid place for a character. Be careful!,
  513. // that place might not be the previous location!
  514. if (Extension->CurrentCharSlot == Extension->InterruptReadBuffer) {
  515. *(Extension->InterruptReadBuffer+
  516. (Extension->BufferSize-1)) =
  517. Extension->SpecialChars.ErrorChar;
  518. } else {
  519. *(Extension->CurrentCharSlot-1) =
  520. Extension->SpecialChars.ErrorChar;
  521. }
  522. }
  523. // If the application has requested it, abort all reads
  524. // and writes on an error.
  525. if (Extension->HandFlow.ControlHandShake & SERIAL_ERROR_ABORT) {
  526. CyzInsertQueueDpc(&Extension->CommErrorDpc,NULL,NULL,Extension);
  527. }
  528. }
  529. }
  530. }
  531. UCHAR
  532. CyzProcessLSR(
  533. IN PCYZ_DEVICE_EXTENSION Extension,
  534. IN UCHAR LineStatus
  535. )
  536. {
  537. // UCHAR LineStatus = 0; // READ_LINE_STATUS(Extension->Controller);
  538. CYZ_LOCKED_PAGED_CODE();
  539. if (Extension->EscapeChar) {
  540. CyzPutChar(
  541. Extension,
  542. Extension->EscapeChar
  543. );
  544. CyzPutChar(
  545. Extension,
  546. (UCHAR)(SERIAL_LSRMST_LSR_NODATA)
  547. );
  548. CyzPutChar(
  549. Extension,
  550. LineStatus
  551. );
  552. }
  553. if (LineStatus & SERIAL_LSR_OE) {
  554. Extension->PerfStats.SerialOverrunErrorCount++;
  555. Extension->WmiPerfData.SerialOverrunErrorCount++;
  556. Extension->ErrorWord |= SERIAL_ERROR_OVERRUN;
  557. if (Extension->HandFlow.FlowReplace &
  558. SERIAL_ERROR_CHAR) {
  559. CyzPutChar(
  560. Extension,
  561. Extension->SpecialChars.ErrorChar
  562. );
  563. }
  564. }
  565. if (LineStatus & SERIAL_LSR_BI) {
  566. Extension->ErrorWord |= SERIAL_ERROR_BREAK;
  567. if (Extension->HandFlow.FlowReplace &
  568. SERIAL_BREAK_CHAR) {
  569. CyzPutChar(
  570. Extension,
  571. Extension->SpecialChars.BreakChar
  572. );
  573. }
  574. } else {
  575. //
  576. // Framing errors only count if they
  577. // occur exclusive of a break being
  578. // received.
  579. //
  580. if (LineStatus & SERIAL_LSR_PE) {
  581. Extension->PerfStats.ParityErrorCount++;
  582. Extension->WmiPerfData.ParityErrorCount++;
  583. Extension->ErrorWord |= SERIAL_ERROR_PARITY;
  584. if (Extension->HandFlow.FlowReplace &
  585. SERIAL_ERROR_CHAR) {
  586. CyzPutChar(
  587. Extension,
  588. Extension->SpecialChars.ErrorChar
  589. );
  590. }
  591. }
  592. if (LineStatus & SERIAL_LSR_FE) {
  593. Extension->PerfStats.FrameErrorCount++;
  594. Extension->WmiPerfData.FrameErrorCount++;
  595. Extension->ErrorWord |= SERIAL_ERROR_FRAMING;
  596. if (Extension->HandFlow.FlowReplace &
  597. SERIAL_ERROR_CHAR) {
  598. CyzPutChar(
  599. Extension,
  600. Extension->SpecialChars.ErrorChar
  601. );
  602. }
  603. }
  604. }
  605. //
  606. // If the application has requested it,
  607. // abort all the reads and writes
  608. // on an error.
  609. //
  610. if (Extension->HandFlow.ControlHandShake &
  611. SERIAL_ERROR_ABORT) {
  612. CyzInsertQueueDpc(
  613. &Extension->CommErrorDpc,
  614. NULL,
  615. NULL,
  616. Extension
  617. );
  618. }
  619. //
  620. // Check to see if we have a wait
  621. // pending on the comm error events. If we
  622. // do then we schedule a dpc to satisfy
  623. // that wait.
  624. //
  625. if (Extension->IsrWaitMask) {
  626. if ((Extension->IsrWaitMask & SERIAL_EV_ERR) &&
  627. (LineStatus & (SERIAL_LSR_OE |
  628. SERIAL_LSR_PE |
  629. SERIAL_LSR_FE))) {
  630. Extension->HistoryMask |= SERIAL_EV_ERR;
  631. }
  632. if ((Extension->IsrWaitMask & SERIAL_EV_BREAK) &&
  633. (LineStatus & SERIAL_LSR_BI)) {
  634. Extension->HistoryMask |= SERIAL_EV_BREAK;
  635. }
  636. if (Extension->IrpMaskLocation &&
  637. Extension->HistoryMask) {
  638. *Extension->IrpMaskLocation =
  639. Extension->HistoryMask;
  640. Extension->IrpMaskLocation = NULL;
  641. Extension->HistoryMask = 0;
  642. Extension->CurrentWaitIrp->IoStatus.Information =
  643. sizeof(ULONG);
  644. CyzInsertQueueDpc(
  645. &Extension->CommWaitDpc,
  646. NULL,
  647. NULL,
  648. Extension
  649. );
  650. }
  651. }
  652. return LineStatus;
  653. }
  654. BOOLEAN
  655. CyzTxStart(
  656. IN PVOID Context
  657. )
  658. /*--------------------------------------------------------------------------
  659. CyzTxStart()
  660. Description: Enable Tx interrupt.
  661. Parameters:
  662. Extension: Pointer to device extension.
  663. Return Value: None
  664. --------------------------------------------------------------------------*/
  665. {
  666. struct BUF_CTRL *buf_ctrl;
  667. ULONG tx_bufsize, tx_get, tx_put;
  668. ULONG numOfLongs, numOfBytes;
  669. PCYZ_DEVICE_EXTENSION Extension = Context;
  670. if (Extension->PowerState != PowerDeviceD0) {
  671. return FALSE;
  672. }
  673. //doTransmitStuff:;
  674. if( //(Extension->DeviceIsOpened) && moved to before CyzTxStart
  675. (Extension->WriteLength || Extension->TransmitImmediate ||
  676. Extension->SendXoffChar || Extension->SendXonChar)) {
  677. buf_ctrl = Extension->BufCtrl;
  678. tx_put = CYZ_READ_ULONG(&buf_ctrl->tx_put);
  679. tx_get = CYZ_READ_ULONG(&buf_ctrl->tx_get);
  680. tx_bufsize = Extension->TxBufsize;
  681. if ((tx_put >= tx_bufsize) || (tx_get >= tx_bufsize)) {
  682. return FALSE;
  683. }
  684. if ((tx_put+1 == tx_get) || ((tx_put==tx_bufsize-1)&&(tx_get==0))) {
  685. return FALSE;
  686. }
  687. Extension->EmptiedTransmit = TRUE;
  688. if (Extension->HandFlow.ControlHandShake &
  689. SERIAL_OUT_HANDSHAKEMASK) {
  690. CyzHandleModemUpdate(Extension,TRUE,0);
  691. }
  692. // LOGENTRY(LOG_MISC, ZSIG_TX_START,
  693. // Extension->PortIndex+1,
  694. // Extension->WriteLength,
  695. // Extension->TXHolding);
  696. //
  697. // We can only send the xon character if
  698. // the only reason we are holding is because
  699. // of the xoff. (Hardware flow control or
  700. // sending break preclude putting a new character
  701. // on the wire.)
  702. //
  703. if (Extension->SendXonChar &&
  704. !(Extension->TXHolding & ~CYZ_TX_XOFF)) {
  705. if ((Extension->HandFlow.FlowReplace &
  706. SERIAL_RTS_MASK) ==
  707. SERIAL_TRANSMIT_TOGGLE) {
  708. //
  709. // We have to raise if we're sending
  710. // this character.
  711. //
  712. CyzSetRTS(Extension);
  713. Extension->PerfStats.TransmittedCount++;
  714. Extension->WmiPerfData.TransmittedCount++;
  715. CyzIssueCmd(Extension,C_CM_SENDXON,0L,FALSE);
  716. CyzInsertQueueDpc(
  717. &Extension->StartTimerLowerRTSDpc,
  718. NULL,
  719. NULL,
  720. Extension
  721. )?Extension->CountOfTryingToLowerRTS++:0;
  722. } else {
  723. Extension->PerfStats.TransmittedCount++;
  724. Extension->WmiPerfData.TransmittedCount++;
  725. CyzIssueCmd(Extension,C_CM_SENDXON,0L,FALSE);
  726. }
  727. Extension->SendXonChar = FALSE;
  728. Extension->HoldingEmpty = FALSE;
  729. //
  730. // If we send an xon, by definition we
  731. // can't be holding by Xoff.
  732. //
  733. Extension->TXHolding &= ~CYZ_TX_XOFF;
  734. //
  735. // If we are sending an xon char then
  736. // by definition we can't be "holding"
  737. // up reception by Xoff.
  738. //
  739. Extension->RXHolding &= ~CYZ_RX_XOFF;
  740. } else if (Extension->SendXoffChar &&
  741. !Extension->TXHolding) {
  742. if ((Extension->HandFlow.FlowReplace &
  743. SERIAL_RTS_MASK) ==
  744. SERIAL_TRANSMIT_TOGGLE) {
  745. //
  746. // We have to raise if we're sending
  747. // this character.
  748. //
  749. CyzSetRTS(Extension);
  750. Extension->PerfStats.TransmittedCount++;
  751. Extension->WmiPerfData.TransmittedCount++;
  752. CyzIssueCmd(Extension,C_CM_SENDXOFF,0L,FALSE);
  753. CyzInsertQueueDpc(
  754. &Extension->StartTimerLowerRTSDpc,
  755. NULL,
  756. NULL,
  757. Extension
  758. )?Extension->CountOfTryingToLowerRTS++:0;
  759. } else {
  760. Extension->PerfStats.TransmittedCount++;
  761. Extension->WmiPerfData.TransmittedCount++;
  762. CyzIssueCmd(Extension,C_CM_SENDXOFF,0L,FALSE);
  763. }
  764. //
  765. // We can't be sending an Xoff character
  766. // if the transmission is already held
  767. // up because of Xoff. Therefore, if we
  768. // are holding then we can't send the char.
  769. //
  770. //
  771. // If the application has set xoff continue
  772. // mode then we don't actually stop sending
  773. // characters if we send an xoff to the other
  774. // side.
  775. //
  776. if (!(Extension->HandFlow.FlowReplace &
  777. SERIAL_XOFF_CONTINUE)) {
  778. Extension->TXHolding |= CYZ_TX_XOFF;
  779. if ((Extension->HandFlow.FlowReplace &
  780. SERIAL_RTS_MASK) ==
  781. SERIAL_TRANSMIT_TOGGLE) {
  782. CyzInsertQueueDpc(
  783. &Extension->StartTimerLowerRTSDpc,
  784. NULL,
  785. NULL,
  786. Extension
  787. )?Extension->CountOfTryingToLowerRTS++:0;
  788. }
  789. }
  790. Extension->SendXoffChar = FALSE;
  791. Extension->HoldingEmpty = FALSE;
  792. } else if(Extension->TransmitImmediate&&(!Extension->TXHolding ||
  793. (Extension->TXHolding == CYZ_TX_XOFF) )) {
  794. Extension->TransmitImmediate = FALSE;
  795. if ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK)
  796. == SERIAL_TRANSMIT_TOGGLE) {
  797. CyzSetRTS(Extension);
  798. Extension->PerfStats.TransmittedCount++;
  799. Extension->WmiPerfData.TransmittedCount++;
  800. CYZ_WRITE_UCHAR( &Extension->TxBufaddr[tx_put],
  801. Extension->ImmediateChar);
  802. if (tx_put + 1 == tx_bufsize) {
  803. CYZ_WRITE_ULONG(&buf_ctrl->tx_put,0);
  804. } else {
  805. CYZ_WRITE_ULONG(&buf_ctrl->tx_put,tx_put + 1);
  806. }
  807. CyzInsertQueueDpc(
  808. &Extension->StartTimerLowerRTSDpc,NULL,NULL,
  809. Extension)? Extension->CountOfTryingToLowerRTS++:0;
  810. } else {
  811. Extension->PerfStats.TransmittedCount++;
  812. Extension->WmiPerfData.TransmittedCount++;
  813. CYZ_WRITE_UCHAR(&Extension->TxBufaddr[tx_put],
  814. Extension->ImmediateChar);
  815. if (tx_put + 1 == tx_bufsize) {
  816. CYZ_WRITE_ULONG(&buf_ctrl->tx_put,0);
  817. } else {
  818. CYZ_WRITE_ULONG(&buf_ctrl->tx_put,tx_put + 1);
  819. }
  820. }
  821. Extension->HoldingEmpty = FALSE;
  822. CyzInsertQueueDpc(
  823. &Extension->CompleteImmediateDpc,
  824. NULL,
  825. NULL,
  826. Extension
  827. );
  828. } else if (!Extension->TXHolding) {
  829. ULONG amountToWrite1, amountToWrite2;
  830. ULONG newput;
  831. ULONG amount1;
  832. if (tx_put >= tx_get) {
  833. if (tx_get == 0) {
  834. amountToWrite1 = tx_bufsize - tx_put -1;
  835. amountToWrite2 = 0;
  836. if (amountToWrite1 > Extension->WriteLength){
  837. amountToWrite1 = Extension->WriteLength;
  838. }
  839. newput = amountToWrite1 + 1;
  840. } else if (tx_get == 1) {
  841. amountToWrite1 = tx_bufsize - tx_put;
  842. amountToWrite2 = 0;
  843. if (amountToWrite1 > Extension->WriteLength){
  844. amountToWrite1 = Extension->WriteLength;
  845. newput = amountToWrite1 + 1;
  846. } else {
  847. newput = 0;
  848. }
  849. } else {
  850. amountToWrite1 = tx_bufsize - tx_put;
  851. amountToWrite2 = tx_get - 1;
  852. if (amountToWrite1 > Extension->WriteLength) {
  853. amountToWrite1 = Extension->WriteLength;
  854. amountToWrite2 = 0;
  855. newput = amountToWrite1 + 1;
  856. } else if (amountToWrite1 == Extension->WriteLength) {
  857. amountToWrite2 = 0;
  858. newput = 0;
  859. } else {
  860. if (amountToWrite2 > Extension->WriteLength - amountToWrite1) {
  861. amountToWrite2 = Extension->WriteLength - amountToWrite1;
  862. newput = amountToWrite2 + 1;
  863. }
  864. }
  865. }
  866. } else {
  867. //
  868. // put < get
  869. //
  870. amountToWrite1 = tx_get - tx_put - 1;
  871. amountToWrite2 = 0;
  872. if (amountToWrite1 > Extension->WriteLength) {
  873. amountToWrite1 = Extension->WriteLength;
  874. newput = amountToWrite1 + 1;
  875. }
  876. }
  877. if ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK)
  878. == SERIAL_TRANSMIT_TOGGLE) {
  879. // We have to raise if we're sending
  880. // this character.
  881. CyzSetRTS(Extension);
  882. if (amountToWrite1) {
  883. Extension->PerfStats.TransmittedCount += amountToWrite1;
  884. Extension->WmiPerfData.TransmittedCount += amountToWrite1;
  885. amount1 = amountToWrite1;
  886. while (amount1 && (tx_put & 0x07)) {
  887. CYZ_WRITE_UCHAR(
  888. (PUCHAR)&Extension->TxBufaddr[tx_put],
  889. *((PUCHAR)Extension->WriteCurrentChar));
  890. tx_put++;
  891. ((PUCHAR)Extension->WriteCurrentChar)++;
  892. amount1--;
  893. }
  894. #if _WIN64
  895. numOfLongs = amount1/8;
  896. numOfBytes = amount1%8;
  897. RtlCopyMemory((PULONG64)&Extension->TxBufaddr[tx_put],
  898. (PULONG64)Extension->WriteCurrentChar,
  899. numOfLongs*8);
  900. tx_put += 8*numOfLongs;
  901. (PULONG64)Extension->WriteCurrentChar += numOfLongs;
  902. #else
  903. numOfLongs = amount1/sizeof(ULONG);
  904. numOfBytes = amount1%sizeof(ULONG);
  905. // RtlCopyMemory((PULONG)&Extension->TxBufaddr[tx_put],
  906. // (PULONG)Extension->WriteCurrentChar,
  907. // numOfLongs*sizeof(ULONG));
  908. // tx_put += sizeof(ULONG)*numOfLongs;
  909. // (PULONG)Extension->WriteCurrentChar += numOfLongs;
  910. while (numOfLongs--) {
  911. CYZ_WRITE_ULONG(
  912. (PULONG)(&Extension->TxBufaddr[tx_put]),
  913. *((PULONG)Extension->WriteCurrentChar));
  914. tx_put += sizeof(ULONG);
  915. ((PULONG)Extension->WriteCurrentChar)++;
  916. }
  917. #endif
  918. while (numOfBytes--) {
  919. CYZ_WRITE_UCHAR(
  920. (PUCHAR)&Extension->TxBufaddr[tx_put],
  921. *((PUCHAR)Extension->WriteCurrentChar));
  922. tx_put++;
  923. ((PUCHAR)Extension->WriteCurrentChar)++;
  924. }
  925. if (tx_put == tx_bufsize) {
  926. tx_put = 0;
  927. }
  928. CYZ_WRITE_ULONG(&buf_ctrl->tx_put,tx_put);
  929. }
  930. if (amountToWrite2) {
  931. Extension->PerfStats.TransmittedCount += amountToWrite2;
  932. Extension->WmiPerfData.TransmittedCount += amountToWrite2;
  933. #if _WIN64
  934. numOfLongs = amountToWrite2/8;
  935. numOfBytes = amountToWrite2%8;
  936. RtlCopyMemory((PULONG64)&Extension->TxBufaddr[tx_put],
  937. (PULONG64)Extension->WriteCurrentChar,
  938. numOfLongs*8);
  939. tx_put += 8*numOfLongs;
  940. (PULONG64)Extension->WriteCurrentChar += numOfLongs;
  941. #else
  942. numOfLongs = amountToWrite2/sizeof(ULONG);
  943. numOfBytes = amountToWrite2%sizeof(ULONG);
  944. // RtlCopyMemory((PULONG)&Extension->TxBufaddr[tx_put],
  945. // (PULONG)Extension->WriteCurrentChar,
  946. // numOfLongs*sizeof(ULONG));
  947. // tx_put += sizeof(ULONG)*numOfLongs;
  948. // (PULONG)Extension->WriteCurrentChar += numOfLongs;
  949. while (numOfLongs--) {
  950. CYZ_WRITE_ULONG(
  951. (PULONG)(&Extension->TxBufaddr[tx_put]),
  952. *((PULONG)Extension->WriteCurrentChar));
  953. tx_put += sizeof(ULONG);
  954. ((PULONG)Extension->WriteCurrentChar)++;
  955. }
  956. #endif
  957. while (numOfBytes--) {
  958. CYZ_WRITE_UCHAR(
  959. (PUCHAR)&Extension->TxBufaddr[tx_put],
  960. *((PUCHAR)Extension->WriteCurrentChar));
  961. tx_put++;
  962. ((PUCHAR)Extension->WriteCurrentChar)++;
  963. }
  964. CYZ_WRITE_ULONG(&buf_ctrl->tx_put,amountToWrite2);
  965. }
  966. CyzInsertQueueDpc(
  967. &Extension->StartTimerLowerRTSDpc,
  968. NULL,
  969. NULL,
  970. Extension
  971. )?Extension->CountOfTryingToLowerRTS++:0;
  972. } else {
  973. if (amountToWrite1) {
  974. Extension->PerfStats.TransmittedCount += amountToWrite1;
  975. Extension->WmiPerfData.TransmittedCount += amountToWrite1;
  976. amount1 = amountToWrite1;
  977. while (amount1 && (tx_put & 0x07)) {
  978. CYZ_WRITE_UCHAR(
  979. (PUCHAR)&Extension->TxBufaddr[tx_put],
  980. *((PUCHAR)Extension->WriteCurrentChar));
  981. tx_put++;
  982. ((PUCHAR)Extension->WriteCurrentChar)++;
  983. amount1--;
  984. }
  985. #if _WIN64
  986. numOfLongs = amount1/8;
  987. numOfBytes = amount1%8;
  988. RtlCopyMemory((PULONG64)&Extension->TxBufaddr[tx_put],
  989. (PULONG64)Extension->WriteCurrentChar,
  990. numOfLongs*8);
  991. tx_put += 8*numOfLongs;
  992. (PULONG64)Extension->WriteCurrentChar += numOfLongs;
  993. #else
  994. numOfLongs = amount1/sizeof(ULONG);
  995. numOfBytes = amount1%sizeof(ULONG);
  996. // RtlCopyMemory((PULONG)&Extension->TxBufaddr[tx_put],
  997. // (PULONG)Extension->WriteCurrentChar,
  998. // numOfLongs*sizeof(ULONG));
  999. // tx_put += sizeof(ULONG)*numOfLongs;
  1000. // (PULONG)Extension->WriteCurrentChar += numOfLongs;
  1001. while (numOfLongs--) {
  1002. CYZ_WRITE_ULONG(
  1003. (PULONG)(&Extension->TxBufaddr[tx_put]),
  1004. *((PULONG)Extension->WriteCurrentChar));
  1005. tx_put += sizeof(ULONG);
  1006. ((PULONG)Extension->WriteCurrentChar)++;
  1007. }
  1008. #endif
  1009. while (numOfBytes--) {
  1010. CYZ_WRITE_UCHAR(
  1011. (PUCHAR)&Extension->TxBufaddr[tx_put],
  1012. *((PUCHAR)Extension->WriteCurrentChar));
  1013. tx_put++;
  1014. ((PUCHAR)Extension->WriteCurrentChar)++;
  1015. }
  1016. if (tx_put == tx_bufsize) {
  1017. tx_put = 0;
  1018. }
  1019. CYZ_WRITE_ULONG(&buf_ctrl->tx_put,tx_put);
  1020. }
  1021. if (amountToWrite2) {
  1022. Extension->PerfStats.TransmittedCount += amountToWrite2;
  1023. Extension->WmiPerfData.TransmittedCount += amountToWrite2;
  1024. #if _WIN64
  1025. numOfLongs = amountToWrite2/8;
  1026. numOfBytes = amountToWrite2%8;
  1027. RtlCopyMemory((PULONG64)&Extension->TxBufaddr[tx_put],
  1028. (PULONG64)Extension->WriteCurrentChar,
  1029. numOfLongs*8);
  1030. tx_put += 8*numOfLongs;
  1031. (PULONG64)Extension->WriteCurrentChar += numOfLongs;
  1032. #else
  1033. numOfLongs = amountToWrite2/sizeof(ULONG);
  1034. numOfBytes = amountToWrite2%sizeof(ULONG);
  1035. // RtlCopyMemory((PULONG)&Extension->TxBufaddr[tx_put],
  1036. // (PULONG)Extension->WriteCurrentChar,
  1037. // numOfLongs*sizeof(ULONG));
  1038. // tx_put += sizeof(ULONG)*numOfLongs;
  1039. // (PULONG)Extension->WriteCurrentChar += numOfLongs;
  1040. while (numOfLongs--) {
  1041. CYZ_WRITE_ULONG(
  1042. (PULONG)(&Extension->TxBufaddr[tx_put]),
  1043. *((PULONG)Extension->WriteCurrentChar));
  1044. tx_put += sizeof(ULONG);
  1045. ((PULONG)Extension->WriteCurrentChar)++;
  1046. }
  1047. #endif
  1048. while (numOfBytes--) {
  1049. CYZ_WRITE_UCHAR(
  1050. (PUCHAR)&Extension->TxBufaddr[tx_put],
  1051. *((PUCHAR)Extension->WriteCurrentChar));
  1052. tx_put++;
  1053. ((PUCHAR)Extension->WriteCurrentChar)++;
  1054. }
  1055. CYZ_WRITE_ULONG(&buf_ctrl->tx_put,amountToWrite2);
  1056. }
  1057. }
  1058. //LOGENTRY(LOG_MISC, ZSIG_WRITE_TO_FW,
  1059. // Extension->PortIndex+1,
  1060. // amountToWrite1+amountToWrite2,
  1061. // 0);
  1062. Extension->HoldingEmpty = FALSE;
  1063. Extension->WriteLength -= (amountToWrite1+amountToWrite2);
  1064. if (!Extension->WriteLength) {
  1065. if (Extension->ReturnStatusAfterFwEmpty) {
  1066. // We will CompleteWrite only when fw buff empties...
  1067. Extension->WriteLength += (amountToWrite1+amountToWrite2);
  1068. Extension->ReturnWriteStatus = TRUE;
  1069. } else {
  1070. CyzQueueCompleteWrite(Extension);
  1071. } // if-ReturnStatusAfterFwEmpty-else.
  1072. } // There is WriteLength
  1073. } // !Extension->TXHolding
  1074. } //There is data to be sent
  1075. // In the normal code, HoldingEmpty will be set to True here. But
  1076. // if we want to make sure that CyzWrite had finished the transmission,
  1077. // HoldingEmpty will be TRUE only when the firmware empties the firmware
  1078. // tx buffer.
  1079. //txfempty if (!Extension->ReturnStatusAfterFwEmpty) {
  1080. //txfempty Extension->HoldingEmpty = TRUE;
  1081. //txfempty}
  1082. return(FALSE);
  1083. }
  1084. //
  1085. //BOOLEAN
  1086. //CyzSendXon(
  1087. // IN PVOID Context
  1088. // )
  1089. ///*--------------------------------------------------------------------------
  1090. // CyzSendXon()
  1091. //
  1092. // Description: Send a Xon.
  1093. //
  1094. // Parameters:
  1095. //
  1096. // Exetension: Pointer to device extension.
  1097. //
  1098. // Return Value: Always FALSE.
  1099. //--------------------------------------------------------------------------*/
  1100. //{
  1101. // PCYZ_DEVICE_EXTENSION Extension = Context;
  1102. //
  1103. // if(!(Extension->TXHolding & ~CYZ_TX_XOFF)) {
  1104. // if ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) ==
  1105. // SERIAL_TRANSMIT_TOGGLE) {
  1106. //
  1107. // CyzSetRTS(Extension);
  1108. //
  1109. // Extension->PerfStats.TransmittedCount++;
  1110. // Extension->WmiPerfData.TransmittedCount++;
  1111. // CyzIssueCmd(Extension,C_CM_SENDXON,0L);
  1112. //
  1113. // CyzInsertQueueDpc(&Extension->StartTimerLowerRTSDpc,NULL,
  1114. // NULL,Extension)?Extension->CountOfTryingToLowerRTS++:0;
  1115. // } else {
  1116. //
  1117. // Extension->PerfStats.TransmittedCount++;
  1118. // Extension->WmiPerfData.TransmittedCount++;
  1119. // CyzIssueCmd(Extension,C_CM_SENDXON,0L);
  1120. // }
  1121. //
  1122. // // If we send an xon, by definition we can't be holding by Xoff.
  1123. //
  1124. // Extension->TXHolding &= ~CYZ_TX_XOFF;
  1125. // Extension->RXHolding &= ~CYZ_RX_XOFF;
  1126. // }
  1127. // return(FALSE);
  1128. //}
  1129. //
  1130. //
  1131. //
  1132. //
  1133. //BOOLEAN
  1134. //CyzSendXoff(
  1135. // IN PVOID Context
  1136. // )
  1137. ///*--------------------------------------------------------------------------
  1138. // CyzSendXoff()
  1139. //
  1140. // Description: Send a Xoff.
  1141. //
  1142. // Parameters:
  1143. //
  1144. // Extension: Pointer to device extension.
  1145. //
  1146. // Return Value: Always FALSE.
  1147. //--------------------------------------------------------------------------*/
  1148. //{
  1149. // PCYZ_DEVICE_EXTENSION Extension = Context;
  1150. //
  1151. // if(!Extension->TXHolding) {
  1152. // if ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) ==
  1153. // SERIAL_TRANSMIT_TOGGLE) {
  1154. //
  1155. // CyzSetRTS(Extension);
  1156. //
  1157. // Extension->PerfStats.TransmittedCount++;
  1158. // Extension->WmiPerfData.TransmittedCount++;
  1159. // CyzIssueCmd(Extension,C_CM_SENDXOFF,0L);
  1160. //
  1161. // CyzInsertQueueDpc(&Extension->StartTimerLowerRTSDpc,NULL,
  1162. // NULL,Extension)?Extension->CountOfTryingToLowerRTS++:0;
  1163. // } else {
  1164. //
  1165. // Extension->PerfStats.TransmittedCount++;
  1166. // Extension->WmiPerfData.TransmittedCount++;
  1167. // CyzIssueCmd(Extension,C_CM_SENDXOFF,0L);
  1168. // }
  1169. //
  1170. // // no xoff is sent if the transmission is already held up.
  1171. // // If xoff continue mode is set, we don't actually stop sending
  1172. //
  1173. // if (!(Extension->HandFlow.FlowReplace & SERIAL_XOFF_CONTINUE)) {
  1174. // Extension->TXHolding |= CYZ_TX_XOFF;
  1175. //
  1176. // if ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) ==
  1177. // SERIAL_TRANSMIT_TOGGLE) {
  1178. //
  1179. // CyzInsertQueueDpc(&Extension->StartTimerLowerRTSDpc,NULL,
  1180. // NULL,Extension)?Extension->CountOfTryingToLowerRTS++:0;
  1181. // }
  1182. // }
  1183. // }
  1184. //
  1185. // return(FALSE);
  1186. //}
  1187. ULONG
  1188. CyzAmountInTxBuffer(
  1189. IN PCYZ_DEVICE_EXTENSION extension
  1190. )
  1191. /*--------------------------------------------------------------------------
  1192. CyzAmountInTxBuffer()
  1193. Description: Gets the amount in the Tx Buffer in the board.
  1194. Parameters:
  1195. Extension: Pointer to device extension.
  1196. Return Value: Return the number of bytes in the HW Tx buffer.
  1197. --------------------------------------------------------------------------*/
  1198. {
  1199. struct BUF_CTRL *buf_ctrl;
  1200. ULONG tx_put, tx_get, tx_bufsize;
  1201. ULONG txAmount1, txAmount2;
  1202. buf_ctrl = extension->BufCtrl;
  1203. tx_put = CYZ_READ_ULONG(&buf_ctrl->tx_put);
  1204. tx_get = CYZ_READ_ULONG(&buf_ctrl->tx_get);
  1205. tx_bufsize = extension->TxBufsize;
  1206. if (tx_put >= tx_get) {
  1207. txAmount1 = tx_put - tx_get;
  1208. txAmount2 = 0;
  1209. } else {
  1210. txAmount1 = tx_bufsize - tx_get;
  1211. txAmount2 = tx_put;
  1212. }
  1213. return(txAmount1+txAmount2);
  1214. }
  1215. VOID
  1216. CyzQueueCompleteWrite(
  1217. IN PCYZ_DEVICE_EXTENSION Extension
  1218. )
  1219. /*--------------------------------------------------------------------------
  1220. CyzQueueCompleteWrite()
  1221. Description: Queue CompleteWrite dpc
  1222. Parameters:
  1223. Extension: Pointer to device extension.
  1224. Return Value: None
  1225. --------------------------------------------------------------------------*/
  1226. {
  1227. PIO_STACK_LOCATION IrpSp;
  1228. //LOGENTRY(LOG_MISC, ZSIG_WRITE_COMPLETE_QUEUE,
  1229. // Extension->PortIndex+1,
  1230. // 0,
  1231. // 0);
  1232. //
  1233. // No More characters left. This
  1234. // write is complete. Take care
  1235. // when updating the information field,
  1236. // we could have an xoff counter masquerading
  1237. // as a write irp.
  1238. //
  1239. IrpSp = IoGetCurrentIrpStackLocation(
  1240. Extension->CurrentWriteIrp
  1241. );
  1242. Extension->CurrentWriteIrp->IoStatus.Information =
  1243. (IrpSp->MajorFunction == IRP_MJ_WRITE)?
  1244. (IrpSp->Parameters.Write.Length):
  1245. (1);
  1246. CyzInsertQueueDpc(
  1247. &Extension->CompleteWriteDpc,
  1248. NULL,
  1249. NULL,
  1250. Extension
  1251. );
  1252. }
  1253. BOOLEAN
  1254. CyzCheckIfTxEmpty(
  1255. IN PVOID Context
  1256. )
  1257. /*--------------------------------------------------------------------------
  1258. CyzCheckIfTxEmpty()
  1259. Routine Description: This routine is used to set the FIFO settings
  1260. during the InternalIoControl.
  1261. Arguments:
  1262. Context - Pointer to a structure that contains a pointer to the device
  1263. extension and a pointer to the Basic structure.
  1264. Return Value: This routine always returns FALSE.
  1265. --------------------------------------------------------------------------*/
  1266. {
  1267. PCYZ_CLOSE_SYNC S = Context;
  1268. PCYZ_DEVICE_EXTENSION Extension = S->Extension;
  1269. PULONG pHoldingEmpty = S->Data;
  1270. *pHoldingEmpty = Extension->HoldingEmpty;
  1271. return FALSE;
  1272. }