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.

605 lines
17 KiB

  1. /*++
  2. Module Name:
  3. isr.c
  4. Environment:
  5. Kernel mode
  6. Revision History :
  7. --*/
  8. #include "precomp.h"
  9. BOOLEAN
  10. MoxaISR(
  11. IN PKINTERRUPT InterruptObject,
  12. IN PVOID Context
  13. )
  14. {
  15. PMOXA_GLOBAL_DATA globalData;
  16. PMOXA_DEVICE_EXTENSION extension;
  17. USHORT boardNo, port, portNo, temp;
  18. PUSHORT ip;
  19. PIO_STACK_LOCATION irpSp;
  20. UCHAR ack;
  21. BOOLEAN servicedAnInterrupt = FALSE;
  22. BOOLEAN thisPassServiced;
  23. PLIST_ENTRY firstInterruptEntry = Context;
  24. PLIST_ENTRY interruptEntry;
  25. PMOXA_MULTIPORT_DISPATCH dispatch;
  26. MoxaIRQok = TRUE;
  27. if (!firstInterruptEntry)
  28. return (servicedAnInterrupt);
  29. MoxaKdPrint(MX_DBG_TRACE_ISR,("Enter ISR(first=%x)\n",firstInterruptEntry));
  30. if (IsListEmpty(firstInterruptEntry))
  31. return (servicedAnInterrupt);
  32. do {
  33. thisPassServiced = FALSE;
  34. interruptEntry = firstInterruptEntry->Flink;
  35. do {
  36. PMOXA_CISR_SW cisrsw =
  37. CONTAINING_RECORD(
  38. interruptEntry,
  39. MOXA_CISR_SW,
  40. SharerList
  41. );
  42. MoxaKdPrint(MX_DBG_TRACE_ISR,("CISRSW=%x\n",cisrsw));
  43. if (!cisrsw)
  44. return (servicedAnInterrupt);
  45. dispatch = &cisrsw->Dispatch;
  46. globalData = dispatch->GlobalData;
  47. boardNo = (USHORT)dispatch->BoardNo;
  48. if (!globalData || boardNo < 0)
  49. return (servicedAnInterrupt);
  50. MoxaKdPrint(MX_DBG_TRACE_ISR,("Board=%d,Pending=%x,IntIndx=%x,BoardReady=%d\n",
  51. boardNo,
  52. *globalData->IntPend[boardNo],
  53. *globalData->IntNdx[boardNo],
  54. globalData->BoardReady[boardNo]
  55. ));
  56. if (globalData->PciIntAckBase[boardNo]) {
  57. ack = READ_PORT_UCHAR(globalData->PciIntAckBase[boardNo]);
  58. MoxaKdPrint(MX_DBG_TRACE_ISR,("Ack Interrupt%d/%x/%x\n",boardNo,globalData->PciIntAckBase[boardNo],ack));
  59. ack |= 4;
  60. WRITE_PORT_UCHAR(globalData->PciIntAckBase[boardNo],ack);
  61. }
  62. if ((globalData->BoardReady[boardNo] == TRUE)
  63. &&(*globalData->IntPend[boardNo] == 0xff)
  64. &&((*globalData->IntNdx[boardNo] == 0)||( *globalData->IntNdx[boardNo]==0x80))
  65. ) {
  66. servicedAnInterrupt = TRUE;
  67. thisPassServiced = TRUE;
  68. ip = (PUSHORT)(globalData->IntTable[boardNo]
  69. + *globalData->IntNdx[boardNo]);
  70. for (port=0; port<globalData->NumPorts[boardNo]; port++) {
  71. portNo = boardNo * MAXPORT_PER_CARD + port;
  72. if (!(extension = globalData->Extension[portNo]))
  73. continue;
  74. if ((temp = ip[extension->PortIndex]) != 0) {
  75. ip[extension->PortIndex] = 0;
  76. if ((!extension->DeviceIsOpened) ||
  77. (extension->PowerState != PowerDeviceD0))
  78. continue;
  79. if (temp & (IntrTx | IntrTxTrigger)) {
  80. if (extension->WriteLength) {
  81. if (!extension->IsrOutFlag) {
  82. extension->IsrOutFlag = 1;
  83. MoxaInsertQueueDpc(
  84. &extension->IsrOutDpc,
  85. NULL,
  86. NULL,
  87. extension
  88. );
  89. }
  90. }
  91. else if (*(PSHORT)(extension->PortOfs + HostStat) & (WakeupTx|WakeupTxTrigger)) {
  92. *(PSHORT)(extension->PortOfs + HostStat) &= ~(WakeupTx|WakeupTxTrigger);
  93. irpSp = IoGetCurrentIrpStackLocation(
  94. extension->CurrentWriteIrp);
  95. extension->CurrentWriteIrp->IoStatus.Information =
  96. irpSp->Parameters.Write.Length;
  97. MoxaInsertQueueDpc(
  98. &extension->CompleteWriteDpc,
  99. NULL,
  100. NULL,
  101. extension
  102. );
  103. }
  104. }
  105. if (temp & IntrRxTrigger) {
  106. if (extension->ReadLength) {
  107. if (!extension->IsrInFlag) {
  108. extension->IsrInFlag = 1;
  109. MoxaInsertQueueDpc(
  110. &extension->IsrInDpc,
  111. NULL,
  112. NULL,
  113. extension
  114. );
  115. }
  116. }
  117. }
  118. if (temp & IntrRx) {
  119. if (extension->IsrWaitMask & SERIAL_EV_RXCHAR)
  120. extension->HistoryMask |= SERIAL_EV_RXCHAR;
  121. }
  122. if (temp & IntrEvent) {
  123. if (extension->IsrWaitMask & SERIAL_EV_RXFLAG)
  124. extension->HistoryMask |= SERIAL_EV_RXFLAG;
  125. }
  126. if (temp & IntrRx80Full) {
  127. if (extension->IsrWaitMask & SERIAL_EV_RX80FULL)
  128. extension->HistoryMask |= SERIAL_EV_RX80FULL;
  129. }
  130. if (temp & IntrBreak) {
  131. extension->ErrorWord |= SERIAL_ERROR_BREAK;
  132. if (extension->IsrWaitMask & SERIAL_EV_BREAK)
  133. extension->HistoryMask |= SERIAL_EV_BREAK;
  134. if (extension->HandFlow.ControlHandShake &
  135. SERIAL_ERROR_ABORT) {
  136. MoxaInsertQueueDpc(
  137. &extension->CommErrorDpc,
  138. NULL,
  139. NULL,
  140. extension
  141. );
  142. }
  143. }
  144. if (temp & IntrLine) {
  145. //
  146. // 9-24-01 by William
  147. //
  148. #if 0
  149. MoxaInsertQueueDpc(
  150. &extension->IntrLineDpc,
  151. NULL,
  152. NULL,
  153. extension
  154. );
  155. #endif
  156. USHORT modemStatus;
  157. MoxaFuncGetLineStatus(
  158. extension->PortOfs,
  159. &modemStatus
  160. );
  161. if (extension->IsrWaitMask & (SERIAL_EV_CTS |
  162. SERIAL_EV_DSR |
  163. SERIAL_EV_RLSD)) {
  164. USHORT change;
  165. change = modemStatus ^ extension->ModemStatus;
  166. if ((change & LSTATUS_CTS) &&
  167. (extension->IsrWaitMask & SERIAL_EV_CTS))
  168. extension->HistoryMask |= SERIAL_EV_CTS;
  169. if ((change & LSTATUS_DSR) &&
  170. (extension->IsrWaitMask & SERIAL_EV_DSR))
  171. extension->HistoryMask |= SERIAL_EV_DSR;
  172. if ((change & LSTATUS_DCD) &&
  173. (extension->IsrWaitMask & SERIAL_EV_RLSD))
  174. extension->HistoryMask |= SERIAL_EV_RLSD;
  175. }
  176. extension->ModemStatus = modemStatus;
  177. // end
  178. }
  179. if (temp & IntrError) {
  180. //
  181. // 9-24-01 by William
  182. //
  183. #if 0
  184. MoxaInsertQueueDpc(
  185. &extension->IntrErrorDpc,
  186. NULL,
  187. NULL,
  188. extension
  189. );
  190. #endif
  191. USHORT dataError;
  192. MoxaFuncGetDataError(
  193. extension->PortOfs,
  194. &dataError
  195. );
  196. if ( dataError & SERIAL_ERROR_QUEUEOVERRUN ) {
  197. extension->PerfStats.BufferOverrunErrorCount++;
  198. }
  199. if (dataError & SERIAL_ERROR_OVERRUN) {
  200. extension->PerfStats.SerialOverrunErrorCount++;
  201. }
  202. if (dataError & SERIAL_ERROR_PARITY) {
  203. extension->PerfStats.ParityErrorCount++;
  204. }
  205. if (dataError & SERIAL_ERROR_FRAMING) {
  206. extension->PerfStats.FrameErrorCount++;
  207. }
  208. extension->ErrorWord |= (dataError &
  209. (SERIAL_ERROR_OVERRUN | SERIAL_ERROR_PARITY |
  210. SERIAL_ERROR_FRAMING | SERIAL_ERROR_QUEUEOVERRUN));
  211. if (extension->IsrWaitMask & SERIAL_EV_ERR) {
  212. if (dataError & (SERIAL_ERROR_OVERRUN |
  213. SERIAL_ERROR_PARITY |
  214. SERIAL_ERROR_FRAMING))
  215. extension->HistoryMask |= SERIAL_EV_ERR;
  216. }
  217. if (extension->HandFlow.ControlHandShake &
  218. SERIAL_ERROR_ABORT) {
  219. MoxaInsertQueueDpc(
  220. &extension->CommErrorDpc,
  221. NULL,
  222. NULL,
  223. extension
  224. );
  225. }
  226. // end
  227. }
  228. if (extension->IrpMaskLocation &&
  229. extension->HistoryMask) {
  230. *extension->IrpMaskLocation =
  231. extension->HistoryMask;
  232. extension->IrpMaskLocation = NULL;
  233. extension->HistoryMask = 0;
  234. extension->CurrentWaitIrp->IoStatus.Information =
  235. sizeof(ULONG);
  236. MoxaInsertQueueDpc(
  237. &extension->CommWaitDpc,
  238. NULL,
  239. NULL,
  240. extension
  241. );
  242. }
  243. }
  244. }
  245. *globalData->IntPend[boardNo] = 0;
  246. }
  247. interruptEntry = interruptEntry->Flink;
  248. servicedAnInterrupt |= thisPassServiced;
  249. }
  250. while (interruptEntry != firstInterruptEntry);
  251. }
  252. while (thisPassServiced == TRUE);
  253. MoxaKdPrint(MX_DBG_TRACE_ISR,("Exit ISR\n"));
  254. return (servicedAnInterrupt);
  255. }
  256. VOID
  257. MoxaIsrIn(
  258. IN PKDPC Dpc,
  259. IN PVOID DeferredContext,
  260. IN PVOID SystemContext1,
  261. IN PVOID SystemContext2
  262. )
  263. {
  264. PMOXA_DEVICE_EXTENSION extension = DeferredContext;
  265. KIRQL oldIrql;
  266. IoAcquireCancelSpinLock(&oldIrql);
  267. KeSynchronizeExecution(
  268. extension->Interrupt,
  269. MoxaIsrGetData,
  270. extension
  271. );
  272. IoReleaseCancelSpinLock(oldIrql);
  273. MoxaDpcEpilogue(extension, Dpc);
  274. }
  275. BOOLEAN
  276. MoxaIsrGetData(
  277. IN PVOID Context
  278. )
  279. {
  280. PMOXA_DEVICE_EXTENSION extension = Context;
  281. PIO_STACK_LOCATION irpSp;
  282. USHORT max;
  283. if (extension->ReadLength) {
  284. extension->NumberNeededForRead = extension->ReadLength;
  285. MoxaGetData(extension);
  286. extension->ReadLength = extension->NumberNeededForRead;
  287. if (!extension->ReadLength) {
  288. *(PSHORT)(extension->PortOfs + HostStat) &= ~WakeupRxTrigger;
  289. irpSp = IoGetCurrentIrpStackLocation(
  290. extension->CurrentReadIrp);
  291. extension->CurrentReadIrp->IoStatus.Information =
  292. irpSp->Parameters.Read.Length;
  293. extension->CountOnLastRead = MOXA_COMPLETE_READ_COMPLETE;
  294. MoxaInsertQueueDpc(
  295. &extension->CompleteReadDpc,
  296. NULL,
  297. NULL,
  298. extension
  299. );
  300. }
  301. else {
  302. /* 8-14-01 by William
  303. max = *(PUSHORT)(extension->PortOfs + RX_mask) - 128;
  304. */
  305. max = *(PUSHORT)(extension->PortOfs + RX_mask) - RX_offset;
  306. if (extension->NumberNeededForRead > max)
  307. *(PUSHORT)(extension->PortOfs + Rx_trigger) = max;
  308. else
  309. *(PUSHORT)(extension->PortOfs + Rx_trigger) =
  310. (USHORT)extension->NumberNeededForRead;
  311. *(PSHORT)(extension->PortOfs + HostStat) |= WakeupRxTrigger;
  312. }
  313. }
  314. extension->IsrInFlag = 0;
  315. return FALSE;
  316. }
  317. VOID
  318. MoxaIsrOut(
  319. IN PKDPC Dpc,
  320. IN PVOID DeferredContext,
  321. IN PVOID SystemContext1,
  322. IN PVOID SystemContext2
  323. )
  324. {
  325. PMOXA_DEVICE_EXTENSION extension = DeferredContext;
  326. KIRQL oldIrql;
  327. IoAcquireCancelSpinLock(&oldIrql);
  328. KeSynchronizeExecution(
  329. extension->Interrupt,
  330. MoxaIsrPutData,
  331. extension
  332. );
  333. IoReleaseCancelSpinLock(oldIrql);
  334. MoxaDpcEpilogue(extension, Dpc);
  335. }
  336. BOOLEAN
  337. MoxaIsrPutData(
  338. IN PVOID Context
  339. )
  340. {
  341. PMOXA_DEVICE_EXTENSION extension = Context;
  342. if (extension->WriteLength)
  343. MoxaPutData(extension);
  344. extension->IsrOutFlag = 0;
  345. return FALSE;
  346. }
  347. VOID
  348. MoxaIntrLine(
  349. IN PKDPC Dpc,
  350. IN PVOID DeferredContext,
  351. IN PVOID SystemContext1,
  352. IN PVOID SystemContext2
  353. )
  354. {
  355. PMOXA_DEVICE_EXTENSION extension = DeferredContext;
  356. KIRQL oldIrql;
  357. PUCHAR ofs = extension->PortOfs;
  358. USHORT modemStatus;
  359. MoxaFuncGetLineStatus(
  360. ofs,
  361. &modemStatus
  362. );
  363. if (extension->IsrWaitMask & (SERIAL_EV_CTS |
  364. SERIAL_EV_DSR |
  365. SERIAL_EV_RLSD)) {
  366. USHORT change;
  367. change = modemStatus ^ extension->ModemStatus;
  368. if ((change & LSTATUS_CTS) &&
  369. (extension->IsrWaitMask & SERIAL_EV_CTS))
  370. extension->HistoryMask |= SERIAL_EV_CTS;
  371. if ((change & LSTATUS_DSR) &&
  372. (extension->IsrWaitMask & SERIAL_EV_DSR))
  373. extension->HistoryMask |= SERIAL_EV_DSR;
  374. if ((change & LSTATUS_DCD) &&
  375. (extension->IsrWaitMask & SERIAL_EV_RLSD))
  376. extension->HistoryMask |= SERIAL_EV_RLSD;
  377. }
  378. extension->ModemStatus = modemStatus;
  379. IoAcquireCancelSpinLock(&oldIrql);
  380. if (extension->IrpMaskLocation &&
  381. extension->HistoryMask) {
  382. *extension->IrpMaskLocation =
  383. extension->HistoryMask;
  384. extension->IrpMaskLocation = NULL;
  385. extension->HistoryMask = 0;
  386. extension->CurrentWaitIrp->IoStatus.Information =
  387. sizeof(ULONG);
  388. MoxaInsertQueueDpc(
  389. &extension->CommWaitDpc,
  390. NULL,
  391. NULL,
  392. extension
  393. );
  394. }
  395. IoReleaseCancelSpinLock(oldIrql);
  396. MoxaDpcEpilogue(extension, Dpc);
  397. }
  398. VOID
  399. MoxaIntrError(
  400. IN PKDPC Dpc,
  401. IN PVOID DeferredContext,
  402. IN PVOID SystemContext1,
  403. IN PVOID SystemContext2
  404. )
  405. {
  406. PMOXA_DEVICE_EXTENSION extension = DeferredContext;
  407. KIRQL oldIrql;
  408. PUCHAR ofs = extension->PortOfs;
  409. USHORT dataError;
  410. KeAcquireSpinLock(
  411. &extension->ControlLock,
  412. &oldIrql
  413. );
  414. MoxaFuncGetDataError(
  415. ofs,
  416. &dataError
  417. );
  418. KeReleaseSpinLock(
  419. &extension->ControlLock,
  420. oldIrql
  421. );
  422. if ( dataError & SERIAL_ERROR_QUEUEOVERRUN ) {
  423. extension->PerfStats.BufferOverrunErrorCount++;
  424. }
  425. if (dataError & SERIAL_ERROR_OVERRUN) {
  426. extension->PerfStats.SerialOverrunErrorCount++;
  427. }
  428. if (dataError & SERIAL_ERROR_PARITY) {
  429. extension->PerfStats.ParityErrorCount++;
  430. }
  431. if (dataError & SERIAL_ERROR_FRAMING) {
  432. extension->PerfStats.FrameErrorCount++;
  433. }
  434. extension->ErrorWord |= (dataError &
  435. (SERIAL_ERROR_OVERRUN | SERIAL_ERROR_PARITY |
  436. SERIAL_ERROR_FRAMING | SERIAL_ERROR_QUEUEOVERRUN));
  437. if (extension->IsrWaitMask & SERIAL_EV_ERR) {
  438. if (dataError & (SERIAL_ERROR_OVERRUN |
  439. SERIAL_ERROR_PARITY |
  440. SERIAL_ERROR_FRAMING))
  441. extension->HistoryMask |= SERIAL_EV_ERR;
  442. }
  443. if (extension->HandFlow.ControlHandShake &
  444. SERIAL_ERROR_ABORT) {
  445. MoxaInsertQueueDpc(
  446. &extension->CommErrorDpc,
  447. NULL,
  448. NULL,
  449. extension
  450. );
  451. }
  452. IoAcquireCancelSpinLock(&oldIrql);
  453. if (extension->IrpMaskLocation &&
  454. extension->HistoryMask) {
  455. *extension->IrpMaskLocation =
  456. extension->HistoryMask;
  457. extension->IrpMaskLocation = NULL;
  458. extension->HistoryMask = 0;
  459. extension->CurrentWaitIrp->IoStatus.Information =
  460. sizeof(ULONG);
  461. MoxaInsertQueueDpc(
  462. &extension->CommWaitDpc,
  463. NULL,
  464. NULL,
  465. extension
  466. );
  467. }
  468. IoReleaseCancelSpinLock(oldIrql);
  469. MoxaDpcEpilogue(extension, Dpc);
  470. }