Source code of Windows XP (NT5)
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.

2898 lines
84 KiB

  1. page,132
  2. ;---------------------------Module-Header-------------------------------
  3. ; Module Name: IBMINT.ASM
  4. ;
  5. ; Created: Fri 06-Feb-1987 10:45:12
  6. ; Author: Walt Moore [waltm]
  7. ;
  8. ; Copyright (c) Microsoft Corporation 1985-1990. All Rights Reserved
  9. ;
  10. ; General Description:
  11. ; This file contains the interrupt time routines for the
  12. ; IBM Windows communications driver.
  13. ;
  14. ; The interrupt code is preloaded and fixed.
  15. ;
  16. ; History:
  17. ;
  18. ; **********************************************************************
  19. ; Tue Dec 19 1989 09:35:15 -by- Amit Chatterjee [amitc]
  20. ; ----------------------------------------------------------------------
  21. ; Added a far entry point 'FakeCOMIntFar' so that the routine 'FakeCOMInt'
  22. ; could be called from the 'InitAPort' routine in IBMCOM.ASM
  23. ;
  24. ; 26.Nov.90 richp
  25. ;
  26. ; Changed interrupt routines to use new VPICD services for bi-modal/multi-
  27. ; modal interrupt handling. They now work in straight real mode for real
  28. ; mode Windows, but can also handle interrupts in real mode or protected
  29. ; mode for standard mode Windows, and handle interrupts in RING 0 protected
  30. ; mode for enhanced mode Windows, even when the Windows VM is not currently
  31. ; executing.
  32. ;
  33. ; sudeepb 10-Jan-1993 changed the costly cli/sti with non-trapping
  34. ; FCLI/FSTI macros
  35. ;-----------------------------------------------------------------------;
  36. subttl Communications Hardware Interrupt Service Routines
  37. .xlist
  38. include cmacros.inc
  39. include comdev.inc
  40. include ibmcom.inc
  41. include ins8250.inc
  42. include BIMODINT.INC
  43. include vint.inc
  44. .list
  45. externFP GetSystemMsecCount
  46. externW COMptrs
  47. externW activeCOMs
  48. externD lpPostMessage
  49. ifdef NEC_98
  50. externFP Comm1 ;(ins 92.09.25)
  51. externFP Comm2 ;(ins 92.09.25)
  52. externFP Comm3 ;(ins 92.09.25)
  53. externFP SetFIFOmodeFar ;(ins 94.04.18)
  54. externFP Set8251modeFar ;(ins 94.04.18)
  55. externW Port_TBL ;(ins 92.08.24)
  56. externW Port_EOI ;(ins 92.08.24)
  57. externB Vect_TBL ;(ins 92.08.24)
  58. externB Mask_TBL ;(ins 92.08.24)
  59. externW RECLoopCounter ;(ins 93.03.31)
  60. BIOS_FLAG5 equ 58h ; ins 93.03.24 (IOrecovery)
  61. BIOS_FLAG7 equ 5bh ; ins 93.03.24 (IOrecovery)
  62. endif ; NEC_98
  63. sBegin Data
  64. PUBLIC IRQhooks
  65. IRQhooks label byte
  66. DefineIRQhook MACRO num
  67. IFDEF No_DOSX_Bimodal_Services
  68. IRQhook&num IRQ_Hook_Struc <,,,,IntCodeOFFSET DEF_COM_INT_&num,,,, \
  69. IntCodeOFFSET DEF_RM_COM_INT_&num>
  70. ELSE
  71. IRQhook&num IRQ_Hook_Struc <,,,,IntCodeOFFSET DEF_COM_INT_&num>
  72. ENDIF
  73. ENDM
  74. ??portnum = 1
  75. REPT MAXCOM+1
  76. DefineIRQhook %??portnum
  77. ??portnum = ??portnum+1
  78. ENDM
  79. PURGE DefineIRQhook
  80. EXTRN VCD_int_callback:fword
  81. ifdef NEC_98
  82. TicCount dw 0 ;Timeout counter (ins 92.09.25)
  83. endif ; NEC_98
  84. sEnd data
  85. createSeg _INTERRUPT,IntCode,word,public,CODE
  86. sBegin IntCode
  87. assumes cs,IntCode
  88. page
  89. IFDEF No_DOSX_Bimodal_Services
  90. public RM_IntDataSeg
  91. RM_IntDataSeg dw 0
  92. ; this variable is written into by a routine in inicom
  93. ; if the 286 DOS extender is present. This variable
  94. ; contains the SEGMENT value of the data selector "_DATA"
  95. ; so that the real mode interrupt handler may use the
  96. ; data segment, and not it's selector !
  97. PUBLIC RM_CallBack
  98. RM_CallBack dd 0
  99. ENDIF
  100. Control proc far
  101. ret
  102. Control endp
  103. IFDEF No_DOSX_Bimodal_Services
  104. DEF_RM_Handler proc far
  105. push es
  106. push di
  107. push ax
  108. mov es, cs:[RM_IntDataSeg]
  109. mov di, es:[di.First_DEB] ; ES:DI -> ComDEB
  110. add di, SIZE ComDEB ; ES:DI -> BIS
  111. mov es:[di.BIS_Mode], 4
  112. push cs
  113. call NEAR PTR COMHandler
  114. mov es:[di.BIS_Mode], 0
  115. pop ax
  116. pop di ; ES:DI -> IRQ_Hook_Struc
  117. jc short DEF_RM_chain
  118. pop es
  119. pop di
  120. add sp, 4
  121. iret
  122. DEF_RM_chain:
  123. call DOCLI
  124. push bp
  125. mov bp, sp ;stack frame:
  126. ; bp+8 -> OldInt CS
  127. ; bp+6 -> OldInt IP
  128. ; bp+4 -> di
  129. ; bp+2 -> es
  130. ; bp+0 -> bp
  131. les di, es:[di.RM_OldIntVec]
  132. mov [bp+6], di
  133. mov [bp+8], es
  134. pop bp
  135. pop es
  136. pop di
  137. ret ; far ret to OldInt handler
  138. DEF_RM_Handler endp
  139. ENDIF ;No_DOSX_Bimodal_Services
  140. Define_DEF_COM_INT MACRO num
  141. IFDEF No_DOSX_Bimodal_Services
  142. PUBLIC DEF_RM_COM_INT_&num
  143. DEF_RM_COM_INT_&num proc far
  144. sub sp, 4
  145. push di
  146. mov di, DataOFFSET IRQhook&num
  147. jmp DEF_RM_Handler
  148. DEF_RM_COM_INT_&num endp
  149. ENDIF
  150. PUBLIC DEF_COM_INT_&num
  151. DEF_COM_INT_&num proc far
  152. sub sp, 4
  153. push di
  154. mov di, DataOFFSET IRQhook&num
  155. ifdef NEC_98
  156. jmp DEF_COM_DUMMY
  157. else ; NEC_98
  158. jmp DEF_Handler
  159. endif ; NEC_98
  160. DEF_COM_INT_&num endp
  161. ENDM
  162. ??portnum = 2
  163. REPT MAXCOM
  164. Define_DEF_COM_INT %??portnum
  165. ??portnum = ??portnum+1
  166. ENDM
  167. PURGE Define_DEF_COM_INT
  168. ifdef NEC_98
  169. DEF_COM_DUMMY:
  170. jmp short DEF_Handler
  171. endif ; NEC_98
  172. IFDEF No_DOSX_Bimodal_Services
  173. PUBLIC DEF_RM_COM_INT_1
  174. DEF_RM_COM_INT_1 proc far
  175. sub sp, 4
  176. push di
  177. mov di, DataOFFSET IRQhook1
  178. jmp DEF_RM_Handler
  179. DEF_RM_COM_INT_1 endp
  180. ENDIF
  181. PUBLIC DEF_COM_INT_1
  182. DEF_COM_INT_1 proc far
  183. sub sp, 4
  184. push di
  185. mov di, DataOFFSET IRQhook1
  186. IF2
  187. .errnz $ - OFFSET DEF_Handler
  188. ENDIF
  189. DEF_COM_INT_1 endp
  190. DEF_Handler proc far
  191. push es
  192. push di
  193. push ax
  194. mov ax, _DATA
  195. mov es, ax
  196. mov di, es:[di.First_DEB] ; ES:DI -> ComDEB
  197. add di, SIZE ComDEB ; ES:DI -> BIS
  198. push cs
  199. call NEAR PTR COMHandler
  200. pop ax
  201. pop di ; ES:DI -> IRQ_Hook_Struc
  202. jc short DEF_chain
  203. pop es
  204. pop di
  205. add sp, 4
  206. iret
  207. DEF_chain:
  208. call DOCLI
  209. push bp
  210. mov bp, sp ;stack frame:
  211. ; bp+8 -> OldInt CS
  212. ; bp+6 -> OldInt IP
  213. ; bp+4 -> di
  214. ; bp+2 -> es
  215. ; bp+0 -> bp
  216. les di, es:[di.OldIntVec]
  217. mov [bp+6], di
  218. mov [bp+8], es
  219. pop bp
  220. pop es
  221. pop di
  222. ret ; far ret to OldInt handler
  223. DEF_Handler endp
  224. ;------------------------------------------------------------------------------
  225. ;
  226. ; ENTER: ES:DI -> BIS
  227. ;
  228. ; EXIT: Carry set, if IRQ not handled by any com ports
  229. ;
  230. COMHandler proc far
  231. push ds
  232. push si
  233. push ax
  234. push bx
  235. mov si, es
  236. mov ds, si
  237. mov bh, -1
  238. ch_chk_all:
  239. lea si, [di-SIZE ComDEB] ;ds:si -> ComDEB
  240. mov si, [si.IRQhook]
  241. mov si, [si.First_DEB]
  242. mov bl, -1
  243. ch_next_com:
  244. inc bl ; first time bl = 0
  245. xor ax, ax
  246. xchg ax, [di.BIS_Mode]
  247. lea di, [si+SIZE ComDEB]
  248. mov [di.BIS_Mode], ax
  249. ifdef NEC_98
  250. test [si.AOBA_flag],fFIFO_Mode ; (ins 94.04.16) |
  251. jz @F ;Now, 8251 mode (ins 94.04.16) |
  252. call AOBA_CommInt ; (ins 94.04.16) |
  253. jmp short ch_AOBA_int ; (ins 94.05.17) |
  254. @@: ; (ins 94.04.16) |
  255. call CommInt
  256. ch_AOBA_int: ; (ins 94.05.17)
  257. else ; NEC_98
  258. call CommInt
  259. endif ; NEC_98
  260. and al, 80h
  261. or bl, al
  262. mov si, [si.NextDEB]
  263. or si, si
  264. jnz ch_next_com
  265. test bl, 7Fh ;Q: more than 1 com port?
  266. jnz short ch_shared ; Y: check if handled
  267. or bl, bl ;Q: int handled by port?
  268. stc
  269. jns ch_exit ; N:
  270. ch_eoi:
  271. xor ax, ax
  272. .errnz BIH_API_EOI
  273. xor bx, bx
  274. xchg bx, es:[di.BIS_Mode]
  275. call es:[bx][di.BIS_User_Mode_API]
  276. lea si, [di-SIZE ComDEB] ; ds:si -> ComDEB
  277. mov si, [si.IRQhook]
  278. mov al, [si.OldMask]
  279. shr al, 1 ; shift bit 0 into Carry (0, if unmasked
  280. cmc ; -1, if originally masked)
  281. ch_exit:
  282. pop bx
  283. pop ax
  284. pop si
  285. pop ds
  286. ret
  287. ch_shared:
  288. inc bh ; count loop
  289. or bl, bl ;Q: int handled by any port?
  290. js ch_chk_all ; Y: check all ports again
  291. or bh, bh ;Q: first time thru loop?
  292. stc
  293. jz ch_exit ; Y: int wasn't for a COM port, so
  294. ; chain to next IRQ handler
  295. jmp ch_eoi
  296. COMHandler endp
  297. IFDEF No_DOSX_Bimodal_Services
  298. PUBLIC Entry_From_RM
  299. Entry_From_RM proc far
  300. ;
  301. ; Simulate the far ret
  302. ;
  303. cld
  304. lodsw
  305. mov es:[di.RealMode_IP], ax
  306. lodsw
  307. mov es:[di.RealMode_CS], ax
  308. add es:[di.RealMode_SP], 4
  309. push es
  310. push di
  311. .286
  312. ;
  313. ; Push far addr of Ret_To_IRET to cleanup stack and return to DPMI host
  314. ;
  315. push cs
  316. push IntCodeOFFSET Ret_To_IRET
  317. ;
  318. ; Push far addr of proc to call, so we can do a far ret to it
  319. ;
  320. push es:[di.RealMode_CX] ; segment of callback
  321. push es:[di.RealMode_DX] ; offset of callback
  322. mov di, es:[di.RealMode_DI]
  323. ret ; far ret to cx:dx
  324. ; called proc will do a far ret
  325. Ret_To_IRET: ; <- to here
  326. pop di
  327. pop es
  328. iret
  329. .8086
  330. Entry_From_RM endp
  331. PUBLIC RM_APIHandler
  332. RM_APIHandler proc far
  333. cmp ax, BIH_API_Call_Back
  334. jne APIHandler
  335. call cs:[RM_CallBack]
  336. ret
  337. RM_APIHandler endp
  338. ENDIF
  339. ;------------------------------------------------------------------------------
  340. ;
  341. ; ENTER: ES:DI -> BIS
  342. ;
  343. APIHandler proc far
  344. or ax, ax
  345. jnz short api_not_EOI
  346. .errnz BIH_API_EOI
  347. ifdef NEC_98
  348. push dx ; (ins 93.03.20)
  349. mov ax, es:[di.BIS_IRQ_Number] ; (ins 92.10.06)
  350. cmp al,8 ;Q: slave IRQ? (ins 92.10.06)
  351. mov al,EOI ; (ins 92.10.06)
  352. jb short api_master ; N: (ins 92.10.06)
  353. mov dx,08h ;Pic port address save (ins 93.03.11)
  354. NEWIODELAY 1 ;<OUT 5F,AL> (ins 93.03.08)
  355. out dx,al ; (ins 93.03.08)
  356. mov al,ISR_READ ;Isr read command byte (ins 93.03.08)
  357. NEWIODELAY 1 ;<OUT 5F,AL> (ins 93.03.08)
  358. out dx,al ; (ins 93.03.08)
  359. NEWIODELAY 1 ;<OUT 5F,AL> (ins 93.03.08)
  360. in al,SLAVE_ISR ; (ins 93.03.08)
  361. test al,0ffh ; (ins 93.03.08)
  362. jnz EOI_INT50 ; (ins 93.03.08)
  363. mov al,EOI ; (ins 93.03.08)
  364. NEWIODELAY 1 ;<OUT 5F,AL> (ins 93.03.08)
  365. jmp short api_master ; (ins 93.03.08)
  366. EOI_INT50: ; (ins 93.03.08)
  367. NEWIODELAY 1 ;<OUT 5F,AL> (ins 93.03.08)
  368. pop dx ; (ins 93.03.20)
  369. ret ; (ins 93.03.08)
  370. api_master: ; (ins 92.10.06)
  371. out 00h,al ; EOI master (ins 92.10.06)
  372. NEWIODELAY 1 ;<OUT 5F,AL> (ins 93.03.08)
  373. pop dx ; (ins 93.03.20)
  374. ret ; (ins 92.10.06)
  375. else ; NEC_98
  376. mov ax, es:[di.BIS_IRQ_Number]
  377. cmp al,8 ;Q: slave IRQ?
  378. mov al,EOI
  379. jb short api_master ; N:
  380. out 0A0h,al ; Y: EOI slave
  381. api_master:
  382. out INTA0,al ; EOI master
  383. ret
  384. endif ; NEC_98
  385. api_not_EOI:
  386. cmp ax, BIH_API_Call_Back
  387. jae short api_callme
  388. push dx
  389. push cx
  390. ifdef NEC_98
  391. mov dx, 0002h ; (ins 92.10.06)
  392. else ; NEC_98
  393. mov dx, INTA1
  394. endif ; NEC_98
  395. mov cx, es:[di.BIS_IRQ_Number]
  396. cmp cl, 8 ;Q: 2nd PIC?
  397. jb @f ; N:
  398. ifdef NEC_98
  399. mov dx, 000Ah ; (ins 92.10.06)
  400. else ; NEC_98
  401. mov dx, 0A1h ; Y: dx = mask port
  402. endif ; NEC_98
  403. sub cl, 8
  404. @@:
  405. cmp al, BIH_API_Get_Mask ;Q: get IRQ mask?
  406. jae api_get_mask ; Y:
  407. mov ah, al
  408. mov ch, 1
  409. shl ch, cl ; ch = mask byte
  410. pushf
  411. call DOCLI
  412. in al, dx ; get current PIC mask state
  413. cmp ah, BIH_API_Mask ;Q: mask IRQ?
  414. jne @f ; N:
  415. or al, ch ; Y: set IRQ's bit
  416. jmp short api_mask_exit
  417. @@:
  418. not ch ; N: clear IRQ's bit to unmask
  419. and al, ch
  420. api_mask_exit:
  421. out dx, al
  422. pop ax
  423. test ah, 2 ;Q: ints were enabled?
  424. jz @f ; N:
  425. call DOSTI
  426. @@:
  427. pop cx
  428. pop dx
  429. ret
  430. api_get_mask:
  431. in al, dx ; get current PIC mask state
  432. inc cl
  433. shr al, cl ; move IRQ's bit into carry
  434. ; Carry set, if IRQ masked
  435. pop cx
  436. pop dx
  437. ret
  438. api_callme:
  439. push cx
  440. push dx
  441. ret ; far ret to call back, which will
  442. ; do a far ret to our caller
  443. APIHandler endp
  444. ;--------------------------Fake a Hardware Interrupt----------------------;
  445. ; FakeCOMInt
  446. ;
  447. ; This routine fakes a hardware interrupt to IRQ3 or IRQ4
  448. ; to clear out characters pending in the buffer
  449. ;
  450. ; Entry:
  451. ; DS:SI --> DEB
  452. ; INTERRUPTS DISABLED!
  453. ; Returns:
  454. ; None
  455. ; Error Returns:
  456. ; None
  457. ; Registers Preserved:
  458. ;
  459. ; Registers Destroyed:
  460. ; AX,DX,FLAGS
  461. ; History: glenn steffler 5/17/89
  462. ;-----------------------------------------------------------------------;
  463. FakeCOMInt proc near
  464. ; call DOCLI ;Done by caller
  465. ;
  466. ; WARNING: jumping into the middle of CommInt, so the stack must be set
  467. ; properly.
  468. ;
  469. push dx
  470. push bx
  471. push cx
  472. push di
  473. push es
  474. push EvtWord[si]
  475. ifdef NEC_98
  476. test [si.AOBA_flag],fFIFO_Mode ; (ins 94.04.16) |
  477. jz @F ;Now, 8251 mode (ins 94.04.16) |
  478. mov dx,Port[si] ;Get device I/O address (ins 94.04.16) |
  479. add dl, ACE_IIDR ; (ins 94.04.16) |
  480. push dx ; (ins 94.04.18) |
  481. jmp AOBA_FakeXmitEmpty ; (ins 94.04.18) |
  482. @@: ; (ins 94.04.16) |
  483. else ; NEC_98
  484. mov dx,Port[si] ;Get device I/O address
  485. add dl, ACE_IIDR
  486. endif ; NEC_98
  487. push dx
  488. jmp FakeXmitEmpty ;Process the fake interrupt, DS:SI is
  489. ; already pointing to proper DEB
  490. ;
  491. ; FakeXmitEmpty falls in XmitEmpty which jumps back into CommInt. When CommInt
  492. ; determines that no interrupt is pending, then it will near return back to
  493. ; FakeCOMIntFar which can far ret back to its caller.
  494. ;
  495. FakeCOMInt endp
  496. public FakeCOMIntFar
  497. FakeCOMIntFar proc far
  498. call FakeCOMInt
  499. ret
  500. FakeCOMIntFar endp
  501. ;--------------------------Interrupt Handler----------------------------
  502. ;
  503. ; CommInt - Interrupt handler for com ports
  504. ;
  505. ; Interrupt handlers for PC com ports. This is the communications
  506. ; interrupt service routine for RS232 communications. When an RS232
  507. ; event occurs the interrupt vectors here. This routine determines
  508. ; who the caller was and services the appropriate interrupt. The
  509. ; interrupts are prioritized in the following order:
  510. ;
  511. ; 1. line status interrupt
  512. ; 2. read data available interrupt
  513. ; 3. transmit buffer empty interrupt
  514. ; 4. modem service interrupt
  515. ;
  516. ; This routine continues to service until all interrupts have been
  517. ; satisfied.
  518. ;
  519. ; Entry:
  520. ; DS:SI --> DEB
  521. ; INTERRUPTS DISABLED!
  522. ; Returns:
  523. ; AL = 0, if not handled, -1, if handled
  524. ;
  525. ;-----------------------------------------------------------------------
  526. assumes ds,Data
  527. assumes es,nothing
  528. ; Dispatch table for interrupt types
  529. ifndef NEC_98
  530. SrvTab label word
  531. dw OFFSET ModemStatus ;[0] Modem Status Interrupt
  532. dw OFFSET XmitEmpty ;[2] Tx Holding Reg. Interrupt
  533. dw OFFSET DataAvail ;[4] Rx Data Available Interrupt
  534. ; or [C] if 16550 & 16550A
  535. dw OFFSET LineStat ;[6] Reciever Line Status Interrupt
  536. endif ; NEC_98
  537. public CommInt
  538. CommInt proc near
  539. xor al, al
  540. cmp word ptr [VCD_int_callback+4], 0
  541. je short @F ; jump if no callback (not 3.1 VCD)
  542. test [si.VCDflags], fCOM_ignore_ints ;Q: we still own port?
  543. ifdef NEC_98
  544. jz IntLoop45 ; [QN] (ins 92.09.xx)
  545. ret ; [QN] (ins 92.09.xx)
  546. IntLoop45: ; [QN] (ins 92.09.xx)
  547. else ; NEC_98
  548. jnz IntLoop40 ; N: ignore the int
  549. endif ; NEC_98
  550. .386
  551. push esi
  552. mov esi, [si.VCD_data]
  553. call [VCD_int_callback]
  554. pop esi
  555. .8086
  556. @@:
  557. push dx
  558. ifdef NEC_98
  559. mov dx,StatusPort[si] ; [QN] (ins 92.08.xx)
  560. in al, dx ; Get Status [QN] (ins 92.08.xx)
  561. test al,(TX_RDY+TX_EMP+RX_RDY); [QN] (ins 92.08.xx)
  562. jnz IntLoop_qn ; Yes [QN] (ins 93.03.17)
  563. or al, 1 ; No [QN] (ins 93.03.17)
  564. jmp short IntLoop30 ; [QN] (ins 93.03.17)
  565. IntLoop_qn: ; [QN] (ins 93.03.17)
  566. xor al, al ; [QN] (ins 93.03.17)
  567. else ; NEC_98
  568. mov dx,Port[si] ;Get comm I/O port
  569. add dl,ACE_IIDR ;--> Interrupt ID Register
  570. in al, dx
  571. test al, 1 ;Q: interrupt pending?
  572. jnz short IntLoop30 ; N:
  573. endif ; NEC_98
  574. push bx
  575. push cx
  576. push di
  577. push es
  578. mov cx, EvtWord[si]
  579. push cx
  580. jmp short IntLoop10
  581. InterruptLoop_ChkTx:
  582. cmp QOutCount[si],0 ;Output queue empty?
  583. je short InterruptLoop ; Y: don't chk tx
  584. ifdef NEC_98
  585. call KickTxINT ; (ins 92.09.xx)
  586. else ; NEC_98
  587. pop dx
  588. push dx
  589. dec dx ; to IER
  590. .errnz ACE_IIDR - ACE_IER - 1
  591. in al, dx
  592. and al,NOT ACE_ETBEI ; disable it
  593. iodelay
  594. out dx, al
  595. or al, ACE_ETBEI ; enable it again
  596. iodelay
  597. out dx, al
  598. iodelay
  599. out dx, al
  600. endif ; NEC_98
  601. InterruptLoop:
  602. ifdef NEC_98
  603. mov dx,StatusPort[si] ;Get ID reg I/O Address (ins 92.08.xx)
  604. ; (ins 92.08.xx)
  605. IntLoop10: ; (ins 92.08.xx)
  606. in al,dx ;Get Interrupt Id (ins 92.08.xx)
  607. test al,RX_RDY ; (ins 92.08.xx)
  608. jz Intloop15 ; (ins 92.08.xx)
  609. jmp DataAvail ;Receive Data (ins 92.08.xx)
  610. ; (ins 92.08.xx)
  611. IntLoop15: ; (ins 92.08.xx)
  612. test al,(TX_RDY) ; (ins 92.08.xx)
  613. jz IntLoop20 ; (ins 92.08.xx)
  614. jmp XmitEmpty ;Send Data (ins 92.08.xx)
  615. ; (ins 92.08.xx)
  616. ;Check whether tx queue (ins 92.08.xx)
  617. ; has data (ins 92.08.xx)
  618. IntLoop17: ; (ins 92.08.xx)
  619. mov dx,StatusPort[si] ;Get ID reg I/O Address (ins 92.08.xx)
  620. in al,dx ;Get Status (ins 92.08.xx)
  621. test al,RX_RDY ; (ins 92.08.xx)
  622. jz IntLoop20 ; (ins 92.08.xx)
  623. jmp short DataAvail ;Receive Data (ins 92.08.xx)
  624. else ; NEC_98
  625. pop dx ;Get ID reg I/O address
  626. in al,dx ;Get Interrupt Id
  627. test al,1 ;Interrupt need servicing?
  628. jnz IntLoop20 ;No, all done
  629. IntLoop10:
  630. and ax, 07h
  631. mov di,ax
  632. push dx ;Save Id register
  633. jmp SrvTab[di] ;Service the Interrupt
  634. endif ; NEC_98
  635. IntLoop20:
  636. mov ax,EvtMask[si] ;Mask the event word to only the
  637. and ax, EvtWord[si] ; user specified bits
  638. mov EvtWord[si], ax
  639. pop bx
  640. test [si.NotifyFlagsHI], CN_Notify
  641. jz short ci_exit
  642. not bx
  643. and ax, bx ; bits set in ax are new events
  644. jnz short ci_new_events
  645. ci_exit:
  646. pop es
  647. assumes es,nothing
  648. pop di
  649. pop cx
  650. pop bx
  651. xor al, al
  652. IntLoop30:
  653. pop dx
  654. and al, 1
  655. dec al ; 0->-1, 1->0
  656. IntLoop40:
  657. ret
  658. ci_new_events:
  659. mov ax, CN_EVENT
  660. call notify_owner
  661. jmp ci_exit
  662. CommInt endp
  663. page
  664. ;----------------------------Private-Routine----------------------------;
  665. ;
  666. ; LineStat - Line Status Interrupt Handler
  667. ;
  668. ; Break detection is handled and set in the event word if
  669. ; enabled. Other errors (overrun, parity, framing) are
  670. ; saved for the data available interrupt.
  671. ;
  672. ; This routine used to fall into DataAvail for the bulk of its processing.
  673. ; This is no longer the case... A very popular internal modem seems to
  674. ; operate differently than a real 8250 when parity errors occur. Falling
  675. ; into the DataAvail handler on a parity error caused the same character
  676. ; to be received twice. Having this routine save the LSR status, and
  677. ; return to InterruptLoop fixes the problem, and still works on real COMM
  678. ; ports. The extra overhead isn't a big deal since this routine is only
  679. ; entered when there is an exception like a parity error.
  680. ;
  681. ; This routine is jumped to, and will perform a jump back into
  682. ; the dispatch loop.
  683. ;
  684. ; Entry:
  685. ; DS:SI --> DEB
  686. ; DX = Port.IIDR
  687. ; Returns:
  688. ; None
  689. ; Error Returns:
  690. ; None
  691. ; Registers Destroyed:
  692. ; AX,FLAGS
  693. ; History:
  694. ;-----------------------------------------------------------------------;
  695. ; assumes ds,Data
  696. assumes es,nothing
  697. public LineStat ;Public for debugging
  698. LineStat proc near
  699. ifdef NEC_98
  700. ;=======================================================================[QN]|
  701. ; [QN]|
  702. ; Read Line Status [QN]|
  703. ; [QN]|
  704. ; <Entry> [QN]|
  705. ; none [QN]|
  706. ; [QN]|
  707. ; <Exit> [QN]|
  708. ; [AL]= Line Status [QN]|
  709. ; [QN]|
  710. ; <Modified> [QN]|
  711. ; AL Registor [QN]|
  712. ; [QN]|
  713. ; < Status Format > 8251 USART [QN]|
  714. ; Bit (7) (6) (5) (4) (3) (2) (1) (0) [QN]|
  715. ; none [bd] [fe] [oe] [pe] none none none ---------+ [QN]|
  716. ; I [QN]|
  717. ; < Status Format > 8250 USART MS-Windows format I [QN]|
  718. ; Bit (7) (6) (5) (4) (3) (2) (1) (0) I [QN]|
  719. ; none none none [bd] [fe] [pe] [oe] none <--------+ [QN]|
  720. ; [QN]|
  721. ;=======================================================================[QN]|
  722. push dx ; [QN]|
  723. push bx ; [QN]|
  724. push ax ; [QN]|
  725. mov dx,StatusPort[si] ; [QN]|
  726. in al,dx ; [QN]|
  727. and al,01111000b ; [QN]|
  728. test al,00111000B ; Error ? [QN]|
  729. jz LINE_SR_10 ; NO ! -> Reset Error [QN]|
  730. push ax ; [QN]|
  731. test al,01000000b ; [QN]|
  732. jz LINE_SR_EV_Err ; [QN]|
  733. or by EvtWord[si],EV_Break ;Show break [QN]|
  734. LINE_SR_EV_Err: ; [QN]|
  735. or by EvtWord[si],EV_Err ;Line Status Error [QN]|
  736. ; [QN]|
  737. ; AH AL BH [QN]|
  738. mov al,CommandShadow[si] ;******** 0bfop000 ******** [QN]|
  739. or al,ERR_RESET ;******** 0bf1p000 ******** [QN]|
  740. out dx,al ; Reset ! [QN]|
  741. pop ax ; [QN]|
  742. LINE_SR_10: ;Adjust Bit Arrange to [QN]|
  743. ; MS-Windows Format (bit4-1) [QN]|
  744. shr al,1 ;******** 00bf1p00 ******** [QN]|
  745. shr al,1 ;******** 000bf1p0 ******** [QN]|
  746. mov ah,al ;000bf1p0 000bf1p0 ******** [QN]|
  747. mov bh,al ;000bf1p0 000bf1p0 000bf1p0 [QN]|
  748. ;Clear Bit 2,1 [QN]|
  749. and al,11111001B ;000bf1p0 000bf1p0 000bf1p0 [QN]|
  750. ;Save (PE)Bit [QN]|
  751. and ah,00000010B ;000000p0 000bf1p0 000bf1p0 [QN]|
  752. ;Save (OE)Bit [QN]|
  753. and bh,00000100B ;000000p0 000bf1p0 00000100 [QN]|
  754. shl ah,1 ;0000000p 000bf1p0 00000100 [QN]|
  755. shr bh,1 ;0000000p 000bf1p0 00000010 [QN]|
  756. ;Reshuffle (PE) and (OE) bit [QN]|
  757. or ah,bh ;0000001p 000bf1p0 00000010 [QN]|
  758. ;Save Bit 2,1 [QN]|
  759. or al,ah ;0000001p 000bf11p 00000010 [QN]|
  760. mov dl,al ; [QN]|
  761. pop ax ; [QN]|
  762. mov al,dl ; [QN]|
  763. pop bx ; [QN]|
  764. pop dx ; [QN]|
  765. test al,ACE_PE+ACE_FE+ACE_OR ;Parity, Framing, Overrun error?
  766. jz @f
  767. mov LSRShadow[si],al ;yes, save status for DataAvail
  768. @@:
  769. ret ; qnes 92.10.06
  770. else ; NEC_98
  771. or by EvtWord[si],EV_Err ;Show line status error
  772. add dl,ACE_LSR-ACE_IIDR ;--> Line Status Register
  773. in al,dx
  774. test al,ACE_PE+ACE_FE+ACE_OR ;Parity, Framing, Overrun error?
  775. jz @f
  776. mov LSRShadow[si],al ;yes, save status for DataAvail
  777. @@:
  778. test al,ACE_BI ;Break detect?
  779. jz InterruptLoop_ChkTx ;Not break detect interrupt
  780. or by EvtWord[si],EV_Break ;Show break
  781. jmp short InterruptLoop_ChkTx
  782. endif ; NEC_98
  783. LineStat endp
  784. page
  785. ;----------------------------Private-Routine----------------------------;
  786. ;
  787. ; DataAvail - Data Available Interrupt Handler
  788. ;
  789. ; The available character is read and stored in the input queue.
  790. ; If the queue has reached the point that a handshake is needed,
  791. ; one is issued (if enabled). EOF detection, Line Status errors,
  792. ; and lots of other stuff is checked.
  793. ;
  794. ; This routine is jumped to, and will perform a jump back into
  795. ; the dispatch loop.
  796. ;
  797. ; Entry:
  798. ; DS:SI --> DEB
  799. ; DX = Port.IIDR
  800. ; Returns:
  801. ; None
  802. ; Error Returns:
  803. ; None
  804. ; Registers Destroyed:
  805. ; AX,BX,CX,DI,ES,FLAGS
  806. ; History:
  807. ;-----------------------------------------------------------------------;
  808. ; assumes ds,Data
  809. assumes es,nothing
  810. public DataAvail ;public for debugging
  811. DataAvail proc near
  812. ifdef NEC_98
  813. ;---------------------------------------------------------------;(ins 92.08.24)
  814. ; LineStat......Read Line Status ;(ins 92.08.24)
  815. ; return = AL (Line Status) ;(ins 92.08.24)
  816. ;---------------------------------------------------------------;(ins 92.08.24)
  817. ;(ins 92.08.24)
  818. call LineStat ;Read 8251 Line Status ;(ins 92.08.24)
  819. mov dx, DataPort[si] ;Store Read Data Port ;(ins 92.08.24)
  820. in al, dx ;Receive Data ;(ins 92.08.24)
  821. NEWIODELAY 14 ;<OUT 5F,AL> ;(ins 93.10.27)
  822. else ; NEC_98
  823. sub dl,ACE_IIDR-ACE_RBR ;--> receiver buffer register
  824. in al,dx ;Read received character
  825. endif ; NEC_98
  826. and [si.NotifyFlagsHI], NOT CN_Idle ; flag as not idle
  827. mov ah,LSRShadow[si] ;what did the last Line Status intrpt
  828. mov bh,ah ; have to say?
  829. or ah,ah
  830. jz @f
  831. and ah,ErrorMask[si] ;there was an error, record it
  832. or by ComErr[si],ah
  833. IFNDEF KKBUGFIX ; 1/05/93:TakuA:Fix #1666
  834. mov LSRShadow[si],0
  835. ENDIF
  836. ifndef NEC_98
  837. .errnz ACE_OR-CE_OVERRUN ;Must be the same bits
  838. .errnz ACE_PE-CE_RXPARITY
  839. .errnz ACE_FE-CE_FRAME
  840. .errnz ACE_BI-CE_BREAK
  841. endif ; NEC_98
  842. @@:
  843. ; Regardless of the character received, flag the event in case
  844. ; the user wants to see it.
  845. or by EvtWord[si],EV_RxChar ;Show a character received
  846. .errnz HIGH EV_RxChar
  847. ; Check the input queue, and see if there is room for another
  848. ; character. If not, or if the end of file character has already
  849. ; been received, then go declare overflow.
  850. DataAvail00:
  851. IFDEF KKBUGFIX ; 1/05/93:TakuA:Fix #1666
  852. mov bh,LSRShadow[si]
  853. mov LSRShadow[si],0
  854. ENDIF
  855. mov cx,QInCount[si] ;Get queue count (used later too)
  856. cmp cx,QInSize[si] ;Is queue full?
  857. jge DataAvail20 ; Yes, comm overrun
  858. test EFlags[si],fEOF ;Has end of file been received?
  859. jnz DataAvail20 ; Yes - treat as overflow
  860. ; Test to see if there was a parity error, and replace
  861. ; the character with the parity character if so
  862. test bh,ACE_PE ;Parity error
  863. jz DataAvail25 ; No
  864. test [si.DCB_Flags2],fPErrChar ;Parity error replacement character?
  865. jz DataAvail25 ; No
  866. mov al,[si.DCB_PEChar] ; Yes, get parity replacement char
  867. ; Skip all other processing except event checking and the queing
  868. ; of the parity error replacement character
  869. jmp short DataAvail80 ;Skip all but event check, queing
  870. DataAvail20:
  871. or by ComErr[si],CE_RXOVER ;Show queue overrun
  872. jmp short DataAvail50
  873. ; See if we need to strip null characters, and skip
  874. ; queueing if this is one. Also remove any parity bits.
  875. DataAvail25:
  876. and al,RxMask[si] ;Remove any parity bits
  877. jnz DataAvail30 ;Not a Null character
  878. test [si.DCB_Flags2],fNullStrip ;Are we stripping received nulls?
  879. jnz DataAvail50 ; Yes, put char in the bit bucket
  880. ; Check to see if we need to check for EOF characters, and if so
  881. ; see if this character is it.
  882. DataAvail30:
  883. test [si.DCB_Flags],fBinary ;Is this binary stuff?
  884. jnz DataAvail60 ; Yes, skip EOF check
  885. cmp al,[si.DCB_EOFChar] ;Is this the EOF character?
  886. jnz DataAvail60 ; No, see about queing the charcter
  887. or EFlags[si],fEOF ;Set end of file flag
  888. DataAvail50:
  889. jmp DataAvail140 ;Skip the queing process
  890. ; If output XOn/XOff is enabled, see if the character just received
  891. ; is either an XOn or XOff character. If it is, then set or
  892. ; clear the XOffReceived flag as appropriate.
  893. DataAvail60:
  894. test [si.DCB_Flags2],fOutX ;Output handshaking?
  895. jz DataAvail80 ; No
  896. cmp al,[si.DCB_XoffChar] ;Is this an X-Off character?
  897. jnz DataAvail70 ; No, see about XOn or Ack
  898. or HSFlag[si],XOffReceived ;Show XOff received, ENQ or ETX [rkh]
  899. test [si.DCB_Flags],fEnqAck+fEtxAck ;Enq or Etx Ack?
  900. jz DataAvail50 ; No
  901. cmp cx,[si.DCB_XonLim] ;See if at XOn limit
  902. ja DataAvail50 ; No
  903. and HSFlag[si],NOT XOffReceived ;Show ENQ or ETX not received
  904. and HSFlag[si], NOT XOnPending+XOffSent
  905. mov al, [si.DCB_XonChar]
  906. call OutHandshakingChar
  907. jmp DataAvail50 ;Done
  908. DataAvail70:
  909. cmp al,[si.DCB_XonChar] ;Is this an XOn character?
  910. jnz DataAvail80 ; No, just a normal character
  911. and HSFlag[si],NOT XOffReceived
  912. test [si.DCB_Flags],fEnqAck+fEtxAck ;Enq or Etx Ack?
  913. jz DataAvail75 ; No - jump to FakeXmitEmpty to get
  914. ; transmitting going again
  915. and HSFlag[si],NOT EnqSent
  916. DataAvail75:
  917. jmp FakeXmitEmpty ;Restart transmit
  918. ; Now see if this is a character for which we need to set an event as
  919. ; having occured. If it is, then set the appropriate event flag
  920. DataAvail80:
  921. cmp al,[si.DCB_EVTChar] ;Is it the event generating character?
  922. jne DataAvail90 ; No
  923. or by EvtWord[si],EV_RxFlag ;Show received specific character
  924. ; Finally, a valid character that we want to keep, and we have
  925. ; room in the queue. Place the character in the queue.
  926. ; If the discard flag is set, then discard the character
  927. DataAvail90:
  928. test MiscFlags[si], Discard ;Discarding characters ?
  929. jnz DataAvail50 ; Yes
  930. lea bx, [si+SIZE ComDEB] ; DS:BX -> BIS
  931. mov bx, [bx.BIS_Mode] ; mode will be either 0 or 4
  932. les di,QInAddr[si][bx] ;Get queue base pointer from either
  933. assumes es,nothing ; QInAddr or AltQInAddr
  934. mov bx,QInPut[si] ;Get index into queue
  935. mov es:[bx][di],al ;Store the character
  936. inc bx ;Update queue index
  937. cmp bx,QInSize[si] ;See if time for wrap-around
  938. jc DataAvail100 ;Not time to wrap
  939. xor bx,bx ;Wrap-around is a new zero pointer
  940. DataAvail100:
  941. mov QInPut[si],bx ;Store updated pointer
  942. inc cx ;And update queue population
  943. mov QInCount[si],cx
  944. ; If flow control has been enabled, see if we are within the
  945. ; limit that requires us to halt the host's transmissions
  946. cmp cx,XOffPoint[si] ;Time to see about XOff?
  947. jc DataAvail120 ; Not yet
  948. test HSFlag[si],HSSent ;Handshake already sent?
  949. jnz DataAvail120 ; Yes, don't send it again
  950. mov ah,HHSLines[si] ;Should hardware lines be dropped?
  951. or ah,ah ; (i.e. do we have HW HS enabled?)
  952. jz DataAvail110 ; No
  953. ifdef NEC_98
  954. mov al,CommandShadow[si] ;8251 Command get (ins 92.08.xx)
  955. test ah,ACE_DTR ;DTR handshake Enable ? (ins 92.08.xx)
  956. jz DataAvail101 ; No (ins 92.08.xx)
  957. and al,not DTR ;Clear 8251's DTR Line ! (ins 92.08.xx)
  958. DataAvail101: ; (ins 92.08.xx)
  959. test ah,ACE_RTS ;RTS handshake Enable ? (ins 92.08.xx)
  960. jz DataAvail102 ; No (ins 92.08.xx)
  961. and al,not RTS ;Clear 8251's RTS Line ! (ins 92.08.xx)
  962. DataAvail102: ; (ins 92.08.xx)
  963. mov dx,CommandPort[si] ;GET Command port address (ins 92.08.xx)
  964. out dx,al ; (ins 92.08.xx)
  965. mov CommandShadow[si],al ;Get Back 8251 Command (ins 92.08.xx)
  966. or HSFlag[si],HHSDropped ; and remember they were dropped(ins 92.08.xx)
  967. else ; NEC_98
  968. add dl,ACE_MCR ; Yes
  969. in al,dx ;Clear the necessary bits
  970. not ah
  971. and al,ah
  972. or HSFlag[si],HHSDropped ;Show lines have been dropped
  973. out dx,al ; and drop the lines
  974. sub dl,ACE_MCR
  975. endif ; NEC_98
  976. DataAvail110:
  977. test [si.DCB_Flags2],fInX ;Input Xon/XOff handshaking
  978. jz DataAvail120 ; No
  979. or HSFlag[si], XOffSent
  980. mov al, [si.DCB_XoffChar]
  981. call OutHandshakingChar
  982. DataAvail120:
  983. cmp cx, [si.RecvTrigger] ;Q: time to call owner's callback?
  984. jb short DataAvail130 ; N:
  985. test [si.NotifyFlagsHI], CN_RECEIVE
  986. jnz short DataAvail140 ; jump if notify already sent and
  987. ; data in buffer hasn't dropped
  988. ; below threshold
  989. mov ax, IntCodeOFFSET DataAvail140
  990. push ax
  991. mov ax, CN_RECEIVE
  992. %OUT probably should just set a flag and notify after EOI
  993. jmp notify_owner
  994. DataAvail130:
  995. and [si.NotifyFlagsHI], NOT CN_RECEIVE
  996. DataAvail140:
  997. ifdef NEC_98
  998. mov dx,StatusPort[si] ; [QN][BA] (ins 93.03.23)
  999. in al,dx ; [QN][BA] (ins 93.03.23)
  1000. test al,01000000b ; [QN][BA] (ins 93.03.23)
  1001. jz @f ; [QN][BA] (ins 93.03.23)
  1002. or by EvtWord[si],EV_Break ; [QN][BA] (ins 93.03.23)
  1003. @@: ; [QN][BA] (ins 93.03.23)
  1004. test [si.DCB_Flags],fBinary ;Is this binary stuff? <add 92.10.13>|
  1005. jnz DataAvail140_Binary ; Yes <add 93.03.23>|
  1006. mov dx,StatusPort[si] ;Get ID reg I/O Address (ins 92.08.xx)
  1007. in al,dx ;Get Interrupt Id (ins 92.08.xx)
  1008. test al,RX_RDY ;Is this RX_ready ? (ins 92.08.xx)
  1009. jz @F ; No (ins 92.08.xx)
  1010. mov dx, DataPort[si] ;Store Read Data Port (ins 92.08.xx)
  1011. in al, dx ;Receive Data (ins 92.08.xx)
  1012. NEWIODELAY 14 ;<OUT 5F,AL> (ins 93.10.27)
  1013. jmp DataAvail00
  1014. @@:
  1015. jmp InterruptLoop ;;;92.10.05
  1016. DataAvail140_Binary: ;Receive Binary <add 92.10.13>|
  1017. push cx ; <add 92.10.13>|
  1018. mov cx, [RECLoopCounter] ; [QN][BA](ins 93.03.30)
  1019. RetryReadData2: ; <add 92.10.13>|
  1020. mov dx,StatusPort[si] ;Get ID reg I/O address <add 92.10.13>|
  1021. in al,dx ;Get Interrupt Id <add 92.10.13>|
  1022. test al,RX_RDY ;Is this RX_ready ? <add 92.10.13>|
  1023. jz @F ; No <add 92.10.13>|
  1024. pop cx ; <add 92.10.13>|
  1025. mov dx, DataPort[si] ; Store Read Data Port <add 92.10.13>|
  1026. in al, dx ;Receive Data <add 92.10.13>|
  1027. NEWIODELAY 14 ;<OUT 5F,AL> (ins 93.10.27)
  1028. jmp DataAvail00 ; <add 92.10.13>|
  1029. @@: ; <add 92.10.13>|
  1030. loop RetryReadData2 ; <add 92.10.13>|
  1031. pop cx ; <add 92.10.13>|
  1032. jmp InterruptLoop ; <add 92.10.13>|
  1033. else ; NEC_98
  1034. pop dx
  1035. push dx
  1036. add dl, ACE_LSR-ACE_IIDR
  1037. in al, dx
  1038. test al, ACE_DR ;Q: more data available?
  1039. jz @F ; N:
  1040. sub dl, ACE_LSR ; Y: go read it
  1041. in al, dx ;Read available character
  1042. jmp DataAvail00
  1043. @@:
  1044. jmp InterruptLoop_ChkTx
  1045. endif ; NEC_98
  1046. DataAvail endp
  1047. OutHandshakingChar proc near
  1048. ifdef NEC_98
  1049. mov dx,StatusPort[si] ;Get ID reg I/O Address (ins 92.08.xx)|
  1050. mov ah, al ; (ins 92.08.xx)|
  1051. @@: ; (ins 92.08.xx)|
  1052. in al, dx ; (ins 92.08.xx)|
  1053. test al,(TX_RDY+TX_EMP) ;Is this TX_empty ? (ins 92.08.xx)|
  1054. jz @B ; (ins 92.08.xx)|
  1055. mov dx,DataPort[si] ; (ins 92.09.24)|
  1056. else ; NEC_98
  1057. add dl, ACE_LSR
  1058. mov ah, al
  1059. @@:
  1060. in al, dx
  1061. test al, ACE_THRE
  1062. jz @B
  1063. sub dl, ACE_LSR
  1064. endif ; NEC_98
  1065. mov al, ah
  1066. out dx, al
  1067. ret
  1068. OutHandshakingChar endp
  1069. page
  1070. ;----------------------------Private-Routine----------------------------;
  1071. ;
  1072. ; XmitEmpty - Transmitter Register Empty
  1073. ;
  1074. ; Entry:
  1075. ; DS:SI --> DEB
  1076. ; DX = Port.IIDR
  1077. ; Returns:
  1078. ; None
  1079. ; Error Returns:
  1080. ; None
  1081. ; Registers Destroyed:
  1082. ; AX,BX,CX,DI,ES,FLAGS
  1083. ; History:
  1084. ;-----------------------------------------------------------------------;
  1085. ; assumes ds,Data
  1086. assumes es,nothing
  1087. public FakeXmitEmpty
  1088. FakeXmitEmpty:
  1089. pop dx
  1090. push dx
  1091. ; "Kick" the transmitter interrupt routine into operation.
  1092. ifdef NEC_98
  1093. call KickTxINT ; (ins 92.09.xx)
  1094. mov dx,StatusPort[si] ;Get Status Port (ins 92.08.xx)
  1095. mov ah, al ; (ins 92.08.xx)
  1096. in al, dx ; (ins 92.08.xx)
  1097. test al,(TX_RDY+TX_EMP) ;Is this TX_ready ? (ins 92.08.xx)
  1098. else ; NEC_98
  1099. dec dl
  1100. .errnz ACE_IIDR - ACE_IER-1
  1101. in al,dx ;Get current IER state
  1102. test al,ACE_ETBEI ;Interrupt already enabled?
  1103. jnz @F ; Yes, don't reenable it
  1104. or al,ACE_ETBEI ; No, enable it
  1105. out dx,al
  1106. iodelay ;8250, 8250-B bug requires
  1107. out dx,al ; writting register twice
  1108. @@:
  1109. add dl,ACE_LSR-ACE_IER ;--> Line Status Register
  1110. iodelay
  1111. in al,dx ;Is xmit really empty?
  1112. sub dl,ACE_LSR-ACE_THR ;--> Transmitter Holding Register
  1113. test al,ACE_THRE
  1114. endif ; NEC_98
  1115. jnz short XmitEmpty5 ; Y: send next char
  1116. jmp InterruptLoop ; N: return to processing loop
  1117. public XmitEmpty
  1118. XmitEmpty proc near
  1119. ifdef NEC_98
  1120. call MSR_READ ; (ins 92.09.xx)
  1121. mov dx,StatusPort[si] ;Get ID reg I/O Address (ins 92.08.xx)
  1122. in al, dx ; (ins 92.08.xx)
  1123. test al,(TX_EMP+TX_RDY) ;Is this TX_empty ? (ins 92.08.xx)
  1124. else ; NEC_98
  1125. add dl,ACE_LSR-ACE_IIDR ;--> Line Status Register
  1126. in al,dx ;Is xmit really empty?
  1127. sub dl,ACE_LSR-ACE_THR ;--> Transmitter Holding Register
  1128. test al,ACE_THRE
  1129. endif ; NEC_98
  1130. jz Xmit_jumpto90 ;Transmitter not empty, cannot send
  1131. ; If the hardware handshake lines are down, then XOff/XOn cannot
  1132. ; be sent. If they are up and XOff/XOn has been received, still
  1133. ; allow us to transmit an XOff/XOn character. It will make
  1134. ; a dead lock situation less possible (even though there are
  1135. ; some which could happen that cannot be handled).
  1136. XmitEmpty5:
  1137. mov ah,HSFlag[si] ;Get handshaking flag
  1138. test ah,HHSDown+BreakSet ;Hardware lines down or break set?
  1139. jnz Xmit_jumpto100 ; Yes, cannot transmit
  1140. ; Give priority to any handshake character waiting to be
  1141. ; sent. If there are none, then check to see if there is
  1142. ; an "immediate" character to be sent. If not, try the queue.
  1143. XmitEmpty10:
  1144. test [si.DCB_Flags],fEnqAck+fEtxAck ;Enq or Etx Ack?
  1145. jnz XmitEmpty40 ; Yes
  1146. XmitEmpty15:
  1147. test ah,HSPending ;XOff or XOn pending
  1148. jz XmitEmpty40 ; No
  1149. XmitEmpty20:
  1150. and ah,NOT XOnPending+XOffSent
  1151. mov al,[si.DCB_XonChar] ;Get XOn character
  1152. XmitEmpty30:
  1153. mov HSFlag[si],ah ;Save updated handshake flag
  1154. ifdef NEC_98
  1155. mov dx,DataPort[si] ;(ins 92.09.24)
  1156. endif ; NEC_98
  1157. jmp XmitEmpty110 ;Go output the character
  1158. Xmit_jumpto90:
  1159. jmp XmitEmpty90
  1160. ; If any of the lines which were specified for a timeout are low, then
  1161. ; don't send any characters. Note that by putting the check here,
  1162. ; XOff and Xon can still be sent even though the lines might be low.
  1163. ; Also test to see if a software handshake was received. If so,
  1164. ; then transmission cannot continue. By delaying the software check
  1165. ; to here, XOn/XOff can still be issued even though the host told
  1166. ; us to stop transmission.
  1167. XmitEmpty40:
  1168. test ah,CannotXmit ;Anything preventing transmission?
  1169. jz XmitEmpty45 ; No
  1170. Xmit_jumpto100:
  1171. jmp XmitEmpty100 ; Yes, disarm and exit
  1172. ; If a character has been placed in the single character "transmit
  1173. ; immediately" buffer, clear that flag and pick up that character
  1174. ; without affecting the transmitt queue.
  1175. XmitEmpty45:
  1176. test EFlags[si],fTxImmed ;Character to xmit immediately?
  1177. jz XmitEmpty515 ; No, try the queue
  1178. and EFlags[si],NOT fTxImmed ;Clear xmit immediate flag
  1179. mov al,ImmedChar[si] ;Get char to xmit
  1180. ifdef NEC_98
  1181. mov dx,DataPort[si] ;(ins 92.09.xx)
  1182. endif ; NEC_98
  1183. jmp XmitEmpty110 ;Transmit the character
  1184. XmitEmpty515:
  1185. mov cx,QOutCount[si] ;Output queue empty?
  1186. jcxz Xmit_jumpto90 ; Yes, go set an event
  1187. test [si.DCB_Flags],fEtxAck ;Etx Ack?
  1188. jz XmitEmpty55 ; No
  1189. mov cx,QOutMod[si] ;Get number bytes sent since last ETX
  1190. cmp cx,[si.DCB_XonLim] ;At Etx limit yet?
  1191. jne XmitEmpty51 ; No, inc counter
  1192. mov QOutMod[si],0 ; Yes, zero counter
  1193. or HSFlag[si],EtxSent ;Show ETX sent
  1194. jmp short XE_sendXOFF
  1195. XmitEmpty51:
  1196. inc cx ; Update counter
  1197. mov QOutMod[si],cx ; Save counter
  1198. jmp short XmitEmpty59 ; Send queue character
  1199. XmitEmpty55:
  1200. test [si.DCB_Flags],fEnqAck ;Enq Ack?
  1201. jz XmitEmpty59 ; No, send queue character
  1202. mov cx,QOutMod[si] ;Get number bytes sent since last ENQ
  1203. or cx,cx ;At the front again?
  1204. jnz XmitEmpty56 ; No, inc counter
  1205. mov QOutMod[si],1 ; Yes, send ENQ
  1206. or HSFlag[si],EnqSent ;Show ENQ sent
  1207. XE_sendXOFF:
  1208. mov al,[si.DCB_XoffChar]
  1209. ifdef NEC_98
  1210. mov dx,DataPort[si] ;(ins 92.09.24)
  1211. endif ; NEC_98
  1212. jmp short XmitEmpty110 ;Go output the character
  1213. XmitEmpty56:
  1214. inc cx ;Update counter
  1215. cmp cx,[si.DCB_XonLim] ;At end of our out buffer len?
  1216. jne XmitEmpty58 ; No
  1217. xor cx,cx ;Show at front again.
  1218. XmitEmpty58:
  1219. mov QOutMod[si],cx ;Save counter
  1220. XmitEmpty59:
  1221. lea bx, [si+SIZE ComDEB] ; DS:BX -> BIS
  1222. mov bx, [bx.BIS_Mode] ; mode will be either 0 or 4
  1223. les di,QOutAddr[si][bx] ;Get queue base pointer from either
  1224. assumes es,nothing ; QOutAddr or AltQOutAddr
  1225. mov bx,QOutGet[si] ;Get pointer into queue
  1226. mov al,es:[bx][di] ;Get the character
  1227. inc bx ;Update queue pointer
  1228. cmp bx,QOutSize[si] ;See if time for wrap-around
  1229. jc XmitEmpty60 ;Not time for wrap
  1230. xor bx,bx ;Wrap by zeroing the index
  1231. XmitEmpty60:
  1232. mov QOutGet[si],bx ;Save queue index
  1233. mov cx,QOutCount[si] ;Output queue empty?
  1234. dec cx ;Dec # of bytes in queue
  1235. mov QOutCount[si],cx ; and save new population
  1236. ifdef NEC_98
  1237. mov dx,DataPort[si] ; (ins 92.08.xx)
  1238. endif ; NEC_98
  1239. out dx,al ;Send char
  1240. cmp cx, [si.SendTrigger] ;Q: time to call owner's callback?
  1241. jae short XmitEmpty70 ; N:
  1242. test [si.NotifyFlagsHI], CN_TRANSMIT
  1243. jnz short XmitEmpty80 ; jump if notify already sent and
  1244. ; data in buffer hasn't raised
  1245. ; above threshold
  1246. mov ax, IntCodeOFFSET XmitEmpty80
  1247. push ax
  1248. mov ax, CN_TRANSMIT
  1249. ifdef NEC_98
  1250. jmp notify_owner
  1251. else ; NEC_98
  1252. jmp short notify_owner
  1253. endif ; NEC_98
  1254. XmitEmpty70:
  1255. and [si.NotifyFlagsHI], NOT CN_TRANSMIT
  1256. XmitEmpty80:
  1257. %OUT check fNoFIFO in EFlags[si] to determine if we can queue more output
  1258. ifdef NEC_98
  1259. jmp IntLoop17 ;92.10.03
  1260. else ; NEC_98
  1261. jmp InterruptLoop
  1262. endif ; NEC_98
  1263. ; No more characters to transmit. Flag this as an event.
  1264. XmitEmpty90:
  1265. or by EvtWord[si],EV_TxEmpty
  1266. ; Cannot continue transmitting (for any of a number of reasons).
  1267. ; Disable the transmit interrupt. When it's time resume, the
  1268. ; transmit interrupt will be reenabled, which will generate an
  1269. ; interrupt.
  1270. XmitEmpty100:
  1271. ifdef NEC_98
  1272. cmp [si.DCB_id],ID_Com1 ;Is This Com1 ID ? (ins 92.08.xx)|
  1273. jne XmitEmpty102 ;No, go to KickTx5 (ins 92.08.xx)|
  1274. mov dx,MaskFFPort[si] ;F/F Port Mask Bit (ins 92.08.xx)|
  1275. in al,dx ; (ins 92.08.xx)|
  1276. mov MaskFFShadow[si],al ;Save the Old Mask bit (ins 92.08.xx)|
  1277. ; (ins 92.08.xx)|
  1278. XmitEmpty102: ; (ins 92.08.xx)|
  1279. mov al,MaskFFShadow[si] ;mask data(port C) save (ins 92.08.xx)|
  1280. test al,MSK_TXR ;Check a tx.RDY INT mask(ins 93.06.18)|
  1281. jz XmitEmpty105 ; disable (ins 92.08.xx)|
  1282. and al,NOT(MSK_TXE+MSK_TXR) ;= 11111001b (ins 92.08.xx)|
  1283. mov dx,MaskFFPort[si] ;Port address (Port C) (ins 92.08.xx)|
  1284. mov MaskFFShadow[si],al ;Masking data save (ins 92.08.xx)|
  1285. XmitEmpty110: ; (ins 92.08.xx)|
  1286. out dx,al ;Masking set (ins 92.08.xx)|
  1287. XmitEmpty105: ; (ins 92.08.xx)|
  1288. jmp IntLoop17 ; (ins 92.09.xx)|
  1289. else ; NEC_98
  1290. inc dx ;--> Interrupt Enable Register
  1291. .errnz ACE_IER-ACE_THR-1
  1292. in al,dx ;I don't know why it has to be read
  1293. and al,NOT ACE_ETBEI ; first, but it works this way
  1294. XmitEmpty110:
  1295. out dx,al
  1296. jmp InterruptLoop
  1297. endif ; NEC_98
  1298. XmitEmpty endp
  1299. page
  1300. ;----------------------------Private-Routine----------------------------;
  1301. ;
  1302. ; ModemStatus - Modem Status Interrupt Handler
  1303. ;
  1304. ; Entry:
  1305. ; DS:SI --> DEB
  1306. ; DX = Port.IIDR
  1307. ; Returns:
  1308. ; None
  1309. ; Error Returns:
  1310. ; None
  1311. ; Registers Destroyed:
  1312. ; AX,BX,CX,DI,ES,FLAGS
  1313. ; History:
  1314. ;-----------------------------------------------------------------------;
  1315. ; assumes ds,Data
  1316. assumes es,nothing
  1317. public ModemStatus ;Public for debugging
  1318. ModemStatus proc near
  1319. ; Get the modem status value and shadow it for MSRWait.
  1320. ifdef NEC_98
  1321. push ax ; [QN]|
  1322. push cx ; [QN]|
  1323. mov ch,al ;Save a local copy [QN]|
  1324. ; [QN]|
  1325. ; [Modem Status format (in AL and CH)] : [Assign of Event Word] [QN]|
  1326. ; +------------- DRLSD : EV_RLSD = 0000|0000 0010|0000b |
  1327. ; | +---------- TERI : EV_Ring = 0000|0001 0000|0000b |
  1328. ; | | +------- DDSR : EV_DSR = 0000|0000 0001|0000b |
  1329. ; | | | +---- DCTS : EV_CTS = 0000|0000 0000|1000b |
  1330. ; (*)(*)(*)(*)|(R)(E)(D)(C) : [QN]|
  1331. ; <ah> <al> <cl> [QN]|
  1332. mov ah,al ; ****|REDC ****|REDC ****|**** [QN]|
  1333. shr ax,1 ; 0***|*RED C***|*RED ****|**** [QN]|
  1334. shr ax,1 ; 00**|**RE DC**|**RE ****|**** [QN]|
  1335. ror al,1 ; 000*|**RE EDC*|***R ****|**** [QN]|
  1336. ror al,1 ; 000*|**RE REDC|**** ****|**** [QN]|
  1337. ror al,1 ; 000*|**RE *RED|C*** ****|**** [QN]|
  1338. mov cl,al ; *RED|C*** [QN]|
  1339. and ax, 0118h ; 0000|000E 000D|C000 [QN]|
  1340. and cl, 40h ; 0R00|0000 [QN]|
  1341. shr cl, 1 ; 00R0|0000 [QN]|
  1342. or al, cl ; 0000|000E 00RD|C000 [QN]|
  1343. ; [QN]|
  1344. and ax,EV_CTS+EV_DSR+EV_RLSD+EV_Ring ; [QN]|
  1345. ; 0000|000E 00RD|C000 [QN]|
  1346. or EvtWord[si],ax ; [QN]|
  1347. ; [QN]|
  1348. ; [Modem Status format (in CH)] : [Assign of Event Word] [QN]|
  1349. ; +------------------------- RLSD : EV_RLSDS = 0001|0000 0000|0000b |
  1350. ; | +---------------------- RI : EV_RingTe = 0010|0000 0000|0000b |
  1351. ; | | +------------------- DSR : EV_DSRS = 0000|1000 0000|0000b |
  1352. ; | | | +---------------- CTS : EV_CTSS = 0000|0100 0000|0000b |
  1353. ; (R)(I)(D)(C)|(*)(*)(*)(*) [QN]|
  1354. ; ; <ah> <al> <cl> [QN]|
  1355. mov ah,ch ; RIDC|**** ****|**** RIDC|**** [QN]|
  1356. shr ah,1 ; 0RID|C*** ****|**** RIDC|**** [QN]|
  1357. shr ah,1 ; 00RI|DC** ****|**** RIDC|**** [QN]|
  1358. and ax,EV_CTSS+EV_DSRS ; 0000|DC00 0000|0000 RIDC|**** [QN]|
  1359. or EvtWord[si],ax ; [QN]|
  1360. ; [QN]|
  1361. mov ah,ch ; RIDC|**** ****|**** RIDC|**** [QN]|
  1362. mov cl,3 ; [QN]|
  1363. shr ah,cl ; 000R|IDC* ****|**** RIDC|**** [QN]|
  1364. and ax,EV_RLSDS ; 000R|0000 0000|0000 RIDC|**** [QN]|
  1365. or EvtWord[si],ax ; [QN]|
  1366. ; [QN]|
  1367. mov ah,ch ; RIDC|**** ****|**** RIDC|**** [QN]|
  1368. shr ah, 1 ; 0RID|C*** ****|**** RIDC|**** [QN]|
  1369. and ax,EV_RingTe ; 00I0|0000 0000|0000 RIDC|**** [QN]|
  1370. or EvtWord[si],ax ; [QN]|
  1371. ; [QN]|
  1372. ModemStatus10: ; [QN]|
  1373. mov al,OutHHSLines[si] ; [QN]|
  1374. or al,al ; [QN]|
  1375. jz ModemStatus30 ;No H/W handshake on output [QN]|
  1376. and ch,al ; [QN]|
  1377. cmp ch,al ;Lines set for Xmit? [QN]|
  1378. je ModemStatus20 ; Yes [QN]|
  1379. or HSFlag[si],HHSDown ;Show H/W lines have dropped [QN]|
  1380. jmp short ModemStatus30 ; [QN]|
  1381. ; [QN]|
  1382. ModemStatus20: ; [QN]|
  1383. and HSFlag[si],NOT HHSDown ; [QN]|
  1384. call KickTxINT ; (ins 92.09.xx) [QN]|
  1385. ; [QN]|
  1386. ModemStatus30: ; [QN]|
  1387. mov ax,EvtMask[si] ;Mask event signal [QN]|
  1388. and EvtWord[si],ax ; that user need [QN]|
  1389. ; [QN]|
  1390. pop cx ; [QN]|
  1391. pop ax ; [QN]|
  1392. ret ; (ins 92.09.xx) [QN]|
  1393. else ; NEC_98
  1394. add dl,ACE_MSR-ACE_IIDR ;--> Modem Status Register
  1395. in al,dx
  1396. mov MSRShadow[si],al ;Save MSR data for others
  1397. mov ch,al ;Save a local copy
  1398. ; Create the event mask for the delta signals
  1399. mov ah,al ;Just a lot of shifting
  1400. shr ax,1
  1401. shr ax,1
  1402. shr ah,1
  1403. mov cl,3
  1404. shr ax,cl
  1405. and ax,EV_CTS+EV_DSR+EV_RLSD+EV_Ring
  1406. or EvtWord[si],ax
  1407. mov ah,ch ;[rkh]...
  1408. shr ah,1
  1409. shr ah,1
  1410. and ax,EV_CTSS+EV_DSRS
  1411. or EvtWord[si],ax
  1412. mov ah,ch
  1413. mov cl,3
  1414. shr ah,cl
  1415. and ax,EV_RLSD
  1416. or EvtWord[si],ax
  1417. mov ah,ch
  1418. mov cl,3
  1419. shl ah,cl
  1420. and ax,EV_RingTe
  1421. or EvtWord[si],ax
  1422. .errnz EV_CTS-0000000000001000b
  1423. .errnz EV_DSR-0000000000010000b
  1424. .errnz EV_RLSD-0000000000100000b
  1425. .errnz EV_Ring-0000000100000000b
  1426. .errnz EV_CTSS-0000010000000000b ;[rkh]
  1427. .errnz EV_DSRS-0000100000000000b
  1428. .errnz EV_RLSDS-0001000000000000b
  1429. .errnz EV_RingTe-0010000000000000b
  1430. .errnz ACE_DCTS-00000001b
  1431. .errnz ACE_DDSR-00000010b
  1432. .errnz ACE_DRLSD-00001000b
  1433. .errnz ACE_RI-01000000b
  1434. .errnz ACE_TERI-00000100b ;[rkh]
  1435. .errnz ACE_CTS-00010000b
  1436. .errnz ACE_DSR-00100000b
  1437. .errnz ACE_RLSD-10000000b
  1438. ModemStatus10:
  1439. mov al,OutHHSLines[si] ;Get output hardware handshake lines
  1440. or al,al ;Any lines that must be set?
  1441. jz ModemStatus40 ;No hardware handshake on output
  1442. and ch,al ;Mask bits of interest
  1443. cmp ch,al ;Lines set for Xmit?
  1444. je ModemStatus20 ; Yes
  1445. or HSFlag[si],HHSDown ;Show hardware lines have dropped
  1446. ModemStatus30:
  1447. jmp InterruptLoop
  1448. ModemStatus40:
  1449. jmp InterruptLoop_ChkTx
  1450. ; Lines are set for xmit. Kick an xmit interrupt if needed
  1451. ModemStatus20:
  1452. and HSFlag[si],NOT (HHSDown OR HHSAlwaysDown)
  1453. ;Show hardware lines back up
  1454. mov cx,QOutCount[si] ;Output queue empty?
  1455. jcxz ModemStatus30 ; Yes, return to InterruptLoop
  1456. jmp FakeXmitEmpty ;Restart transmit
  1457. endif ; NEC_98
  1458. ModemStatus endp
  1459. page
  1460. ;------------------------------------------------------------------------------
  1461. ;
  1462. ; ENTER: AX = message #
  1463. ; DS:SI -> DEB
  1464. notify_owner proc near
  1465. or [si.NotifyFlags], ax
  1466. lea di, [si+SIZE ComDEB]
  1467. mov ax, ds
  1468. mov es, ax
  1469. mov ax, BIH_API_Call_Back ; call immediate, or in protected mode
  1470. mov bx, 1 ; force SYS VM, if enhanced mode
  1471. mov cx, _INTERRUPT
  1472. mov dx, IntCodeOFFSET callback_event
  1473. %OUT use equate
  1474. push ds
  1475. push si
  1476. mov si, 1 ; low priority boost
  1477. push bp
  1478. mov bp, es:[di.BIS_Mode]
  1479. call es:[bp][di.BIS_User_Mode_API]
  1480. pop bp
  1481. pop si
  1482. pop ds
  1483. ret
  1484. notify_owner endp
  1485. ;------------------------------------------------------------------------------
  1486. ;
  1487. ; ENTER: ES:DI -> BIS
  1488. ;
  1489. callback_event proc far
  1490. lea si, [di-SIZE ComDEB]
  1491. mov ax, es
  1492. mov ds, ax
  1493. ifdef NEC_98
  1494. mov al, [si.NotifyFlagsLO] ;ins 94.12.02 KBNES
  1495. and al, al ;ins 94.12.02 KBNES
  1496. jnz @f ;ins 94.12.02 KBNES
  1497. ret ;ins 94.12.02 KBNES
  1498. @@: ;ins 94.12.02 KBNES
  1499. endif ; NEC_98
  1500. mov ax, [si.NotifyHandle]
  1501. push ax ; push hWnd
  1502. mov ax, WM_COMMNOTIFY
  1503. push ax ; push wMsg
  1504. xor ax, ax
  1505. mov al, [si.DCB_Id]
  1506. push ax ; push wParam = ComID
  1507. xor al, al
  1508. push ax ; push high word of lParam
  1509. xchg al, [si.NotifyFlagsLO]
  1510. or [si.NotifyFlagsHI], al
  1511. push ax ; push low word of lParam = event flags
  1512. call [lpPostMessage]
  1513. ret
  1514. callback_event endp
  1515. PUBLIC TimerProc
  1516. TimerProc proc far
  1517. push ds
  1518. mov ax, _DATA
  1519. mov ds, ax
  1520. assumes ds,data
  1521. mov ax, [activeCOMs]
  1522. or ax, ax
  1523. jz short tp_nonactive
  1524. push si
  1525. mov si, DataOFFSET COMptrs
  1526. mov cx, MAXCOM+1
  1527. tp_lp:
  1528. push si
  1529. mov si, [si] ; si -> ComDEB
  1530. shr ax, 1
  1531. jnc tp_lpend
  1532. cmp [si.RecvTrigger], -1 ;Q: owner wants notification?
  1533. je short tp_lpend ; N: skip notify
  1534. cmp [si.QInCount], 0 ;Q: anything in input queue?
  1535. je short tp_lpend ; N: skip notify
  1536. test [si.NotifyFlagsHI], CN_RECEIVE ;Q: timeout notify already given?
  1537. jnz short tp_lpend ; N: skip notify
  1538. xor [si.NotifyFlagsHI], CN_Idle ;Q: first timer call?
  1539. js short tp_lpend ; Y: skip notify
  1540. push ax
  1541. push cx
  1542. mov ax, CN_RECEIVE ; N: notify owner
  1543. call notify_owner
  1544. pop cx
  1545. pop ax
  1546. tp_lpend:
  1547. pop si
  1548. inc si ; inc to ptr to next ComDEB
  1549. inc si
  1550. or ax, ax
  1551. loopnz tp_lp
  1552. pop si
  1553. tp_nonactive:
  1554. pop ds
  1555. assumes ds,nothing
  1556. ret
  1557. TimerProc endp
  1558. page
  1559. ifdef NEC_98
  1560. ;===========================================================================
  1561. ; System Timer Interrupt Routine
  1562. ;
  1563. ; if ( QOutCount[si] != 0x0000 )
  1564. ; {
  1565. ; KickTx ();
  1566. ; }
  1567. ;===========================================================================
  1568. public TickEntry1 ;(ins 92.09.25)
  1569. public TickEntry2 ;(ins 92.09.25)
  1570. public TickEntry3 ;(ins 92.09.25)
  1571. TickEntry1 proc far ;for COM1
  1572. push si ;
  1573. push ds ;
  1574. push ax ;
  1575. mov si,dataOFFSET Comm1 ;
  1576. mov ax, _DATA ;
  1577. mov ds, ax
  1578. jmp short TickWork ;
  1579. ;
  1580. TickEntry2: ;for COM2
  1581. push si ;
  1582. push ds ;
  1583. push ax ;
  1584. mov si,dataOFFSET Comm2 ;
  1585. mov ax, _DATA ;
  1586. mov ds, ax
  1587. jmp short TickWork ;
  1588. ;
  1589. TickEntry3: ;for COM3
  1590. push si ;
  1591. push ds ;
  1592. push ax ;
  1593. mov si,dataOFFSET Comm3 ;
  1594. mov ax, _DATA ;
  1595. mov ds, ax
  1596. ;
  1597. public TickWork ;
  1598. TickWork: ;
  1599. cmp QOutCount[si],wo 00h ;Does queue empty ?
  1600. jz TickNoWork ; Yes : Goto Return
  1601. push dx ;
  1602. call KickTxINT ;
  1603. pop dx ;
  1604. TickNoWork: ;
  1605. pop ax ;
  1606. pop ds ;
  1607. pop si ;
  1608. ret ;
  1609. ;(ins end 92.09.25)
  1610. TickEntry1 endp
  1611. page
  1612. ;----------------------------Private-Routine----------------------------
  1613. ; MSR Read
  1614. ;-----------------------------------------------------------------------
  1615. public MSR_READ_Call ;(ins 92.08.xx)
  1616. MSR_READ_Call proc far ;(ins 92.08.xx)
  1617. call MSR_READ ;(ins 92.08.xx)
  1618. ret ;(ins 92.08.xx)
  1619. MSR_READ_Call endp ;(ins 92.08.xx)
  1620. MSR_READ PROC NEAR
  1621. push cx ;
  1622. push ax ;
  1623. mov dx,StatusPort[si] ; 8251 Status Port ( DSR )
  1624. in al,dx ; Read Status
  1625. mov ch,al ; save to CH
  1626. mov dx,ReadSigPort[si] ; MODEM Status Port (CS,CD,CI)
  1627. in al,dx ; Read Status
  1628. ;---------------------------------
  1629. ; CD='a' CI='b' DR='c' CS='d'
  1630. ; a,b,c,d = ( 0 or 1 )
  1631. mov ah,al ; [AH] I [AL] I [CH]
  1632. xor al,al ; bda????? 00000000 c???????
  1633. and ch,10000000b ; bda????? 00000000 c0000000
  1634. and ah,11100000b ; bda00000 00000000 c0000000
  1635. rol ah,1 ; da00000b 00000000 c0000000
  1636. rol ah,1 ; a00000bd 00000000 c0000000
  1637. shr ax,1 ; 0a00000b d0000000 c0000000
  1638. shr al,1 ; 0a00000b 0d000000 c0000000
  1639. or al,ch ; 0a00000b cd000000 c0000000
  1640. shr ax,1 ; 00a00000 bcd00000 c0000000
  1641. rol ah,1 ; 0a000000 bcd00000 c0000000
  1642. rol ah,1 ; a0000000 bcd00000 c0000000
  1643. rol ah,1 ; 0000000a bcd00000 c0000000
  1644. shr ax,1 ; 00000000 abcd0000 c0000000
  1645. ;
  1646. mov cl,al ; restore AL
  1647. pop ax ;
  1648. xor cl,11010000b ; Bit invert
  1649. mov ch,cl ; (CD,CS,CI is active Low )
  1650. and cl,0f0h ;
  1651. xor MSRShadow[si],cl ;
  1652. shr by MSRShadow[si],1 ;
  1653. shr by MSRShadow[si],1 ;
  1654. shr by MSRShadow[si],1 ;
  1655. shr by MSRShadow[si],1 ;
  1656. or MSRShadow[si],ch ;
  1657. mov al,MSRShadow[si] ;
  1658. pop cx ;
  1659. call ModemStatus ;Set Event Flag
  1660. ret
  1661. MSR_READ ENDP
  1662. ;------------------------------------------------------------------------------
  1663. ; AOBA-bug ins 94.11.19 KBNES
  1664. ;------------------------------------------------------------------------------
  1665. public AOBA_MSR_READ_Call
  1666. AOBA_MSR_READ_Call proc far
  1667. call AOBA_MSR_READ
  1668. ret
  1669. AOBA_MSR_READ_Call endp
  1670. AOBA_MSR_READ PROC NEAR
  1671. push ax
  1672. push dx
  1673. mov dx,Port[si] ;Get comm I/O port
  1674. add dl,ACE_MSR ;
  1675. in al,dx
  1676. mov MSRShadow[si],al ;Save MSR data for others
  1677. call ModemStatus ;Set Event Flag
  1678. pop dx ;
  1679. pop ax ;
  1680. ret
  1681. AOBA_MSR_READ ENDP
  1682. ;------------------------------------------------------------------------------
  1683. ; AOBA-bug ins end 94.11.19 KBNES
  1684. ;------------------------------------------------------------------------------
  1685. ;----------------------------Private-Routine----------------------------;
  1686. ;
  1687. ; KickTxINT - Kick Transmitter
  1688. ;
  1689. ; "Kick" the transmitter interrupt routine into operation.
  1690. ; If the Transmitter Holding Register isn't empty, then
  1691. ; nothing needs to be done. If it is empty, then the xmit
  1692. ; interrupt needs to enabled in the IER.
  1693. ;
  1694. ; Entry:
  1695. ; DS:SI --> DEB
  1696. ; INTERRUPTS DISABLED!
  1697. ; Returns:
  1698. ; None
  1699. ; Error Returns:
  1700. ; None
  1701. ; Registers Preserved:
  1702. ; BX,CX,SI,DI,DS,ES
  1703. ; Registers Destroyed:
  1704. ; AX,DX,FLAGS
  1705. ; History:
  1706. ;-----------------------------------------------------------------------;
  1707. assumes ds,Data
  1708. assumes es,nothing
  1709. public KickTxINT ;Public for debugging
  1710. KickTxINT proc near
  1711. cmp [si.DCB_id],ID_Com1 ;Is This Com1 ID ? (ins 92.08.xx)
  1712. jne KickTxINT5 ;No, go to KickTx5 (ins 92.08.xx)
  1713. mov dx,MaskFFPort[si] ;F/F Port Mask Bit (ins 92.08.xx)
  1714. in al,dx ; (ins 92.08.xx)
  1715. mov MaskFFShadow[si],al ;Save the Old Mask bit (ins 92.08.xx)
  1716. ; (ins 92.08.xx)
  1717. KickTxINT5: ; (ins 92.08.xx)
  1718. mov al,MaskFFShadow[si] ;mask data(port C) save (ins 92.08.xx)
  1719. test al,MSK_TXR ;(ins 93.06.18)
  1720. jnz KickTxINT10 ; Enable (ins 92.08.xx)
  1721. KickTxINT9:
  1722. or al,MSK_TXR+MSK_RXR ; (ins 93.06.18)
  1723. mov dx,MaskFFPort[si] ;Port address (Port C) (ins 92.08.xx)
  1724. mov MaskFFShadow[si],al ;Masking data save (ins 92.08.xx)
  1725. out dx,al ;Masking set (ins 92.08.xx)
  1726. ret ; (ins 92.08.xx)
  1727. KickTxINT10: ; (ins 92.08.xx)|
  1728. and al,NOT(MSK_TXR+MSK_RXR) ; (ins 93.06.18)
  1729. mov dx,MaskFFPort[si] ;Port address (Port C) (ins 93.03.22)
  1730. out dx,al ;Masking set (ins 93.03.22)
  1731. NEWIODELAY 1 ;<OUT 5F,AL> (ins 93.03.22)
  1732. jmp short KickTxINT9 ; (ins 93.03.22)
  1733. ; (ins 93.03.22)
  1734. KickTxINT endp
  1735. ;--------------------------Interrupt Handler----------------------------
  1736. ;
  1737. ; AOBA_CommInt - Interrupt handler for com ports
  1738. ;
  1739. ; Interrupt handlers for PC com ports. This is the communications
  1740. ; interrupt service routine for RS232 communications. When an RS232
  1741. ; event occurs the interrupt vectors here. This routine determines
  1742. ; who the caller was and services the appropriate interrupt. The
  1743. ; interrupts are prioritized in the following order:
  1744. ;
  1745. ; 1. line status interrupt
  1746. ; 2. read data available interrupt
  1747. ; 3. transmit buffer empty interrupt
  1748. ; 4. modem service interrupt
  1749. ;
  1750. ; This routine continues to service until all interrupts have been
  1751. ; satisfied.
  1752. ;
  1753. ; Entry:
  1754. ; DS:SI --> DEB
  1755. ; INTERRUPTS DISABLED!
  1756. ; Returns:
  1757. ; AL = 0, if not handled, -1, if handled
  1758. ;
  1759. ;-----------------------------------------------------------------------
  1760. assumes ds,Data
  1761. assumes es,nothing
  1762. ; Dispatch table for interrupt types
  1763. SrvTab label word
  1764. dw OFFSET AOBA_ModemStatus ;[0] Modem Status Interrupt
  1765. dw OFFSET AOBA_XmitEmpty ;[2] Tx Holding Reg. Interrupt
  1766. dw OFFSET AOBA_DataAvail ;[4] Rx Data Available Interrupt
  1767. ; or [C] if 16550 & 16550A
  1768. dw OFFSET AOBA_LineStat ;[6] Reciever Line Status Interrupt
  1769. public AOBA_CommInt
  1770. AOBA_CommInt proc near
  1771. xor al, al
  1772. cmp word ptr [VCD_int_callback+4], 0
  1773. je short @F ; jump if no callback (not 3.1 VCD)
  1774. test [si.VCDflags], fCOM_ignore_ints ;Q: we still own port?
  1775. jnz AOBA_IntLoop40 ; N: ignore the int
  1776. .386
  1777. push esi
  1778. mov esi, [si.VCD_data]
  1779. call [VCD_int_callback]
  1780. pop esi
  1781. .8086
  1782. @@:
  1783. push dx
  1784. mov dx,Port[si] ;Get comm I/O port
  1785. add dl,ACE_IIDR ;--> Interrupt ID Register
  1786. in al, dx
  1787. test al, 1 ;Q: interrupt pending?
  1788. jnz short AOBA_IntLoop30 ; N:
  1789. push bx
  1790. push cx
  1791. push di
  1792. push es
  1793. mov cx, EvtWord[si]
  1794. push cx
  1795. jmp short AOBA_IntLoop10
  1796. public AOBA_InterruptLoop_ChkTx
  1797. AOBA_InterruptLoop_ChkTx:
  1798. cmp QOutCount[si],0 ;Output queue empty?
  1799. je short AOBA_InterruptLoop ; Y: don't chk tx
  1800. call KickTxINT ; (ins 94.04.16)
  1801. public AOBA_InterruptLoop
  1802. AOBA_InterruptLoop:
  1803. pop dx ;Get ID reg I/O address
  1804. mov dx,Port[si] ;Get comm I/O port (ins 94.04.16)
  1805. add dl,ACE_IIDR ;--> Interrupt ID Register (ins 94.04.16)
  1806. in al,dx ;Get Interrupt Id
  1807. test al,1 ;Interrupt need servicing?
  1808. jnz AOBA_IntLoop20 ;No, all done
  1809. public AOBA_IntLoop10
  1810. AOBA_IntLoop10:
  1811. and ax, 07h
  1812. mov di,ax
  1813. push dx ;Save Id register
  1814. jmp SrvTab[di] ;Service the Interrupt
  1815. public AOBA_IntLoop20
  1816. AOBA_IntLoop20:
  1817. mov ax,EvtMask[si] ;Mask the event word to only the
  1818. and ax, EvtWord[si] ; user specified bits
  1819. mov EvtWord[si], ax
  1820. pop bx
  1821. test [si.NotifyFlagsHI], CN_Notify
  1822. jz short AOBA_ci_exit
  1823. not bx
  1824. and ax, bx ; bits set in ax are new events
  1825. jnz short AOBA_ci_new_events
  1826. public AOBA_ci_exit
  1827. AOBA_ci_exit:
  1828. pop es
  1829. assumes es,nothing
  1830. pop di
  1831. pop cx
  1832. pop bx
  1833. xor al, al
  1834. public AOBA_IntLoop30
  1835. AOBA_IntLoop30:
  1836. pop dx
  1837. and al, 1
  1838. dec al ; 0->-1, 1->0
  1839. public AOBA_IntLoop40
  1840. AOBA_IntLoop40:
  1841. ret
  1842. public AOBA_ci_new_events
  1843. AOBA_ci_new_events:
  1844. mov ax, CN_EVENT
  1845. call notify_owner
  1846. jmp AOBA_ci_exit
  1847. public AOBA_CommInt
  1848. AOBA_CommInt endp
  1849. page
  1850. ;----------------------------Private-Routine----------------------------;
  1851. ;
  1852. ; AOBA_LineStat - Line Status Interrupt Handler
  1853. ;
  1854. ; Break detection is handled and set in the event word if
  1855. ; enabled. Other errors (overrun, parity, framing) are
  1856. ; saved for the data available interrupt.
  1857. ;
  1858. ; This routine used to fall into DataAvail for the bulk of its processing.
  1859. ; This is no longer the case... A very popular internal modem seems to
  1860. ; operate differently than a real 8250 when parity errors occur. Falling
  1861. ; into the DataAvail handler on a parity error caused the same character
  1862. ; to be received twice. Having this routine save the LSR status, and
  1863. ; return to InterruptLoop fixes the problem, and still works on real COMM
  1864. ; ports. The extra overhead isn't a big deal since this routine is only
  1865. ; entered when there is an exception like a parity error.
  1866. ;
  1867. ; This routine is jumped to, and will perform a jump back into
  1868. ; the dispatch loop.
  1869. ;
  1870. ; Entry:
  1871. ; DS:SI --> DEB
  1872. ; DX = Port.IIDR
  1873. ; Returns:
  1874. ; None
  1875. ; Error Returns:
  1876. ; None
  1877. ; Registers Destroyed:
  1878. ; AX,FLAGS
  1879. ; History:
  1880. ;-----------------------------------------------------------------------;
  1881. ; assumes ds,Data
  1882. assumes es,nothing
  1883. public AOBA_LineStat ;Public for debugging
  1884. AOBA_LineStat proc near
  1885. or by EvtWord[si],EV_Err ;Show line status error
  1886. mov dx,Port[si] ;Get comm I/O port (ins 94.04.16)
  1887. add dl,ACE_LSR ;--> Line Status Register (ins 94.04.16)
  1888. in al,dx
  1889. test al,ACE_PE+ACE_FE+ACE_OR ;Parity, Framing, Overrun error?
  1890. jz @f
  1891. mov LSRShadow[si],al ;yes, save status for DataAvail
  1892. @@:
  1893. test al,ACE_BI ;Break detect?
  1894. jz AOBA_InterruptLoop_ChkTx ;Not break detect interrupt
  1895. or by EvtWord[si],EV_Break ;Show break
  1896. jmp short AOBA_InterruptLoop_ChkTx
  1897. AOBA_LineStat endp
  1898. page
  1899. ;----------------------------Private-Routine----------------------------;
  1900. ;
  1901. ; AOBA_DataAvail - Data Available Interrupt Handler
  1902. ;
  1903. ; The available character is read and stored in the input queue.
  1904. ; If the queue has reached the point that a handshake is needed,
  1905. ; one is issued (if enabled). EOF detection, Line Status errors,
  1906. ; and lots of other stuff is checked.
  1907. ;
  1908. ; This routine is jumped to, and will perform a jump back into
  1909. ; the dispatch loop.
  1910. ;
  1911. ; Entry:
  1912. ; DS:SI --> DEB
  1913. ; DX = Port.IIDR
  1914. ; Returns:
  1915. ; None
  1916. ; Error Returns:
  1917. ; None
  1918. ; Registers Destroyed:
  1919. ; AX,BX,CX,DI,ES,FLAGS
  1920. ; History:
  1921. ;-----------------------------------------------------------------------;
  1922. ; assumes ds,Data
  1923. assumes es,nothing
  1924. public AOBA_DataAvail ;public for debugging
  1925. AOBA_DataAvail proc near
  1926. mov dx,Port[si] ;Get comm I/O port (ins 94.04.16)
  1927. add dl,ACE_RBR ;--> receiver buffer register (ins 94.04.16)
  1928. in al,dx ;Read received character
  1929. and [si.NotifyFlagsHI], NOT CN_Idle ; flag as not idle
  1930. mov ah,LSRShadow[si] ;what did the last Line Status intrpt
  1931. mov bh,ah ; have to say?
  1932. or ah,ah
  1933. jz @f
  1934. and ah,ErrorMask[si] ;there was an error, record it
  1935. or by ComErr[si],ah
  1936. IFNDEF KKBUGFIX ; 1/05/93:TakuA:Fix #1666
  1937. mov LSRShadow[si],0
  1938. ENDIF
  1939. @@:
  1940. ; Regardless of the character received, flag the event in case
  1941. ; the user wants to see it.
  1942. or by EvtWord[si],EV_RxChar ;Show a character received
  1943. .errnz HIGH EV_RxChar
  1944. ; Check the input queue, and see if there is room for another
  1945. ; character. If not, or if the end of file character has already
  1946. ; been received, then go declare overflow.
  1947. public AOBA_DataAvail00
  1948. AOBA_DataAvail00:
  1949. IFDEF KKBUGFIX ; 1/05/93:TakuA:Fix #1666
  1950. mov bh,LSRShadow[si]
  1951. mov LSRShadow[si],0
  1952. ENDIF
  1953. mov cx,QInCount[si] ;Get queue count (used later too)
  1954. cmp cx,QInSize[si] ;Is queue full?
  1955. jge AOBA_DataAvail20 ; Yes, comm overrun
  1956. test EFlags[si],fEOF ;Has end of file been received?
  1957. jnz AOBA_DataAvail20 ; Yes - treat as overflow
  1958. ; Test to see if there was a parity error, and replace
  1959. ; the character with the parity character if so
  1960. test bh,ACE_PE ;Parity error
  1961. jz AOBA_DataAvail25 ; No
  1962. test [si.DCB_Flags2],fPErrChar ;Parity error replacement character?
  1963. jz AOBA_DataAvail25 ; No
  1964. mov al,[si.DCB_PEChar] ; Yes, get parity replacement char
  1965. ; Skip all other processing except event checking and the queing
  1966. ; of the parity error replacement character
  1967. jmp short AOBA_DataAvail80 ;Skip all but event check, queing
  1968. public AOBA_DataAvail20
  1969. AOBA_DataAvail20:
  1970. or by ComErr[si],CE_RXOVER ;Show queue overrun
  1971. jmp short AOBA_DataAvail50
  1972. ; See if we need to strip null characters, and skip
  1973. ; queueing if this is one. Also remove any parity bits.
  1974. public AOBA_DataAvail25
  1975. AOBA_DataAvail25:
  1976. and al,RxMask[si] ;Remove any parity bits
  1977. jnz AOBA_DataAvail30 ;Not a Null character
  1978. test [si.DCB_Flags2],fNullStrip ;Are we stripping received nulls?
  1979. jnz AOBA_DataAvail50 ; Yes, put char in the bit bucket
  1980. ; Check to see if we need to check for EOF characters, and if so
  1981. ; see if this character is it.
  1982. public AOBA_DataAvail30
  1983. AOBA_DataAvail30:
  1984. test [si.DCB_Flags],fBinary ;Is this binary stuff?
  1985. jnz AOBA_DataAvail60 ; Yes, skip EOF check
  1986. cmp al,[si.DCB_EOFChar] ;Is this the EOF character?
  1987. jnz AOBA_DataAvail60 ; No, see about queing the charcter
  1988. or EFlags[si],fEOF ;Set end of file flag
  1989. public AOBA_DataAvail50
  1990. AOBA_DataAvail50:
  1991. jmp AOBA_DataAvail140 ;Skip the queing process
  1992. ; If output XOn/XOff is enabled, see if the character just received
  1993. ; is either an XOn or XOff character. If it is, then set or
  1994. ; clear the XOffReceived flag as appropriate.
  1995. public AOBA_DataAvail60
  1996. AOBA_DataAvail60:
  1997. test [si.DCB_Flags2],fOutX ;Output handshaking?
  1998. jz AOBA_DataAvail80 ; No
  1999. cmp al,[si.DCB_XoffChar] ;Is this an X-Off character?
  2000. jnz AOBA_DataAvail70 ; No, see about XOn or Ack
  2001. or HSFlag[si],XOffReceived ;Show XOff received, ENQ or ETX [rkh]
  2002. test [si.DCB_Flags],fEnqAck+fEtxAck ;Enq or Etx Ack?
  2003. jz AOBA_DataAvail50 ; No
  2004. cmp cx,[si.DCB_XonLim] ;See if at XOn limit
  2005. ja AOBA_DataAvail50 ; No
  2006. and HSFlag[si],NOT XOffReceived ;Show ENQ or ETX not received
  2007. and HSFlag[si], NOT XOnPending+XOffSent
  2008. mov al, [si.DCB_XonChar]
  2009. call AOBA_OutHandshakingChar
  2010. jmp AOBA_DataAvail50 ;Done
  2011. public AOBA_DataAvail70
  2012. AOBA_DataAvail70:
  2013. cmp al,[si.DCB_XonChar] ;Is this an XOn character?
  2014. jnz AOBA_DataAvail80 ; No, just a normal character
  2015. and HSFlag[si],NOT XOffReceived
  2016. test [si.DCB_Flags],fEnqAck+fEtxAck ;Enq or Etx Ack?
  2017. jz AOBA_DataAvail75 ; No - jump to FakeXmitEmpty to get
  2018. ; transmitting going again
  2019. and HSFlag[si],NOT EnqSent
  2020. public AOBA_DataAvail75
  2021. AOBA_DataAvail75:
  2022. jmp AOBA_FakeXmitEmpty ;Restart transmit
  2023. ; Now see if this is a character for which we need to set an event as
  2024. ; having occured. If it is, then set the appropriate event flag
  2025. public AOBA_DataAvail80
  2026. AOBA_DataAvail80:
  2027. cmp al,[si.DCB_EVTChar] ;Is it the event generating character?
  2028. jne AOBA_DataAvail90 ; No
  2029. or by EvtWord[si],EV_RxFlag ;Show received specific character
  2030. ; Finally, a valid character that we want to keep, and we have
  2031. ; room in the queue. Place the character in the queue.
  2032. ; If the discard flag is set, then discard the character
  2033. public AOBA_DataAvail90
  2034. AOBA_DataAvail90:
  2035. test MiscFlags[si], Discard ;Discarding characters ?
  2036. jnz AOBA_DataAvail50 ; Yes
  2037. lea bx, [si+SIZE ComDEB] ; DS:BX -> BIS
  2038. mov bx, [bx.BIS_Mode] ; mode will be either 0 or 4
  2039. les di,QInAddr[si][bx] ;Get queue base pointer from either
  2040. assumes es,nothing ; QInAddr or AltQInAddr
  2041. mov bx,QInPut[si] ;Get index into queue
  2042. mov es:[bx][di],al ;Store the character
  2043. inc bx ;Update queue index
  2044. cmp bx,QInSize[si] ;See if time for wrap-around
  2045. jc AOBA_DataAvail100 ;Not time to wrap
  2046. xor bx,bx ;Wrap-around is a new zero pointer
  2047. public AOBA_DataAvail100
  2048. AOBA_DataAvail100:
  2049. mov QInPut[si],bx ;Store updated pointer
  2050. inc cx ;And update queue population
  2051. mov QInCount[si],cx
  2052. ; If flow control has been enabled, see if we are within the
  2053. ; limit that requires us to halt the host's transmissions
  2054. cmp cx,XOffPoint[si] ;Time to see about XOff?
  2055. jc AOBA_DataAvail120 ; Not yet
  2056. test HSFlag[si],HSSent ;Handshake already sent?
  2057. jnz AOBA_DataAvail120 ; Yes, don't send it again
  2058. mov ah,HHSLines[si] ;Should hardware lines be dropped?
  2059. or ah,ah ; (i.e. do we have HW HS enabled?)
  2060. jz AOBA_DataAvail110 ; No
  2061. ;[QN]---------------------------------------------------------------------------+
  2062. mov al,CommandShadow[si] ;8251 Command get (ins 94.04.16) |
  2063. test ah,ACE_DTR ;DTR handshake Enable ? (ins 94.04.16) |
  2064. jz AOBA_DataAvail101 ; No (ins 94.04.16) |
  2065. and al,not DTR ;Clear 8251's DTR Line ! (ins 94.04.16) |
  2066. public AOBA_DataAvail101
  2067. AOBA_DataAvail101: ; (ins 94.04.16) |
  2068. test ah,ACE_RTS ;RTS handshake Enable ? (ins 94.04.16) |
  2069. jz AOBA_DataAvail102 ; No (ins 94.04.16) |
  2070. and al,not RTS ;Clear 8251's RTS Line ! (ins 94.04.16) |
  2071. public AOBA_DataAvail102
  2072. AOBA_DataAvail102: ; (ins 94.04.16) |
  2073. mov dx,CommandPort[si] ;GET Command port address (ins 94.04.16) |
  2074. call int_Set8251mode ;Change to 8251 mode (ins 94.04.16) |
  2075. out dx,al ; (ins 94.04.16) |
  2076. call int_SetFIFOmode ;Change to FIFO mode (ins 94.04.16) |
  2077. mov CommandShadow[si],al ;Get Back 8251 Command (ins 94.04.16) |
  2078. or HSFlag[si],HHSDropped ; (ins 94.04.16) |
  2079. ;[QN]---------------------------------------------------------------------------+
  2080. public AOBA_DataAvail110
  2081. AOBA_DataAvail110:
  2082. test [si.DCB_Flags2],fInX ;Input Xon/XOff handshaking
  2083. jz AOBA_DataAvail120 ; No
  2084. or HSFlag[si], XOffSent
  2085. mov al, [si.DCB_XoffChar]
  2086. call AOBA_OutHandshakingChar
  2087. public AOBA_DataAvail120
  2088. AOBA_DataAvail120:
  2089. cmp cx, [si.RecvTrigger] ;Q: time to call owner's callback?
  2090. jb short AOBA_DataAvail130 ; N:
  2091. test [si.NotifyFlagsHI], CN_RECEIVE
  2092. jnz short AOBA_DataAvail140 ; jump if notify already sent and
  2093. ; data in buffer hasn't dropped
  2094. ; below threshold
  2095. mov ax, IntCodeOFFSET AOBA_DataAvail140
  2096. push ax
  2097. mov ax, CN_RECEIVE
  2098. %OUT probably should just set a flag and notify after EOI
  2099. jmp notify_owner
  2100. public AOBA_DataAvail130
  2101. AOBA_DataAvail130:
  2102. and [si.NotifyFlagsHI], NOT CN_RECEIVE
  2103. public AOBA_DataAvail140
  2104. AOBA_DataAvail140:
  2105. pop dx
  2106. push dx
  2107. mov dx,Port[si] ;Get comm I/O port (ins 94.04.16)
  2108. add dl,ACE_LSR ; (ins 94.04.16)
  2109. out 5fh,al ; (ins 94.05.18)
  2110. out 5fh,al ; (ins 94.05.18)
  2111. out 5fh,al ; (ins 94.05.18)
  2112. out 5fh,al ; (ins 94.05.18)
  2113. in al, dx
  2114. test al, ACE_DR ;Q: more data available?
  2115. jz @F ; N:
  2116. mov dx,Port[si] ;Get comm I/O port (ins 94.04.16)
  2117. add dl,ACE_RBR ; (ins 94.04.16)
  2118. in al, dx ;Read available character
  2119. jmp AOBA_DataAvail00
  2120. @@:
  2121. jmp AOBA_InterruptLoop_ChkTx
  2122. AOBA_DataAvail endp
  2123. public AOBA_OutHandshakingChar
  2124. AOBA_OutHandshakingChar proc near
  2125. mov dx,Port[si] ;Get comm I/O port (ins 94.04.16)
  2126. add dl,ACE_LSR ; (ins 94.04.16)
  2127. mov ah, al
  2128. @@:
  2129. out 5fh,al ; (ins 94.05.18)
  2130. out 5fh,al ; (ins 94.05.18)
  2131. out 5fh,al ; (ins 94.05.18)
  2132. out 5fh,al ; (ins 94.05.18)
  2133. in al, dx
  2134. test al,ACE_TSRE ; (ins 94.05.17)
  2135. jz @B
  2136. mov dx,Port[si] ;Get comm I/O port (ins 94.04.16)
  2137. add dl,ACE_THR ; (ins 94.04.16)
  2138. mov al, ah
  2139. out dx, al
  2140. ret
  2141. AOBA_OutHandshakingChar endp
  2142. page
  2143. ;----------------------------Private-Routine----------------------------;
  2144. ;
  2145. ; AOBA_XmitEmpty - Transmitter Register Empty
  2146. ;
  2147. ; Entry:
  2148. ; DS:SI --> DEB
  2149. ; DX = Port.IIDR
  2150. ; Returns:
  2151. ; None
  2152. ; Error Returns:
  2153. ; None
  2154. ; Registers Destroyed:
  2155. ; AX,BX,CX,DI,ES,FLAGS
  2156. ; History:
  2157. ;-----------------------------------------------------------------------;
  2158. ; assumes ds,Data
  2159. assumes es,nothing
  2160. public AOBA_FakeXmitEmpty
  2161. AOBA_FakeXmitEmpty:
  2162. pop dx
  2163. push dx
  2164. ; "Kick" the transmitter interrupt routine into operation.
  2165. call KickTxINT ;Bug fixed PC-11419 AutoCAD (ins 94.09.07)
  2166. mov dx,Port[si] ;Get comm I/O port (ins 94.04.16)
  2167. add dl,ACE_LSR ; (ins 94.04.16)
  2168. NEWIODELAY 1 ;<OUT 5F,AL> (ins 94.04.18)
  2169. in al,dx ;Is xmit really empty?
  2170. mov dx,Port[si] ;Get comm I/O port (ins 94.04.16)
  2171. add dl,ACE_THR ;--> Transmitter Holding Register(ins 94.04.16)
  2172. test al,ACE_TSRE ; (ins 94.05.17)
  2173. jnz short AOBA_XmitEmpty5 ; Y: send next char
  2174. jmp AOBA_InterruptLoop ; N: return to processing loop
  2175. public AOBA_XmitEmpty
  2176. AOBA_XmitEmpty proc near
  2177. call AOBA_MSR_READ ;AOBA-bug del 94.11.19 KBNES
  2178. mov dx,Port[si] ;Get comm I/O port (ins 94.04.16)
  2179. add dl,ACE_LSR ;--> Line Status Register (ins 94.04.16)
  2180. out 5fh,al ; (ins 94.05.18)
  2181. out 5fh,al ; (ins 94.05.18)
  2182. out 5fh,al ; (ins 94.05.18)
  2183. out 5fh,al ; (ins 94.05.18)
  2184. in al,dx ;Is xmit really empty?
  2185. mov dx,Port[si] ;Get comm I/O port (ins 94.04.16)
  2186. add dl,ACE_THR ;--> Transmitter Holding Register(ins 94.04.16)
  2187. test al,ACE_TSRE ; (ins 94.05.17)
  2188. jz AOBA_Xmit_jumpto90 ;Transmitter not empty, cannot send
  2189. ; If the hardware handshake lines are down, then XOff/XOn cannot
  2190. ; be sent. If they are up and XOff/XOn has been received, still
  2191. ; allow us to transmit an XOff/XOn character. It will make
  2192. ; a dead lock situation less possible (even though there are
  2193. ; some which could happen that cannot be handled).
  2194. public AOBA_XmitEmpty5
  2195. AOBA_XmitEmpty5:
  2196. mov ah,HSFlag[si] ;Get handshaking flag
  2197. test ah,HHSDown+BreakSet ;Hardware lines down or break set?
  2198. jnz AOBA_Xmit_jumpto100 ; Yes, cannot transmit
  2199. ; Give priority to any handshake character waiting to be
  2200. ; sent. If there are none, then check to see if there is
  2201. ; an "immediate" character to be sent. If not, try the queue.
  2202. public AOBA_XmitEmpty10
  2203. AOBA_XmitEmpty10:
  2204. test [si.DCB_Flags],fEnqAck+fEtxAck ;Enq or Etx Ack?
  2205. jnz AOBA_XmitEmpty40 ; Yes
  2206. public AOBA_XmitEmpty15
  2207. AOBA_XmitEmpty15:
  2208. test ah,HSPending ;XOff or XOn pending
  2209. jz AOBA_XmitEmpty40 ; No
  2210. public AOBA_XmitEmpty20
  2211. AOBA_XmitEmpty20:
  2212. and ah,NOT XOnPending+XOffSent
  2213. mov al,[si.DCB_XonChar] ;Get XOn character
  2214. public AOBA_XmitEmpty30
  2215. AOBA_XmitEmpty30:
  2216. mov HSFlag[si],ah ;Save updated handshake flag
  2217. jmp AOBA_XmitEmpty110 ;Go output the character
  2218. public AOBA_Xmit_jumpto90
  2219. AOBA_Xmit_jumpto90:
  2220. jmp AOBA_XmitEmpty90
  2221. ; If any of the lines which were specified for a timeout are low, then
  2222. ; don't send any characters. Note that by putting the check here,
  2223. ; XOff and Xon can still be sent even though the lines might be low.
  2224. ; Also test to see if a software handshake was received. If so,
  2225. ; then transmission cannot continue. By delaying the software check
  2226. ; to here, XOn/XOff can still be issued even though the host told
  2227. ; us to stop transmission.
  2228. public AOBA_XmitEmpty40
  2229. AOBA_XmitEmpty40:
  2230. test ah,CannotXmit ;Anything preventing transmission?
  2231. jz AOBA_XmitEmpty45 ; No
  2232. public AOBA_Xmit_jumpto100
  2233. AOBA_Xmit_jumpto100:
  2234. jmp AOBA_XmitEmpty100 ; Yes, disarm and exit
  2235. ; If a character has been placed in the single character "transmit
  2236. ; immediately" buffer, clear that flag and pick up that character
  2237. ; without affecting the transmitt queue.
  2238. public AOBA_XmitEmpty45
  2239. AOBA_XmitEmpty45:
  2240. test EFlags[si],fTxImmed ;Character to xmit immediately?
  2241. jz AOBA_XmitEmpty515 ; No, try the queue
  2242. and EFlags[si],NOT fTxImmed ;Clear xmit immediate flag
  2243. mov al,ImmedChar[si] ;Get char to xmit
  2244. jmp AOBA_XmitEmpty110 ;Transmit the character
  2245. public AOBA_XmitEmpty515
  2246. AOBA_XmitEmpty515:
  2247. mov cx,QOutCount[si] ;Output queue empty?
  2248. jcxz AOBA_Xmit_jumpto90 ; Yes, go set an event
  2249. test [si.DCB_Flags],fEtxAck ;Etx Ack?
  2250. jz AOBA_XmitEmpty55 ; No
  2251. mov cx,QOutMod[si] ;Get number bytes sent since last ETX
  2252. cmp cx,[si.DCB_XonLim] ;At Etx limit yet?
  2253. jne AOBA_XmitEmpty51 ; No, inc counter
  2254. mov QOutMod[si],0 ; Yes, zero counter
  2255. or HSFlag[si],EtxSent ;Show ETX sent
  2256. jmp short AOBA_XE_sendXOFF
  2257. public AOBA_XmitEmpty51
  2258. AOBA_XmitEmpty51:
  2259. inc cx ; Update counter
  2260. mov QOutMod[si],cx ; Save counter
  2261. jmp short AOBA_XmitEmpty59 ; Send queue character
  2262. public AOBA_XmitEmpty55
  2263. AOBA_XmitEmpty55:
  2264. test [si.DCB_Flags],fEnqAck ;Enq Ack?
  2265. jz AOBA_XmitEmpty59 ; No, send queue character
  2266. mov cx,QOutMod[si] ;Get number bytes sent since last ENQ
  2267. or cx,cx ;At the front again?
  2268. jnz AOBA_XmitEmpty56 ; No, inc counter
  2269. mov QOutMod[si],1 ; Yes, send ENQ
  2270. or HSFlag[si],EnqSent ;Show ENQ sent
  2271. public AOBA_XE_sendXOFF
  2272. AOBA_XE_sendXOFF:
  2273. mov al,[si.DCB_XoffChar]
  2274. jmp short AOBA_XmitEmpty110 ;Go output the character
  2275. public AOBA_XmitEmpty56
  2276. AOBA_XmitEmpty56:
  2277. inc cx ;Update counter
  2278. cmp cx,[si.DCB_XonLim] ;At end of our out buffer len?
  2279. jne AOBA_XmitEmpty58 ; No
  2280. xor cx,cx ;Show at front again.
  2281. public AOBA_XmitEmpty58
  2282. AOBA_XmitEmpty58:
  2283. mov QOutMod[si],cx ;Save counter
  2284. public AOBA_XmitEmpty59
  2285. AOBA_XmitEmpty59:
  2286. lea bx, [si+SIZE ComDEB] ; DS:BX -> BIS
  2287. mov bx, [bx.BIS_Mode] ; mode will be either 0 or 4
  2288. les di,QOutAddr[si][bx] ;Get queue base pointer from either
  2289. assumes es,nothing ; QOutAddr or AltQOutAddr
  2290. mov bx,QOutGet[si] ;Get pointer into queue
  2291. mov al,es:[bx][di] ;Get the character
  2292. inc bx ;Update queue pointer
  2293. cmp bx,QOutSize[si] ;See if time for wrap-around
  2294. jc AOBA_XmitEmpty60 ;Not time for wrap
  2295. xor bx,bx ;Wrap by zeroing the index
  2296. public AOBA_XmitEmpty60
  2297. AOBA_XmitEmpty60:
  2298. mov QOutGet[si],bx ;Save queue index
  2299. mov cx,QOutCount[si] ;Output queue empty?
  2300. dec cx ;Dec # of bytes in queue
  2301. mov QOutCount[si],cx ; and save new population
  2302. mov dx,Port[si] ;Get comm I/O port (ins 94.04.16)
  2303. add dl,ACE_THR ; (ins 94.04.16)
  2304. out dx,al ;Send char
  2305. cmp cx, [si.SendTrigger] ;Q: time to call owner's callback?
  2306. jae short AOBA_XmitEmpty70 ; N:
  2307. test [si.NotifyFlagsHI], CN_TRANSMIT
  2308. jnz short AOBA_XmitEmpty80 ; jump if notify already sent and
  2309. ; data in buffer hasn't raised
  2310. ; above threshold
  2311. mov ax, IntCodeOFFSET AOBA_XmitEmpty80
  2312. push ax
  2313. mov ax, CN_TRANSMIT
  2314. jmp notify_owner
  2315. public AOBA_XmitEmpty70
  2316. AOBA_XmitEmpty70:
  2317. and [si.NotifyFlagsHI], NOT CN_TRANSMIT
  2318. public AOBA_XmitEmpty80
  2319. AOBA_XmitEmpty80:
  2320. %OUT check fNoFIFO in EFlags[si] to determine if we can queue more output
  2321. jmp AOBA_InterruptLoop
  2322. ; No more characters to transmit. Flag this as an event.
  2323. public AOBA_XmitEmpty90
  2324. AOBA_XmitEmpty90:
  2325. or by EvtWord[si],EV_TxEmpty
  2326. ; Cannot continue transmitting (for any of a number of reasons).
  2327. ; Disable the transmit interrupt. When it's time resume, the
  2328. ; transmit interrupt will be reenabled, which will generate an
  2329. ; interrupt.
  2330. public AOBA_XmitEmpty100
  2331. AOBA_XmitEmpty100:
  2332. ;[QN]-------------------------------------------------------------------------+
  2333. cmp [si.DCB_id],ID_Com1 ;Is This Com1 ID ? (ins 94.05.19)|
  2334. jne AOBA_XmitEmpty102 ;No, go to KickTx5 (ins 94.05.19)|
  2335. mov dx,MaskFFPort[si] ;F/F Port Mask Bit (ins 94.05.19)|
  2336. in al,dx ; (ins 94.05.19)|
  2337. mov MaskFFShadow[si],al ;Save the Old Mask bit (ins 94.05.19)|
  2338. ; (ins 94.05.19)|
  2339. AOBA_XmitEmpty102: ; (ins 94.05.19)|
  2340. mov al,MaskFFShadow[si] ;mask data(port C) save (ins 94.05.19)|
  2341. test al,MSK_TXR ;Check a tx.RDY INT mask(ins 94.05.19)|
  2342. jz AOBA_XmitEmpty110 ; disable (ins 94.05.19)|
  2343. and al,NOT(MSK_TXE+MSK_TXR) ;= 11111001b (ins 94.05.19)|
  2344. mov dx,MaskFFPort[si] ;Port address (Port C) (ins 94.05.19)|
  2345. mov MaskFFShadow[si],al ;Masking data save (ins 94.05.19)|
  2346. ;-----------------------------------------------------------------------------+
  2347. public AOBA_XmitEmpty110
  2348. AOBA_XmitEmpty110:
  2349. out dx,al
  2350. jmp AOBA_InterruptLoop
  2351. AOBA_XmitEmpty endp
  2352. page
  2353. ;----------------------------Private-Routine----------------------------;
  2354. ;
  2355. ; AOBA_ModemStatus - Modem Status Interrupt Handler
  2356. ;
  2357. ; Entry:
  2358. ; DS:SI --> DEB
  2359. ; DX = Port.IIDR
  2360. ; Returns:
  2361. ; None
  2362. ; Error Returns:
  2363. ; None
  2364. ; Registers Destroyed:
  2365. ; AX,BX,CX,DI,ES,FLAGS
  2366. ; History:
  2367. ;-----------------------------------------------------------------------;
  2368. ; assumes ds,Data
  2369. assumes es,nothing
  2370. public AOBA_ModemStatus ;Public for debugging
  2371. AOBA_ModemStatus proc near
  2372. ; Get the modem status value and shadow it for MSRWait.
  2373. mov dx,Port[si] ;Get comm I/O port (ins 94.04.16)
  2374. add dl,ACE_MSR ; (ins 94.04.16)
  2375. in al,dx
  2376. mov MSRShadow[si],al ;Save MSR data for others
  2377. mov ch,al ;Save a local copy
  2378. ; Create the event mask for the delta signals
  2379. mov ah,al ;Just a lot of shifting
  2380. shr ax,1
  2381. shr ax,1
  2382. shr ah,1
  2383. mov cl,3
  2384. shr ax,cl
  2385. and ax,EV_CTS+EV_DSR+EV_RLSD+EV_Ring
  2386. or EvtWord[si],ax
  2387. mov ah,ch ;[rkh]...
  2388. shr ah,1
  2389. shr ah,1
  2390. and ax,EV_CTSS+EV_DSRS
  2391. or EvtWord[si],ax
  2392. mov ah,ch
  2393. mov cl,3
  2394. shr ah,cl
  2395. and ax,EV_RLSD
  2396. or EvtWord[si],ax
  2397. mov ah,ch
  2398. mov cl,3
  2399. shl ah,cl
  2400. and ax,EV_RingTe
  2401. or EvtWord[si],ax
  2402. public AOBA_ModemStatus10
  2403. AOBA_ModemStatus10:
  2404. mov al,OutHHSLines[si] ;Get output hardware handshake lines
  2405. or al,al ;Any lines that must be set?
  2406. jz AOBA_ModemStatus40 ;No hardware handshake on output
  2407. and ch,al ;Mask bits of interest
  2408. cmp ch,al ;Lines set for Xmit?
  2409. je AOBA_ModemStatus20 ; Yes
  2410. or HSFlag[si],HHSDown ;Show hardware lines have dropped
  2411. public AOBA_ModemStatus30
  2412. AOBA_ModemStatus30:
  2413. jmp AOBA_InterruptLoop
  2414. public AOBA_ModemStatus40
  2415. AOBA_ModemStatus40:
  2416. jmp AOBA_InterruptLoop_ChkTx
  2417. ; Lines are set for xmit. Kick an xmit interrupt if needed
  2418. public AOBA_ModemStatus20
  2419. AOBA_ModemStatus20:
  2420. and HSFlag[si],NOT (HHSDown OR HHSAlwaysDown)
  2421. ;Show hardware lines back up
  2422. mov cx,QOutCount[si] ;Output queue empty?
  2423. jcxz AOBA_ModemStatus30 ; Yes, return to InterruptLoop
  2424. jmp AOBA_FakeXmitEmpty ;Restart transmit
  2425. AOBA_ModemStatus endp
  2426. ;-----------------------------Public-Routine----------------------------;
  2427. ; int_Set8251mode - Change to 8251 mode
  2428. ;
  2429. ; Entry:
  2430. ;
  2431. ; Returns:
  2432. ;
  2433. ; Error Returns:
  2434. ; NONE
  2435. ; Registers Destroyed:
  2436. ; NONE
  2437. ; History: QNES T-MATUDA
  2438. ;-----------------------------------------------------------------------;
  2439. int_Set8251mode proc near
  2440. push dx ;
  2441. push ax ;
  2442. mov dx,Port[si] ;
  2443. add dx,ACE_FCR ;
  2444. in al, dx ;
  2445. NEWIODELAY 3 ; <OUT 5F,AL>
  2446. test al, 01h ;
  2447. jz int_running_fifo_mode ;
  2448. and al, 0feh
  2449. out dx,al ;
  2450. NEWIODELAY 3 ; <OUT 5F,AL>
  2451. @@: ;
  2452. in al,dx ;
  2453. NEWIODELAY 3 ; <OUT 5F,AL>
  2454. test al,ACE_EFIFO ;
  2455. jnz @B ;
  2456. int_running_fifo_mode: ;
  2457. pop ax ;
  2458. pop dx ;
  2459. ret
  2460. int_Set8251mode endp
  2461. ;-----------------------------Public-Routine----------------------------;
  2462. ; int_SetFIFOmode - Change to FIFO mode
  2463. ;
  2464. ; Entry:
  2465. ;
  2466. ; Returns:
  2467. ;
  2468. ; Error Returns:
  2469. ; NONE
  2470. ; Registers Destroyed:
  2471. ; NONE
  2472. ; History: QNES T-MATUDA
  2473. ;-----------------------------------------------------------------------;
  2474. int_SetFIFOmode proc near
  2475. push dx ;
  2476. push ax ;
  2477. mov dx,Port[si] ;
  2478. add dx,ACE_FCR ;
  2479. in al, dx ;
  2480. NEWIODELAY 3 ; <OUT 5F,AL>
  2481. test al, 01h ;
  2482. jnz int_running_8251_mode ;
  2483. ;Set_FIFO == RLInt_Enable + ACE_TRIG14 + ACE_EFIFO
  2484. mov al,Set_FIFO ;set FIFO mode
  2485. out dx,al ;
  2486. NEWIODELAY 3 ; <OUT 5F,AL>
  2487. int_running_8251_mode: ;
  2488. pop ax ;
  2489. pop dx ;
  2490. ret
  2491. int_SetFIFOmode endp
  2492. TOMOE_PAT DB 16 DUP('PATCH !!') ;PATCH AREA (ins 92.11.11)
  2493. endif ; NEC_98
  2494. ifdef DEBUG
  2495. public Control, DEF_Handler, COMHandler, APIHandler
  2496. public InterruptLoop, IntLoop10, IntLoop20
  2497. public DataAvail25, DataAvail30, DataAvail50
  2498. public DataAvail60, DataAvail70, DataAvail80, DataAvail90
  2499. public DataAvail100, DataAvail110, DataAvail120
  2500. public DataAvail130, DataAvail140, OutHandshakingChar
  2501. public XmitEmpty10, XmitEmpty20, XmitEmpty30, XmitEmpty40
  2502. public XmitEmpty59, XmitEmpty60
  2503. public XmitEmpty90, XmitEmpty100, XmitEmpty110
  2504. public ModemStatus10, ModemStatus20, ModemStatus30
  2505. public notify_owner, callback_event
  2506. endif
  2507. DOSTI proc near
  2508. FSTI
  2509. ret
  2510. DOSTI endp
  2511. DOCLI proc near
  2512. FCLI
  2513. ret
  2514. DOCLI endp
  2515. sEnd IntCode
  2516. end