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.

1114 lines
35 KiB

  1. /*-------------------------------------------------------------------
  2. | openclos.c - RocketPort/VS1000 driver Open & Close code.
  3. 12-6-00 add code to force modem status update on open.
  4. 5-13-99 - enable RTS toggling for VS
  5. 2-15-99 - clear any xoff tx state on port-open for VS.
  6. 2-09-99 - initialize RocketPort & VS modemstatus variables used
  7. to detect and generate modem status change event callbacks.
  8. Spurious initial events could be generated previously. kpb
  9. 9-24-98 add RING emulation, adjust VS port-close to wait on tx-data,
  10. start using user-configured tx-data port-close wait timeout option.
  11. 6-13-97 allow multiple instances of opening monitor port.
  12. 5-27-96 minor corrections in ForceExtensionSettings - RTS setup
  13. replaced this with code from ioctl(previous last case was clearing
  14. SERIAL_RTS_STATE when shouldn't have. NULL_STRIPPING setup,
  15. this was using RxCompare1 register, ioctl code using 0 so
  16. changed to match. kpb.
  17. 4-16-96 add sDisLocalLoopback() to open() routine - kpb
  18. Copyright 1993-97 Comtrol Corporation. All rights reserved.
  19. |--------------------------------------------------------------------*/
  20. #include "precomp.h"
  21. static LARGE_INTEGER SerialGetCharTime(IN PSERIAL_DEVICE_EXTENSION Extension);
  22. /******************************************************************************
  23. Function : SerialCreateOpen
  24. Purpose: Open a device.
  25. Call: SerialCreateOpen(DeviceObject,Irp)
  26. PDEVICE_OBJECT DeviceObject: Pointer to the Device Object
  27. PIRP Irp: Pointer to the I/O Request Packet
  28. Return: STATUS_SUCCESS: if successful
  29. STATUS_DEVICE_ALREADY_ATTACHED: if device is already open
  30. STATUS_NOT_A_DIRECTORY : if someone thinks this is a file!
  31. STATUS_INSUFFICIENT_RESOURCES : if Tx or Rx buffer couldn't be
  32. allocated from memory
  33. Comments: This function is the device driver OPEN entry point
  34. ******************************************************************************/
  35. NTSTATUS
  36. SerialCreateOpen(
  37. IN PDEVICE_OBJECT DeviceObject,
  38. IN PIRP Irp
  39. )
  40. {
  41. PSERIAL_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
  42. BOOLEAN acceptingIRPs;
  43. ExtTrace(extension,D_Ioctl,("Open Port"));
  44. acceptingIRPs = SerialIRPPrologue(extension);
  45. if (acceptingIRPs == FALSE) {
  46. // || (extension->PNPState != SERIAL_PNP_STARTED)) {
  47. MyKdPrint(D_Init,("NotAccIrps\n"))
  48. Irp->IoStatus.Information = 0;
  49. Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
  50. SerialCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  51. return STATUS_NO_SUCH_DEVICE;
  52. }
  53. // object for special ioctls
  54. if (extension->DeviceType != DEV_PORT)
  55. {
  56. MyKdPrint(D_Init,("Open Driver\n"))
  57. //MyKdPrint(D_Init,("Driver IrpCnt:%d\n",extension->PendingIRPCnt))
  58. // Hardware is ready, indicate that the device is open
  59. //extension->DeviceIsOpen=TRUE;
  60. ++extension->DeviceIsOpen; // more than one can open
  61. // If it is the rocketsys dev object return don't set up serial port
  62. Irp->IoStatus.Status = STATUS_SUCCESS;
  63. Irp->IoStatus.Information=0L;
  64. SerialCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  65. return STATUS_SUCCESS;
  66. }
  67. // Check for the device already being open
  68. if (extension->DeviceIsOpen)
  69. {
  70. Irp->IoStatus.Status = STATUS_DEVICE_ALREADY_ATTACHED;
  71. Irp->IoStatus.Information = 0;
  72. SerialCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  73. return STATUS_DEVICE_ALREADY_ATTACHED;
  74. }
  75. // Make sure they aren't trying to create a directory.
  76. if (IoGetCurrentIrpStackLocation(Irp)->Parameters.Create.Options &
  77. FILE_DIRECTORY_FILE)
  78. {
  79. Irp->IoStatus.Status = STATUS_NOT_A_DIRECTORY;
  80. Irp->IoStatus.Information = 0;
  81. SerialCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  82. return STATUS_NOT_A_DIRECTORY;
  83. }
  84. // Create a system side buffer for the RX data.
  85. extension->RxQ.QSize = 4096 + 1;
  86. extension->RxQ.QBase= our_locked_alloc(extension->RxQ.QSize, "exRX");
  87. // Check that Rx buffer allocation was succesful
  88. if (!extension->RxQ.QBase)
  89. { extension->RxQ.QSize = 0;
  90. Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  91. Irp->IoStatus.Information = 0;
  92. SerialCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  93. return STATUS_INSUFFICIENT_RESOURCES;
  94. }
  95. extension->RxQ.QPut = extension->RxQ.QGet = 0;
  96. #ifdef TXBUFFER
  97. // Create a system side buffer for the TX data.
  98. extension->TxBufSize = 4096;
  99. extension->TxBuf= our_locked_alloc(extension->TxBufSize, "exTX");
  100. // Check that Tx buffer allocation was succesful
  101. if (!extension->TxBuf)
  102. { extension->TxBufSize = 0;
  103. Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  104. Irp->IoStatus.Information = 0;
  105. SerialCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  106. return STATUS_INSUFFICIENT_RESOURCES;
  107. }
  108. // Buffer allocation was successful
  109. // Set up the indexes for our buffers
  110. extension->TxIn = extension->TxOut = 0;
  111. #endif //TXBUFFER
  112. //------ reset our performance stats
  113. extension->OldStats.TransmittedCount =
  114. extension->OurStats.TransmittedCount;
  115. extension->OldStats.FrameErrorCount =
  116. extension->OurStats.FrameErrorCount;
  117. extension->OldStats.SerialOverrunErrorCount =
  118. extension->OurStats.SerialOverrunErrorCount;
  119. extension->OldStats.BufferOverrunErrorCount =
  120. extension->OurStats.BufferOverrunErrorCount;
  121. extension->OldStats.ParityErrorCount =
  122. extension->OurStats.ParityErrorCount;
  123. // Must start with a clear HistoryMask
  124. extension->HistoryMask = 0;
  125. extension->WaitIsISRs = 0;
  126. extension->IrpMaskLocation = &extension->DummyIrpMaskLoc;
  127. extension->IsrWaitMask = 0;
  128. // Must start with a clear ErrorWord
  129. extension->ErrorWord = 0;
  130. extension->RXHolding = 0;
  131. extension->TXHolding = 0;
  132. #ifdef S_VS
  133. if (extension->Port == NULL)
  134. {
  135. MyKdPrint(D_Error,("FATAL Err5F\n"))
  136. KdBreakPoint();
  137. }
  138. pDisLocalLoopback(extension->Port);
  139. PortFlushTx(extension->Port); // flush tx hardware
  140. PortFlushRx(extension->Port); // flush tx hardware
  141. // Clear any software flow control states
  142. #ifdef DO_LATER
  143. //sClrTxXOFF(extension->ChP);
  144. #endif
  145. #else
  146. // Set pointers to the Rocket's info
  147. extension->ChP = &extension->ch;
  148. sDisLocalLoopback(extension->ChP);
  149. sFlushRxFIFO(extension->ChP);
  150. sFlushTxFIFO(extension->ChP);
  151. // Clear any software flow control states
  152. sClrTxXOFF(extension->ChP);
  153. // Clear any pending errors
  154. if(sGetChanStatus(extension->ChP) & STATMODE)
  155. { // Take channel out of statmode if necessary
  156. sDisRxStatusMode(extension->ChP);
  157. }
  158. // Clear any pending modem changes
  159. sGetChanIntID(extension->ChP);
  160. #endif
  161. extension->escapechar = 0; // virtual NT port uses this
  162. // Set Status to indicate no flow control
  163. extension->DevStatus = COM_RXFLOW_ON;
  164. // Clear any holding states
  165. extension->TXHolding = 0;
  166. // Start with 0 chars queued
  167. extension->TotalCharsQueued = 0;
  168. // Force settings as specified in the extension
  169. // Line settings and flow control settings "stick" between close and open
  170. ForceExtensionSettings(extension);
  171. #ifdef S_VS
  172. //force an update of modem status to get current status from
  173. // hub.
  174. extension->Port->old_msr_value = ! extension->Port->msr_value;
  175. #else
  176. // fix, used to detect change and trip callbacks for rocketport.
  177. extension->EventModemStatus = extension->ModemStatus;
  178. SetExtensionModemStatus(extension);
  179. // Enable Rx, Tx and interrupts for the channel
  180. sEnRxFIFO(extension->ChP); // Enable Rx
  181. sEnTransmit(extension->ChP); // Enable Tx
  182. sSetRxTrigger(extension->ChP,TRIG_1); // always trigger
  183. sEnInterrupts(extension->ChP, extension->IntEnables);// allow interrupts
  184. #endif
  185. extension->ISR_Flags = 0;
  186. // Make sure we don't have a stale value in this var
  187. extension->WriteLength = 0;
  188. // Hardware is ready, indicate that the device is open
  189. extension->DeviceIsOpen=TRUE;
  190. // check if we should set RS485 override option
  191. if (extension->port_config->RS485Override)
  192. extension->Option |= OPTION_RS485_OVERRIDE;
  193. else extension->Option &= ~OPTION_RS485_OVERRIDE;
  194. if (!extension->port_config->RS485Low)
  195. extension->Option |= OPTION_RS485_HIGH_ACTIVE;
  196. else extension->Option &= ~OPTION_RS485_HIGH_ACTIVE;
  197. if (extension->Option & OPTION_RS485_OVERRIDE) // 485 override
  198. {
  199. if (extension->Option & OPTION_RS485_HIGH_ACTIVE)
  200. { // normal case, emulate standard operation
  201. extension->Option |= OPTION_RS485_SOFTWARE_TOGGLE;
  202. extension->DTRRTSStatus &= ~SERIAL_RTS_STATE;
  203. #ifdef S_VS
  204. pEnRTSToggleHigh( extension->Port );
  205. #else
  206. sClrRTS(extension->ChP);
  207. #endif
  208. }
  209. else
  210. { // hardware reverse case
  211. #ifdef S_VS
  212. pEnRTSToggleLow( extension->Port );
  213. #else
  214. sEnRTSToggle(extension->ChP);
  215. #endif
  216. extension->DTRRTSStatus |= SERIAL_RTS_STATE;
  217. }
  218. }
  219. // Finish the Irp
  220. Irp->IoStatus.Status = STATUS_SUCCESS;
  221. Irp->IoStatus.Information=0L;
  222. SerialCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  223. return STATUS_SUCCESS;
  224. }
  225. /******************************************************************************
  226. Function : SerialClose
  227. Purpose: Close a device.
  228. Call: SerialClose(DeviceObject,Irp)
  229. PDEVICE_OBJECT DeviceObject: Pointer to the Device Object
  230. PIRP Irp: Pointer to the I/O Request Packet
  231. Return: STATUS_SUCCESS: always
  232. Comments: This function is the device driver CLOSE entry point
  233. ******************************************************************************/
  234. NTSTATUS
  235. SerialClose(
  236. IN PDEVICE_OBJECT DeviceObject,
  237. IN PIRP Irp
  238. )
  239. {
  240. LARGE_INTEGER charTime; // 100 ns ticks per char, related to baud rate
  241. PSERIAL_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
  242. LARGE_INTEGER WaitTime; // Actual time req'd for buffer to drain
  243. ULONG check_cnt, nochg_cnt;
  244. ULONG last_tx_count;
  245. ULONG tx_count;
  246. BOOLEAN acceptingIRPs;
  247. ULONG time_to_stall;
  248. acceptingIRPs = SerialIRPPrologue(extension);
  249. if (acceptingIRPs == FALSE) {
  250. MyKdPrint(D_Init,("NotAccIrps Close\n"))
  251. Irp->IoStatus.Information = 0;
  252. Irp->IoStatus.Status = STATUS_SUCCESS;
  253. SerialCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  254. return STATUS_SUCCESS;
  255. }
  256. // object for special ioctls
  257. if (extension->DeviceType != DEV_PORT)
  258. {
  259. MyKdPrint(D_Init,("Close Driver\n"))
  260. //MyKdPrint(D_Init,("Driver IrpCnt:%d\n",extension->PendingIRPCnt))
  261. // Hardware is ready, indicate that the device is open
  262. --extension->DeviceIsOpen;
  263. // If it is the rocketsys dev object return don't set up serial port
  264. Irp->IoStatus.Status = STATUS_SUCCESS;
  265. Irp->IoStatus.Information=0L;
  266. SerialCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  267. return STATUS_SUCCESS;
  268. }
  269. ExtTrace(extension,D_Ioctl,("Close"))
  270. // Calculate 100ns ticks to delay for each character
  271. // Negate for call to KeDelay...
  272. charTime = RtlLargeIntegerNegate(SerialGetCharTime(extension));
  273. #ifdef TXBUFFER
  274. // Wait until ISR has pulled all data out of system side TxBuf
  275. while (extension->TxIn != extension->TxOut)
  276. { // Determine how many characters are actually in TxBuf
  277. TxCount= (extension->TxIn - extension->TxOut);
  278. if (TxCount < 0L)
  279. TxCount+=extension->TxBufSize;
  280. WaitTime= RtlExtendedIntegerMultiply(charTime,TxCount);
  281. KeDelayExecutionThread(KernelMode,FALSE,&WaitTime);
  282. }
  283. #endif //TXBUFFER
  284. // Send an XON if Tx is suspend by IS_FLOW
  285. // send now so we are sure that it gets out of the port before shutdown
  286. if (extension->HandFlow.FlowReplace & SERIAL_AUTO_RECEIVE)
  287. {
  288. if(!(extension->DevStatus & COM_RXFLOW_ON))
  289. {
  290. #ifdef S_RK
  291. sWriteTxPrioByte(extension->ChP,extension->SpecialChars.XonChar);
  292. extension->DevStatus |= COM_RXFLOW_ON;
  293. #endif
  294. extension->RXHolding &= ~SERIAL_RX_XOFF;
  295. }
  296. }
  297. //----- wait for Tx data to finish spooling out
  298. // If tx-data still in transmit buffers, then stall close for
  299. // the configured amount of time waiting for data to spool out.
  300. // If no data movement is seen, we timeout after TxCloseTime.
  301. // If data movement is seen, wait and timeout after (TxCloseTime*3).
  302. time_to_stall = extension->port_config->TxCloseTime;
  303. if (time_to_stall <= 0)
  304. time_to_stall = 1; // use 1-sec if set to 0
  305. if (time_to_stall > 240) // 4-minute max
  306. time_to_stall = 240;
  307. time_to_stall *= 10; // change from seconds to 100ms(1/10th sec) units
  308. #ifdef S_RK
  309. tx_count = extension->TotalCharsQueued + sGetTxCnt(extension->ChP);
  310. if ((sGetChanStatusLo(extension->ChP) & DRAINED) != DRAINED)
  311. ++tx_count;
  312. #else
  313. tx_count = extension->TotalCharsQueued +
  314. PortGetTxCntRemote(extension->Port) +
  315. PortGetTxCnt(extension->Port);
  316. #endif
  317. last_tx_count = tx_count;
  318. if (tx_count != 0)
  319. {
  320. ExtTrace(extension,D_Ioctl,("Tx Stall"));
  321. }
  322. // wait for Tx data to finish spooling out
  323. check_cnt = 0;
  324. nochg_cnt = 0;
  325. while ( (tx_count != 0) && (check_cnt < (time_to_stall*2)) )
  326. {
  327. // set wait-time to .1 second.(-1000 000 = relative(-), 100-ns units)
  328. WaitTime = RtlConvertLongToLargeInteger(-1000000L);
  329. KeDelayExecutionThread(KernelMode,FALSE,&WaitTime);
  330. if (tx_count != last_tx_count)
  331. {
  332. tx_count = last_tx_count;
  333. nochg_cnt = 0;
  334. }
  335. else
  336. {
  337. ++nochg_cnt;
  338. if (nochg_cnt > (time_to_stall)) // no draining occuring!
  339. break; // bail out of while loop
  340. }
  341. ++check_cnt;
  342. #ifdef S_RK
  343. tx_count = extension->TotalCharsQueued + sGetTxCnt(extension->ChP);
  344. if ((sGetChanStatusLo(extension->ChP) & DRAINED) != DRAINED)
  345. ++tx_count;
  346. #else
  347. tx_count = extension->TotalCharsQueued +
  348. PortGetTxCntRemote(extension->Port) +
  349. PortGetTxCnt(extension->Port);
  350. #endif
  351. } // while tx_count
  352. if (tx_count != 0)
  353. {
  354. ExtTrace(extension,D_Ioctl,("Tx Dropped!"));
  355. }
  356. #ifdef COMMENT_OUT
  357. // Calculate total chars and time, then wait.
  358. WaitTime= RtlExtendedIntegerMultiply(charTime,sGetTxCnt(extension->ChP));
  359. KeDelayExecutionThread(KernelMode,FALSE,&WaitTime);
  360. #endif
  361. #ifdef S_RK
  362. // Tx Data is drained, shut down the port
  363. sDisInterrupts(extension->ChP, extension->IntEnables);
  364. // Disable all Tx and Rx functions
  365. sDisTransmit(extension->ChP);
  366. sDisRxFIFO(extension->ChP);
  367. sDisRTSFlowCtl(extension->ChP);
  368. sDisCTSFlowCtl(extension->ChP);
  369. sDisRTSToggle(extension->ChP);
  370. sClrBreak(extension->ChP);
  371. // Drop the modem outputs
  372. // Takes care of DTR flow control as well
  373. sClrRTS(extension->ChP);
  374. sClrDTR(extension->ChP);
  375. #else
  376. // add this, 2-9-99, kpb, CNC xon/xoff problems...
  377. PortFlushRx(extension->Port); // flush rx hardware
  378. PortFlushTx(extension->Port); // flush tx hardware
  379. pClrBreak(extension->Port);
  380. pDisDTRFlowCtl(extension->Port);
  381. pDisRTSFlowCtl(extension->Port);
  382. pDisCTSFlowCtl(extension->Port);
  383. pDisRTSToggle(extension->Port);
  384. pDisDSRFlowCtl(extension->Port);
  385. pDisCDFlowCtl(extension->Port);
  386. pDisTxSoftFlowCtl(extension->Port);
  387. pDisRxSoftFlowCtl(extension->Port);
  388. pDisNullStrip(extension->Port);
  389. pClrRTS(extension->Port);
  390. pClrDTR(extension->Port);
  391. #endif
  392. //extension->ModemCtl &= ~(CTS_ACT | DSR_ACT | CD_ACT);
  393. extension->DTRRTSStatus &= ~(SERIAL_DTR_STATE | SERIAL_RTS_STATE);
  394. #ifdef TXBUFFER
  395. // Release the memory being used for this device's buffers...
  396. extension->TxBufSize = 0;
  397. our_free(extension->TxBuf,"exTX");
  398. extension->TxBuf = NULL;
  399. #endif //TXBUFFER
  400. extension->DeviceIsOpen = FALSE;
  401. extension->RxQ.QSize = 0;
  402. our_free(extension->RxQ.QBase,"exRx");
  403. extension->RxQ.QBase = NULL;
  404. // Finish the Irp
  405. Irp->IoStatus.Status = STATUS_SUCCESS;
  406. Irp->IoStatus.Information = 0L;
  407. SerialCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  408. return STATUS_SUCCESS;
  409. }
  410. /***************************************************************************
  411. Routine Description:
  412. This function is used to kill all longstanding IO operations.
  413. Arguments:
  414. DeviceObject - Pointer to the device object for this device
  415. Irp - Pointer to the IRP for the current request
  416. Return Value:
  417. The function value is the final status of the call
  418. ****************************************************************************/
  419. NTSTATUS
  420. SerialCleanup(
  421. IN PDEVICE_OBJECT DeviceObject,
  422. IN PIRP Irp
  423. )
  424. {
  425. PSERIAL_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
  426. KIRQL oldIrql;
  427. BOOLEAN acceptingIRPs;
  428. MyKdPrint(D_Init,("SerialCleanup\n"))
  429. acceptingIRPs = SerialIRPPrologue(extension);
  430. if (acceptingIRPs == FALSE) {
  431. Irp->IoStatus.Information = 0;
  432. Irp->IoStatus.Status = STATUS_SUCCESS;
  433. SerialCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  434. return STATUS_SUCCESS;
  435. }
  436. if (extension->DeviceType != DEV_PORT)
  437. {
  438. MyKdPrint(D_Init,("Driver IrpCnt:%d\n",extension->PendingIRPCnt))
  439. }
  440. #if DBG
  441. if (extension->CurrentWriteIrp)
  442. {
  443. MyKdPrint(D_Error,("CleanUp WriteQ\n"))
  444. }
  445. if (extension->CurrentReadIrp)
  446. {
  447. MyKdPrint(D_Error,("CleanUp ReadQ\n"))
  448. }
  449. if (extension->CurrentPurgeIrp)
  450. {
  451. MyKdPrint(D_Error,("CleanUp PurgeQ\n"))
  452. }
  453. if (extension->CurrentWaitIrp)
  454. {
  455. MyKdPrint(D_Error,("CleanUp WaitQ\n"))
  456. }
  457. #endif
  458. ExtTrace(extension,D_Ioctl,("SerialCleanup"));
  459. // First kill all the reads and writes.
  460. SerialKillAllReadsOrWrites(
  461. DeviceObject,
  462. &extension->WriteQueue,
  463. &extension->CurrentWriteIrp
  464. );
  465. SerialKillAllReadsOrWrites(
  466. DeviceObject,
  467. &extension->ReadQueue,
  468. &extension->CurrentReadIrp
  469. );
  470. // Next get rid of purges.
  471. SerialKillAllReadsOrWrites(
  472. DeviceObject,
  473. &extension->PurgeQueue,
  474. &extension->CurrentPurgeIrp
  475. );
  476. // Get rid of any mask operations.
  477. //SerialKillAllReadsOrWrites(
  478. // DeviceObject,
  479. // &extension->MaskQueue,
  480. // &extension->CurrentMaskIrp
  481. // );
  482. if (extension->DeviceType != DEV_PORT)
  483. {
  484. MyKdPrint(D_Init,("Driver IrpCnt:%d\n",extension->PendingIRPCnt))
  485. }
  486. // Now get rid of any pending wait mask irp.
  487. IoAcquireCancelSpinLock(&oldIrql);
  488. if (extension->CurrentWaitIrp) {
  489. PDRIVER_CANCEL cancelRoutine;
  490. cancelRoutine = extension->CurrentWaitIrp->CancelRoutine;
  491. extension->CurrentWaitIrp->Cancel = TRUE;
  492. if (cancelRoutine)
  493. { extension->CurrentWaitIrp->CancelIrql = oldIrql;
  494. extension->CurrentWaitIrp->CancelRoutine = NULL;
  495. cancelRoutine( DeviceObject, extension->CurrentWaitIrp );
  496. }
  497. }
  498. else
  499. { IoReleaseCancelSpinLock(oldIrql);
  500. }
  501. Irp->IoStatus.Status = STATUS_SUCCESS;
  502. Irp->IoStatus.Information=0L;
  503. SerialCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  504. return STATUS_SUCCESS;
  505. }
  506. /************************************************************************
  507. Routine: SerialGetCharTime
  508. This function will return the number of 100 nanosecond intervals
  509. there are in one character time (based on the present form
  510. of flow control.
  511. Return Value:
  512. 100 nanosecond intervals in a character time.
  513. *************************************************************************/
  514. LARGE_INTEGER SerialGetCharTime(IN PSERIAL_DEVICE_EXTENSION Extension)
  515. {
  516. ULONG dataSize;
  517. ULONG paritySize;
  518. ULONG stopSize;
  519. ULONG charTime;
  520. ULONG bitTime;
  521. dataSize = Extension->LineCtl.WordLength;
  522. if(!Extension->LineCtl.Parity)
  523. paritySize = 0;
  524. else
  525. paritySize = 1;
  526. if(Extension->LineCtl.StopBits == STOP_BIT_1)
  527. stopSize = 1;
  528. else
  529. stopSize = 2;
  530. // Calculate number of 100 nanosecond intervals in a single bit time
  531. if (Extension->BaudRate == 0)
  532. {
  533. MyKdPrint(D_Init, ("0 Baud!\n"))
  534. Extension->BaudRate = 9600;
  535. }
  536. bitTime = (10000000+(Extension->BaudRate-1))/Extension->BaudRate;
  537. // Calculate number of 100 nanosecond intervals in a character time
  538. charTime = bitTime + ((dataSize+paritySize+stopSize)*bitTime);
  539. return RtlConvertUlongToLargeInteger(charTime);
  540. }
  541. /*****************************************************************************
  542. Function : ForceExtensionSettings
  543. Description: "Forces" the RocketPort to settings as indicated
  544. by the device extension
  545. Note: This is somewhat redundant to SerialSetHandFlow() in ioctl.c.
  546. *****************************************************************************/
  547. VOID ForceExtensionSettings(IN PSERIAL_DEVICE_EXTENSION Extension)
  548. #ifdef S_VS
  549. {
  550. /////////////////////////////////////////////////////////////
  551. // set the baud rate....
  552. ProgramBaudRate(Extension, Extension->BaudRate);
  553. /////////////////////////////////////////////////////////////
  554. // set Line Control.... Data, Parity, Stop
  555. ProgramLineControl(Extension, &Extension->LineCtl);
  556. // HandFlow related options
  557. /////////////////////////////////////////////////////////////
  558. // set up RTS control
  559. Extension->Option &= ~OPTION_RS485_SOFTWARE_TOGGLE;
  560. switch(Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK)
  561. {
  562. case SERIAL_RTS_CONTROL: // RTS Should be asserted while open
  563. pDisRTSFlowCtl(Extension->Port);
  564. pSetRTS(Extension->Port);
  565. Extension->DTRRTSStatus |= SERIAL_RTS_STATE;
  566. break;
  567. case SERIAL_RTS_HANDSHAKE: // RTS hardware input flow control
  568. // Rocket can't determine RTS state... indicate true for this option
  569. pEnRTSFlowCtl(Extension->Port);
  570. Extension->DTRRTSStatus |= SERIAL_RTS_STATE;
  571. break;
  572. case SERIAL_TRANSMIT_TOGGLE: // RTS transmit toggle enabled
  573. if ( Extension->Option & OPTION_RS485_HIGH_ACTIVE ) {
  574. Extension->Option |= OPTION_RS485_SOFTWARE_TOGGLE;
  575. Extension->DTRRTSStatus &= ~SERIAL_RTS_STATE;
  576. pEnRTSToggleHigh(Extension->Port);
  577. } else {
  578. pEnRTSToggleLow(Extension->Port);
  579. Extension->DTRRTSStatus |= SERIAL_RTS_STATE;
  580. }
  581. break;
  582. default:
  583. pDisRTSFlowCtl(Extension->Port);
  584. // Is RTS_CONTROL off?
  585. pClrRTS(Extension->Port);
  586. Extension->DTRRTSStatus &= ~SERIAL_RTS_STATE;
  587. break;
  588. }
  589. if (Extension->Option & OPTION_RS485_OVERRIDE) // 485 override
  590. {
  591. if (Extension->Option & OPTION_RS485_HIGH_ACTIVE)
  592. { // normal case, emulate standard operation
  593. Extension->Option |= OPTION_RS485_SOFTWARE_TOGGLE;
  594. Extension->DTRRTSStatus &= ~SERIAL_RTS_STATE;
  595. pEnRTSToggleHigh(Extension->Port);
  596. }
  597. else
  598. { // hardware reverse case
  599. pEnRTSToggleLow(Extension->Port);
  600. Extension->DTRRTSStatus |= SERIAL_RTS_STATE;
  601. }
  602. }
  603. /////////////////////////////////////////////////////////////
  604. // set up DTR control
  605. pDisDTRFlowCtl(Extension->Port);
  606. // Should DTR be asserted when the port is opened?
  607. if ( (Extension->HandFlow.ControlHandShake & SERIAL_DTR_MASK) ==
  608. SERIAL_DTR_CONTROL )
  609. {
  610. pSetDTR(Extension->Port);
  611. Extension->DTRRTSStatus |= SERIAL_DTR_STATE;
  612. }
  613. else if ( (Extension->HandFlow.ControlHandShake & SERIAL_DTR_MASK) ==
  614. SERIAL_DTR_HANDSHAKE )
  615. {
  616. pEnDTRFlowCtl(Extension->Port);
  617. Extension->DTRRTSStatus |= SERIAL_DTR_STATE;
  618. }
  619. else
  620. {
  621. pClrDTR(Extension->Port);
  622. Extension->DTRRTSStatus &= ~SERIAL_DTR_STATE;
  623. }
  624. ///////////////////////////////////
  625. // DSR hardware output flow control
  626. if (Extension->HandFlow.ControlHandShake & SERIAL_DSR_HANDSHAKE)
  627. {
  628. pEnDSRFlowCtl(Extension->Port);
  629. }
  630. else
  631. {
  632. pDisDSRFlowCtl(Extension->Port);
  633. }
  634. ///////////////////////////////////
  635. // DCD hardware output flow control
  636. if (Extension->HandFlow.ControlHandShake & SERIAL_DCD_HANDSHAKE)
  637. {
  638. pEnCDFlowCtl(Extension->Port);
  639. }
  640. else
  641. {
  642. pDisCDFlowCtl(Extension->Port);
  643. }
  644. /////////////////////////////////////////////////////////////
  645. // Set up CTS Flow Control
  646. if (Extension->HandFlow.ControlHandShake & SERIAL_CTS_HANDSHAKE)
  647. {
  648. pEnCTSFlowCtl(Extension->Port);
  649. }
  650. else
  651. {
  652. pDisCTSFlowCtl(Extension->Port);
  653. }
  654. /////////////////////////////////////////////////////////////
  655. // Set up NULL stripping OPTIONAL
  656. // fix: this was using RxCompare1 register, ioctl code using 0 so
  657. // changed to match.
  658. if (Extension->HandFlow.FlowReplace & SERIAL_NULL_STRIPPING)
  659. {
  660. pEnNullStrip(Extension->Port);
  661. }
  662. else
  663. {
  664. pDisNullStrip(Extension->Port);
  665. }
  666. /////////////////////////////////////////////////////////////
  667. // Set up Software Flow Control OPTIONAL
  668. /////////////////////////////////////////////////////////////
  669. // Special chars needed by RocketPort
  670. pSetXOFFChar(Extension->Port,Extension->SpecialChars.XoffChar);
  671. pSetXONChar(Extension->Port,Extension->SpecialChars.XonChar);
  672. // Software input flow control
  673. // SERIAL_AUTO_RECEIVE
  674. if (Extension->HandFlow.FlowReplace & SERIAL_AUTO_RECEIVE)
  675. {
  676. pEnRxSoftFlowCtl(Extension->Port);
  677. }
  678. else
  679. {
  680. pDisRxSoftFlowCtl(Extension->Port);
  681. }
  682. // Software output flow control
  683. if (Extension->HandFlow.FlowReplace & SERIAL_AUTO_TRANSMIT)
  684. {
  685. pEnTxSoftFlowCtl(Extension->Port);
  686. }
  687. else
  688. {
  689. pDisTxSoftFlowCtl(Extension->Port);
  690. }
  691. }
  692. #else // rocketport code
  693. {
  694. /////////////////////////////////////////////////////////////
  695. // set the baud rate....
  696. ProgramBaudRate(Extension, Extension->BaudRate);
  697. /////////////////////////////////////////////////////////////
  698. // set Line Control.... Data, Parity, Stop
  699. ProgramLineControl(Extension, &Extension->LineCtl);
  700. // HandFlow related options
  701. /////////////////////////////////////////////////////////////
  702. // set up RTS control
  703. Extension->Option &= ~OPTION_RS485_SOFTWARE_TOGGLE;
  704. switch(Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK)
  705. {
  706. case SERIAL_RTS_CONTROL: // RTS Should be asserted while open
  707. sSetRTS(Extension->ChP);
  708. Extension->DTRRTSStatus |= SERIAL_RTS_STATE;
  709. break;
  710. case SERIAL_RTS_HANDSHAKE: // RTS hardware input flow control
  711. // Rocket can't determine RTS state... indicate true for this option
  712. sEnRTSFlowCtl(Extension->ChP);
  713. Extension->DTRRTSStatus |= SERIAL_RTS_STATE;
  714. break;
  715. case SERIAL_TRANSMIT_TOGGLE: // RTS transmit toggle enabled
  716. if (Extension->Option & OPTION_RS485_HIGH_ACTIVE)
  717. { // normal case, emulate standard operation
  718. Extension->Option |= OPTION_RS485_SOFTWARE_TOGGLE;
  719. Extension->DTRRTSStatus &= ~SERIAL_RTS_STATE;
  720. sClrRTS(Extension->ChP);
  721. }
  722. else
  723. { // hardware reverse case
  724. sEnRTSToggle(Extension->ChP);
  725. Extension->DTRRTSStatus |= SERIAL_RTS_STATE;
  726. }
  727. break;
  728. default:
  729. // Is RTS_CONTROL off?
  730. sClrRTS(Extension->ChP);
  731. Extension->DTRRTSStatus &= ~SERIAL_RTS_STATE;
  732. break;
  733. }
  734. if (Extension->Option & OPTION_RS485_OVERRIDE) // 485 override
  735. {
  736. if (Extension->Option & OPTION_RS485_HIGH_ACTIVE)
  737. { // normal case, emulate standard operation
  738. Extension->Option |= OPTION_RS485_SOFTWARE_TOGGLE;
  739. Extension->DTRRTSStatus &= ~SERIAL_RTS_STATE;
  740. sClrRTS(Extension->ChP);
  741. }
  742. else
  743. { // hardware reverse case
  744. sEnRTSToggle(Extension->ChP);
  745. Extension->DTRRTSStatus |= SERIAL_RTS_STATE;
  746. }
  747. }
  748. /////////////////////////////////////////////////////////////
  749. // set up DTR control
  750. // Should DTR be asserted when the port is opened?
  751. if( Extension->HandFlow.ControlHandShake &
  752. (SERIAL_DTR_CONTROL|SERIAL_DTR_HANDSHAKE)
  753. )
  754. {
  755. sSetDTR(Extension->ChP);
  756. Extension->DTRRTSStatus |= SERIAL_DTR_STATE;
  757. }
  758. else
  759. {
  760. sClrDTR(Extension->ChP);
  761. Extension->DTRRTSStatus &= ~SERIAL_DTR_STATE;
  762. }
  763. /////////////////////////////////////////////////////////////
  764. // Set up CTS Flow Control
  765. if (Extension->HandFlow.ControlHandShake & SERIAL_CTS_HANDSHAKE)
  766. {
  767. sEnCTSFlowCtl(Extension->ChP);
  768. }
  769. else
  770. {
  771. sDisCTSFlowCtl(Extension->ChP);
  772. }
  773. /////////////////////////////////////////////////////////////
  774. // Set up NULL stripping OPTIONAL
  775. // fix: this was using RxCompare1 register, ioctl code using 0 so
  776. // changed to match.
  777. if (Extension->HandFlow.FlowReplace & SERIAL_NULL_STRIPPING)
  778. {
  779. sEnRxIgnore0(Extension->ChP,0);
  780. }
  781. else
  782. {
  783. sDisRxCompare0(Extension->ChP);
  784. }
  785. /////////////////////////////////////////////////////////////
  786. // Set up Software Flow Control OPTIONAL
  787. /////////////////////////////////////////////////////////////
  788. // Special chars needed by RocketPort
  789. sSetTxXOFFChar(Extension->ChP,Extension->SpecialChars.XoffChar);
  790. sSetTxXONChar(Extension->ChP,Extension->SpecialChars.XonChar);
  791. // SERIAL_AUTO_RECEIVE is taken care of by the driver
  792. // Software output flow control
  793. if (Extension->HandFlow.FlowReplace & SERIAL_AUTO_TRANSMIT)
  794. {
  795. sEnTxSoftFlowCtl(Extension->ChP);
  796. }
  797. else
  798. {
  799. sDisTxSoftFlowCtl(Extension->ChP);
  800. sClrTxXOFF(Extension->ChP);
  801. }
  802. }
  803. #endif
  804. #ifdef S_RK
  805. /*****************************************************************************
  806. Function : SetExtensionModemStatus
  807. Description: Reads and saves a copy of the modem control inputs,
  808. then fills out the ModemStatus member in the extension.
  809. *****************************************************************************/
  810. VOID
  811. SetExtensionModemStatus(
  812. IN PSERIAL_DEVICE_EXTENSION extension
  813. )
  814. {
  815. unsigned int ModemStatus = 0; // start off with no status
  816. ULONG wstat;
  817. //MyKdPrint(D_Init, ("SetExtModemStat"))
  818. // ModemCtl is an image of the RocketPort's modem status
  819. // ModemStatus member is passed to host via IOCTL
  820. #if DBG
  821. // this is called during isr.c poll, so put
  822. // some assertions where we have been burned before...
  823. if (extension->board_ext->config == NULL)
  824. {
  825. MyKdPrint(D_Init, ("SetExtMdm Err0\n"))
  826. return;
  827. }
  828. #ifdef S_RK
  829. if (!extension->board_ext->config->RocketPortFound)
  830. {
  831. MyKdPrint(D_Init, ("SetExtMdm Err1\n"))
  832. return;
  833. }
  834. #endif
  835. if (NULL == extension->ChP)
  836. {
  837. MyKdPrint(D_Init, ("SetExtMdm Err2\n"))
  838. return;
  839. }
  840. if (0 == extension->ChP->ChanStat)
  841. {
  842. MyKdPrint(D_Init, ("SetExtMdm Err3\n"))
  843. return;
  844. }
  845. if (NULL == extension->port_config)
  846. {
  847. MyKdPrint(D_Init, ("SetExtMdm Err4\n"))
  848. return;
  849. }
  850. #endif
  851. // Read the port's modem control inputs and save off a copy
  852. extension->ModemCtl = sGetModemStatus(extension->ChP);
  853. if (extension->port_config->MapCdToDsr) // if CD to DSR option, swap signals
  854. {
  855. // swap CD and DSR handling for RJ11 board owners,
  856. // so they can have pick between CD or DSR
  857. if ((extension->ModemCtl & (CD_ACT | DSR_ACT)) == CD_ACT)
  858. {
  859. // swap
  860. extension->ModemCtl &= ~CD_ACT;
  861. extension->ModemCtl |= DSR_ACT;
  862. }
  863. else if ((extension->ModemCtl & (CD_ACT | DSR_ACT)) == DSR_ACT)
  864. {
  865. extension->ModemCtl &= ~DSR_ACT;
  866. extension->ModemCtl |= CD_ACT;
  867. }
  868. }
  869. // handle RPortPlus RI signal
  870. if (extension->board_ext->config->IsRocketPortPlus)
  871. {
  872. if (sGetRPlusModemRI(extension->ChP))
  873. ModemStatus |= SERIAL_RI_STATE;
  874. else ModemStatus &= ~SERIAL_RI_STATE;
  875. }
  876. #ifdef RING_FAKE
  877. if (extension->port_config->RingEmulate)
  878. {
  879. if (extension->ring_timer != 0) // RI on
  880. ModemStatus |= SERIAL_RI_STATE;
  881. else ModemStatus &= ~SERIAL_RI_STATE;
  882. }
  883. #endif
  884. if (extension->ModemCtl & COM_MDM_DSR) // if DSR on
  885. {
  886. ModemStatus |= SERIAL_DSR_STATE;
  887. if (extension->TXHolding & SERIAL_TX_DSR) // holding
  888. {
  889. extension->TXHolding &= ~SERIAL_TX_DSR; // clear holding
  890. // if not holding due to other reason
  891. if ((extension->TXHolding &
  892. (SERIAL_TX_DCD | SERIAL_TX_DSR | ST_XOFF_FAKE)) == 0)
  893. sEnTransmit(extension->ChP); // re-enable transmit
  894. }
  895. }
  896. else // if DSR off
  897. {
  898. if (extension->HandFlow.ControlHandShake & SERIAL_DSR_HANDSHAKE)
  899. {
  900. if (!(extension->TXHolding & SERIAL_TX_DSR)) // not holding
  901. {
  902. extension->TXHolding |= SERIAL_TX_DSR; // set holding
  903. sDisTransmit(extension->ChP); // hold transmit
  904. }
  905. }
  906. }
  907. if (extension->ModemCtl & COM_MDM_CTS) // if CTS on
  908. {
  909. ModemStatus |= SERIAL_CTS_STATE;
  910. if (extension->TXHolding & SERIAL_TX_CTS) // holding
  911. extension->TXHolding &= ~SERIAL_TX_CTS; // clear holding
  912. }
  913. else // cts off
  914. {
  915. if (extension->HandFlow.ControlHandShake & SERIAL_CTS_HANDSHAKE)
  916. {
  917. if (!(extension->TXHolding & SERIAL_TX_CTS)) // not holding
  918. extension->TXHolding |= SERIAL_TX_CTS; // set holding
  919. }
  920. }
  921. if (extension->ModemCtl & COM_MDM_CD) // if CD on
  922. {
  923. ModemStatus |= SERIAL_DCD_STATE;
  924. if (extension->TXHolding & SERIAL_TX_DCD) // holding
  925. {
  926. extension->TXHolding &= ~SERIAL_TX_DCD; // clear holding
  927. // if not holding due to other reason
  928. if ((extension->TXHolding &
  929. (SERIAL_TX_DCD | SERIAL_TX_DSR | ST_XOFF_FAKE)) == 0)
  930. sEnTransmit(extension->ChP); // re-enable transmit
  931. }
  932. }
  933. else // if CD off
  934. {
  935. if (extension->HandFlow.ControlHandShake & SERIAL_DCD_HANDSHAKE)
  936. {
  937. if (!(extension->TXHolding & SERIAL_TX_DCD)) // not holding
  938. {
  939. extension->TXHolding |= SERIAL_TX_DCD; // set holding
  940. sDisTransmit(extension->ChP); // hold transmit
  941. }
  942. }
  943. }
  944. // handle holding detection if xon,xoff tx control activated
  945. if (extension->HandFlow.FlowReplace & SERIAL_AUTO_TRANSMIT)
  946. {
  947. wstat = sGetChanStatusLo(extension->ChP);
  948. // check for tx-flowed off condition to report
  949. if ((wstat & (TXFIFOMT | TXSHRMT)) == TXSHRMT)
  950. {
  951. if (!extension->TXHolding) // not holding
  952. {
  953. wstat = sGetChanStatusLo(extension->ChP);
  954. if ((wstat & (TXFIFOMT | TXSHRMT)) == TXSHRMT)
  955. {
  956. extension->TXHolding |= SERIAL_TX_XOFF; // holding
  957. }
  958. }
  959. }
  960. else // clear xoff holding report
  961. {
  962. if (extension->TXHolding & SERIAL_TX_XOFF)
  963. extension->TXHolding &= ~SERIAL_TX_XOFF; // not holding
  964. }
  965. }
  966. extension->ModemStatus = ModemStatus;
  967. }
  968. #endif