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.

784 lines
22 KiB

  1. /*--------------------------------------------------------------------------
  2. *
  3. * Copyright (C) Cyclades Corporation, 1996-2001.
  4. * All rights reserved.
  5. *
  6. * Cyclom-Y Port Driver
  7. *
  8. * This file: cyyopcl.c
  9. *
  10. * Description: This module contains the code related to opening,
  11. * closing and cleaning up in the Cyclom-Y Port driver.
  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. BOOLEAN
  31. CyyMarkOpen(
  32. IN PVOID Context
  33. );
  34. BOOLEAN
  35. CyyNullSynch(
  36. IN PVOID Context
  37. );
  38. #ifdef ALLOC_PRAGMA
  39. #pragma alloc_text(PAGESER,CyyGetCharTime)
  40. #pragma alloc_text(PAGESER,CyyMarkClose)
  41. #pragma alloc_text(PAGESER,CyyCleanup)
  42. #pragma alloc_text(PAGESER,CyyClose)
  43. #pragma alloc_text(PAGESER,CyyMarkClose)
  44. #pragma alloc_text(PAGESER,CyyMarkOpen)
  45. //
  46. // Always paged
  47. //
  48. #pragma alloc_text(PAGESRP0,CyyCreateOpen)
  49. #endif // ALLOC_PRAGMA
  50. BOOLEAN
  51. CyyNullSynch(
  52. IN PVOID Context
  53. )
  54. /*------------------------------------------------------------------------
  55. Just a bogus little routine to synch with the ISR.
  56. ------------------------------------------------------------------------*/
  57. {
  58. UNREFERENCED_PARAMETER(Context);
  59. return FALSE;
  60. }
  61. NTSTATUS
  62. CyyCreateOpen(
  63. IN PDEVICE_OBJECT DeviceObject,
  64. IN PIRP Irp
  65. )
  66. /*--------------------------------------------------------------------------
  67. CyyCreateOpen()
  68. Description: We connect up to the interrupt for the create/open
  69. and initialize the structures needed to maintain an open for a
  70. device.
  71. Arguments:
  72. DeviceObject - Pointer to the device object for this device
  73. Irp - Pointer to the IRP for the current request
  74. Return Value: The function value is the final status of the call
  75. --------------------------------------------------------------------------*/
  76. {
  77. PCYY_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
  78. NTSTATUS localStatus;
  79. PAGED_CODE();
  80. if (extension->PNPState != CYY_PNP_STARTED) {
  81. Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  82. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  83. return STATUS_INSUFFICIENT_RESOURCES;
  84. }
  85. //
  86. // Lock out changes to PnP state until we have our open state decided
  87. //
  88. ExAcquireFastMutex(&extension->OpenMutex);
  89. if ((localStatus = CyyIRPPrologue(Irp, extension)) != STATUS_SUCCESS) {
  90. ExReleaseFastMutex(&extension->OpenMutex);
  91. if(localStatus != STATUS_PENDING) {
  92. CyyCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  93. }
  94. return localStatus;
  95. }
  96. if (InterlockedIncrement(&extension->OpenCount) != 1) {
  97. ExReleaseFastMutex(&extension->OpenMutex);
  98. InterlockedDecrement(&extension->OpenCount);
  99. Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
  100. CyyCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  101. return STATUS_ACCESS_DENIED;
  102. }
  103. CyyDbgPrintEx(CYYIRPPATH, "Dispatch entry for: %x\n", Irp);
  104. CyyDbgPrintEx(CYYDIAG3, "In CyyCreateOpen\n");
  105. // Before we do anything, let's make sure they aren't trying
  106. // to create a directory. This is a silly, but what's a driver to do!?
  107. if (IoGetCurrentIrpStackLocation(Irp)->Parameters.Create.Options &
  108. FILE_DIRECTORY_FILE) {
  109. ExReleaseFastMutex(&extension->OpenMutex);
  110. Irp->IoStatus.Status = STATUS_NOT_A_DIRECTORY;
  111. Irp->IoStatus.Information = 0;
  112. InterlockedDecrement(&extension->OpenCount);
  113. CyyCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  114. return STATUS_NOT_A_DIRECTORY;
  115. }
  116. // Create a buffer for the RX data when no reads are outstanding.
  117. extension->InterruptReadBuffer = NULL;
  118. extension->BufferSize = 0;
  119. // Try to allocate large buffers, whether the system is MmLargeSystem,
  120. // MmMediumSystem or MmSmallSystem.
  121. extension->BufferSize = 4096;
  122. extension->InterruptReadBuffer =
  123. ExAllocatePool(NonPagedPool,extension->BufferSize);
  124. if (!extension->InterruptReadBuffer) {
  125. extension->BufferSize = 2048;
  126. extension->InterruptReadBuffer =
  127. ExAllocatePool(NonPagedPool,extension->BufferSize);
  128. if (!extension->InterruptReadBuffer) {
  129. extension->BufferSize = 1024;
  130. extension->InterruptReadBuffer =
  131. ExAllocatePool(NonPagedPool,extension->BufferSize);
  132. if (!extension->InterruptReadBuffer) {
  133. extension->BufferSize = 128;
  134. extension->InterruptReadBuffer =
  135. ExAllocatePool(NonPagedPool,extension->BufferSize);
  136. }
  137. }
  138. }
  139. #if 0
  140. switch (MmQuerySystemSize()) {
  141. case MmLargeSystem: {
  142. extension->BufferSize = 4096;
  143. extension->InterruptReadBuffer =
  144. ExAllocatePool(NonPagedPool,extension->BufferSize);
  145. if (extension->InterruptReadBuffer)
  146. break;
  147. }
  148. default: {
  149. extension->BufferSize = 1024;
  150. extension->InterruptReadBuffer =
  151. ExAllocatePool(NonPagedPool,extension->BufferSize);
  152. if (extension->InterruptReadBuffer) break;
  153. extension->BufferSize = 128;
  154. extension->InterruptReadBuffer =
  155. ExAllocatePool(NonPagedPool,extension->BufferSize);
  156. break;
  157. }
  158. }
  159. #endif
  160. if (!extension->InterruptReadBuffer) {
  161. ExReleaseFastMutex(&extension->OpenMutex);
  162. extension->BufferSize = 0;
  163. Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  164. Irp->IoStatus.Information = 0;
  165. InterlockedDecrement(&extension->OpenCount);
  166. CyyCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  167. return STATUS_INSUFFICIENT_RESOURCES;
  168. }
  169. //
  170. // Ok, it looks like we really are going to open. Lock down the
  171. // driver.
  172. //
  173. CyyLockPagableSectionByHandle(CyyGlobals.PAGESER_Handle);
  174. //
  175. // Power up the stack
  176. //
  177. (void)CyyGotoPowerState(DeviceObject, extension, PowerDeviceD0);
  178. //
  179. // Not currently waiting for wake up
  180. //
  181. extension->SendWaitWake = FALSE;
  182. // "flush" the read queue by initializing the count of characters.
  183. extension->CharsInInterruptBuffer = 0;
  184. extension->LastCharSlot = extension->InterruptReadBuffer +
  185. (extension->BufferSize - 1);
  186. extension->ReadBufferBase = extension->InterruptReadBuffer;
  187. extension->CurrentCharSlot = extension->InterruptReadBuffer;
  188. extension->FirstReadableChar = extension->InterruptReadBuffer;
  189. extension->TotalCharsQueued = 0;
  190. // set up the default xon/xoff limits.
  191. extension->HandFlow.XoffLimit = extension->BufferSize >> 3;
  192. extension->HandFlow.XonLimit = extension->BufferSize >> 1;
  193. extension->WmiCommData.XoffXmitThreshold = extension->HandFlow.XoffLimit;
  194. extension->WmiCommData.XonXmitThreshold = extension->HandFlow.XonLimit;
  195. extension->BufferSizePt8 = ((3*(extension->BufferSize>>2))+
  196. (extension->BufferSize>>4));
  197. //
  198. // Mark the device as busy for WMI
  199. //
  200. extension->WmiCommData.IsBusy = TRUE;
  201. extension->IrpMaskLocation = NULL;
  202. extension->HistoryMask = 0;
  203. extension->IsrWaitMask = 0;
  204. #if !DBG
  205. // Clear out the statistics.
  206. KeSynchronizeExecution(extension->Interrupt,CyyClearStats,extension);
  207. #endif
  208. extension->EscapeChar = 0;
  209. // Synchronize with the ISR and mark the device as open
  210. KeSynchronizeExecution(extension->Interrupt,CyyMarkOpen,extension);
  211. Irp->IoStatus.Status = STATUS_SUCCESS;
  212. //
  213. // We have been marked open, so now the PnP state can change
  214. //
  215. ExReleaseFastMutex(&extension->OpenMutex);
  216. localStatus = Irp->IoStatus.Status;
  217. Irp->IoStatus.Information=0L;
  218. if (!NT_SUCCESS(localStatus)) {
  219. if (extension->InterruptReadBuffer != NULL) {
  220. ExFreePool(extension->InterruptReadBuffer);
  221. extension->InterruptReadBuffer = NULL;
  222. }
  223. InterlockedDecrement(&extension->OpenCount);
  224. }
  225. CyyCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  226. return localStatus;
  227. }
  228. //TODO FANNY: DO WE NEED THIS?
  229. #if 0
  230. VOID
  231. SerialDrainUART(IN PSERIAL_DEVICE_EXTENSION PDevExt,
  232. IN PLARGE_INTEGER PDrainTime)
  233. {
  234. PAGED_CODE();
  235. //
  236. // Wait until all characters have been emptied out of the hardware.
  237. //
  238. while ((READ_LINE_STATUS(PDevExt->Controller) &
  239. (SERIAL_LSR_THRE | SERIAL_LSR_TEMT))
  240. != (SERIAL_LSR_THRE | SERIAL_LSR_TEMT)) {
  241. KeDelayExecutionThread(KernelMode, FALSE, PDrainTime);
  242. }
  243. }
  244. #endif
  245. NTSTATUS
  246. CyyClose(
  247. IN PDEVICE_OBJECT DeviceObject,
  248. IN PIRP Irp
  249. )
  250. /*--------------------------------------------------------------------------
  251. CyyClose()
  252. Description: We simply disconnect the interrupt for now.
  253. Arguments:
  254. DeviceObject - Pointer to the device object for this device
  255. Irp - Pointer to the IRP for the current request
  256. Return Value: The function value is the final status of the call
  257. --------------------------------------------------------------------------*/
  258. {
  259. LARGE_INTEGER tenCharDelay;
  260. LARGE_INTEGER charTime;
  261. PCYY_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
  262. ULONG i;
  263. NTSTATUS status;
  264. //
  265. // Number of opens still active
  266. //
  267. LONG openCount;
  268. //
  269. // Number of DPC's still pending
  270. //
  271. ULONG pendingDPCs;
  272. ULONG flushCount;
  273. //
  274. // Grab a mutex
  275. //
  276. ExAcquireFastMutex(&extension->CloseMutex);
  277. //
  278. // We succeed a close on a removing device
  279. //
  280. if ((status = CyyIRPPrologue(Irp, extension)) != STATUS_SUCCESS) {
  281. CyyDbgPrintEx(DPFLTR_INFO_LEVEL, "Close prologue failed for: %x\n",
  282. Irp);
  283. if (status == STATUS_DELETE_PENDING) {
  284. extension->BufferSize = 0;
  285. ExFreePool(extension->InterruptReadBuffer);
  286. extension->InterruptReadBuffer = NULL;
  287. status = Irp->IoStatus.Status = STATUS_SUCCESS;
  288. }
  289. if (status != STATUS_PENDING) {
  290. CyyCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  291. openCount = InterlockedDecrement(&extension->OpenCount);
  292. ASSERT(openCount == 0);
  293. }
  294. ExReleaseFastMutex(&extension->CloseMutex);
  295. return status;
  296. }
  297. ASSERT(extension->OpenCount >= 1);
  298. if (extension->OpenCount < 1) {
  299. CyyDbgPrintEx(DPFLTR_ERROR_LEVEL, "Close open count bad for: 0x%x\n",
  300. Irp);
  301. CyyDbgPrintEx(DPFLTR_ERROR_LEVEL, "Count: %x Addr: 0x%x\n",
  302. extension->OpenCount, &extension->OpenCount);
  303. ExReleaseFastMutex(&extension->CloseMutex);
  304. Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
  305. CyyCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  306. return STATUS_INVALID_DEVICE_REQUEST;
  307. }
  308. CyyDbgPrintEx(CYYIRPPATH, "Dispatch entry for: %x\n", Irp);
  309. CyyDbgPrintEx(CYYDIAG3, "In CyyClose\n");
  310. charTime.QuadPart = -CyyGetCharTime(extension).QuadPart;
  311. extension->DeviceIsOpened = FALSE;
  312. // Turn break off in case it is on
  313. //Call of CyyTurnOffBreak removed, because as DeviceIsOpened will be
  314. //FALSE in the ISR, the Stop Break cannot be executed. Anyway, any
  315. //char (other than Send Break) sent to the FIFO will stop the Break.
  316. //KeSynchronizeExecution(extension->Interrupt,CyyTurnOffBreak,extension);
  317. // Wait until all characters have been emptied out of the hardware.
  318. for(i = 0 ; i < MAX_CHAR_FIFO ; i++) {
  319. KeDelayExecutionThread(KernelMode,FALSE,&charTime);
  320. }
  321. // TODO FANNY: SHOULD WE CALL SerialMarkHardwareBroken()? SEE LATER...
  322. // Synchronize with the ISR to let it know that interrupts are
  323. // no longer important.
  324. KeSynchronizeExecution(extension->Interrupt,CyyMarkClose,extension);
  325. // If the driver has automatically transmitted an Xoff in
  326. // the context of automatic receive flow control then we
  327. // should transmit an Xon.
  328. if (extension->RXHolding & CYY_RX_XOFF) {
  329. //volatile unsigned char *pt_chip = extension->Controller;
  330. //ULONG index = extension->BusIndex;
  331. //
  332. //cy_wreg(CAR,extension->CdChannel & 0x03);
  333. PUCHAR chip = extension->Cd1400;
  334. ULONG bus = extension->IsPci;
  335. CD1400_WRITE(chip,bus,CAR,extension->CdChannel & 0x03);
  336. CyyCDCmd(extension,CCR_SENDSC_SCHR1);
  337. //TODO FANNY: SHOULD WE CALL SerialMarkHardwareBroken()? SEE LATER...
  338. }
  339. // The hardware is hopefully empty. Delay 10 chars before dropping DTR.
  340. tenCharDelay.QuadPart = charTime.QuadPart * 10;
  341. KeDelayExecutionThread(KernelMode,TRUE,&tenCharDelay);
  342. CyyClrDTR(extension);
  343. // We have to be very careful how we clear the RTS line.
  344. // Transmit toggling might have been on at some point.
  345. //
  346. // We know that there is nothing left that could start
  347. // out the "polling" execution path. We need to
  348. // check the counter that indicates that the execution
  349. // path is active. If it is then we loop delaying one
  350. // character time. After each delay we check to see if
  351. // the counter has gone to zero. When it has we know that
  352. // the execution path should be just about finished. We
  353. // make sure that we still aren't in the routine that
  354. // synchronized execution with the ISR by synchronizing
  355. // ourselve with the ISR.
  356. if (extension->CountOfTryingToLowerRTS) {
  357. do {
  358. KeDelayExecutionThread(KernelMode,FALSE,&charTime);
  359. } while (extension->CountOfTryingToLowerRTS);
  360. KeSynchronizeExecution(extension->Interrupt,CyyNullSynch,NULL);
  361. }
  362. CyyClrRTS(extension);
  363. // Clean out the holding reasons (since we are closed).
  364. extension->RXHolding = 0;
  365. extension->TXHolding = 0;
  366. //
  367. // Mark device as not busy for WMI
  368. //
  369. extension->WmiCommData.IsBusy = FALSE;
  370. // Release the buffers.
  371. extension->BufferSize = 0;
  372. if (extension->InterruptReadBuffer != NULL) { // added in DDK build 2072
  373. ExFreePool(extension->InterruptReadBuffer);
  374. }
  375. extension->InterruptReadBuffer = NULL;
  376. //
  377. // Stop waiting for wakeup
  378. //
  379. extension->SendWaitWake = FALSE;
  380. if (extension->PendingWakeIrp != NULL) {
  381. IoCancelIrp(extension->PendingWakeIrp);
  382. }
  383. //
  384. // Power down our device stack
  385. //
  386. (void)CyyGotoPowerState(DeviceObject, extension, PowerDeviceD3);
  387. Irp->IoStatus.Status = STATUS_SUCCESS;
  388. Irp->IoStatus.Information=0L;
  389. CyyCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  390. //
  391. // Unlock the pages. If this is the last reference to the section
  392. // then the driver code will be flushed out.
  393. //
  394. //
  395. // First, we have to let the DPC's drain. No more should be queued
  396. // since we aren't taking interrupts now....
  397. //
  398. pendingDPCs = InterlockedDecrement(&extension->DpcCount);
  399. LOGENTRY(LOG_CNT, 'DpD7', 0, extension->DpcCount, 0); // Added in build 2128
  400. if (pendingDPCs) {
  401. CyyDbgPrintEx(CYYDIAG1,"Draining DPC's: %x\n", Irp);
  402. KeWaitForSingleObject(&extension->PendingDpcEvent, Executive,
  403. KernelMode, FALSE, NULL);
  404. }
  405. CyyDbgPrintEx(CYYDIAG1, "DPC's drained: %x\n", Irp);
  406. //
  407. // Pages must be locked to release the mutex, so don't unlock
  408. // them until after we release the mutex
  409. //
  410. ExReleaseFastMutex(&extension->CloseMutex);
  411. //
  412. // Reset for next open
  413. //
  414. InterlockedIncrement(&extension->DpcCount);
  415. LOGENTRY(LOG_CNT, 'DpI6', 0, extension->DpcCount, 0); // Added in build 2128
  416. openCount = InterlockedDecrement(&extension->OpenCount);
  417. //
  418. // Open count may be non-zero if someone was trying to open
  419. // at the same time we decremented
  420. //
  421. // ASSERT(openCount == 0);
  422. CyyUnlockPagableImageSection(CyyGlobals.PAGESER_Handle);
  423. return STATUS_SUCCESS;
  424. }
  425. BOOLEAN
  426. CyyMarkOpen(
  427. IN PVOID Context
  428. )
  429. /*------------------------------------------------------------------------
  430. CyyMarkOpen()
  431. Routine Description: This routine mark the fact that somebody opened
  432. the device and its worthwhile to pay attention to interrupts.
  433. Arguments:
  434. Context - Really a pointer to the device extension.
  435. Return Value: This routine always returns FALSE.
  436. ------------------------------------------------------------------------*/
  437. {
  438. PCYY_DEVICE_EXTENSION extension = Context;
  439. CyyReset(extension);
  440. extension->DeviceIsOpened = TRUE;
  441. extension->ErrorWord = 0;
  442. return FALSE;
  443. }
  444. VOID
  445. CyyDisableCd1400Channel(IN PVOID Context)
  446. /*++
  447. Routine Description:
  448. This routine disables the UART and puts it in a "safe" state when
  449. not in use (like a close or powerdown).
  450. Arguments:
  451. Context - Really a pointer to the device extension.
  452. Return Value:
  453. This routine always returns FALSE.
  454. --*/
  455. {
  456. PCYY_DEVICE_EXTENSION extension = Context;
  457. PCYY_DISPATCH pDispatch;
  458. PUCHAR chip = extension->Cd1400;
  459. ULONG bus = extension->IsPci;
  460. ULONG i;
  461. //
  462. // Prepare for the closing by stopping interrupts.
  463. //
  464. CD1400_WRITE(chip,bus,CAR,extension->CdChannel & 0x03);
  465. CD1400_WRITE(chip,bus,SRER,0x00); // Disable MdmCh, RxData, TxRdy
  466. // Flush TX FIFO
  467. //CD1400_WRITE(chip,bus,CAR,extension->CdChannel & 0x03);
  468. CyyCDCmd(extension,CCR_FLUSH_TXFIFO);
  469. pDispatch = (PCYY_DISPATCH)extension->OurIsrContext;
  470. pDispatch->Cd1400[extension->PortIndex] = NULL;
  471. for (i = 0; i < CYY_MAX_PORTS; i++) {
  472. if (pDispatch->Cd1400[extension->PortIndex] != NULL) {
  473. break;
  474. }
  475. }
  476. if (i == CYY_MAX_PORTS) {
  477. // This was the last port, we can clear any pending interrupt.
  478. CYY_CLEAR_INTERRUPT(extension->BoardMemory,bus);
  479. }
  480. }
  481. BOOLEAN
  482. CyyMarkClose(
  483. IN PVOID Context
  484. )
  485. /*------------------------------------------------------------------------
  486. CyyMarkClose()
  487. Routine Description: This routine merely sets a boolean to false to
  488. mark the fact that somebody closed the device and it's no longer
  489. worthwhile to pay attention to interrupts.
  490. Arguments:
  491. Context - Really a pointer to the device extension.
  492. Return Value: This routine always returns FALSE.
  493. ------------------------------------------------------------------------*/
  494. {
  495. PCYY_DEVICE_EXTENSION extension = Context;
  496. CyyDisableCd1400Channel(Context);
  497. extension->DeviceIsOpened = FALSE;
  498. return FALSE;
  499. }
  500. NTSTATUS
  501. CyyCleanup(
  502. IN PDEVICE_OBJECT DeviceObject,
  503. IN PIRP Irp
  504. )
  505. /*------------------------------------------------------------------------
  506. CyyCleanup()
  507. Routine Description: This function is used to kill all longstanding
  508. IO operations.
  509. Arguments:
  510. DeviceObject - Pointer to the device object for this device
  511. Irp - Pointer to the IRP for the current request
  512. Return Value: The function value is the final status of the call
  513. ------------------------------------------------------------------------*/
  514. {
  515. PCYY_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
  516. NTSTATUS status;
  517. PAGED_CODE();
  518. //
  519. // We succeed a cleanup on a removing device
  520. //
  521. if ((status = CyyIRPPrologue(Irp, extension)) != STATUS_SUCCESS) {
  522. if (status == STATUS_DELETE_PENDING) {
  523. status = Irp->IoStatus.Status = STATUS_SUCCESS;
  524. }
  525. if (status != STATUS_PENDING) {
  526. CyyCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  527. }
  528. return status;
  529. }
  530. CyyDbgPrintEx(CYYIRPPATH, "Dispatch entry for: %x\n", Irp);
  531. CyyKillPendingIrps(DeviceObject);
  532. Irp->IoStatus.Status = STATUS_SUCCESS;
  533. Irp->IoStatus.Information=0L;
  534. CyyCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  535. return STATUS_SUCCESS;
  536. }
  537. LARGE_INTEGER
  538. CyyGetCharTime(
  539. IN PCYY_DEVICE_EXTENSION Extension
  540. )
  541. /*------------------------------------------------------------------------
  542. CyyGetCharTime()
  543. Routine Description: return the number of 100 nanosecond intervals
  544. there are in one character time.
  545. Arguments:
  546. Extension - Just what it says.
  547. Return Value: 100 nanosecond intervals in a character time.
  548. ------------------------------------------------------------------------*/
  549. {
  550. ULONG dataSize;
  551. ULONG paritySize;
  552. ULONG stopSize;
  553. ULONG charTime;
  554. ULONG bitTime;
  555. LARGE_INTEGER tmp;
  556. if ((Extension->cor1 & COR1_DATA_MASK) == COR1_5_DATA) {
  557. dataSize = 5;
  558. } else if ((Extension->cor1 & COR1_DATA_MASK) == COR1_6_DATA) {
  559. dataSize = 6;
  560. } else if ((Extension->cor1 & COR1_DATA_MASK) == COR1_7_DATA) {
  561. dataSize = 7;
  562. } else {
  563. dataSize = 8;
  564. }
  565. paritySize = 1;
  566. if ((Extension->cor1 & COR1_PARITY_MASK) == COR1_NONE_PARITY) {
  567. paritySize = 0;
  568. }
  569. if ((Extension->cor1 & COR1_STOP_MASK) == COR1_1_STOP) {
  570. stopSize = 1;
  571. } else {
  572. stopSize = 2;
  573. }
  574. //
  575. // First we calculate the number of 100 nanosecond intervals
  576. // are in a single bit time (Approximately).
  577. //
  578. bitTime = (10000000+(Extension->CurrentBaud-1))/Extension->CurrentBaud;
  579. charTime = bitTime + ((dataSize+paritySize+stopSize)*bitTime);
  580. tmp.QuadPart = charTime;
  581. return tmp;
  582. }
  583.