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.

2784 lines
71 KiB

  1. /*++
  2. Module Name:
  3. ioctl.c
  4. Environment:
  5. Kernel mode
  6. Revision History :
  7. --*/
  8. #include "precomp.h"
  9. NTSTATUS
  10. MoxaIoControl(
  11. IN PDEVICE_OBJECT DeviceObject,
  12. IN PIRP Irp
  13. )
  14. {
  15. NTSTATUS status;
  16. //
  17. // The current stack location. This contains all of the
  18. // information we need to process this particular request.
  19. //
  20. PIO_STACK_LOCATION irpSp;
  21. //
  22. PMOXA_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
  23. ULONG ioControlCode;
  24. KIRQL oldIrql;
  25. //
  26. // We expect to be open so all our pages are locked down. This is, after
  27. // all, an IO operation, so the device should be open first.
  28. //
  29. if (extension->DeviceIsOpened != TRUE) {
  30. Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
  31. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  32. return STATUS_INVALID_DEVICE_REQUEST;
  33. }
  34. irpSp = IoGetCurrentIrpStackLocation(Irp);
  35. ioControlCode = irpSp->Parameters.DeviceIoControl.IoControlCode;
  36. if (extension->ControlDevice) {
  37. if (
  38. (ioControlCode != IOCTL_MOXA_GetSeg) &&
  39. (ioControlCode != IOCTL_MOXA_RdData) &&
  40. (ioControlCode != IOCTL_MOXA_WrData) &&
  41. (ioControlCode != IOCTL_MOXA_FiData) &&
  42. (ioControlCode != IOCTL_MOXA_Statistic) &&
  43. (ioControlCode != IOCTL_MOXA_Linked) &&
  44. (ioControlCode != IOCTL_MOXA_PortStatus)) {
  45. Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
  46. Irp->IoStatus.Information = 0;
  47. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  48. return STATUS_INVALID_DEVICE_REQUEST;
  49. }
  50. }
  51. else {
  52. if ((status = MoxaIRPPrologue(Irp, extension))
  53. != STATUS_SUCCESS) {
  54. Irp->IoStatus.Status = status;
  55. MoxaCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  56. return status;
  57. }
  58. if (MoxaCompleteIfError(
  59. DeviceObject,
  60. Irp
  61. ) != STATUS_SUCCESS)
  62. return STATUS_CANCELLED;
  63. }
  64. Irp->IoStatus.Information = 0L;
  65. status = STATUS_SUCCESS;
  66. switch (ioControlCode) {
  67. case IOCTL_SERIAL_SET_BAUD_RATE : {
  68. ULONG baudRate;
  69. SHORT divisor;
  70. if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
  71. sizeof(SERIAL_BAUD_RATE)) {
  72. status = STATUS_BUFFER_TOO_SMALL;
  73. break;
  74. }
  75. else
  76. baudRate = ((PSERIAL_BAUD_RATE)(Irp->AssociatedIrp.SystemBuffer))->BaudRate;
  77. if (baudRate > extension->MaxBaud) {
  78. status = STATUS_INVALID_PARAMETER;
  79. break;
  80. }
  81. status = MoxaGetDivisorFromBaud(
  82. extension->ClockType,
  83. baudRate,
  84. &divisor
  85. );
  86. //
  87. // Make sure we are at power D0
  88. //
  89. #if 0
  90. if (NT_SUCCESS(status)) {
  91. if (extension->PowerState != PowerDeviceD0) {
  92. status = MoxaGotoPowerState(extension->Pdo, extension,
  93. PowerDeviceD0);
  94. if (!NT_SUCCESS(status)) {
  95. break;
  96. }
  97. }
  98. }
  99. #endif
  100. if (extension->PowerState != PowerDeviceD0) {
  101. status = STATUS_INVALID_DEVICE_REQUEST;
  102. break;
  103. }
  104. // MoxaKdPrint(MX_DBG_TRACE,("Set Baud to %d,divisor = %x,clock type=%x\n",baudRate,divisor,extension->ClockType));
  105. KeAcquireSpinLock(
  106. &extension->ControlLock,
  107. &oldIrql
  108. );
  109. if (NT_SUCCESS(status)) {
  110. extension->CurrentBaud = baudRate;
  111. extension->WmiCommData.BaudRate = baudRate;
  112. MoxaFunc(
  113. extension->PortOfs,
  114. FC_SetBaud,
  115. divisor
  116. );
  117. }
  118. KeReleaseSpinLock(
  119. &extension->ControlLock,
  120. oldIrql
  121. );
  122. break;
  123. }
  124. case IOCTL_SERIAL_GET_BAUD_RATE: {
  125. PSERIAL_BAUD_RATE Br = (PSERIAL_BAUD_RATE)Irp->AssociatedIrp.SystemBuffer;
  126. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  127. sizeof(SERIAL_BAUD_RATE)) {
  128. status = STATUS_BUFFER_TOO_SMALL;
  129. break;
  130. }
  131. KeAcquireSpinLock(
  132. &extension->ControlLock,
  133. &oldIrql
  134. );
  135. Br->BaudRate = extension->CurrentBaud;
  136. KeReleaseSpinLock(
  137. &extension->ControlLock,
  138. oldIrql
  139. );
  140. Irp->IoStatus.Information = sizeof(SERIAL_BAUD_RATE);
  141. break;
  142. }
  143. case IOCTL_SERIAL_SET_LINE_CONTROL: {
  144. PSERIAL_LINE_CONTROL Lc =
  145. ((PSERIAL_LINE_CONTROL)(Irp->AssociatedIrp.SystemBuffer));
  146. UCHAR lData;
  147. UCHAR lStop;
  148. UCHAR lParity;
  149. UCHAR mask = 0xff;
  150. if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
  151. sizeof(SERIAL_LINE_CONTROL)) {
  152. status = STATUS_BUFFER_TOO_SMALL;
  153. break;
  154. }
  155. //
  156. // Make sure we are at power D0
  157. //
  158. #if 0
  159. if (extension->PowerState != PowerDeviceD0) {
  160. status = MoxaGotoPowerState(extension->Pdo, extension,
  161. PowerDeviceD0);
  162. if (!NT_SUCCESS(status)) {
  163. break;
  164. }
  165. }
  166. #endif
  167. if (extension->PowerState != PowerDeviceD0) {
  168. status = STATUS_INVALID_DEVICE_REQUEST;
  169. break;
  170. }
  171. switch (Lc->WordLength) {
  172. case 5:
  173. lData = MOXA_5_DATA;
  174. mask = 0x1f;
  175. break;
  176. case 6:
  177. lData = MOXA_6_DATA;
  178. mask = 0x3f;
  179. break;
  180. case 7:
  181. lData = MOXA_7_DATA;
  182. mask = 0x7f;
  183. break;
  184. case 8:
  185. lData = MOXA_8_DATA;
  186. break;
  187. default:
  188. status = STATUS_INVALID_PARAMETER;
  189. goto DoneWithIoctl;
  190. }
  191. extension->WmiCommData.BitsPerByte = Lc->WordLength;
  192. switch (Lc->Parity) {
  193. case NO_PARITY:
  194. lParity = MOXA_NONE_PARITY;
  195. extension->WmiCommData.Parity = SERIAL_WMI_PARITY_NONE;
  196. break;
  197. case EVEN_PARITY:
  198. lParity = MOXA_EVEN_PARITY;
  199. extension->WmiCommData.Parity = SERIAL_WMI_PARITY_EVEN;
  200. break;
  201. case ODD_PARITY:
  202. lParity = MOXA_ODD_PARITY;
  203. extension->WmiCommData.Parity = SERIAL_WMI_PARITY_ODD;
  204. break;
  205. case SPACE_PARITY:
  206. lParity = MOXA_SPACE_PARITY;
  207. extension->WmiCommData.Parity = SERIAL_WMI_PARITY_SPACE;
  208. break;
  209. case MARK_PARITY:
  210. lParity = MOXA_MARK_PARITY;
  211. extension->WmiCommData.Parity = SERIAL_WMI_PARITY_MARK;
  212. break;
  213. default:
  214. status = STATUS_INVALID_PARAMETER;
  215. goto DoneWithIoctl;
  216. }
  217. switch (Lc->StopBits) {
  218. case STOP_BIT_1:
  219. lStop = MOXA_1_STOP;
  220. extension->WmiCommData.StopBits = SERIAL_WMI_STOP_1;
  221. break;
  222. case STOP_BITS_1_5:
  223. if (lData != MOXA_5_DATA) {
  224. status = STATUS_INVALID_PARAMETER;
  225. goto DoneWithIoctl;
  226. }
  227. lStop = MOXA_1_5_STOP;
  228. extension->WmiCommData.StopBits = SERIAL_WMI_STOP_1_5;
  229. break;
  230. case STOP_BITS_2:
  231. if (lData == MOXA_5_DATA) {
  232. status = STATUS_INVALID_PARAMETER;
  233. goto DoneWithIoctl;
  234. }
  235. lStop = MOXA_2_STOP;
  236. extension->WmiCommData.StopBits = SERIAL_WMI_STOP_2;
  237. break;
  238. default:
  239. status = STATUS_INVALID_PARAMETER;
  240. goto DoneWithIoctl;
  241. }
  242. KeAcquireSpinLock(
  243. &extension->ControlLock,
  244. &oldIrql
  245. );
  246. extension->DataMode = lData | lParity | lStop;
  247. extension->ValidDataMask = mask;
  248. MoxaFunc(
  249. extension->PortOfs,
  250. FC_SetDataMode,
  251. extension->DataMode
  252. );
  253. KeReleaseSpinLock(
  254. &extension->ControlLock,
  255. oldIrql
  256. );
  257. break;
  258. }
  259. case IOCTL_SERIAL_GET_LINE_CONTROL: {
  260. PSERIAL_LINE_CONTROL Lc = (PSERIAL_LINE_CONTROL)Irp->AssociatedIrp.SystemBuffer;
  261. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  262. sizeof(SERIAL_LINE_CONTROL)) {
  263. status = STATUS_BUFFER_TOO_SMALL;
  264. break;
  265. }
  266. KeAcquireSpinLock(
  267. &extension->ControlLock,
  268. &oldIrql
  269. );
  270. if ((extension->DataMode & MOXA_DATA_MASK) == MOXA_5_DATA) {
  271. Lc->WordLength = 5;
  272. } else if ((extension->DataMode & MOXA_DATA_MASK)
  273. == MOXA_6_DATA) {
  274. Lc->WordLength = 6;
  275. } else if ((extension->DataMode & MOXA_DATA_MASK)
  276. == MOXA_7_DATA) {
  277. Lc->WordLength = 7;
  278. } else if ((extension->DataMode & MOXA_DATA_MASK)
  279. == MOXA_8_DATA) {
  280. Lc->WordLength = 8;
  281. }
  282. if ((extension->DataMode & MOXA_PARITY_MASK)
  283. == MOXA_NONE_PARITY) {
  284. Lc->Parity = NO_PARITY;
  285. } else if ((extension->DataMode & MOXA_PARITY_MASK)
  286. == MOXA_ODD_PARITY) {
  287. Lc->Parity = ODD_PARITY;
  288. } else if ((extension->DataMode & MOXA_PARITY_MASK)
  289. == MOXA_EVEN_PARITY) {
  290. Lc->Parity = EVEN_PARITY;
  291. } else if ((extension->DataMode & MOXA_PARITY_MASK)
  292. == MOXA_MARK_PARITY) {
  293. Lc->Parity = MARK_PARITY;
  294. } else if ((extension->DataMode & MOXA_PARITY_MASK)
  295. == MOXA_SPACE_PARITY) {
  296. Lc->Parity = SPACE_PARITY;
  297. }
  298. if (extension->DataMode & MOXA_2_STOP) {
  299. Lc->StopBits = STOP_BITS_2;
  300. } else if (extension->DataMode & MOXA_1_5_STOP) {
  301. Lc->StopBits = STOP_BITS_1_5;
  302. } else {
  303. Lc->StopBits = STOP_BIT_1;
  304. }
  305. Irp->IoStatus.Information = sizeof(SERIAL_LINE_CONTROL);
  306. KeReleaseSpinLock(
  307. &extension->ControlLock,
  308. oldIrql
  309. );
  310. break;
  311. }
  312. case IOCTL_SERIAL_SET_TIMEOUTS: {
  313. PSERIAL_TIMEOUTS newTimeouts =
  314. ((PSERIAL_TIMEOUTS)(Irp->AssociatedIrp.SystemBuffer));
  315. if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
  316. sizeof(SERIAL_TIMEOUTS)) {
  317. status = STATUS_BUFFER_TOO_SMALL;
  318. break;
  319. }
  320. if ((newTimeouts->ReadIntervalTimeout == MAXULONG) &&
  321. (newTimeouts->ReadTotalTimeoutMultiplier == MAXULONG) &&
  322. (newTimeouts->ReadTotalTimeoutConstant == MAXULONG)) {
  323. status = STATUS_INVALID_PARAMETER;
  324. break;
  325. }
  326. KeAcquireSpinLock(
  327. &extension->ControlLock,
  328. &oldIrql
  329. );
  330. extension->Timeouts.ReadIntervalTimeout =
  331. newTimeouts->ReadIntervalTimeout;
  332. extension->Timeouts.ReadTotalTimeoutMultiplier =
  333. newTimeouts->ReadTotalTimeoutMultiplier;
  334. extension->Timeouts.ReadTotalTimeoutConstant =
  335. newTimeouts->ReadTotalTimeoutConstant;
  336. extension->Timeouts.WriteTotalTimeoutMultiplier =
  337. newTimeouts->WriteTotalTimeoutMultiplier;
  338. extension->Timeouts.WriteTotalTimeoutConstant =
  339. newTimeouts->WriteTotalTimeoutConstant;
  340. KeReleaseSpinLock(
  341. &extension->ControlLock,
  342. oldIrql
  343. );
  344. break;
  345. }
  346. case IOCTL_SERIAL_GET_TIMEOUTS: {
  347. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  348. sizeof(SERIAL_TIMEOUTS)) {
  349. status = STATUS_BUFFER_TOO_SMALL;
  350. break;
  351. }
  352. KeAcquireSpinLock(
  353. &extension->ControlLock,
  354. &oldIrql
  355. );
  356. *((PSERIAL_TIMEOUTS)Irp->AssociatedIrp.SystemBuffer) =
  357. extension->Timeouts;
  358. Irp->IoStatus.Information = sizeof(SERIAL_TIMEOUTS);
  359. KeReleaseSpinLock(
  360. &extension->ControlLock,
  361. oldIrql
  362. );
  363. break;
  364. }
  365. case IOCTL_SERIAL_SET_CHARS: {
  366. PSERIAL_CHARS newChars =
  367. ((PSERIAL_CHARS)(Irp->AssociatedIrp.SystemBuffer));
  368. if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
  369. sizeof(SERIAL_CHARS)) {
  370. status = STATUS_BUFFER_TOO_SMALL;
  371. break;
  372. }
  373. //
  374. // 9-26-01 by William
  375. //
  376. // if (newChars->XonChar == newChars->XoffChar) {
  377. if ((newChars->XonChar == newChars->XoffChar) &&
  378. (extension->HandFlow.FlowReplace & (SERIAL_AUTO_TRANSMIT|SERIAL_AUTO_RECEIVE) )
  379. ) {
  380. status = STATUS_INVALID_PARAMETER;
  381. break;
  382. }
  383. KeAcquireSpinLock(
  384. &extension->ControlLock,
  385. &oldIrql
  386. );
  387. if (extension->EscapeChar) {
  388. if ((extension->EscapeChar == newChars->XonChar) ||
  389. (extension->EscapeChar == newChars->XoffChar)) {
  390. status = STATUS_INVALID_PARAMETER;
  391. KeReleaseSpinLock(
  392. &extension->ControlLock,
  393. oldIrql
  394. );
  395. break;
  396. }
  397. }
  398. extension->SpecialChars = *newChars;
  399. extension->WmiCommData.XonCharacter = newChars->XonChar;
  400. extension->WmiCommData.XoffCharacter = newChars->XoffChar;
  401. {
  402. int i;
  403. PUCHAR ofs;
  404. USHORT cnt;
  405. ofs = extension->PortOfs;
  406. for (i=0; i<sizeof(SERIAL_CHARS); i++)
  407. (ofs + FuncArg)[i] = ((PUCHAR)newChars)[i];
  408. /*12-11-00 by William
  409. cnt = 50;
  410. *(ofs + FuncCode) = FC_SetChars;
  411. while (*(ofs + FuncCode)) {
  412. MoxaDelay(1);
  413. if (--cnt == 0)
  414. break;
  415. }
  416. */
  417. *(ofs + FuncCode) = FC_SetChars;
  418. MoxaWaitFinish(ofs);
  419. }
  420. KeReleaseSpinLock(
  421. &extension->ControlLock,
  422. oldIrql
  423. );
  424. break;
  425. }
  426. case IOCTL_SERIAL_GET_CHARS: {
  427. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  428. sizeof(SERIAL_CHARS)) {
  429. status = STATUS_BUFFER_TOO_SMALL;
  430. break;
  431. }
  432. KeAcquireSpinLock(
  433. &extension->ControlLock,
  434. &oldIrql
  435. );
  436. *((PSERIAL_CHARS)Irp->AssociatedIrp.SystemBuffer) =
  437. extension->SpecialChars;
  438. Irp->IoStatus.Information = sizeof(SERIAL_CHARS);
  439. KeReleaseSpinLock(
  440. &extension->ControlLock,
  441. oldIrql
  442. );
  443. break;
  444. }
  445. case IOCTL_SERIAL_SET_DTR:
  446. case IOCTL_SERIAL_CLR_DTR: {
  447. #if 0
  448. if (extension->PowerState != PowerDeviceD0) {
  449. status = MoxaGotoPowerState(extension->Pdo, extension, PowerDeviceD0);
  450. if (!NT_SUCCESS(status)) {
  451. break;
  452. }
  453. }
  454. #endif
  455. if (extension->PowerState != PowerDeviceD0) {
  456. status = STATUS_INVALID_DEVICE_REQUEST;
  457. break;
  458. }
  459. KeAcquireSpinLock(
  460. &extension->ControlLock,
  461. &oldIrql
  462. );
  463. if ((extension->HandFlow.ControlHandShake & SERIAL_DTR_MASK)
  464. == SERIAL_DTR_HANDSHAKE) {
  465. status = STATUS_INVALID_PARAMETER;
  466. } else {
  467. USHORT arg;
  468. arg =
  469. ((irpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_SET_DTR) ? (1):(0));
  470. MoxaFunc(
  471. extension->PortOfs,
  472. FC_DTRcontrol,
  473. arg
  474. );
  475. if ( arg )
  476. MoxaFlagBit[extension->PortNo] |= 1;
  477. else
  478. MoxaFlagBit[extension->PortNo] &= 0xFE;
  479. }
  480. KeReleaseSpinLock(
  481. &extension->ControlLock,
  482. oldIrql
  483. );
  484. break;
  485. }
  486. case IOCTL_SERIAL_RESET_DEVICE: {
  487. break;
  488. }
  489. case IOCTL_SERIAL_SET_RTS:
  490. case IOCTL_SERIAL_CLR_RTS: {
  491. #if 0
  492. if (extension->PowerState != PowerDeviceD0) {
  493. status = MoxaGotoPowerState(extension->Pdo, extension, PowerDeviceD0);
  494. if (!NT_SUCCESS(status)) {
  495. break;
  496. }
  497. }
  498. #endif
  499. if (extension->PowerState != PowerDeviceD0) {
  500. status = STATUS_INVALID_DEVICE_REQUEST;
  501. break;
  502. }
  503. KeAcquireSpinLock(
  504. &extension->ControlLock,
  505. &oldIrql
  506. );
  507. if (((extension->HandFlow.FlowReplace & SERIAL_RTS_MASK)
  508. == SERIAL_RTS_HANDSHAKE) ||
  509. ((extension->HandFlow.FlowReplace & SERIAL_RTS_MASK)
  510. == SERIAL_TRANSMIT_TOGGLE)) {
  511. status = STATUS_INVALID_PARAMETER;
  512. } else {
  513. USHORT arg;
  514. arg =
  515. ((irpSp->Parameters.DeviceIoControl.IoControlCode ==
  516. IOCTL_SERIAL_SET_RTS) ? (1):(0));
  517. MoxaFunc(
  518. extension->PortOfs,
  519. FC_RTScontrol,
  520. arg
  521. );
  522. if ( arg )
  523. MoxaFlagBit[extension->PortNo] |= 2;
  524. else
  525. MoxaFlagBit[extension->PortNo] &= 0xFD;
  526. }
  527. KeReleaseSpinLock(
  528. &extension->ControlLock,
  529. oldIrql
  530. );
  531. break;
  532. }
  533. case IOCTL_SERIAL_SET_XOFF: {
  534. KeAcquireSpinLock(
  535. &extension->ControlLock,
  536. &oldIrql
  537. );
  538. extension->TXHolding |= SERIAL_TX_WAITING_FOR_XON;
  539. MoxaFlagBit[extension->PortNo] |= 4;
  540. MoxaFunc(
  541. extension->PortOfs,
  542. FC_SetXoffState,
  543. Magic_code
  544. );
  545. KeReleaseSpinLock(
  546. &extension->ControlLock,
  547. oldIrql
  548. );
  549. break;
  550. }
  551. case IOCTL_SERIAL_SET_XON: {
  552. KeAcquireSpinLock(
  553. &extension->ControlLock,
  554. &oldIrql
  555. );
  556. extension->TXHolding &= ~SERIAL_TX_WAITING_FOR_XON;
  557. MoxaFlagBit[extension->PortNo] &= 0xFB;
  558. MoxaFunc(
  559. extension->PortOfs,
  560. FC_SetXonState,
  561. Magic_code
  562. );
  563. KeReleaseSpinLock(
  564. &extension->ControlLock,
  565. oldIrql
  566. );
  567. break;
  568. }
  569. case IOCTL_SERIAL_SET_BREAK_ON: {
  570. #if 0
  571. if (extension->PowerState != PowerDeviceD0) {
  572. status = MoxaGotoPowerState(extension->Pdo, extension, PowerDeviceD0);
  573. if (!NT_SUCCESS(status)) {
  574. break;
  575. }
  576. }
  577. #endif
  578. if (extension->PowerState != PowerDeviceD0) {
  579. status = STATUS_INVALID_DEVICE_REQUEST;
  580. break;
  581. }
  582. KeAcquireSpinLock(
  583. &extension->ControlLock,
  584. &oldIrql
  585. );
  586. MoxaFunc(
  587. extension->PortOfs,
  588. FC_SendBreak,
  589. Magic_code
  590. );
  591. extension->SendBreak = TRUE;
  592. KeReleaseSpinLock(
  593. &extension->ControlLock,
  594. oldIrql
  595. );
  596. break;
  597. }
  598. case IOCTL_SERIAL_SET_BREAK_OFF: {
  599. #if 0
  600. if (extension->PowerState != PowerDeviceD0) {
  601. status = MoxaGotoPowerState(extension->Pdo, extension, PowerDeviceD0);
  602. if (!NT_SUCCESS(status)) {
  603. break;
  604. }
  605. }
  606. #endif
  607. if (extension->PowerState != PowerDeviceD0) {
  608. status = STATUS_INVALID_DEVICE_REQUEST;
  609. break;
  610. }
  611. KeAcquireSpinLock(
  612. &extension->ControlLock,
  613. &oldIrql
  614. );
  615. MoxaFunc(
  616. extension->PortOfs,
  617. FC_StopBreak,
  618. Magic_code
  619. );
  620. extension->SendBreak = FALSE;
  621. KeReleaseSpinLock(
  622. &extension->ControlLock,
  623. oldIrql
  624. );
  625. break;
  626. }
  627. case IOCTL_SERIAL_SET_QUEUE_SIZE: {
  628. break;
  629. }
  630. case IOCTL_SERIAL_GET_WAIT_MASK: {
  631. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  632. sizeof(ULONG)) {
  633. status = STATUS_BUFFER_TOO_SMALL;
  634. break;
  635. }
  636. Irp->IoStatus.Information = sizeof(ULONG);
  637. *((ULONG *)Irp->AssociatedIrp.SystemBuffer) = extension->IsrWaitMask;
  638. break;
  639. }
  640. case IOCTL_SERIAL_SET_WAIT_MASK: {
  641. ULONG newMask;
  642. if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
  643. sizeof(ULONG)) {
  644. status = STATUS_BUFFER_TOO_SMALL;
  645. break;
  646. }
  647. else
  648. newMask = *((ULONG *)Irp->AssociatedIrp.SystemBuffer);
  649. if (newMask & ~(SERIAL_EV_RXCHAR |
  650. SERIAL_EV_RXFLAG |
  651. SERIAL_EV_TXEMPTY |
  652. SERIAL_EV_CTS |
  653. SERIAL_EV_DSR |
  654. SERIAL_EV_RLSD |
  655. SERIAL_EV_BREAK |
  656. SERIAL_EV_ERR |
  657. SERIAL_EV_RING |
  658. SERIAL_EV_PERR |
  659. SERIAL_EV_RX80FULL |
  660. SERIAL_EV_EVENT1 |
  661. SERIAL_EV_EVENT2)) {
  662. status = STATUS_INVALID_PARAMETER;
  663. break;
  664. }
  665. return MoxaStartOrQueue(
  666. extension,
  667. Irp,
  668. &extension->MaskQueue,
  669. &extension->CurrentMaskIrp,
  670. MoxaStartMask
  671. );
  672. }
  673. case IOCTL_SERIAL_WAIT_ON_MASK: {
  674. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  675. sizeof(ULONG)) {
  676. status = STATUS_BUFFER_TOO_SMALL;
  677. break;
  678. }
  679. return MoxaStartOrQueue(
  680. extension,
  681. Irp,
  682. &extension->MaskQueue,
  683. &extension->CurrentMaskIrp,
  684. MoxaStartMask
  685. );
  686. }
  687. case IOCTL_SERIAL_IMMEDIATE_CHAR: {
  688. UCHAR c;
  689. if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
  690. sizeof(UCHAR)) {
  691. status = STATUS_BUFFER_TOO_SMALL;
  692. break;
  693. }
  694. IoAcquireCancelSpinLock(&oldIrql);
  695. c = *((UCHAR *)(Irp->AssociatedIrp.SystemBuffer));
  696. IoReleaseCancelSpinLock(oldIrql);
  697. KeAcquireSpinLock(
  698. &extension->ControlLock,
  699. &oldIrql
  700. );
  701. /* 9-14-01 by William
  702. MoxaFunc(
  703. extension->PortOfs,
  704. FC_ImmSend,
  705. c
  706. );
  707. KeReleaseSpinLock(
  708. &extension->ControlLock,
  709. oldIrql
  710. );
  711. */
  712. //
  713. // 9-14-01 by William
  714. //
  715. *(PUSHORT)(extension->PortOfs + FuncArg) = c;
  716. *(extension->PortOfs + FuncCode) = FC_ImmSend;
  717. if (MoxaWaitFinish(extension->PortOfs) == FALSE) {
  718. status = STATUS_UNSUCCESSFUL;
  719. KeReleaseSpinLock(
  720. &extension->ControlLock,
  721. oldIrql
  722. );
  723. break;
  724. }
  725. KeReleaseSpinLock(
  726. &extension->ControlLock,
  727. oldIrql
  728. );
  729. IoAcquireCancelSpinLock(&oldIrql);
  730. if (extension->Interrupt) {
  731. KeSynchronizeExecution(
  732. extension->Interrupt,
  733. MoxaProcessEmptyTransmit,
  734. extension
  735. );
  736. }
  737. else {
  738. MoxaProcessEmptyTransmit(extension);
  739. }
  740. IoReleaseCancelSpinLock(oldIrql);
  741. // end
  742. break;
  743. }
  744. case IOCTL_SERIAL_PURGE: {
  745. ULONG mask;
  746. if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
  747. sizeof(ULONG)) {
  748. status = STATUS_BUFFER_TOO_SMALL;
  749. break;
  750. }
  751. mask = *((ULONG *)(Irp->AssociatedIrp.SystemBuffer));
  752. if ((!mask) || (mask & (~(SERIAL_PURGE_TXABORT |
  753. SERIAL_PURGE_RXABORT |
  754. SERIAL_PURGE_TXCLEAR |
  755. SERIAL_PURGE_RXCLEAR
  756. )
  757. )
  758. )) {
  759. status = STATUS_INVALID_PARAMETER;
  760. break;
  761. }
  762. return MoxaStartOrQueue(
  763. extension,
  764. Irp,
  765. &extension->PurgeQueue,
  766. &extension->CurrentPurgeIrp,
  767. MoxaStartPurge
  768. );
  769. }
  770. case IOCTL_SERIAL_GET_HANDFLOW: {
  771. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  772. sizeof(SERIAL_HANDFLOW)) {
  773. status = STATUS_BUFFER_TOO_SMALL;
  774. break;
  775. }
  776. Irp->IoStatus.Information = sizeof(SERIAL_HANDFLOW);
  777. KeAcquireSpinLock(
  778. &extension->ControlLock,
  779. &oldIrql
  780. );
  781. *((PSERIAL_HANDFLOW)Irp->AssociatedIrp.SystemBuffer) =
  782. extension->HandFlow;
  783. KeReleaseSpinLock(
  784. &extension->ControlLock,
  785. oldIrql
  786. );
  787. break;
  788. }
  789. case IOCTL_SERIAL_SET_HANDFLOW: {
  790. MOXA_IOCTL_SYNC S;
  791. PSERIAL_HANDFLOW handFlow = Irp->AssociatedIrp.SystemBuffer;
  792. if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
  793. sizeof(SERIAL_HANDFLOW)) {
  794. status = STATUS_BUFFER_TOO_SMALL;
  795. break;
  796. }
  797. if (handFlow->ControlHandShake & SERIAL_CONTROL_INVALID) {
  798. status = STATUS_INVALID_PARAMETER;
  799. break;
  800. }
  801. if (handFlow->FlowReplace & SERIAL_FLOW_INVALID) {
  802. status = STATUS_INVALID_PARAMETER;
  803. break;
  804. }
  805. if ((handFlow->ControlHandShake & SERIAL_DTR_MASK) ==
  806. SERIAL_DTR_MASK) {
  807. status = STATUS_INVALID_PARAMETER;
  808. break;
  809. }
  810. if ((handFlow->XonLimit < 0) ||
  811. ((ULONG)handFlow->XonLimit > extension->RxBufferSize)) {
  812. status = STATUS_INVALID_PARAMETER;
  813. break;
  814. }
  815. //
  816. // 10-03-01 by William
  817. //
  818. // if ((handFlow->XoffLimit < 0) ||
  819. // ((ULONG)handFlow->XoffLimit > extension->RxBufferSize)) {
  820. // status = STATUS_INVALID_PARAMETER;
  821. // break;
  822. //
  823. // }
  824. KeAcquireSpinLock(
  825. &extension->ControlLock,
  826. &oldIrql
  827. );
  828. if (extension->EscapeChar) {
  829. if (handFlow->FlowReplace & SERIAL_ERROR_CHAR) {
  830. status = STATUS_INVALID_PARAMETER;
  831. KeReleaseSpinLock(
  832. &extension->ControlLock,
  833. oldIrql
  834. );
  835. break;
  836. }
  837. }
  838. //
  839. // Set flowcontrol
  840. //
  841. S.Extension = extension;
  842. S.Data = handFlow;
  843. KeSynchronizeExecution(extension->Interrupt, MoxaSetupNewHandFlow, &S);
  844. KeReleaseSpinLock(
  845. &extension->ControlLock,
  846. oldIrql
  847. );
  848. break;
  849. }
  850. case IOCTL_SERIAL_GET_MODEMSTATUS: {
  851. USHORT data;
  852. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  853. sizeof(ULONG)) {
  854. status = STATUS_BUFFER_TOO_SMALL;
  855. break;
  856. }
  857. Irp->IoStatus.Information = sizeof(ULONG);
  858. MoxaFuncGetLineStatus(extension->PortOfs, &data);
  859. *(PULONG)Irp->AssociatedIrp.SystemBuffer = (ULONG) (data << 4);
  860. break;
  861. }
  862. case IOCTL_SERIAL_GET_DTRRTS: {
  863. MOXA_IOCTL_FUNC_ARGU func;
  864. USHORT modemControl;
  865. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  866. sizeof(ULONG)) {
  867. status = STATUS_BUFFER_TOO_SMALL;
  868. break;
  869. }
  870. Irp->IoStatus.Information = sizeof(ULONG);
  871. KeAcquireSpinLock(
  872. &extension->ControlLock,
  873. &oldIrql
  874. );
  875. MoxaFunc(
  876. extension->PortOfs,
  877. FC_GetDTRRTS,
  878. 0
  879. );
  880. modemControl = *(PUSHORT)(extension->PortOfs + FuncArg);
  881. KeReleaseSpinLock(
  882. &extension->ControlLock,
  883. oldIrql
  884. );
  885. *(PULONG)Irp->AssociatedIrp.SystemBuffer = (ULONG)modemControl;
  886. break;
  887. }
  888. case IOCTL_SERIAL_GET_COMMSTATUS: {
  889. MOXA_IOCTL_SYNC S;
  890. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  891. sizeof(SERIAL_STATUS)) {
  892. status = STATUS_BUFFER_TOO_SMALL;
  893. break;
  894. }
  895. Irp->IoStatus.Information = sizeof(SERIAL_STATUS);
  896. S.Extension = extension;
  897. S.Data = Irp->AssociatedIrp.SystemBuffer;
  898. IoAcquireCancelSpinLock(&oldIrql);
  899. KeSynchronizeExecution(
  900. extension->Interrupt,
  901. MoxaGetCommStatus,
  902. &S
  903. );
  904. IoReleaseCancelSpinLock(oldIrql);
  905. break;
  906. }
  907. case IOCTL_SERIAL_GET_PROPERTIES: {
  908. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  909. sizeof(SERIAL_COMMPROP)) {
  910. status = STATUS_BUFFER_TOO_SMALL;
  911. break;
  912. }
  913. MoxaGetProperties(
  914. extension,
  915. Irp->AssociatedIrp.SystemBuffer
  916. );
  917. Irp->IoStatus.Information = sizeof(SERIAL_COMMPROP);
  918. break;
  919. }
  920. case IOCTL_SERIAL_XOFF_COUNTER: {
  921. break;
  922. }
  923. case IOCTL_SERIAL_LSRMST_INSERT: {
  924. break;
  925. }
  926. case IOCTL_SERIAL_CONFIG_SIZE: {
  927. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  928. sizeof(ULONG)) {
  929. status = STATUS_BUFFER_TOO_SMALL;
  930. break;
  931. }
  932. Irp->IoStatus.Information = sizeof(ULONG);
  933. Irp->IoStatus.Status = STATUS_SUCCESS;
  934. *(PULONG)Irp->AssociatedIrp.SystemBuffer = 0;
  935. break;
  936. }
  937. case IOCTL_SERIAL_GET_STATS: {
  938. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  939. sizeof(SERIALPERF_STATS)) {
  940. status = STATUS_BUFFER_TOO_SMALL;
  941. break;
  942. }
  943. Irp->IoStatus.Information = sizeof(SERIALPERF_STATS);
  944. Irp->IoStatus.Status = STATUS_SUCCESS;
  945. KeSynchronizeExecution(
  946. extension->Interrupt,
  947. MoxaGetStats,
  948. Irp
  949. );
  950. break;
  951. }
  952. case IOCTL_SERIAL_CLEAR_STATS: {
  953. KeSynchronizeExecution(
  954. extension->Interrupt,
  955. MoxaClearStats,
  956. extension
  957. );
  958. break;
  959. }
  960. case IOCTL_MOXA_Driver: {
  961. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  962. sizeof(ULONG)) {
  963. status = STATUS_BUFFER_TOO_SMALL;
  964. break;
  965. }
  966. Irp->IoStatus.Information = sizeof(ULONG);
  967. *(PULONG)Irp->AssociatedIrp.SystemBuffer = MX_DRIVER;
  968. break;
  969. }
  970. #if 0
  971. case IOCTL_MOXA_Reset: {
  972. PMOXA_GLOBAL_DATA globalData;
  973. PMOXA_DEVICE_EXTENSION portExt;
  974. SHORT i;
  975. if (!extension->ControlDevice) {
  976. status = STATUS_INVALID_PARAMETER;
  977. break;
  978. }
  979. if (*(PUSHORT)Irp->AssociatedIrp.SystemBuffer != 0x404) {
  980. status = STATUS_INVALID_PARAMETER;
  981. break;
  982. }
  983. globalData = extension->GlobalData;
  984. for (i=0; i<MAX_PORT; i++) {
  985. portExt = globalData->Extension[i];
  986. if (portExt)
  987. if (portExt->PortExist) {
  988. portExt->PortExist = FALSE;
  989. MoxaCancelTimer(&portExt->ReadRequestTotalTimer,portExt);
  990. MoxaCancelTimer(&portExt->ReadRequestIntervalTimer,portExt);
  991. MoxaCancelTimer(&portExt->WriteRequestTotalTimer,portExt);
  992. KeRemoveQueueDpc(&portExt->CompleteWriteDpc);
  993. KeRemoveQueueDpc(&portExt->CompleteReadDpc);
  994. KeRemoveQueueDpc(&portExt->IsrOutDpc);
  995. KeRemoveQueueDpc(&portExt->IsrInDpc);
  996. KeRemoveQueueDpc(&portExt->TotalReadTimeoutDpc);
  997. KeRemoveQueueDpc(&portExt->IntervalReadTimeoutDpc);
  998. KeRemoveQueueDpc(&portExt->TotalWriteTimeoutDpc);
  999. KeRemoveQueueDpc(&portExt->CommErrorDpc);
  1000. KeRemoveQueueDpc(&portExt->CommWaitDpc);
  1001. //
  1002. // 9-24-01 by William
  1003. //
  1004. // KeRemoveQueueDpc(&portExt->IntrLineDpc);
  1005. // KeRemoveQueueDpc(&portExt->IntrErrorDpc);
  1006. // end
  1007. }
  1008. }
  1009. KeSynchronizeExecution(
  1010. extension->Interrupt,
  1011. MoxaClearDownLoad,
  1012. globalData
  1013. );
  1014. break;
  1015. }
  1016. #endif
  1017. case IOCTL_MOXA_LineInput: {
  1018. //
  1019. // 03-14-02 by William
  1020. //
  1021. #if 0
  1022. if (irpSp->Parameters.DeviceIoControl.InputBufferLength !=
  1023. sizeof(UCHAR)) {
  1024. #endif
  1025. if ((irpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(UCHAR)) ||
  1026. (irpSp->Parameters.DeviceIoControl.OutputBufferLength < 1) ) {
  1027. // end
  1028. status = STATUS_BUFFER_TOO_SMALL;
  1029. break;
  1030. }
  1031. return MoxaStartOrQueue(
  1032. extension,
  1033. Irp,
  1034. &extension->ReadQueue,
  1035. &extension->CurrentReadIrp,
  1036. MoxaStartRead
  1037. );
  1038. }
  1039. case IOCTL_MOXA_OQueue: {
  1040. ULONG count;
  1041. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1042. sizeof(ULONG)) {
  1043. status = STATUS_BUFFER_TOO_SMALL;
  1044. break;
  1045. }
  1046. count = GetDeviceTxQueueWithLock(extension) + extension->WriteLength
  1047. + extension->TotalCharsQueued;
  1048. *((PULONG)Irp->AssociatedIrp.SystemBuffer) = count;
  1049. Irp->IoStatus.Information = sizeof(ULONG);
  1050. break;
  1051. }
  1052. case IOCTL_MOXA_IQueue: {
  1053. ULONG count;
  1054. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1055. sizeof(ULONG)) {
  1056. status = STATUS_BUFFER_TOO_SMALL;
  1057. break;
  1058. }
  1059. count = GetDeviceRxQueueWithLock(extension);
  1060. *((PULONG)Irp->AssociatedIrp.SystemBuffer) = count;
  1061. Irp->IoStatus.Information = sizeof(ULONG);
  1062. break;
  1063. }
  1064. case IOCTL_MOXA_View: {
  1065. //
  1066. // 01-04-02 by William
  1067. //
  1068. // if (irpSp->Parameters.DeviceIoControl.InputBufferLength !=
  1069. // sizeof(UCHAR)) {
  1070. //
  1071. // status = STATUS_BUFFER_TOO_SMALL;
  1072. // break;
  1073. // }
  1074. //
  1075. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1076. sizeof(ULONG)) {
  1077. status = STATUS_BUFFER_TOO_SMALL;
  1078. break;
  1079. }
  1080. // end
  1081. return MoxaStartOrQueue(
  1082. extension,
  1083. Irp,
  1084. &extension->ReadQueue,
  1085. &extension->CurrentReadIrp,
  1086. MoxaStartRead
  1087. );
  1088. }
  1089. case IOCTL_MOXA_TxLowWater: {
  1090. LONG lowWater;
  1091. PMOXA_DEVICE_EXTENSION ext;
  1092. PUCHAR ofs;
  1093. USHORT cardNo, port, portNo;
  1094. if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
  1095. sizeof(LONG)) {
  1096. status = STATUS_BUFFER_TOO_SMALL;
  1097. break;
  1098. }
  1099. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1100. sizeof(LONG)) {
  1101. status = STATUS_BUFFER_TOO_SMALL;
  1102. break;
  1103. }
  1104. lowWater = *((PLONG)Irp->AssociatedIrp.SystemBuffer);
  1105. if (lowWater > 1024)
  1106. lowWater = 1024;
  1107. if (lowWater >= 0) {
  1108. MoxaTxLowWater = lowWater;
  1109. for (cardNo=0; cardNo<MAX_CARD; cardNo++) {
  1110. if ((!MoxaGlobalData->CardType[cardNo]) ||
  1111. (!MoxaGlobalData->NumPorts[cardNo]))
  1112. continue;
  1113. for (port=0; port<MoxaGlobalData->NumPorts[cardNo]; port++) {
  1114. portNo = cardNo * MAXPORT_PER_CARD + port;
  1115. ext = MoxaGlobalData->Extension[portNo];
  1116. ofs = ext->PortOfs;
  1117. *(PUSHORT)(ofs + Tx_trigger) = (USHORT)(MoxaTxLowWater);
  1118. }
  1119. }
  1120. }
  1121. *((PLONG)Irp->AssociatedIrp.SystemBuffer) = MoxaTxLowWater;
  1122. Irp->IoStatus.Information = sizeof(LONG);
  1123. break;
  1124. }
  1125. case IOCTL_MOXA_GetSeg: {
  1126. PMOXA_IOCTL_MxSet Ms = (PMOXA_IOCTL_MxSet)Irp->AssociatedIrp.SystemBuffer;
  1127. PMOXA_GLOBAL_DATA Gd = (PMOXA_GLOBAL_DATA)extension->GlobalData;
  1128. int card;
  1129. if (!extension->ControlDevice) {
  1130. status = STATUS_INVALID_PARAMETER;
  1131. break;
  1132. }
  1133. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1134. sizeof(MOXA_IOCTL_MxSet)) {
  1135. status = STATUS_BUFFER_TOO_SMALL;
  1136. break;
  1137. }
  1138. for ( card=0; card<MAX_CARD; card++ ) {
  1139. if ( !Gd->CardType[card] )
  1140. break;
  1141. Ms->type[card] = Gd->CardType[card];
  1142. Ms->segment[card] = Gd->BankAddr[card].LowPart;
  1143. }
  1144. Ms->total_boards = card;
  1145. Irp->IoStatus.Information = sizeof(MOXA_IOCTL_MxSet);
  1146. break;
  1147. }
  1148. case IOCTL_MOXA_RdData: {
  1149. PMOXA_IOCTL_BlkHead Bh = (PMOXA_IOCTL_BlkHead)Irp->AssociatedIrp.SystemBuffer;
  1150. PMOXA_GLOBAL_DATA Gd = (PMOXA_GLOBAL_DATA)extension->GlobalData;
  1151. PUCHAR base;
  1152. PUCHAR buff;
  1153. int card, len, ofs, ndx;
  1154. if (!extension->ControlDevice) {
  1155. status = STATUS_INVALID_PARAMETER;
  1156. break;
  1157. }
  1158. if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
  1159. sizeof(MOXA_IOCTL_BlkHead)) {
  1160. status = STATUS_BUFFER_TOO_SMALL;
  1161. break;
  1162. }
  1163. for ( card=0; card<MAX_CARD; card++ ) {
  1164. if ( Bh->data_seg == Gd->BankAddr[card].LowPart )
  1165. break;
  1166. }
  1167. if ( card == MAX_CARD ) {
  1168. status = STATUS_INVALID_PARAMETER;
  1169. break;
  1170. }
  1171. base = Gd->CardBase[card];
  1172. ofs = Bh->data_ofs;
  1173. len = Bh->data_len;
  1174. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1175. (unsigned long)len) {
  1176. status = STATUS_BUFFER_TOO_SMALL;
  1177. break;
  1178. }
  1179. buff = (PUCHAR)(Irp->AssociatedIrp.SystemBuffer);
  1180. for ( ndx=0; ndx<len; ndx++ ) {
  1181. if ( (ndx + ofs) >= 0x4000 )
  1182. break;
  1183. buff[ndx] = base[ofs + ndx];
  1184. }
  1185. Irp->IoStatus.Information = ndx;
  1186. break;
  1187. }
  1188. case IOCTL_MOXA_WrData: {
  1189. PMOXA_IOCTL_WrData Wd = (PMOXA_IOCTL_WrData)Irp->AssociatedIrp.SystemBuffer;
  1190. PMOXA_GLOBAL_DATA Gd = (PMOXA_GLOBAL_DATA)extension->GlobalData;
  1191. PUCHAR base;
  1192. int card, len, ofs, ndx;
  1193. if (!extension->ControlDevice) {
  1194. status = STATUS_INVALID_PARAMETER;
  1195. break;
  1196. }
  1197. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1198. sizeof(DWORD)) {
  1199. status = STATUS_BUFFER_TOO_SMALL;
  1200. break;
  1201. }
  1202. for ( card=0; card<MAX_CARD; card++ ) {
  1203. if ( Wd->datahead.data_seg == Gd->BankAddr[card].LowPart )
  1204. break;
  1205. }
  1206. if ( card == MAX_CARD ) {
  1207. status = STATUS_INVALID_PARAMETER;
  1208. break;
  1209. }
  1210. base = Gd->CardBase[card];
  1211. ofs = Wd->datahead.data_ofs;
  1212. len = Wd->datahead.data_len;
  1213. if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
  1214. (sizeof(MOXA_IOCTL_BlkHead) + len)) {
  1215. status = STATUS_BUFFER_TOO_SMALL;
  1216. break;
  1217. }
  1218. for ( ndx=0; ndx<len; ndx++ ) {
  1219. if ( (ndx + ofs) >= 0x4000 )
  1220. break;
  1221. base[ofs + ndx] = Wd->data[ndx];
  1222. }
  1223. *((PULONG)Irp->AssociatedIrp.SystemBuffer) = ndx;
  1224. Irp->IoStatus.Information = sizeof(DWORD);
  1225. break;
  1226. }
  1227. case IOCTL_MOXA_FiData: {
  1228. PMOXA_IOCTL_FiData Fi = (PMOXA_IOCTL_FiData)Irp->AssociatedIrp.SystemBuffer;
  1229. PMOXA_GLOBAL_DATA Gd = (PMOXA_GLOBAL_DATA)extension->GlobalData;
  1230. PUCHAR base;
  1231. int card, len, ofs, ndx;
  1232. if (!extension->ControlDevice) {
  1233. status = STATUS_INVALID_PARAMETER;
  1234. break;
  1235. }
  1236. if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
  1237. sizeof(MOXA_IOCTL_FiData)) {
  1238. status = STATUS_BUFFER_TOO_SMALL;
  1239. break;
  1240. }
  1241. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1242. sizeof(DWORD)) {
  1243. status = STATUS_BUFFER_TOO_SMALL;
  1244. break;
  1245. }
  1246. for ( card=0; card<MAX_CARD; card++ ) {
  1247. if ( Fi->datahead.data_seg == Gd->BankAddr[card].LowPart )
  1248. break;
  1249. }
  1250. if ( card == MAX_CARD ) {
  1251. status = STATUS_INVALID_PARAMETER;
  1252. break;
  1253. }
  1254. base = Gd->CardBase[card];
  1255. ofs = Fi->datahead.data_ofs;
  1256. len = Fi->datahead.data_len;
  1257. for ( ndx=0; ndx<len; ndx++ ) {
  1258. if ( (ndx + ofs) >= 0x4000 )
  1259. break;
  1260. base[ofs + ndx] = Fi->fill_value;
  1261. }
  1262. *((PULONG)Irp->AssociatedIrp.SystemBuffer) = ndx;
  1263. Irp->IoStatus.Information = sizeof(DWORD);
  1264. break;
  1265. }
  1266. case IOCTL_MOXA_Linked: {
  1267. PMOXA_GLOBAL_DATA Gd = extension->GlobalData;
  1268. PUCHAR base;
  1269. ULONG cardNo;
  1270. if (!extension->ControlDevice) {
  1271. status = STATUS_INVALID_PARAMETER;
  1272. break;
  1273. }
  1274. if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
  1275. sizeof(ULONG)) {
  1276. status = STATUS_BUFFER_TOO_SMALL;
  1277. break;
  1278. }
  1279. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1280. sizeof(LONG)) {
  1281. status = STATUS_BUFFER_TOO_SMALL;
  1282. break;
  1283. }
  1284. cardNo = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
  1285. if (cardNo >= MAX_CARD) {
  1286. status = STATUS_INVALID_PARAMETER;
  1287. break;
  1288. }
  1289. if ((Gd->CardType[cardNo] != C320ISA)&&(Gd->CardType[cardNo] != C320PCI)) {
  1290. status = STATUS_INVALID_PARAMETER;
  1291. break;
  1292. }
  1293. base = Gd->CardBase[cardNo];
  1294. if (*((PUSHORT)(base + C320B_unlinked)) == Magic_no) {
  1295. ((LONG)Irp->AssociatedIrp.SystemBuffer) = 1;
  1296. Irp->IoStatus.Information = sizeof(LONG);
  1297. break;
  1298. }
  1299. if (*((PUSHORT)(base + C320_runOK)) == Magic_no) {
  1300. if (*((PUSHORT)(base + C320B_restart)) == Magic_no) { // C320B Reload OK
  1301. ((LONG)Irp->AssociatedIrp.SystemBuffer) = 2;
  1302. Irp->IoStatus.Information = sizeof(LONG);
  1303. *((PUSHORT)(base + C320B_restart)) = 0;
  1304. }
  1305. else { // OK
  1306. ((LONG)Irp->AssociatedIrp.SystemBuffer) = 0;
  1307. Irp->IoStatus.Information = sizeof(LONG);
  1308. }
  1309. }
  1310. else { // Disconnected
  1311. ((LONG)Irp->AssociatedIrp.SystemBuffer) = 1;
  1312. Irp->IoStatus.Information = sizeof(LONG);
  1313. }
  1314. break;
  1315. }
  1316. case IOCTL_MOXA_Statistic: {
  1317. PUSHORT com;
  1318. USHORT comNo[2];
  1319. PMOXA_IOCTL_Statistic St;
  1320. ULONG size;
  1321. int ndx, portNo, nn;
  1322. if (!extension->ControlDevice) {
  1323. status = STATUS_INVALID_PARAMETER;
  1324. break;
  1325. }
  1326. if (irpSp->Parameters.DeviceIoControl.InputBufferLength < 4) {
  1327. status = STATUS_BUFFER_TOO_SMALL;
  1328. break;
  1329. }
  1330. com = (PUSHORT)Irp->AssociatedIrp.SystemBuffer;
  1331. comNo[0] = com[0];
  1332. comNo[1] = com[1];
  1333. if ( comNo[1] < comNo[0] ) {
  1334. status = STATUS_INVALID_PARAMETER;
  1335. break;
  1336. }
  1337. size = sizeof(MOXA_IOCTL_Statistic) * (comNo[1] - comNo[0] + 1);
  1338. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < size) {
  1339. status = STATUS_BUFFER_TOO_SMALL;
  1340. break;
  1341. }
  1342. St = (PMOXA_IOCTL_Statistic)Irp->AssociatedIrp.SystemBuffer;
  1343. nn = 0;
  1344. for ( ndx=(int)comNo[0]; ndx<=(int)comNo[1]; ndx++, nn++ ) {
  1345. if ( ndx > MAX_COM )
  1346. break;
  1347. if ( (ndx <= 0) || (MoxaExtension[ndx] == NULL) )
  1348. continue;
  1349. portNo = (int)MoxaExtension[ndx]->PortNo;
  1350. St[nn].TxCount = MoxaExtension[ndx]->PerfStats.TransmittedCount +
  1351. MoxaTotalTx[portNo];
  1352. St[nn].RxCount = MoxaExtension[ndx]->PerfStats.ReceivedCount +
  1353. MoxaTotalRx[portNo];
  1354. MoxaFuncGetLineStatus(
  1355. MoxaExtension[ndx]->PortOfs,
  1356. (PUSHORT)&MoxaExtension[ndx]->ModemStatus
  1357. );
  1358. St[nn].LStatus = (ULONG)MoxaExtension[ndx]->ModemStatus & 0x0F;
  1359. St[nn].LStatus |= ((MoxaFlagBit[portNo] & 3) << 4);
  1360. if ( MoxaExtension[ndx]->DeviceIsOpened )
  1361. St[nn].LStatus |= 0x80;
  1362. St[nn].FlowCtl = (MoxaExtension[ndx]->HandFlow.ControlHandShake
  1363. & SERIAL_CTS_HANDSHAKE) |
  1364. (MoxaExtension[ndx]->HandFlow.FlowReplace &
  1365. (SERIAL_RTS_HANDSHAKE | SERIAL_AUTO_TRANSMIT |
  1366. SERIAL_AUTO_RECEIVE));
  1367. }
  1368. Irp->IoStatus.Information = size;
  1369. break;
  1370. }
  1371. case IOCTL_MOXA_LoopBack: {
  1372. ULONG mode;
  1373. PMOXA_GLOBAL_DATA Gd = extension->GlobalData;
  1374. if ((Gd->CardType[extension->BoardNo] == C320ISA) ||
  1375. (Gd->CardType[extension->BoardNo] == C320PCI)) {
  1376. status = STATUS_INVALID_PARAMETER;
  1377. break;
  1378. }
  1379. if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
  1380. sizeof(ULONG)) {
  1381. status = STATUS_BUFFER_TOO_SMALL;
  1382. break;
  1383. }
  1384. mode = *(PULONG)Irp->AssociatedIrp.SystemBuffer;
  1385. KeAcquireSpinLock(
  1386. &extension->ControlLock,
  1387. &oldIrql
  1388. );
  1389. MoxaFunc(
  1390. extension->PortOfs,
  1391. FC_DisableCH,
  1392. Magic_code
  1393. );
  1394. if ( mode ) {
  1395. // Set loop back mode
  1396. MoxaFunc(
  1397. extension->PortOfs,
  1398. FC_LoopbackON,
  1399. Magic_code
  1400. );
  1401. } else {
  1402. // Reset loop back mode
  1403. MoxaFunc(
  1404. extension->PortOfs,
  1405. FC_LoopbackOFF,
  1406. Magic_code
  1407. );
  1408. }
  1409. MoxaFunc(
  1410. extension->PortOfs,
  1411. FC_EnableCH,
  1412. Magic_code
  1413. );
  1414. KeReleaseSpinLock(
  1415. &extension->ControlLock,
  1416. oldIrql
  1417. );
  1418. Irp->IoStatus.Information = 0;
  1419. break;
  1420. }
  1421. case IOCTL_MOXA_UARTTest: {
  1422. int ier, old;
  1423. int MoxaReadReg(PUCHAR, int);
  1424. void MoxaWriteReg(PUCHAR, int, int);
  1425. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1426. sizeof(ULONG)) {
  1427. status = STATUS_BUFFER_TOO_SMALL;
  1428. break;
  1429. }
  1430. Irp->IoStatus.Information = sizeof(ULONG);
  1431. *(ULONG *)Irp->AssociatedIrp.SystemBuffer = 0;
  1432. KeAcquireSpinLock(
  1433. &extension->ControlLock,
  1434. &oldIrql
  1435. );
  1436. old = MoxaReadReg(extension->PortOfs, 1);
  1437. MoxaWriteReg(extension->PortOfs, 1, 0);
  1438. ier = MoxaReadReg(extension->PortOfs, 1);
  1439. if ( ier == 0 ) {
  1440. MoxaWriteReg(extension->PortOfs, 1, 3);
  1441. ier = MoxaReadReg(extension->PortOfs, 1);
  1442. if ( ier == 3 )
  1443. *(ULONG *)Irp->AssociatedIrp.SystemBuffer = 1;
  1444. }
  1445. MoxaWriteReg(extension->PortOfs, 1, old);
  1446. KeReleaseSpinLock(
  1447. &extension->ControlLock,
  1448. oldIrql
  1449. );
  1450. break;
  1451. }
  1452. case IOCTL_MOXA_IRQTest: {
  1453. PUCHAR ofs;
  1454. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1455. sizeof(ULONG)) {
  1456. status = STATUS_BUFFER_TOO_SMALL;
  1457. break;
  1458. }
  1459. ofs = extension->PortOfs;
  1460. KeAcquireSpinLock(
  1461. &extension->ControlLock,
  1462. &oldIrql
  1463. );
  1464. MoxaIRQok = FALSE;
  1465. MoxaFunc(
  1466. ofs,
  1467. FC_GenIrq,
  1468. Magic_code
  1469. );
  1470. KeReleaseSpinLock(
  1471. &extension->ControlLock,
  1472. oldIrql
  1473. );
  1474. MoxaDelay(5); /* delay 10 msec */
  1475. if ( MoxaIRQok )
  1476. *((PULONG)Irp->AssociatedIrp.SystemBuffer) = 1;
  1477. else
  1478. *((PULONG)Irp->AssociatedIrp.SystemBuffer) = 0;
  1479. Irp->IoStatus.Information = sizeof(ULONG);
  1480. break;
  1481. }
  1482. case IOCTL_MOXA_LineStatus: {
  1483. USHORT data;
  1484. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1485. sizeof(ULONG)) {
  1486. status = STATUS_BUFFER_TOO_SMALL;
  1487. break;
  1488. }
  1489. Irp->IoStatus.Information = sizeof(ULONG);
  1490. MoxaFuncGetLineStatus(extension->PortOfs, &data);
  1491. *(PULONG)Irp->AssociatedIrp.SystemBuffer = data;
  1492. break;
  1493. }
  1494. case IOCTL_MOXA_PortStatus: {
  1495. ULONG comNo;
  1496. PMOXA_IOCTL_PortStatus Ps;
  1497. if (!extension->ControlDevice) {
  1498. status = STATUS_INVALID_PARAMETER;
  1499. break;
  1500. }
  1501. if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
  1502. sizeof(ULONG)) {
  1503. status = STATUS_BUFFER_TOO_SMALL;
  1504. break;
  1505. }
  1506. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1507. sizeof(MOXA_IOCTL_PortStatus)) {
  1508. status = STATUS_BUFFER_TOO_SMALL;
  1509. break;
  1510. }
  1511. comNo = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
  1512. if ( (comNo <= 0) || (comNo > MAX_COM) ||
  1513. (MoxaExtension[comNo] == NULL) ) {
  1514. status = STATUS_INVALID_PARAMETER;
  1515. break;
  1516. }
  1517. Ps = (PMOXA_IOCTL_PortStatus)Irp->AssociatedIrp.SystemBuffer;
  1518. Ps->Open = (USHORT)MoxaExtension[comNo]->DeviceIsOpened;
  1519. Ps->TxHold = 0;
  1520. if (MoxaExtension[comNo]->HandFlow.ControlHandShake &
  1521. SERIAL_CTS_HANDSHAKE) {
  1522. if ((MoxaExtension[comNo]->ModemStatus & LSTATUS_CTS) == 0)
  1523. Ps->TxHold |= 1;
  1524. }
  1525. if (MoxaExtension[comNo]->TXHolding & SERIAL_TX_WAITING_FOR_XON)
  1526. Ps->TxHold |= 2;
  1527. if (MoxaExtension[comNo]->SendBreak)
  1528. Ps->TxHold |= 4;
  1529. Ps->DataMode = MoxaExtension[comNo]->DataMode;
  1530. Ps->BaudRate = MoxaExtension[comNo]->CurrentBaud;
  1531. Ps->MaxBaudRate = MoxaExtension[comNo]->MaxBaud;
  1532. Ps->TxBuffer = MoxaExtension[comNo]->TxBufferSize;
  1533. Ps->RxBuffer = MoxaExtension[comNo]->RxBufferSize;
  1534. Ps->TxXonThreshold = MoxaExtension[comNo]->HandFlow.XonLimit;
  1535. Ps->TxXoffThreshold = MoxaExtension[comNo]->HandFlow.XoffLimit;
  1536. Ps->FlowControl = (MoxaExtension[comNo]->HandFlow.ControlHandShake &
  1537. SERIAL_CTS_HANDSHAKE) |
  1538. (MoxaExtension[comNo]->HandFlow.FlowReplace &
  1539. (SERIAL_RTS_HANDSHAKE | SERIAL_AUTO_TRANSMIT |
  1540. SERIAL_AUTO_RECEIVE));
  1541. Irp->IoStatus.Information = sizeof(MOXA_IOCTL_PortStatus);
  1542. break;
  1543. }
  1544. default:
  1545. status = STATUS_INVALID_PARAMETER;
  1546. break;
  1547. }
  1548. DoneWithIoctl:;
  1549. Irp->IoStatus.Status = status;
  1550. if (extension->ControlDevice) {
  1551. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1552. }
  1553. else {
  1554. MoxaCompleteRequest(extension, Irp, IO_NO_INCREMENT);
  1555. }
  1556. return status;
  1557. }
  1558. BOOLEAN
  1559. MoxaGetCommStatus(
  1560. IN PVOID Context
  1561. )
  1562. {
  1563. USHORT dataError;
  1564. PMOXA_DEVICE_EXTENSION extension = ((PMOXA_IOCTL_SYNC)Context)->Extension;
  1565. PSERIAL_STATUS stat = ((PMOXA_IOCTL_SYNC)Context)->Data;
  1566. PUCHAR ofs = extension->PortOfs;
  1567. MoxaFuncGetDataError(
  1568. ofs,
  1569. &dataError
  1570. );
  1571. stat->Errors = (extension->ErrorWord|dataError);
  1572. extension->ErrorWord = 0;
  1573. stat->EofReceived = FALSE;
  1574. {
  1575. PUSHORT rptr, wptr;
  1576. USHORT lenMask, count;
  1577. rptr = (PUSHORT)(ofs + RXrptr);
  1578. wptr = (PUSHORT)(ofs + RXwptr);
  1579. lenMask = *(PUSHORT)(ofs + RX_mask);
  1580. count = (*wptr >= *rptr) ? (*wptr - *rptr)
  1581. : (*wptr - *rptr + lenMask + 1);
  1582. stat->AmountInInQueue = (ULONG)count;
  1583. rptr = (PUSHORT)(ofs + TXrptr);
  1584. wptr = (PUSHORT)(ofs + TXwptr);
  1585. lenMask = *(PUSHORT)(ofs + TX_mask);
  1586. count = (*wptr >= *rptr) ? (*wptr - *rptr)
  1587. : (*wptr - *rptr + lenMask + 1);
  1588. stat->AmountInOutQueue = extension->TotalCharsQueued
  1589. + extension->WriteLength;
  1590. stat->AmountInOutQueue += (ULONG)count;
  1591. }
  1592. stat->WaitForImmediate = FALSE;
  1593. stat->HoldReasons = 0;
  1594. MoxaFuncGetLineStatus(
  1595. ofs,
  1596. (PUSHORT)&extension->ModemStatus
  1597. );
  1598. if (extension->HandFlow.ControlHandShake & SERIAL_CTS_HANDSHAKE) {
  1599. if ((extension->ModemStatus & LSTATUS_CTS) == 0)
  1600. stat->HoldReasons |= SERIAL_TX_WAITING_FOR_CTS;
  1601. }
  1602. if (*(PUSHORT)(extension->PortOfs + FlagStat) & Tx_flowOff)
  1603. stat->HoldReasons |= SERIAL_TX_WAITING_FOR_XON;
  1604. if (*(PUSHORT)(extension->PortOfs + FlagStat) & Rx_xoff)
  1605. if (extension->HandFlow.FlowReplace & SERIAL_AUTO_RECEIVE)
  1606. stat->HoldReasons |= SERIAL_TX_WAITING_XOFF_SENT;
  1607. if (extension->SendBreak)
  1608. stat->HoldReasons |= SERIAL_TX_WAITING_ON_BREAK;
  1609. stat->HoldReasons |= (extension->TXHolding & SERIAL_TX_WAITING_FOR_XON);
  1610. return FALSE;
  1611. }
  1612. VOID
  1613. MoxaGetProperties(
  1614. IN PMOXA_DEVICE_EXTENSION Extension,
  1615. IN PSERIAL_COMMPROP Properties
  1616. )
  1617. {
  1618. RtlZeroMemory(
  1619. Properties,
  1620. sizeof(SERIAL_COMMPROP)
  1621. );
  1622. Properties->PacketLength = sizeof(SERIAL_COMMPROP);
  1623. Properties->PacketVersion = 2;
  1624. Properties->ServiceMask = SERIAL_SP_SERIALCOMM;
  1625. Properties->MaxTxQueue = Extension->TxBufferSize;
  1626. Properties->MaxRxQueue = Extension->RxBufferSize;
  1627. Properties->MaxBaud = SERIAL_BAUD_USER;
  1628. Properties->SettableBaud = Extension->SupportedBauds;
  1629. Properties->ProvSubType = SERIAL_SP_RS232;
  1630. Properties->ProvCapabilities = SERIAL_PCF_DTRDSR |
  1631. SERIAL_PCF_RTSCTS |
  1632. SERIAL_PCF_CD |
  1633. SERIAL_PCF_PARITY_CHECK |
  1634. SERIAL_PCF_XONXOFF |
  1635. SERIAL_PCF_SETXCHAR |
  1636. SERIAL_PCF_TOTALTIMEOUTS |
  1637. SERIAL_PCF_INTTIMEOUTS;
  1638. Properties->SettableParams = SERIAL_SP_PARITY |
  1639. SERIAL_SP_BAUD |
  1640. SERIAL_SP_DATABITS |
  1641. SERIAL_SP_STOPBITS |
  1642. SERIAL_SP_HANDSHAKING |
  1643. SERIAL_SP_PARITY_CHECK |
  1644. SERIAL_SP_CARRIER_DETECT;
  1645. Properties->SettableData = SERIAL_DATABITS_5 |
  1646. SERIAL_DATABITS_6 |
  1647. SERIAL_DATABITS_7 |
  1648. SERIAL_DATABITS_8;
  1649. Properties->SettableStopParity = SERIAL_STOPBITS_10 |
  1650. SERIAL_STOPBITS_15 |
  1651. SERIAL_STOPBITS_20 |
  1652. SERIAL_PARITY_NONE |
  1653. SERIAL_PARITY_ODD |
  1654. SERIAL_PARITY_EVEN |
  1655. SERIAL_PARITY_MARK |
  1656. SERIAL_PARITY_SPACE;
  1657. Properties->CurrentTxQueue = Extension->TxBufferSize;
  1658. Properties->CurrentRxQueue = Extension->RxBufferSize;
  1659. }
  1660. #if 0
  1661. BOOLEAN
  1662. MoxaClearDownLoad(
  1663. IN PVOID Context
  1664. )
  1665. {
  1666. PMOXA_GLOBAL_DATA globalData = Context;
  1667. USHORT i;
  1668. globalData->DownLoad = FALSE;
  1669. for (i=0; i<MAX_CARD; i++)
  1670. globalData->NumPorts[i] = 0;
  1671. return FALSE;
  1672. }
  1673. #endif
  1674. VOID
  1675. InitPort(
  1676. IN PMOXA_DEVICE_EXTENSION Extension,
  1677. IN ULONG RxBufSize,
  1678. IN ULONG TxBufSize,
  1679. IN ULONG MaxBaud
  1680. )
  1681. {
  1682. PUCHAR ofs;
  1683. ULONG count;
  1684. Extension->PortExist = TRUE;
  1685. Extension->DeviceIsOpened = FALSE;
  1686. Extension->OpenCount = 0;
  1687. Extension->SendBreak = FALSE;
  1688. Extension->OwnsPowerPolicy = TRUE;
  1689. Extension->GlobalData = MoxaGlobalData;
  1690. Extension->ControlDevice = FALSE;
  1691. Extension->PowerState = PowerDeviceD3;
  1692. //
  1693. // Initialize the count of IRP's pending
  1694. //
  1695. Extension->PendingIRPCnt = 1;
  1696. //
  1697. // Initialize the count of DPC's pending
  1698. //
  1699. Extension->DpcCount = 1;
  1700. InitializeListHead(&Extension->ReadQueue);
  1701. InitializeListHead(&Extension->WriteQueue);
  1702. InitializeListHead(&Extension->MaskQueue);
  1703. InitializeListHead(&Extension->PurgeQueue);
  1704. InitializeListHead(&Extension->AllDevObjs);
  1705. InitializeListHead(&Extension->StalledIrpQueue);
  1706. ExInitializeFastMutex(&Extension->OpenMutex);
  1707. ExInitializeFastMutex(&Extension->CloseMutex);
  1708. KeInitializeEvent(&Extension->PendingIRPEvent, SynchronizationEvent, FALSE);
  1709. KeInitializeEvent(&Extension->PendingDpcEvent, SynchronizationEvent, FALSE);
  1710. KeInitializeEvent(&Extension->PowerD0Event, SynchronizationEvent, FALSE);
  1711. KeInitializeSpinLock(&Extension->ControlLock);
  1712. KeInitializeTimer(&Extension->ReadRequestTotalTimer);
  1713. KeInitializeTimer(&Extension->ReadRequestIntervalTimer);
  1714. KeInitializeTimer(&Extension->WriteRequestTotalTimer);
  1715. KeInitializeDpc(
  1716. &Extension->CompleteWriteDpc,
  1717. MoxaCompleteWrite,
  1718. Extension
  1719. );
  1720. KeInitializeDpc(
  1721. &Extension->IsrOutDpc,
  1722. MoxaIsrOut,
  1723. Extension
  1724. );
  1725. KeInitializeDpc(
  1726. &Extension->CompleteReadDpc,
  1727. MoxaCompleteRead,
  1728. Extension
  1729. );
  1730. KeInitializeDpc(
  1731. &Extension->IsrInDpc,
  1732. MoxaIsrIn,
  1733. Extension
  1734. );
  1735. KeInitializeDpc(
  1736. &Extension->TotalReadTimeoutDpc,
  1737. MoxaReadTimeout,
  1738. Extension
  1739. );
  1740. KeInitializeDpc(
  1741. &Extension->IntervalReadTimeoutDpc,
  1742. MoxaIntervalReadTimeout,
  1743. Extension
  1744. );
  1745. KeInitializeDpc(
  1746. &Extension->TotalWriteTimeoutDpc,
  1747. MoxaWriteTimeout,
  1748. Extension
  1749. );
  1750. KeInitializeDpc(
  1751. &Extension->CommErrorDpc,
  1752. MoxaCommError,
  1753. Extension
  1754. );
  1755. KeInitializeDpc(
  1756. &Extension->CommWaitDpc,
  1757. MoxaCompleteWait,
  1758. Extension
  1759. );
  1760. //
  1761. // 9-24-01 by William
  1762. //
  1763. #if 0
  1764. KeInitializeDpc(
  1765. &Extension->IntrLineDpc,
  1766. MoxaIntrLine,
  1767. Extension
  1768. );
  1769. KeInitializeDpc(
  1770. &Extension->IntrErrorDpc,
  1771. MoxaIntrError,
  1772. Extension
  1773. );
  1774. #endif
  1775. // end
  1776. KeInitializeDpc(
  1777. &Extension->IsrUnlockPagesDpc,
  1778. MoxaUnlockPages,
  1779. Extension);
  1780. Extension->SpecialChars.EofChar = 0;
  1781. Extension->SpecialChars.ErrorChar = 0;
  1782. Extension->SpecialChars.BreakChar = 0;
  1783. Extension->SpecialChars.EventChar = 0;
  1784. Extension->SpecialChars.XonChar = 0x11;
  1785. Extension->SpecialChars.XoffChar = 0x13;
  1786. // Extension->HandFlow.ControlHandShake = SERIAL_DTR_CONTROL;
  1787. Extension->HandFlow.ControlHandShake = 0;
  1788. // Extension->HandFlow.FlowReplace = SERIAL_RTS_CONTROL;
  1789. Extension->HandFlow.FlowReplace = 0;
  1790. Extension->DataMode = MOXA_8_DATA | MOXA_NONE_PARITY;
  1791. Extension->ValidDataMask = 0xff;
  1792. Extension->CurrentBaud = 38400;
  1793. Extension->RxBufferSize = RxBufSize;
  1794. Extension->TxBufferSize = TxBufSize;
  1795. Extension->HandFlow.XoffLimit = Extension->RxBufferSize >> 3;
  1796. Extension->HandFlow.XonLimit = Extension->RxBufferSize >> 1;
  1797. Extension->BufferSizePt8 = ((3*(Extension->RxBufferSize>>2))+
  1798. (Extension->RxBufferSize>>4));
  1799. Extension->SupportedBauds =
  1800. SERIAL_BAUD_USER |
  1801. SERIAL_BAUD_075 |
  1802. SERIAL_BAUD_110 |
  1803. SERIAL_BAUD_134_5 |
  1804. SERIAL_BAUD_150 |
  1805. SERIAL_BAUD_300 |
  1806. SERIAL_BAUD_600 |
  1807. SERIAL_BAUD_1200 |
  1808. SERIAL_BAUD_1800 |
  1809. SERIAL_BAUD_2400 |
  1810. SERIAL_BAUD_4800 |
  1811. SERIAL_BAUD_7200 |
  1812. SERIAL_BAUD_9600 |
  1813. SERIAL_BAUD_14400 |
  1814. SERIAL_BAUD_19200 |
  1815. SERIAL_BAUD_38400;
  1816. Extension->DeviceIsOpened = FALSE;
  1817. Extension->ShortIntervalAmount.QuadPart = -1;
  1818. Extension->LongIntervalAmount.QuadPart = -10000000;
  1819. Extension->CutOverAmount.QuadPart = 200000000;
  1820. ofs = Extension->PortOfs;
  1821. count = 0;
  1822. while ((*(ofs + FuncCode) != 0)&&(count++ < 500))
  1823. MoxaDelay(1);
  1824. *(ofs + FuncCode) = FC_GetClockRate;
  1825. count = 0;
  1826. while ((*(ofs + FuncCode) != 0)&&(count++ < 500)) /* wait cmd process completed */
  1827. MoxaDelay(1);
  1828. Extension->ClockType = *(ofs + FuncArg); /* 0, 1, 2 */
  1829. if (Extension->ClockType) {
  1830. Extension->SupportedBauds |= SERIAL_BAUD_57600;
  1831. if (Extension->ClockType == 2)
  1832. Extension->SupportedBauds |= SERIAL_BAUD_115200;
  1833. }
  1834. Extension->MaxBaud = MaxBaud;
  1835. }
  1836. BOOLEAN
  1837. MoxaGetStats(
  1838. IN PVOID Context
  1839. )
  1840. /*++
  1841. Routine Description:
  1842. In sync with the interrpt service routine (which sets the perf stats)
  1843. return the perf stats to the caller.
  1844. Arguments:
  1845. Context - Pointer to a the irp.
  1846. Return Value:
  1847. This routine always returns FALSE.
  1848. --*/
  1849. {
  1850. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation((PIRP)Context);
  1851. PMOXA_DEVICE_EXTENSION extension = irpSp->DeviceObject->DeviceExtension;
  1852. PSERIALPERF_STATS sp = ((PIRP)Context)->AssociatedIrp.SystemBuffer;
  1853. *sp = extension->PerfStats;
  1854. return FALSE;
  1855. }
  1856. BOOLEAN
  1857. MoxaClearStats(
  1858. IN PVOID Context
  1859. )
  1860. /*++
  1861. Routine Description:
  1862. In sync with the interrpt service routine (which sets the perf stats)
  1863. clear the perf stats.
  1864. Arguments:
  1865. Context - Pointer to a the extension.
  1866. Return Value:
  1867. This routine always returns FALSE.
  1868. --*/
  1869. {
  1870. PSERIALPERF_STATS perf_stats;
  1871. int port;
  1872. perf_stats = &((PMOXA_DEVICE_EXTENSION)Context)->PerfStats;
  1873. port = (int)(((PMOXA_DEVICE_EXTENSION)Context)->PortNo);
  1874. MoxaTotalRx[port] += perf_stats->ReceivedCount;
  1875. MoxaTotalTx[port] += perf_stats->TransmittedCount;
  1876. RtlZeroMemory(
  1877. perf_stats,
  1878. sizeof(SERIALPERF_STATS)
  1879. );
  1880. return FALSE;
  1881. }
  1882. MoxaReadReg(
  1883. IN PUCHAR PortOfs,
  1884. IN int reg
  1885. )
  1886. {
  1887. USHORT value;
  1888. *(PUSHORT)(PortOfs + FuncArg) = (USHORT)reg;
  1889. *(PortOfs + FuncCode) = FC_InUARTreg;
  1890. MoxaWaitFinish(PortOfs);
  1891. value = *(PUSHORT)(PortOfs + FuncArg1);
  1892. return((int)value);
  1893. }
  1894. void
  1895. MoxaWriteReg(
  1896. IN PUCHAR PortOfs,
  1897. IN int reg,
  1898. IN int value
  1899. )
  1900. {
  1901. *(PUSHORT)(PortOfs + FuncArg1) = (USHORT)value;
  1902. *(PUSHORT)(PortOfs + FuncArg) = (USHORT)reg;
  1903. *(PortOfs + FuncCode) = FC_OutUARTreg;
  1904. MoxaWaitFinish(PortOfs);
  1905. }
  1906. //
  1907. // Internal Ioctl
  1908. //
  1909. NTSTATUS
  1910. MoxaInternalIoControl(IN PDEVICE_OBJECT PDevObj, IN PIRP PIrp)
  1911. /*++
  1912. Routine Description:
  1913. This routine provides the initial processing for all of the
  1914. internal Ioctrls for the serial device.
  1915. Arguments:
  1916. PDevObj - Pointer to the device object for this device
  1917. PIrp - Pointer to the IRP for the current request
  1918. Return Value:
  1919. The function value is the final status of the call
  1920. --*/
  1921. {
  1922. //
  1923. // The status that gets returned to the caller and
  1924. // set in the Irp.
  1925. //
  1926. NTSTATUS status;
  1927. //
  1928. // The current stack location. This contains all of the
  1929. // information we need to process this particular request.
  1930. //
  1931. PIO_STACK_LOCATION pIrpStack;
  1932. //
  1933. // Just what it says. This is the serial specific device
  1934. // extension of the device object create for the serial driver.
  1935. //
  1936. PMOXA_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  1937. //
  1938. // A temporary to hold the old IRQL so that it can be
  1939. // restored once we complete/validate this request.
  1940. //
  1941. KIRQL OldIrql;
  1942. NTSTATUS prologueStatus;
  1943. if (pDevExt->ControlDevice) { // Control Device
  1944. status = STATUS_CANCELLED;
  1945. PIrp->IoStatus.Information = 0L;
  1946. PIrp->IoStatus.Status = status;
  1947. IoCompleteRequest(
  1948. PIrp,
  1949. 0
  1950. );
  1951. return status;
  1952. }
  1953. if ((prologueStatus = MoxaIRPPrologue(PIrp, pDevExt))
  1954. != STATUS_SUCCESS) {
  1955. MoxaCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  1956. return prologueStatus;
  1957. }
  1958. if (MoxaCompleteIfError(PDevObj, PIrp) != STATUS_SUCCESS) {
  1959. return STATUS_CANCELLED;
  1960. }
  1961. pIrpStack = IoGetCurrentIrpStackLocation(PIrp);
  1962. PIrp->IoStatus.Information = 0L;
  1963. status = STATUS_SUCCESS;
  1964. switch (pIrpStack->Parameters.DeviceIoControl.IoControlCode) {
  1965. //
  1966. // Send a wait-wake IRP
  1967. //
  1968. case IOCTL_SERIAL_INTERNAL_DO_WAIT_WAKE:
  1969. pDevExt->SendWaitWake = TRUE;
  1970. status = STATUS_SUCCESS;
  1971. break;
  1972. case IOCTL_SERIAL_INTERNAL_CANCEL_WAIT_WAKE:
  1973. pDevExt->SendWaitWake = FALSE;
  1974. if (pDevExt->PendingWakeIrp != NULL) {
  1975. IoCancelIrp(pDevExt->PendingWakeIrp);
  1976. }
  1977. status = STATUS_SUCCESS;
  1978. break;
  1979. //
  1980. // Put the serial port in a "filter-driver" appropriate state
  1981. //
  1982. // WARNING: This code assumes it is being called by a trusted kernel
  1983. // entity and no checking is done on the validity of the settings
  1984. // passed to IOCTL_SERIAL_INTERNAL_RESTORE_SETTINGS
  1985. //
  1986. // If validity checking is desired, the regular ioctl's should be used
  1987. //
  1988. case IOCTL_SERIAL_INTERNAL_BASIC_SETTINGS:
  1989. case IOCTL_SERIAL_INTERNAL_RESTORE_SETTINGS: {
  1990. SERIAL_BASIC_SETTINGS basic;
  1991. PSERIAL_BASIC_SETTINGS pBasic;
  1992. SHORT AppropriateDivisor;
  1993. MOXA_IOCTL_SYNC S;
  1994. if (pIrpStack->Parameters.DeviceIoControl.IoControlCode
  1995. == IOCTL_SERIAL_INTERNAL_BASIC_SETTINGS) {
  1996. //
  1997. // Check the buffer size
  1998. //
  1999. if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength <
  2000. sizeof(SERIAL_BASIC_SETTINGS)) {
  2001. status = STATUS_BUFFER_TOO_SMALL;
  2002. break;
  2003. }
  2004. //
  2005. // Everything is 0 -- timeouts and flow control. If
  2006. // We add additional features, this zero memory method
  2007. // may not work.
  2008. //
  2009. RtlZeroMemory(&basic, sizeof(SERIAL_BASIC_SETTINGS));
  2010. PIrp->IoStatus.Information = sizeof(SERIAL_BASIC_SETTINGS);
  2011. pBasic = (PSERIAL_BASIC_SETTINGS)PIrp->AssociatedIrp.SystemBuffer;
  2012. //
  2013. // Save off the old settings
  2014. //
  2015. RtlCopyMemory(&pBasic->Timeouts, &pDevExt->Timeouts,
  2016. sizeof(SERIAL_TIMEOUTS));
  2017. RtlCopyMemory(&pBasic->HandFlow, &pDevExt->HandFlow,
  2018. sizeof(SERIAL_HANDFLOW));
  2019. pBasic->RxFifo = pDevExt->RxFifoTrigger;
  2020. pBasic->TxFifo = pDevExt->TxFifoAmount;
  2021. //
  2022. // Point to our new settings
  2023. //
  2024. pBasic = &basic;
  2025. } else { // restoring settings
  2026. if (pIrpStack->Parameters.DeviceIoControl.InputBufferLength
  2027. < sizeof(SERIAL_BASIC_SETTINGS)) {
  2028. status = STATUS_BUFFER_TOO_SMALL;
  2029. break;
  2030. }
  2031. pBasic = (PSERIAL_BASIC_SETTINGS)PIrp->AssociatedIrp.SystemBuffer;
  2032. }
  2033. KeAcquireSpinLock(&pDevExt->ControlLock, &OldIrql);
  2034. //
  2035. // Set the timeouts
  2036. //
  2037. RtlCopyMemory(&pDevExt->Timeouts, &pBasic->Timeouts,
  2038. sizeof(SERIAL_TIMEOUTS));
  2039. //
  2040. // Set flowcontrol
  2041. //
  2042. S.Extension = pDevExt;
  2043. S.Data = &pBasic->HandFlow;
  2044. KeSynchronizeExecution(pDevExt->Interrupt, MoxaSetupNewHandFlow, &S);
  2045. pDevExt->TxFifoAmount = (USHORT)pBasic->TxFifo;
  2046. pDevExt->RxFifoTrigger = (USHORT)pBasic->RxFifo;
  2047. MoxaFunc(pDevExt->PortOfs, FC_SetTxFIFOCnt,pDevExt->TxFifoAmount);
  2048. MoxaFunc(pDevExt->PortOfs, FC_SetRxFIFOTrig,pDevExt->RxFifoTrigger);
  2049. KeReleaseSpinLock(&pDevExt->ControlLock, OldIrql);
  2050. break;
  2051. }
  2052. default:
  2053. status = STATUS_INVALID_PARAMETER;
  2054. break;
  2055. }
  2056. PIrp->IoStatus.Status = status;
  2057. MoxaCompleteRequest(pDevExt, PIrp, 0);
  2058. return status;
  2059. }