home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ddkx86v5.zip / DDKX86 / SRC / DEV / ATCOM / ATINTRPT.ASM < prev    next >
Assembly Source File  |  1995-04-14  |  69KB  |  1,995 lines

  1. ;*DDK*************************************************************************/
  2. ;
  3. ; COPYRIGHT (C) Microsoft Corporation, 1989
  4. ; COPYRIGHT    Copyright (C) 1995 IBM Corporation
  5. ;
  6. ;    The following IBM OS/2 WARP source code is provided to you solely for
  7. ;    the purpose of assisting you in your development of OS/2 WARP device
  8. ;    drivers. You may use this code in accordance with the IBM License
  9. ;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
  10. ;    Copyright statement may not be removed.;
  11. ;*****************************************************************************/
  12. ;       SCCSID = @(#)atintrpt.asm       6.12 92/03/03
  13. ; ***************************************************************************
  14. ; *
  15. ; *
  16. ; *
  17. ; ***************************************************************************
  18.  
  19.  
  20. ;********************** START OF SPECIFICATIONS ********************
  21. ;*
  22. ;* SOURCE FILE NAME:  ATINTRPT.ASM
  23. ;*
  24. ;* DESCRIPTIVE NAME:  CBIOS Async Driver Interrupt Handler module
  25. ;*
  26. ;* STATUS: RELEASE 1 LEVEL 2
  27. ;*
  28. ;* FUNCTION:    This module contains interrupt service routines for up
  29. ;*      to 3 Async Communications devices on up to 2 interrupt levels.
  30. ;*      Interrupts are serviced through the interrupt entry point,
  31. ;*      using the Operating System Transfer convention via DevHlp Mgr.
  32. ;*
  33. ;*      Specific subroutines service the following types of 16550 UART
  34. ;*      interrupts (listed in order of high to low priority):
  35. ;*          - modem status interrupt
  36. ;*          - receive data available interrupt
  37. ;*          - transmit hardware empty interrupt
  38. ;*
  39. ;*      The module also contains Timer Tick handler routines to service
  40. ;*      the COM ports' Read and Write Timeout processing requirements.
  41. ;*
  42. ;* NOTES:
  43. ;*     DEPENDENCIES:    ABIOS MUST BE ABSENT
  44. ;*     PATCH LABEL:  0
  45. ;*
  46. ;* ENTRY POINTS:  ComInt1, ComInt2, Ticker
  47. ;*
  48. ;* INTERNAL REFERENCES:
  49. ;*      ProcRun - run a blocked thread
  50. ;*      LinkRP - add the request packet to the end of the request queue
  51. ;*      UnLinkHeadRP - pull the next available request from a request queue
  52. ;*      ReadQueue - move data from our Recieve Queue to user's Read buffer
  53. ;*      WriteQueue - move data from user's Write buffer to our Transmit Queue
  54. ;*      StartNextWRP - pull the next Write request packet and make it current
  55. ;*      CheckTX - enable or disable transmit interrupts as required
  56. ;*      TxFlowDetect - scan Receive Queue for XON/XOFF chars & act accordingly
  57. ;*      DisableRemoteTX - disable the remote transmitter
  58. ;*
  59. ;* EXTERNAL REFERENCES:
  60. ;*      DevHlp_ABIOSCall - call the ABIOS Interrupt Entry Point with:
  61. ;*         Modem Status Request Block
  62. ;*         Combined Receive/Transmit Request Block
  63. ;*         Default Interrupt Handler Request Block
  64. ;*      DevHlp_EOI - signal End of Interrupt
  65. ;*
  66. ;*********************** END OF SPECIFICATIONS **********************
  67.  
  68.  
  69.  
  70. ;       SCCSID = @(#)atintrpt.asm       6.12 92/03/03
  71.  
  72.         PAGE    80,132
  73.         .286p
  74.  
  75.         TITLE   com01.sys - Asynchronous Communication Device Driver
  76.         NAME com01
  77.  
  78. ;       Bryan Diehl
  79. ;       David Gilman
  80.  
  81. ;***    atintrpt.asm - Interrupt Handlers
  82. ;
  83. ;       ComInt          - Interrupt entry point
  84. ;       LxInt           - Line status error interrupt (processed in RxInt)
  85. ;       RxInt           - Receive data interrupt
  86. ;       TxInt           - Transmitter empty interrupt
  87. ;       MxInt           - Modem status interrupt
  88. ;       Ticker          - Main Timer tick handler for timeout processing
  89. ;       WriteTick       - Write timeout processing
  90. ;       ReadTick        - Read timeout processing
  91. ;
  92. ;     Modification History
  93. ;
  94. ;     BD      01/18/87        Re-written to conform to MS standard for
  95. ;                             style, clarity and efficiency.
  96. ;                             New design for read and write.
  97. ;                             Uses timer tick for timeout processing.
  98. ;
  99. ;     BD      04/09/87        Restructure main interrupt so multiple
  100. ;                             nested interrupts are not generated.
  101. ;                             A single nested interrupt is ok.
  102. ;     JGT     05/10/88        Fix TERI event detection     in MxInt (per MS)
  103. ;     YN      05/25/89        MVDM Support - @VDM
  104. ;     ACW     04/16/91        @PVW Added perfview counters/timers
  105. ;     JAG     09/14/93        @67790 Rockwell chipset based PCMCIA modems fail
  106. ;     RAC     12/16/93        76699 Make Perfview optionally assembled
  107. ;     RDW     03/14/94        80677 VDM not getting RI or TERI Signals correctly
  108. ;     WDM     04/21/94        82548 - pvwxport.inc now included in atcom.inc
  109. ;     JAG     12/01/94        101711- SLIP and 16450s not working see bugbug code
  110. ;
  111.  
  112.  
  113.  
  114. .xlist
  115.  
  116. include devhlp.inc
  117. include devsym.inc
  118. include basemaca.inc
  119. include realmac.inc
  120. include osmaca.inc
  121. include error.inc
  122. include protmode.inc
  123. include atcom.inc
  124. include ateisa.inc
  125. include iodelay.inc
  126. include devhlpP.inc            ; 76711
  127. .list
  128.  
  129.  
  130. ;;; new macro for doing EOIs Replaced by new DevEOI  Removed By   76711
  131. ;;                                                   Removed By   76711
  132. ;;DevEOI  MACRO   ByteIRQ                            Removed By   76711
  133. ;;        local   eoi1, eoi2                         Removed By   76711
  134. ;;        push    ax                                 Removed By   76711
  135. ;;        pushf                                      Removed By   76711
  136. ;;        mov     al,ByteIRQ                         Removed By   76711
  137. ;;        shr     al,4                               Removed By   76711
  138. ;;        mov     al,20h                             Removed By   76711
  139. ;;        jnz     eoi2                               Removed By   76711
  140. ;;        cli                                        Removed By   76711
  141. ;;        jnc     eoi1                               Removed By   76711
  142. ;;        out     0a0h,al                            Removed By   76711
  143. ;;eoi1:   out     020h,al                            Removed By   76711
  144. ;;eoi2:   popf                                       Removed By   76711
  145. ;;        pop     ax                                 Removed By   76711
  146. ;;        ENDM                                       Removed By   76711
  147.  
  148.  
  149.         EXTRN   Com1:WORD
  150.         EXTRN   Com2:WORD
  151.         EXTRN   Com3:WORD
  152.         EXTRN   Com4:WORD
  153.         EXTRN   GAS_Switch:WORD
  154.         EXTRN   DevHlp:DWORD
  155.         EXTRN   Flags:BYTE
  156.         EXTRN   Ready:WORD
  157.         extrn   CheckTX:near
  158.         extrn   ProcRun:near
  159.         extrn   ReadQueue:near
  160.         extrn   ReadQueueByte:near
  161.         extrn   SetAlert:near
  162.         extrn   StartNextWRP:near
  163.         extrn   UnLinkHeadRP:near
  164.         extrn   WriteQueue:near
  165.         extrn   WriteQueueByte:near
  166.         EXTRN   VCOMAddress:FAR
  167.         EXTRN   ShrdIRQ1:BYTE
  168.         EXTRN   ShrdIRQ2:BYTE
  169.         EXTRN   ShrdIRQ3:BYTE
  170.         EXTRN   ShrdIRQ4:BYTE
  171.  
  172. DSEG SEGMENT
  173.  
  174. ; interrupt service table based on interrupt id register
  175. ; MxInt is called directly from ComIntx, never through SrvTbl
  176. ; LxInt is called directly from RxInt, never through SrvTbl
  177.  
  178. SrvTab  LABEL   WORD
  179.         DW      OFFSET CSEG:BadInt      ; invalid interrupt value
  180.         DW      OFFSET CSEG:TxInt       ; Tx holding reg. empty interrupt
  181.         DW      OFFSET CSEG:RxInt       ; Rx data available interrupt
  182.         DW      OFFSET CSEG:BadInt      ; invalid interrupt value
  183.  
  184. .errnz  II_MX
  185. .errnz  II_TX-2
  186. .errnz  II_RX-4
  187. .errnz  II_LX-6
  188.  
  189. bad_int DW      0
  190.  
  191. IntID   DB      0
  192. DSEG    ENDS
  193.  
  194.  
  195. CSEG    SEGMENT
  196.  
  197. ;********************** START OF SPECIFICATIONS ********************
  198. ;*
  199. ;* SUBROUTINE  NAME:  ComInt1 / ComInt2
  200. ;*
  201. ;* DESCRIPTIVE NAME:  Interrupt Handlers for COM1 and COM2
  202. ;*
  203. ;*
  204. ;* FUNCTION:
  205. ;*      The interrupts are prioritized in the following order:
  206. ;*              1. line status interrupt
  207. ;*              2. read data available interrupt
  208. ;*              3. transmit buffer empty interrupt
  209. ;*              4. modem service interrupt
  210. ;*
  211. ;*      This routine continues to service until all interrupts from the
  212. ;*      16450 serial controler have been satisfied.
  213. ;*      This is required because in a edge triggered environment all
  214. ;*      interrupting conditions must be cleared before returning from the
  215. ;*      interrupt.  Otherwise, no more interrupts would ever be generated.
  216. ;*
  217. ;*      On entry, the 'Data Moved' flag is cleared.  This is set when
  218. ;*      data is moved in TxInt or at the end of ComInt.  If this flag
  219. ;*      is set, we delay moving receive data until the next interrupt.
  220. ;*      This avoids doing two PhysToVirts on one interrupt.
  221. ;*
  222. ;*      When a request is completed, the request is put on the 'Ready'
  223. ;*      list.  It doesn't get ProcRun'ed until after the EOI.
  224. ;*      This is to minimize our interrupt path length before the EOI.
  225. ;*
  226. ;*      NOTE    interrupt handlers do NOT need to save registers
  227. ;*
  228. ;*      ENTRY   ds = device driver data segment (set up by kernel)
  229. ;*              interrupts disabled
  230. ;*
  231. ;*      EXIT    none
  232. ;*
  233. ;*      USES    none
  234. ;*
  235. ;* INTERNAL REFERENCES:
  236. ;*      ProcRun - run a blocked thread
  237. ;*      LinkRP - add the request packet to the end of the request queue
  238. ;*      UnLinkHeadRP - pull the next available request from a request queue
  239. ;*      ReadQueue - move data from our Recieve Queue to user's Read buffer
  240. ;*      WriteQueue - move data from user's Write buffer to our Transmit Queue
  241. ;*      StartNextWRP - pull the next Write request packet and make it current
  242. ;*      CheckTX - enable or disable transmit interrupts as required
  243. ;*      TxFlowDetect - scan Receive Queue for XON/XOFF chars & act accordingly
  244. ;*      DisableRemoteTX - disable the remote transmitter
  245. ;*
  246. ;* EXTERNAL REFERENCES:
  247. ;*      DevHlp_ABIOSCall - call the ABIOS Interrupt Entry Point with:
  248. ;*         Modem Status Request Block
  249. ;*         Combined Receive/Transmit Request Block
  250. ;*         Default Interrupt Handler Request Block
  251. ;*      DevHlp_EOI - signal End of Interrupt
  252. ;*
  253. ;*********************** END OF SPECIFICATIONS **********************
  254.  
  255.  
  256. Procedure ComInt,FAR
  257.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  258. cint5:  or      si,si
  259.         ljz     cint000                 ; ComInfo pointer is null
  260.  
  261.         test    [si].ci_int_sharing,INT_SHARING ; Int. sharing supported?
  262.         jz      cint6                   ;  N: continue on
  263.         mov     dx,[si].ci_port         ;  Y: read the port
  264.         add     dx,R_INTID              ; point to interrupt ID reg.
  265.         in      al,dx                   ; (al) =  interrupt id
  266.         mov     IntID, al               ; Save Interupt ID
  267.         test    al,II_NONE              ; any interrupts pending?
  268.         jz      cint6                   ;  Y: process the int.
  269.         stc                             ;  N: indicate not our int.
  270.         ret                             ; and return to int. mgr.
  271.  
  272. cint6:
  273.         SaveReg         <si>            ; save si on stack frame
  274.         mov     bp,sp                   ; (bp)   -> stack frame
  275.                                         ; [bp]-2 -> si
  276.  
  277.         inc     [si].ci_depth           ; inc nested interrupt counter
  278.  
  279.         ; cannot do a check until the depth flag has been inc'ed or
  280.         ; ComError will jump to the       exit point on an error!
  281.         ChkComInfoPtr                   ; saves flags
  282.  
  283.         ; zero flag still set from inc above
  284.         .errnz  D_BAD
  285.         ljz     cint0                  ; too many nested interrpts
  286.  
  287.         cmp     [si].ci_nopens,0 ; make sure port is open
  288.         lje     cint00          ; port not open yet, disable chip and EOI
  289.  
  290. cint10: ChkComInfoPtr
  291.         cli                     ; make sure interrupts are disabled
  292.  
  293. ; In order to correctly handle the 'Input Sensitivity to DSR' we have to
  294. ; process Modem Status interrupts before Receive interrupts. This allows
  295. ; us to handle this mode correctly when DSR changes and we recieve data.
  296.  
  297.         mov     dx,[si].ci_port
  298.         add     dx,R_MODMS              ; (dx) -> modem status reg
  299.         in      al,dx                   ; (al) = modem status
  300.         test          al,MS_DCTS OR MS_DDSR OR MS_TERI OR MS_DDCD
  301.         jz      cint20                  ; no MSR changes (interrupt)
  302.  
  303.         call    MxInt                   ; process modem status interrupt
  304.  
  305. cint20:
  306.         ; BUGBUG - START OF      TO RE-ENABLE TX INTERRUPT
  307.         ; if TX interrupt is enabled, then disable and re-enable
  308.         ; to force TX interrupt
  309.         ; Workaround for a hardware     in the 16450 and 16550 chips:
  310.         ;       TX interrupt pending (and highest priority)
  311.         ;       start reading IIR (interrupt identification register)
  312.         ;       reading IIR for TX interrupt clears the TX interrupt
  313.         ;       RX data comes in while still in read cycle
  314.         ;       IIR changes to RX interrupt
  315.         ;       we process the RX interrupt properly, but will never
  316.         ;       get another TX interrupt because it has been cleared.
  317.  
  318.         mov     dx,[si].ci_port
  319.         add     dx,R_INTEN              ; (dx) -> interrupt enable reg
  320.         in      al,dx                   ; (al) =  interrupt enable
  321.         test    al,IE_TX
  322.         jz      cint25                  ; TX interrupts not enabled
  323.  
  324.         ; NOTE: If we're sharing this interrupt line, then we ALWAYS
  325.         ; want to turn the TX int. on at the chip, to cover up for
  326.         ; the fact that on entry, we read the Interrupt ID register,
  327.         ; which cleared any pending TX int.  Turning the TX int. back
  328.         ; on at the chip will restore the correct status of the Interrupt
  329.         ; ID register.
  330. ;       test    [si].ci_int_sharing,INT_SHARING ; Int. sharing supported?
  331. ;       jnz     cint24                  ;  Y: ALWAYS re-enable TX int.
  332.  
  333.         ; NOTE: don't move this test above the "mov dx," above!
  334. ;---    test    [si].ci_flagx,FX_16450  ; Western Digital     16550AF ?
  335. ;---    jz      cint25                  ; 8250 or 16550A
  336.  
  337.  
  338.         ; PCMCIA modems don't have this     and don't like the fix
  339.         ; so lets just skip the hack.
  340.         test    [si].ci_flagx1,FX1_PCMCIA_MODEM ; Is this a PCMCIA modem?
  341.         jz      cint24                          ;  N: Do Re-enable
  342.  
  343.         test    [si].ci_int_sharing,INT_SHARING; Int. sharing supported?
  344.         jz      cint25                      ;  N: go read IIR - haven't read
  345.  
  346.         mov     al,IntID                    ; We read it once already
  347.         jmp     short cint26                ; Go ISR
  348.  
  349. cint24:
  350.         and     al,NOT IE_TX            ; disable TX interrupts first
  351.         out     dx,al
  352.         push    ax
  353.         DevIODelay ax
  354.         pop     ax
  355.         or      al,IE_TX                ; re-enable TX interrupts
  356.         out     dx,al
  357.         ; BUGBUG - END OF      TO RE-ENABLE TX INTERRUPT
  358.  
  359.  
  360. cint25: add     dx,R_INTID-R_INTEN      ; (dx) -> interrupt id reg
  361.         in      al,dx                   ; (al) =  interrupt id
  362. cint26: test    al,II_NONE
  363.         jnz     cint30                  ; no interrupts need servicing
  364.  
  365.         mov     bl,al                   ; (bl) = interrupt id
  366.         and     bx,II_MASK              ; (bx) = index into int service table
  367.  
  368.         .errnz  II_MX
  369. ;       cmp     bl,II_MX
  370.         je      cint10                  ; MX, process above
  371.  
  372.         call    SrvTab[bx]              ; service the Interrupt..
  373.  
  374.         sti                     ; allow higher priority interrupts
  375.                                 ; this CANNOT cause a nested interrupt
  376.                                 ; because we haven't done an EOI yet
  377.  
  378.         jmp     SHORT cint10    ; until all interrupts serviced
  379.  
  380.  
  381. ;*      cint30 - done servicing the actual interrupt(s)
  382. ;                check for Read request completion or data movement
  383. ;
  384. cint30:
  385. ; see if the current read request can be completed.
  386.         cmp     [si].ci_r_rp._hi,0
  387.         lje     cint60                  ; no current read request
  388.  
  389.         mov     cx,[si].ci_qin.ioq_count; (cx) = number of bytes in queue
  390.         cmp     cx,[si].ci_r_to_move
  391.         jae     cint35                  ; enough to complete request
  392.  
  393.         mov     al,[si].ci_dcb_flags3
  394.         and     al,F3_READ_TO_MASK      ; (al) = read timeout mode
  395.  
  396.         ; BUGBUG - no wait mode
  397.         ; 'no wait' mode can get here if there were queued read requests
  398.         ; and then 'no wait' mode was set.
  399.         ; Each queued request will remain blocked until the first interrupt
  400.         ; of any type (rx, tx, mx).
  401.         ; We could complete the current read request and flush all other read
  402.         ; requests when 'no wait' mode is specified in Set DCB.
  403.  
  404.         cmp     al,F3_READ_TO_NW
  405.         je      cint35                  ; no wait mode
  406.  
  407.         cmp     al,F3_READ_TO_WFS
  408.         jne     cint40                  ; not wait for something mode
  409.  
  410.         jcxz    cint40                  ; wait for something mode, but no data
  411.  
  412. cint35: ; enough to finish request (done, no wait or wait for something)
  413.         les     di,[si].ci_r_rp         ; (es:di) -> request packet
  414.         ASSUME  es:NOTHING
  415.         ChkRPPtr
  416.         ChkRPType       CMDINPUT
  417.  
  418.         test    es:[di].PktStatus,STDON
  419.         jnz     cint60                  ; already marked done
  420.  
  421.         or      es:[di].PktStatus,STDON ; mark request done
  422.                                         ; (so we don't run it twice)
  423.  
  424.         ProcReady                       ; put request on 'ready' list
  425.         jmp     SHORT cint60
  426.  
  427.  
  428. ; may have enough data to move up to user buffer
  429. ; make mark higher for real mode hopeing for it to get moved in prot mode
  430. cint40: cmp     cx,RX_MOVE_PROT         ; (cx) = # of bytes in qin from above
  431.         jb      cint60                  ; below prot mode mark, don't move
  432.  
  433.         test    [si].ci_flagx,FX_DATA_MOVED
  434.         jnz     cint60                  ; data already moved on this interrupt
  435.                                         ; set here and in TxInt
  436.  
  437. cint50: or      [si].ci_flagx,FX_DATA_MOVED     ; mark data moved
  438.  
  439.         les     di,[si].ci_r_rp         ; (es:di) -> request packet
  440.         ASSUME  es:NOTHING
  441.         ChkRPPtr
  442.         ChkRPType       CMDINPUT
  443.  
  444.         ; have to move data to user space
  445.         sti                             ; allow interrupts while moving data
  446.         mov     cx,[si].ci_r_to_move    ; set up count
  447.  
  448.         call    ReadQueue               ; move data to user space
  449.                                         ; updates ci_r_to_move
  450.  
  451.         jmp     cint10                  ; may have more interrupts now
  452.  
  453.  
  454. ;*      cint60 - done servicing the actual interrupt and Read data
  455. ;       do post-EOI processing only if not a nested interrupt
  456. cint60:
  457.         cli                             ; no interrupts
  458.  
  459.         DevEOI  <byte ptr [si].ci_irq>,DevHlp   ; Add    76711
  460.  
  461.         cmp     [si].ci_depth,D_NEST
  462.         je      cintnestx                       ; nested interrupt
  463.  
  464.  
  465. ; not a nested interrupt, do post processing
  466. cint80:
  467.         sti     ; Start of allow NESTED INTERRUPTS (after EOI and STI)
  468.         and     [si].ci_flagx,NOT FX_INT_NESTED ; clear nested flag
  469.  
  470.         ; NOTE: a nested interrupt can come in after the sti above and
  471.         ; before clearing the nested flag; this is OK because we are
  472.         ; about to do the post-EOI processing anyway.  This reduces
  473.         ; the number of times we go through the post EOI stuff.
  474.  
  475.         ; ProcRun requests on the ready list
  476.         ; this could be done at timer tick time
  477.         SaveReg         <si>
  478.         mov     si,OFFSET Ready ; (ds:si) -> Ready list
  479.  
  480. cint90: call    UnLinkHeadRP    ; (es:di) -> runnable request packet
  481.         jc      cint95          ; no more to run
  482.         call    ProcRun
  483.         jmp     SHORT cint90    ; try to run another
  484.  
  485. cint95: RestoreReg      <si>    ; (ds:si) -> cominfo
  486.         ChkComInfoPtr
  487.  
  488.         cli             ; no interrupts while we check for nested interrupt
  489.  
  490.         ; End of allow NESTED INTERRUPTS
  491.  
  492.         test    [si].ci_flagx,FX_INT_NESTED
  493.         jnz     cint80          ; nested interrupt occured
  494.  
  495. cint99:
  496.         ; exiting first level interrupt
  497.         and     [si].ci_flagx,NOT FX_DATA_MOVED ; clear data moved flag
  498.  
  499. cintx:  mov     sp,bp           ; restore stack frame
  500.         RestoreReg      <si>    ; (ds:si) -> ComInfo
  501.         ChkComInfoPtr
  502.  
  503. cintxx: dec     [si].ci_depth   ; dec interrupt depth
  504.         .errnz  D_BAD
  505.         clc                     ; clear carry to show it was our interrupt
  506.         ret
  507.  
  508. cintnestx:
  509.         or      [si].ci_flagx,FX_INT_NESTED     ; flag nested interrupt occured
  510.         jmp     SHORT cintx                     ; done
  511.  
  512. ;* cinterr - exit point for internal error at interrupt time
  513. ;
  514. ;       isuue EOI and return
  515. ;       Interrupt level has already been released (UnSetIRQ) and
  516. ;       16450 interrupt disabled in ShutdownPort,
  517. ;       but we still need to issue the EOI for this interrupt.
  518. ;
  519. ;       ENTRY   (ds) -> DD Data Seg
  520.  
  521. Entry   cinterr,,,nocheck
  522.  
  523.         mov     sp,bp           ; restore stack frame
  524.         pop     si              ; (ds:si) -> ComInfo
  525.         ChkComInfoPtr
  526.  
  527.         DevEOI  <byte ptr [si].ci_irq>,DevHlp    ; Add    76711
  528.  
  529.         ; can't get nested ints because 16450 chip interrupts are disabled
  530.         jmp     SHORT cintxx
  531.  
  532. cint0:  ComErr  <ComInt: too many nested interrupts>
  533.  
  534.  
  535. ;* cint00 - interrupt during first open or init, disable chip and EOI
  536. cint00: sti
  537.         mov     dx,[si].ci_port         ; (dx) -> port
  538.         add     dx,R_INTEN              ; (dx) -> interrupt enable register
  539.         xor     ax,ax                   ; (ax) =  0
  540.         out     dx,al                   ; disable interrupts from 16450 chip
  541.  
  542.         DevEOI  <byte ptr [si].ci_irq>,DevHlp   ; Add    76711
  543.  
  544.         ; can't get nested ints because 16450 chip interrupts are disabled
  545.         jmp     cintx
  546.  
  547.  
  548. ;* cint000 - interrupt during driver shut down
  549. cint000:
  550.         sti
  551.         stc                     ; set carry - not my interrupt
  552.         ret                     ; return carry to interrupt manager which
  553.                                 ; will issue EOI for me
  554.  
  555.  
  556. EndProc ComInt
  557.  
  558.  
  559. ;**     BadInt - invalid interrupt handler
  560. ;
  561.  
  562. Procedure BadInt,NEAR
  563.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  564.  
  565.         inc     bad_int
  566.         cmp     bad_int,BAD_MAX
  567.         jl      finish_badint_proc
  568.  
  569. ;--- Reset IER --------------------------------
  570.  
  571.         mov     dx,[si].ci_port
  572.         add     dx,R_INTEN              ; (dx) -> interrupt enable reg
  573.         in      al,dx                   ; (al) =  interrupt enable
  574.  
  575.         push    ax
  576.  
  577.         and     al,NOT IE_TX            ; disable TX interrupts first
  578.         and     al,NOT IE_RX            ; disable RX interrupts first
  579.         and     al,NOT IE_MX            ; disable MX interrupts first
  580.         and     al,NOT IE_LX            ; disable LX interrupts first
  581.         out     dx,al
  582.  
  583.         DevIODelay ax
  584.  
  585.         pop     ax
  586.  
  587.         out     dx,al
  588.  
  589. ;----------------------------------------------
  590.  
  591.         test    [si].ci_badmax,IGNORE_ERROR
  592.         jz      bad_shutdown
  593.  
  594. finish_badint_proc:
  595.         clc                     ; clear carry to show it was our interrupt
  596.         ret
  597.  
  598. bad_shutdown:
  599.  
  600.         test    al, IE_TX
  601.         jz      try_RX
  602.         and     al, NOT IE_TX
  603.         jmp     SHORT fix_it
  604.  
  605. try_RX:
  606.         test    al, IE_RX
  607.         jz      try_LX
  608.         and     al, NOT IE_RX
  609.         jmp     SHORT fix_it
  610.  
  611. try_LX:
  612.         test    al, IE_LX
  613.         jz      try_MX
  614.         and     al, NOT IE_LX
  615.         jmp     SHORT fix_it
  616.  
  617. try_MX:
  618.         test    al, IE_LX
  619.         jz      fix_it
  620.         and     al, NOT IE_LX
  621.         jmp     SHORT fix_it
  622.  
  623. fix_it:
  624.         push    ax
  625.         DevIODelay ax
  626.         pop     ax
  627.  
  628.         out     dx,ax
  629.  
  630.         cmp     bad_int,BAD_MAX+5
  631.         jl      gods_mercy
  632.  
  633.         ComErr  <ComInt : invalid interrupt (presumably LxInt)>
  634.         pop     ax
  635.  
  636. gods_mercy:
  637.  
  638.         clc                     ; clear carry to show it was our interrupt
  639.         ret
  640.  
  641. EndProc BadInt
  642.  
  643. ;**     LxInt - line status interrupt (highest priority)
  644. ;
  645. ;       Overrun, parity, framing, or break error.
  646. ;       Read line status register and save in shadow.
  647. ;       Mark errors in comerr and event.
  648. ;
  649. ;       ENTRY   (ds:si) -> ComInfo
  650. ;               (dx) -> interrupt id register (R_INTID)
  651. ;
  652. ;       EXIT    (al) = LSR error bits only (overrun, parity and frameing)
  653. ;
  654. ;       USES    ax dx
  655.  
  656. Procedure LxInt,NEAR
  657.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  658.  
  659.         ret
  660.  
  661. EndProc LxInt
  662.  
  663.  
  664. ;**     RxInt - Rx Data Available Interrupt (second priority)
  665. ;
  666. ;       ENTRY   (ds:si) -> ComInfo
  667. ;               (dx) -> interrupt id register (R_INTID)
  668. ;
  669. ;       EXIT    none
  670. ;
  671. ;       USES    ax bx cx dx
  672. ;
  673. ;       NOTE    Hardware Differences on Overrun Error
  674. ;
  675. ;               8250 and 16450 (and 16550x in 16450 mode):
  676. ;                 overrun data has over-written valid data in RX HW.
  677. ;                 err char needs to be INSERTED into SW queue BEFORE RX data.
  678. ;
  679. ;               16550A in FIFO mode:
  680. ;                 overrun data has NOT over-written valid data in RX HW FIFO.
  681. ;                 err char needs to be APPENDED to SW queue AFTER RX data.
  682. ;
  683. ;       Pseudo Code:
  684. ;
  685. ;       oflag = 0                               ; overrun shift flag (16 bit)
  686. ;
  687. ;       forever {
  688. ;   top:
  689. ;           call LxInt                          ; read LSR and set error bits
  690. ;
  691. ;           ah = lsrshadow
  692. ;           lsrshadow &= NOT error bits ; turn off error bits in lsrshadow
  693. ;
  694. ;           if (no RX data available)
  695. ;               goto done                       ; no more RX data to process
  696. ;
  697. ;           al = RX data & mask
  698. ;
  699. ; Note: DSR_OK cannot change through iterations of this loop
  700. ; because it changes in MxInt which is a lower priority interrupt.
  701. ;
  702. ;           if (!DSR_OK)                        ; IN_DSR on AND DSR low
  703. ;               goto top                        ; skip this data and errors
  704. ;
  705. ;           if (Overrun Error && Error_Char_Processing) {
  706. ;               if (FIFO_ON || FIFO_APO)
  707. ;                   oflag |= 8000               ; error AFTER 16th char in FIFO
  708. ;               else
  709. ;                   oflag |= 0001               ; error BEFORE 1st char in buf
  710. ;           }
  711. ;
  712. ;           if (Break Interrupt) {
  713. ;               if (Break_Char_Processing)
  714. ;                   al = break_character
  715. ;                   goto q_data                 ; go queue the break char
  716. ;               else
  717. ;                   goto skip_data
  718. ;           }
  719. ;
  720. ;           if (Parity or Framing Error) {
  721. ;               if (Error_Char_Processing)
  722. ;                   al = error_character
  723. ;               goto q_data                     ; don't check for NULL/XON/XOFF
  724. ;           }
  725. ;
  726. ;           if (RX == NULL && NULL_stripping)
  727. ;               goto skip_data
  728. ;
  729. ;           if (OUT_XO) {                       ; output xoff/xon mode
  730. ;               if (RX == XOFF)
  731. ;                   hsflag |= XOFF_RECIEVED     ; set   XOFF received
  732. ;               else if (RX == XON)
  733. ;                   hsflag &= !XOFF_RECIEVED    ; clear XOFF received
  734. ;               else
  735. ;                   goto q_data                 ; not xoff/xon, go queue data
  736. ;
  737. ;               call CheckTX                    ; decide if we can TX now
  738. ;               goto skip_data                  ; DON'T queue the xoff/xon char
  739. ;           }
  740. ;
  741. ;   q_data:
  742. ;           if (oflag & 1 && FIFO_OFF) {
  743. ;               oflag &= !1
  744. ;               call WriteQueueByte(error_character) ; no FIFO, INSERT err char
  745. ;           }
  746. ;           call WriteQueueByte(al)             ; write data
  747. ;
  748. ;   skip_data:
  749. ;           oflag >>= 1                         ; shift overrun flag
  750. ;           if (carry)
  751. ;               call WriteQueueByte(error_character) ; FIFO, APPEND err char
  752. ;       }
  753. ;   done:
  754.  
  755. Procedure RxInt,NEAR
  756.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  757.  
  758.         mov     bad_int,0               ; reset     interrupt count
  759.  
  760.         xor     cx,cx                   ; cx = overrun flags (16 bit shifting)
  761.  
  762. rxi_top:
  763.         ChkComInfoPtr
  764.  
  765.  
  766. ; since LxInt is disabled we must process all line status errors now!
  767.  
  768.         cli                                     ; disable interrupts
  769.  
  770.         ReadLSR                         ; (al) = LSR
  771.  
  772. rxi_lxint:
  773.  
  774. ; @VDM change begin
  775.  
  776.         mov     [si].ci_vdm_LastLSR,al  ; lastLSR = error bits of LSR
  777.  
  778.         test    [si].ci_vdm_flag,VDM_Flag_InUse ; if this port is in use by VDM
  779.         jz      lxi20
  780.                                                 ; get only the error status bits
  781.         cmp     [si].ci_qin.ioq_count,QI_SIZE-2 ;@@ is RcvQ full now?
  782.         jb      no_soft_overrun                 ;@@ no, so go on
  783.         or      ax,CE_SW_OVERRUN                ;@@ yes, so flag soft overrun
  784.  
  785. ifdef PERFVIEW
  786.         pvw_SW_Overrun                          ;@PVW increment perfview cntr
  787. endif
  788.  
  789. no_soft_overrun:
  790.         mov     bx,[si].ci_qin.ioq_in           ; Get the offset of Rcv Head
  791.         sub     bx,[si].ci_qin.ioq_base         ; bx = offset of status
  792.         mov     [si+bx].ci_qstat,al             ; save error LSR for curr char
  793.  
  794. ; @VDM change end
  795.  
  796. lxi20:
  797. IFDEF LXDEBUG
  798.    ;    test    al,LS_OERR OR LS_PERR OR LS_FERR
  799.    ;    jz      lxi40                   ; no errors
  800.  
  801.    ;    ComErr  <LxInt : line status error (al = lsr)>
  802. lxi40:
  803. ENDIF
  804.         test    al,LS_BI                ; break detect?
  805.         jz      lxi50                   ; not break detect interrupt
  806.  
  807.         or      [si].ci_event,EV_BREAK  ; show break in event word
  808.  
  809.         .errnz  LS_OERR-CE_HW_OVERRUN   ; must be the same bits
  810.         .errnz  LS_PERR-CE_RX_PARITY
  811.         .errnz  LS_FERR-CE_FRAME
  812.  
  813. lxi50:
  814.         and     ax,CE_HW_OVERRUN OR CE_RX_PARITY OR CE_FRAME ; mask error bits
  815.         jz      rxi05                    ; no errors
  816.  
  817.         test    ax,CE_HW_OVERRUN
  818.         jz      lxi51
  819.  
  820. ifdef PERFVIEW
  821.         pvw_HW_Overrun                          ;@PVW increment perfview cntr
  822. endif
  823.  
  824. lxi51:
  825.  
  826.         or      [si].ci_comerr,ax       ; combine error bits with prev. errors
  827.         or      [si].ci_event,EV_ERR    ; show line status error
  828.  
  829.  
  830. ; use lsrshadow because LxInt read LSR clearing the error bits.
  831. rxi05:
  832.         mov     ah,[si].ci_lsrshadow            ; (ah) = LSR shadow
  833.  
  834. ; clear the line status data ready and error bits in the shadow
  835.         and     [si].ci_lsrshadow,NOT (LS_DR OR LS_OERR OR LS_PERR OR LS_FERR OR LS_BI)
  836.  
  837.         test    ah,LS_DR
  838. ;       ljz     rxix                            ; no more data available
  839.         jnz     rxi06                           ; no more data available
  840.  
  841.         ret                                     ; save time
  842. rxi06:
  843.         mov     dx,[si].ci_port
  844.         .errnz  R_DATA
  845. ;       add     dx,R_DATA                       ; (dx) -> data I/O Reg.
  846.         in      al,dx                           ; (al) = character from HW
  847.         and     al,[si].ci_cmask                ; clear unwanted bits
  848.  
  849.         sti                                     ; enable interrupts
  850.  
  851.         test    [si].ci_Flagx1,FX1_FLUSH_RX_IP ;;MF flushing RX queue
  852.         ljnz    rxix                           ;;MF yes, drop the data and leave
  853.  
  854. ;* Input Sensitivity to DSR Processing
  855.         test    [si].ci_flagx,FX_IN_DSR_OK
  856.         ljz     rxi_top                         ; DSR is down, ignore all input
  857.                                                 ; loop back and read all input
  858.  
  859.         test    ah,LS_OERR OR LS_PERR OR LS_FERR OR LS_BI
  860.         jz      rxi40             ; not overrun, parity, framing or break error
  861.  
  862. ;* Overrun Error Processing
  863.         test    ah,LS_OERR
  864.         jz      rxi20                           ; not overrun error
  865.         test    [si].ci_dcb_flags2,F2_ERR_CHAR
  866.         jz      rxi20                           ; error character not enabled
  867.  
  868.         mov     dx,0001h                        ; dx = 1; assume NO FIFO
  869.         test    [si].ci_dcb_flags3,F3_FIFO_HW_ON
  870.         jz      rxi10                           ; FIFO HW not on
  871.         mov     dx,8000h                ; FIFO HW on, error AFTER 16th char
  872. rxi10:  or      cx,dx                           ; turn on correct error bit
  873.  
  874. ;* Break Interrupt Processing
  875. rxi20:  test    ah,LS_BI
  876.         jz      rxi30                           ; not break interrupt
  877.         test    [si].ci_dcb_flags2,F2_BRK_CHAR
  878.         ljz     rxi56                           ; break character not enabled
  879.         mov     al,[si].ci_dcb_BrkChar          ; al = break char
  880.         jmp     rxi_q                           ; go queue break char
  881.  
  882. ;* Parity and Framing Error Processing
  883. rxi30:  test    ah,LS_PERR OR LS_FERR
  884.         jz      rxi40                           ; not parity or framing error
  885.  
  886.         ; parity or framing error
  887.         test    [si].ci_dcb_flags2,F2_ERR_CHAR
  888.         ljz     rxi_q                   ; error replace not active,
  889.                                         ; let the character through,
  890.                                         ; but DON'T check for NULL/XON/XOFF
  891.  
  892.         mov     al,[si].ci_dcb_ErrChar  ; al = error char
  893.         jmp     rxi_q                   ; go queue the error char
  894.                                         ; but DON'T check for NULL/XON/XOFF
  895.  
  896. ;* Valid Character With NO Parity Or Framing Errors
  897. ; we have a good character, check it for NULL/XON/XOFF
  898.  
  899. ;* NULL Strip Processing
  900. rxi40:  or      al,al
  901.         jnz     rxi45                   ; not a null character
  902.         test    [si].ci_dcb_flags2,F2_NULL_STRIP
  903.         ljnz    rxi_skip                ; strip the null character
  904.  
  905. ;* XON/XOFF Processing
  906. ; if output XON/XOFF is enabled and char is XON or XOFF,
  907. ;       set/clear the XOFF_received flag
  908. ;       call CheckTx to enable/disable Tx interrupts
  909. ;       drop the character
  910.  
  911. rxi45:  test    [si].ci_vdm_flag,VDM_Flag_InUse ; if this port is in use by VDM
  912.         jnz     rxi46
  913.  
  914.         test    [si].ci_dcb_flags2,F2_OUT_XO
  915.         jz      rxi_q                           ; output XON/XOFF not enabled
  916.         jmp     rxi49
  917.  
  918. rxi46:  pushf
  919.         cli
  920.         cmp     al,XOFFequ              ; Is it a XOff character?
  921.         jne     vdmNextChar_1           ; no, reset state to normal
  922.         cmp     [si].ci_vdm_Rx_State,3  ; are we already in state 3?
  923.         je      vdmNextChar             ; yes - no work to do
  924.         mov     [si].ci_vdm_Rx_State,2  ; set rcv state to 2
  925.                                         ; (Xoff from device not sent to app)
  926.         or      [si].ci_Flagx1,FX_XO_FOUND  ; show we found a ctrl char
  927.         jmp     SHORT vdmNextChar       ; no, test the next character
  928.  
  929. vdmNextChar_1:
  930.         mov     [si].ci_vdm_Rx_State,1  ; set rcv state to normal
  931.         mov     [si].ci_vdm_Tx_Count,0  ;  "   "    "    "   "
  932.  
  933. vdmNextChar:
  934.         cmp     [si].ci_vdm_Tx_State,3  ; VDM are we in state 3?
  935.         jne     vdmnextchar1            ; VDM no, do next character stuff
  936.         inc     [si].ci_vdm_Rx_Count    ; VDM inc received char count
  937.         cmp     [si].ci_vdm_Rx_Count,VDM_Max_Rx_Count ; VDM is it max?
  938.         jne     vdmnextchar1            ; VDM no, do next character stuff
  939.  
  940.         mov     [si].ci_vdm_Rx_Count,0  ; VDM 0 count
  941.         mov     [si].ci_vdm_Tx_State,1  ; VDM reset to normal state
  942.  
  943. vdmnextchar1:
  944.         test    [si].ci_Flagx1,FX_XO_FOUND  ; if ctrl char found
  945.         jz      vdmtxflx                ; nope, so exit
  946.         call    CheckTX                 ; go and turn tx off
  947.         and     [si].ci_Flagx1,NOT FX_XO_FOUND  ; clear ctrl char found flag
  948. vdmtxflx:                                  ; 
  949.         popf                            ; INT restore
  950.         jmp     SHORT rxi_q
  951.  
  952. rxi49:  cmp     al,[si].ci_dcb_XoffChar
  953.         jne     rxi50                           ; not an XOFF, go check XON
  954.  
  955.         or      [si].ci_hsflag,HS_XOFF_RECEIVED
  956.         jmp     SHORT rxi55                     ; go call CheckTx
  957.  
  958. rxi50:  cmp     al,[si].ci_dcb_XonChar
  959.         jne     rxi_q                           ; not an XON
  960.  
  961.         and     [si].ci_hsflag,NOT HS_XOFF_RECEIVED ; show XOFF NOT received
  962. rxi55:  call    CheckTX                         ; may enable Tx Interrupt
  963. rxi56:  jmp     SHORT rxi_skip                  ; skip queueing the xoff/xon
  964.  
  965.  
  966. ;* Queue Data - check for overrun and queue data
  967. rxi_q:
  968.         test    cx,1
  969.         jz      rxi_qq                          ; no overrun error on this byte
  970.  
  971.         test    [si].ci_dcb_flags3,F3_FIFO_HW_ON
  972.         jnz     rxi_qq                          ; FIFO HW on, append err char
  973.  
  974.         and     cx,NOT 1                        ; turn off the error bit
  975.         xchg    al,ah                           ; ah = RX data
  976.         mov     al,[si].ci_dcb_ErrChar          ; al = error char
  977.  
  978.         call    WriteQueueByte                  ; queue the error char
  979.  
  980.         xchg    al,ah                           ; al = RX data
  981.      ;  cli
  982.      ;  INT_Notify                      ;@VDM Macro to see if we need to
  983.      ;                                  ;@VDM notify the VDM of RX, TX or MS
  984.      ;                                  ;@VDM interrupts
  985.      ;  sti
  986.  
  987. rxi_qq:
  988.         call    WriteQueueByte                  ; queue the received character
  989.  
  990.         cli
  991.         INT_Notify                      ;@VDM Macro to see if we need to
  992.         sti                             ;@VDM notify the VDM of RX, TX or MS
  993.                                         ;@VDM interrupts
  994.  
  995. rxi_skip:
  996.         shr     cx,1
  997.         jnc     rxi_loop                        ; no overrun error on this byte
  998.  
  999.  
  1000.         mov     al,[si].ci_dcb_ErrChar          ; al = error char
  1001.         call    WriteQueueByte                  ; queue the error char
  1002.  
  1003.         cli
  1004.         INT_Notify                      ;@VDM Macro to see if we need to
  1005.         sti                             ;@VDM notify the VDM of RX, TX or MS
  1006.                                         ;@VDM interrupts
  1007.  
  1008.  
  1009. rxi_loop:
  1010.         cli
  1011.         ReadLSR                         ; (al) = LSR
  1012.         test    al,LS_DR
  1013.         jz      rxix                            ; no more data available
  1014.  
  1015.         jmp     rxi_lxint                       ; loop back to top
  1016.  
  1017. rxix:
  1018.         ret
  1019.  
  1020. EndProc RxInt
  1021.  
  1022.  
  1023. ;**     TxInt - Tx Holding Register Empty Interrupt (third priority)
  1024. ;
  1025. ;       ENTRY   (ds:si) -> ComInfo
  1026. ;               dx      =  interrupt id register port (R_INTID)
  1027. ;
  1028. ;       EXIT    none
  1029. ;
  1030. ;       USES    ax bx cx dx
  1031. ;
  1032. ;       Pseudo Code:
  1033. ;
  1034. ;       if (8250 && tx not empty)
  1035. ;           return
  1036. ;
  1037. ;       count = 1                               ; assume only TX 1 char
  1038. ;       if (flags3.TX_16)
  1039. ;           count = 16                          ; TX 16 chars
  1040. ;
  1041. ;   do {
  1042. ;       if (hsflag & (XOFF_pending | XON_pending | TX_immediate_pending)) {
  1043. ;           if (hsflag & XOFF_pending) {
  1044. ;               hsflag &= !XOFF_pending
  1045. ;               hsflag |= XOFF_sent
  1046. ;               al = XOFF_char
  1047. ;           }
  1048. ;           else if (hsflag & XON_pending) {
  1049. ;               hsflag &= !(XON_pending | XOFF_sent)
  1050. ;               al = XON_char
  1051. ;           }
  1052. ;           else if (hsflag & TX_immediate_pending) {
  1053. ;               hsflag &= !TX_immediate_pending
  1054. ;               al = TX_immediate_char
  1055. ;           }
  1056. ;           write (al) to port
  1057. ;           call CheckTX
  1058. ;           if (carry)
  1059. ;               goto done                       ; no more to TX, done
  1060. ;           goto continue
  1061. ;       }
  1062. ;
  1063. ;       if (no current request packet)
  1064. ;           internal error
  1065. ;
  1066. ;       al = ReadQueueByte                      ; read next byte of data to TX
  1067. ;       if (got data from queue) {
  1068. ;           write (al) to port
  1069. ;           w_to = w_to_start                   ; reset write timeout
  1070. ;       }
  1071. ;
  1072. ;       if (w_to_move == 0) {                     ; no data left from user buffer
  1073. ;           if (qcount == 0) {                  ; no data in q either
  1074. ;               put request on ready list       ;  done with req, try next one
  1075. ;               clear current request pointer
  1076. ;               call StartNextWRP               ; start next req (calls CheckTX)
  1077. ;               if (carry)
  1078. ;                   goto done                   ; no more req OR cant TX, done
  1079. ;           } else
  1080. ;               goto continue                   ; data left in queue
  1081. ;       }
  1082. ;       if (qcount <= TX_MOVE_PROT) {           ; queue below low water mark
  1083. ;           if (readmode && qcount > TX_MOVE_REAL)
  1084. ;               goto continue
  1085. ;           flag data moved
  1086. ;           call WriteQueue(w_to_move)          ; to get the next chunk of data
  1087. ;       }
  1088. ;   continue:
  1089. ;   } while (--count)
  1090. ;   done:
  1091.  
  1092.  
  1093. Procedure TxInt,NEAR
  1094.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1095.  
  1096.         ; BUGBUG - START OF      TO IGNORE SPURIOUS TX INTERRUPTS
  1097.         ; Workaround for a hardware     in the 8250 chip:
  1098.         ; if TX interrupt is enabled when the transmiter holding
  1099.         ; register is NOT empty, a TX interrupt is generated anyway.
  1100.         ; We have to ignore the spurious TX interrupt.
  1101.         ; Another transmit interrupt will be generated when the
  1102.         ; transmitter holding register actually does empty.
  1103. txi00:
  1104. txi05:
  1105.         test    [si].ci_flagx,FX_16450 OR FX_16550A
  1106.         jnz     txi10                   ; 16450 or FX_16550A
  1107.  
  1108.         ReadLSR                         ; (al) = line status register (uses dx)
  1109.         test    al,LS_THRE
  1110.         ljz     txix                    ; transmitter not empty, can't be tx int
  1111.         ; BUGBUG - END OF      TO IGNORE SPURIOUS TX INTERRUPTS
  1112.  
  1113. txi10:  sti             ; enable RX ints on other port
  1114.  
  1115.         mov     cx,1                    ; cx = tx count = 1
  1116.         test    [si].ci_dcb_flags3,F3_TX_16
  1117.         jz      txitop
  1118.         mov     cx,16                   ; cx = tx count = 16 (FIFO on)
  1119.  
  1120. txitop:
  1121.         test    [si].ci_Flagx1,FX1_FLUSH_TX_IP  ;;MF flushing TX queue
  1122.         ljnz    txix                    ;;MF yes, drop interrupt and leave
  1123.  
  1124.         mov     ah,[si].ci_hsflag       ; get handshake flag
  1125.         test    ah,HS_XON_PENDING OR HS_XOFF_PENDING OR HS_TX_IMMED
  1126.  
  1127. IFDEF   RPTSTRICT
  1128.         Debug = 1
  1129. ENDIF
  1130.  
  1131.         ljnz    txixo                   ; XON/XOFF/TX_IMMED pending, go process
  1132.  
  1133.         cmp     [si].ci_w_rp._hi,0
  1134.         jnz     txi50                   ; current request
  1135.  
  1136.         test    [si].ci_vdm_flag,VDM_Flag_InUse
  1137.         jnz     txi50                   ;@VDM   it is OK  It's a VDM
  1138.  
  1139.         inc     bad_int                 ;it is not OK, increment     mark
  1140.         cmp     bad_int,BAD_MAX         ;it is maximum, go to hell
  1141.         je      txie1                   ;@VDM   internal error
  1142.         call    CheckTX                 ;still have a hope  turn off tx int
  1143.         ret
  1144.  
  1145. txie1:
  1146.         mov     dx,[si].ci_port
  1147.         add     dx,R_INTEN              ; (dx) -> interrupt enable reg
  1148.         in      al,dx                   ; (al) =  interrupt enable
  1149.  
  1150.         test    al,IE_TX
  1151.         jz      txie2
  1152.  
  1153.         and     al,NOT IE_TX            ; disable TX interrupts first
  1154.  
  1155.         out     dx,al
  1156.  
  1157.         ret
  1158.  
  1159. txie2:
  1160.         ComErr  <TxInt : no current request packet>
  1161.  
  1162.         ret
  1163.  
  1164. txi50:  ; read a char from the queue and send it to the HW
  1165.         mov     bad_int,0               ; reset     interrupt count
  1166.         call    ReadQueueByte           ; get next byte from queue
  1167.         jc      txi70                   ; no data in queue
  1168.  
  1169.         mov     dx,[si].ci_port
  1170.         out     dx,al                   ; send data byte
  1171.         cli
  1172.  
  1173.         INT_Notify                      ;@VDM Macro to see if we need to
  1174.                                         ;@VDM notify the VDM of RX, TX or MS
  1175.                                         ;@VDM interrupts
  1176.  
  1177.         sti
  1178.         mov     bx,[si].ci_w_to_start   ; get start value for timeout
  1179.         mov     [si].ci_w_to,bx
  1180.  
  1181. txi70:  cmp     [si].ci_w_to_move,0
  1182.         jne     txi90                   ; data still to move, request not done
  1183.  
  1184.         cmp     [si].ci_qout.ioq_count,0
  1185.         jne     txicont                 ; data still in queue, request not done
  1186.  
  1187.         cmp     [si].ci_w_rp._hi,0
  1188.         je      txi85                   ; no current request packet
  1189.  
  1190. txi80:  ; request is done
  1191.         les     di,[si].ci_w_rp         ; (es:di) -> request packet
  1192.         ASSUME  es:NOTHING
  1193.         ChkRPPtr
  1194.         ChkRPType       CMDOUTPUT
  1195.         ProcReady                       ; put request on ready list (run later)
  1196.         mov     [si].ci_w_rp._hi,0      ; no longer current
  1197.  
  1198. txi85:
  1199.         call    CheckTX         ;;MF    ; disable tx ints if needed
  1200. ;;mf    call    StartNextWRP            ; start the next request (calls CheckTX)
  1201. ;;mf    jc      txix                    ; no more requests OR not ready to TX
  1202.         jmp     txix    ;;mf            ; no more requests
  1203.  
  1204. txi90:
  1205.         mov     bx,[si].ci_qout.ioq_count
  1206.         cmp     bx,TX_MOVE_PROT
  1207.         ja      txicont                 ; not down to prot mode mark
  1208.  
  1209.  
  1210.         ; hit low water mark, move more data
  1211. txi95:  or      [si].ci_flagx,FX_DATA_MOVED     ; mark data moved
  1212.         SaveReg <cx>
  1213.         les     di,[si].ci_w_rp         ; (es:di) -> request packet
  1214.         ASSUME  es:NOTHING
  1215.         ChkRPPtr
  1216.         ChkRPType       CMDOUTPUT
  1217.         mov     cx,[si].ci_w_to_move    ; set up count
  1218.         call    WriteQueue              ; move data into queue
  1219.         RestoreReg <cx>
  1220.  
  1221. txicont:
  1222.  
  1223. ;IFNDEF  RPTSTRICT
  1224. ;        loop    txitop                  ; transmit up to cx characters
  1225. ;ELSE
  1226.         dec     cx
  1227.         jz      txix
  1228.         jmp     txitop                  ; transmit up to cx characters
  1229. ;ENDIF
  1230.  
  1231.  
  1232. ;* handle XOFF/XON/TX_IMMED here
  1233. txixo:
  1234.         mov     bad_int,0               ; reset     interrupt count
  1235.         test    ah,HS_XOFF_PENDING
  1236.         jz      txixo2                  ; not XOFF, must be XON or TX_IMMED
  1237.  
  1238.         ; XOFF pending
  1239.         and     ah,NOT HS_XOFF_PENDING  ; XOFF no longer pending
  1240.         or      ah,HS_XOFF_SENT         ; show XOFF sent
  1241.         mov     [si].ci_hsflag,ah       ; save updated handshake flag
  1242.         mov     al,[si].ci_dcb_xoffchar ; get XOff char
  1243.         jmp     SHORT txixo4            ; go output the character.
  1244.  
  1245. txixo2: ; XON or TX_IMMED pending
  1246.         test    ah,HS_XON_PENDING
  1247.         jz      txixo3                  ; not XON, must be TX_IMMED
  1248.  
  1249.         ; XON pending
  1250.         and     [si].ci_hsflag,NOT (HS_XON_PENDING OR HS_XOFF_SENT)
  1251.         mov     al,[si].ci_dcb_xonchar  ; get XON char
  1252.         jmp     SHORT txixo4            ; go output the character.
  1253.  
  1254. txixo3: ; TX_IMMED pending
  1255.         and     [si].ci_hsflag,NOT HS_TX_IMMED  ; clear xmit immediate flag
  1256.         mov     al,[si].ci_tximm                ; get char to xmit
  1257.  
  1258. txixo4: mov       dx,[si].ci_port
  1259.         out     dx,al                   ; send XON, XOFF, or TxImm char
  1260.         call    CheckTX        ; check if we can still TX
  1261.         jc      txix                    ; not ready to TX, done
  1262.         jmp     SHORT txicont
  1263.  
  1264. txix:
  1265.         pushf
  1266.         cli
  1267.         test    [si].ci_vdm_flag,VDM_Flag_InUse
  1268.         jz      txi89
  1269.         ; VDM using this COM port
  1270.  
  1271.         mov     ax,[si].ci_qout.ioq_count
  1272.         cmp     ax,0
  1273.         jne     txi89
  1274.  
  1275.         test    [si].ci_vdm_flag,VDM_Flag_Blocked_IOCTL
  1276.         jz      txi81
  1277.         ; run IOCTL thread that is blocked
  1278.  
  1279.         push    es
  1280.         push    di
  1281.         push    bx
  1282.         push    ax
  1283.  
  1284.         les     di,[si].ci_vdm_Blocked_IOCTL; (es:di) -> request packet
  1285.         call    ProcRun                 ; run it
  1286.         and     [si].ci_vdm_flag,NOT VDM_Flag_Blocked_IOCTL
  1287.  
  1288.         pop     ax
  1289.         pop     bx
  1290.         pop     di
  1291.         pop     es
  1292.  
  1293. txi81:
  1294.         cmp     [si].ci_vdm_Tx_State,2  ; if TX_State == 2
  1295.         jne     txi89
  1296.         ; TX_STATE == 2
  1297.  
  1298.         ; cmp RX buffer,empty
  1299.         push    ax
  1300.         mov     ax,[si].ci_qin.ioq_count
  1301.         cmp     ax,0
  1302.         pop     ax
  1303.         je      txi82
  1304.  
  1305.         ; RX buffer not empty
  1306.         mov     [si].ci_vdm_Tx_State,3
  1307.         mov     [si].ci_vdm_Rx_count,0
  1308.         jmp     short txi89
  1309.  
  1310. txi82:  ; RX buffer empty
  1311.  
  1312.         mov     [si].ci_vdm_Tx_State,1
  1313.         mov     [si].ci_vdm_Rx_count,0
  1314.  
  1315. txi89:
  1316.         popf
  1317.         ret                             ; leave
  1318.  
  1319. EndProc TxInt
  1320.  
  1321.  
  1322. ;**     MxInt - Modem Status Interrupt (lowest priority)
  1323. ;
  1324. ;       ENTRY   (ds:si) -> ComInfo
  1325. ;               (al) = modem status register
  1326. ;
  1327. ;       EXIT    none
  1328. ;
  1329. ;       USES    ax dx
  1330.  
  1331. Procedure MxInt,HYBRID
  1332.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1333.  
  1334.         mov     bad_int,0               ; reset     interrupt count
  1335.  
  1336.         ChkComInfoPtr
  1337.  
  1338. ;        mov     [si].ci_vdm_LastMSR,al ; RDW 80677
  1339.  
  1340. IFDEF MSR_DEBUG
  1341.         ; Save all MSR values in a circular buffer for debugging
  1342.     DSEG SEGMENT
  1343.         PUBLIC MSR_buf,MSR_ptr
  1344.         MSR_BUF_SIZE    EQU     1024            ; size of MSR_buf
  1345.         MSR_ptr DW      OFFSET DSEG:MSR_buf     ; pointer into MSR_buf
  1346.         MSR_buf DB      MSR_BUF_SIZE dup (0)    ; buffer for MSR values
  1347.     DSEG ENDS
  1348.  
  1349.         push    bx
  1350.         mov     bx,MSR_ptr              ; (bx) -> MSR_buf
  1351.         cmp     bx,OFFSET MSR_buf + MSR_BUF_SIZE
  1352.         jb      mxi10                   ; not at end of buffer
  1353.  
  1354.         mov     bx,OFFSET MSR_buf       ; at end of buffer, wrap to beginning
  1355.  
  1356. mxi10:  mov     [bx],al                 ; save msr value in table
  1357.         inc     bx                      ; (bx) -> next MSR_buf value
  1358.         mov     MSR_ptr,bx
  1359.         pop     bx
  1360. ENDIF
  1361.  
  1362.  
  1363. ; check DSR for input sensitivity to DSR
  1364. ; character is good if:
  1365. ;   input sensitivity to DSR is NOT active OR
  1366. ;   DSR was high before OR is high now
  1367.  
  1368.         .errnz   MS_DSR          - 00100000b
  1369.         .errnz   FX_IN_DSR_OK    - 00100000b
  1370.         .errnz   F1_IN_DSR_SENSE - 01000000b
  1371.  
  1372.         mov     dl,[si].ci_dcb_flags1
  1373.         not      dl                      ; (dl) = NOT flags1
  1374.         shr          dl,1
  1375.         or      dl,[si].ci_msrshadow    ; (dl) = NOT flags1 OR old MSR
  1376.         or      dl,al                   ; (dl) = NOT flags1 OR old OR new MSR
  1377.  
  1378.         and        dl,FX_IN_DSR_OK         ; (dl) = DSR ok
  1379.  
  1380.         and     [si].ci_flagx,NOT FX_IN_DSR_OK
  1381.         or      [si].ci_flagx,dl
  1382.  
  1383.  
  1384. ; save the modem staus register in the shadow.
  1385.  
  1386.         mov     [si].ci_msrshadow,al   ; save MSR data for others
  1387.  
  1388.         ; modem status positions (before shifting)
  1389.         .errnz         MS_DCTS-00000001b
  1390.         .errnz   MS_DDSR-00000010b
  1391.         .errnz   MS_TERI-00000100b
  1392.         .errnz           MS_DDCD-00001000b
  1393.  
  1394.         ; event mask positions (after shifting)
  1395.         .errnz     EV_CTS-000001000b
  1396.         .errnz   EV_DSR-000010000b
  1397.         .errnz   EV_DCD-000100000b
  1398.         .errnz  EV_Ring-100000000b      ; 9 bits!
  1399.  
  1400.                         ; create the event mask from the modem status
  1401.                         ; y = carrier detect
  1402.                         ; t = tailing edge ring indicator
  1403.                         ; d = data set ready
  1404.                         ; c = clear to send
  1405.  
  1406.                         ; 7 6 5 4 3 2 1 0    7 6 5 4 3 2 1 0
  1407.         mov     ah,al   ; . . . . y t d c    . . . . y t d c
  1408.         shr     ax,2    ; . . . . . . y t    d c . . . . y t
  1409.         ror     ah,1    ; t . . . . . . y    d c . . . . y t
  1410.         shr     ax,3    ; . . . t . . . .    . . y d c . . .
  1411.         shr     ah,4    ; . . . . . . . t    . . y d c . . .
  1412.         and     ax,EV_CTS OR EV_DSR OR EV_DCD OR EV_Ring
  1413.         or      [si].ci_event,ax
  1414.  
  1415.         ; So we can us same MxInt routine for standard and enhanced ports
  1416.  
  1417.         call    CheckTX
  1418.  
  1419.  
  1420.         INT_Notify                      ;@VDM Macro to see if we need to
  1421.                                         ;@VDM notify the VDM of RX, TX or MS
  1422.                                         ;@VDM interrupts
  1423.  
  1424. mxx:    ret
  1425.  
  1426. EndProc MxInt
  1427.  
  1428.  
  1429. ;**     Ticker - timeout routine
  1430. ;
  1431. ;       Call timeout routines for read and write on COM1 and COM2.
  1432. ;
  1433. ;       NOTE    timer tick handlers DO need to save registers
  1434. ;
  1435. ;       ENTRY   ds = device driver data segment (set up by kernel)
  1436. ;
  1437. ;       EXIT    none
  1438. ;
  1439. ;       USES    none
  1440.  
  1441. Procedure SwapTicker,FAR
  1442.         ASSUME  cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1443.  
  1444.         pushf
  1445.         pusha
  1446.         SaveReg         <es,ds>
  1447.  
  1448.         mov     si,Com1                 ; (ds:si) -> ComInfo structure
  1449.         or      si,si
  1450.         jz      tic1                    ; no com1 port
  1451.         cmp     [si].ci_nopens,0
  1452.         je      tic1
  1453.  
  1454.  
  1455.         test    [si].ci_flagx,FX_RTS_DROP_PENDING
  1456.         jz      tic0                    ; RTS drop not pending
  1457.  
  1458.         ReadLSR                         ; (al) = LSR
  1459.  
  1460.         and     al,LS_THRE OR LS_TSRE
  1461.         cmp     al,LS_THRE OR LS_TSRE
  1462.         jne     tic0                    ; THR or TSR are not empty
  1463.  
  1464.         and     [si].ci_flagx,NOT FX_RTS_DROP_PENDING
  1465.                                         ; clear flag
  1466.         add     dx,R_MODMC-R_LINES      ; (dx) -> modem control reg.
  1467.         min     al,dx                   ; (al) = MCR
  1468.         and     al,NOT MC_RTS           ; turn RTS off
  1469.         out     dx,al
  1470.  
  1471. tic0:   call    ReadTick
  1472.         call    WriteTick
  1473.  
  1474. tic1:   mov     si,Com2                 ; (ds:si) -> ComInfo structure
  1475.         or      si,si
  1476.         jz      tic3                    ; no com2 port
  1477.         cmp     [si].ci_nopens,0
  1478.         je      tic3
  1479.  
  1480.         test    [si].ci_flagx,FX_RTS_DROP_PENDING
  1481.         jz      tic2                    ; RTS drop not pending
  1482.  
  1483.         ReadLSR                         ; (al) = LSR
  1484.  
  1485.         and     al,LS_THRE OR LS_TSRE
  1486.         cmp     al,LS_THRE OR LS_TSRE
  1487.         jne     tic2                    ; THR or TSR are not empty
  1488.  
  1489.         and     [si].ci_flagx,NOT FX_RTS_DROP_PENDING
  1490.                                         ; clear flag
  1491.         add     dx,R_MODMC-R_LINES      ; (dx) -> modem control reg.
  1492.         min     al,dx                   ; (al) = MCR
  1493.         and     al,NOT MC_RTS           ; turn RTS off
  1494.         out     dx,al
  1495.  
  1496. tic2:   call    ReadTick
  1497.         call    WriteTick
  1498.  
  1499. tic3:   mov     si,Com3                 ; (ds:si) -> ComInfo structure
  1500.         or      si,si
  1501.         jz      tic5                    ; no com3 port
  1502.         cmp     [si].ci_nopens,0
  1503.         jz      tic5
  1504.  
  1505.         test    [si].ci_flagx,FX_RTS_DROP_PENDING
  1506.         jz      tic4                    ; RTS drop not pending
  1507.  
  1508.         ReadLSR                         ; (al) = LSR
  1509.  
  1510.         and     al,LS_THRE OR LS_TSRE
  1511.         cmp     al,LS_THRE OR LS_TSRE
  1512.         jne     tic4                    ; THR or TSR are not empty
  1513.  
  1514.         and     [si].ci_flagx,NOT FX_RTS_DROP_PENDING
  1515.                                         ; clear flag
  1516.         add     dx,R_MODMC-R_LINES      ; (dx) -> modem control reg.
  1517.         min     al,dx                   ; (al) = MCR
  1518.         and     al,NOT MC_RTS           ; turn RTS off
  1519.         out     dx,al
  1520.  
  1521. tic4:   call    ReadTick
  1522.         call    WriteTick
  1523.  
  1524. tic5:   mov     si,Com4                 ; (ds:si) -> ComInfo structure
  1525.         or      si,si
  1526.         jz      ticx                    ; no com4 port
  1527.         cmp     [si].ci_nopens,0
  1528.         je      ticx
  1529.  
  1530.         test    [si].ci_flagx,FX_RTS_DROP_PENDING
  1531.         jz      tic6                    ; RTS drop not pending
  1532.  
  1533.         ReadLSR                         ; (al) = LSR
  1534.  
  1535.         and     al,LS_THRE OR LS_TSRE
  1536.         cmp     al,LS_THRE OR LS_TSRE
  1537.         jne     tic6                    ; THR or TSR are not empty
  1538.  
  1539.         and     [si].ci_flagx,NOT FX_RTS_DROP_PENDING
  1540.                                         ; clear flag
  1541.         add     dx,R_MODMC-R_LINES      ; (dx) -> modem control reg.
  1542.         min     al,dx                   ; (al) = MCR
  1543.         and     al,NOT MC_RTS           ; turn RTS off
  1544.         out     dx,al
  1545.  
  1546. tic6:   call    ReadTick
  1547.         call    WriteTick
  1548.  
  1549. ticx:   RestoreReg      <ds,es>
  1550.         popa
  1551.         popf
  1552.         ret
  1553.  
  1554. EndProc SwapTicker
  1555.  
  1556.  
  1557. ;**     WriteTick - see if a write request timed out
  1558. ;
  1559. ;       If there is a current write request, and infinite timeout
  1560. ;       is not on, decrement the timeout counter.
  1561. ;       If counter goes to zero, calculate the number of characters
  1562. ;       already sent to the hardware, complete the request, and
  1563. ;       start the next write request.
  1564. ;
  1565. ;       ENTRY   (ds:si) -> ComInfo structure
  1566. ;
  1567. ;       EXIT
  1568. ;
  1569. ;       USES    ax dx di es
  1570.  
  1571. Procedure WriteTick,NEAR
  1572.         ASSUME  cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1573.  
  1574.         ChkComInfoPtr
  1575.  
  1576.         test    [si].ci_Flagx1,FX1_FLUSH_TX_IP ;;MF
  1577.         jnz     wtkx                           ;;MF
  1578.  
  1579.         cli
  1580.         cmp     [si].ci_w_rp._hi,0
  1581.         je      wtkx                    ; no current write request
  1582.  
  1583.         test    [si].ci_dcb_flags3,F3_W_INF_TO
  1584.         jnz     wtkx                    ; infinite time
  1585.  
  1586.         dec     [si].ci_w_to            ; record tick
  1587.         jnz     wtkx                    ; no time out
  1588.  
  1589.         les     di,[si].ci_w_rp         ; (es:si) -> request packet
  1590.         ASSUME  es:NOTHING
  1591.         ChkRPPtr
  1592.         ChkRPType       CMDOUTPUT
  1593.  
  1594.         mov     ax,[si].ci_qout.ioq_count
  1595.         add     ax,[si].ci_w_to_move    ; ax = number not written
  1596.         sub     es:[di].IOcount,ax      ; number of bytes actually written
  1597.         FlushQueue      ci_qout
  1598.         mov     [si].ci_w_rp._hi,0      ; no longer current
  1599.  
  1600.         ; Time to Run any requests on ready list, start the next write
  1601.         ; request, and disable tx if needed.
  1602.  
  1603.         sti
  1604.         ; Standard port
  1605.         call    ProcRun
  1606.         cmp     GAS_Switch,0
  1607.         je      skip_alert
  1608.         call    SetAlert                ; set up any SNA alerts
  1609. skip_alert:
  1610. ;;mf    call    StartNextWRP
  1611.         call    CheckTX         ;;MF    ; disable TX ints if needed
  1612.         jmp     SHORT wtkx
  1613.  
  1614.  
  1615. wtkx:   sti
  1616.         ret
  1617.  
  1618. EndProc WriteTick
  1619.  
  1620.  
  1621. ;**     ReadTick - see if a read request timed out
  1622. ;
  1623. ;       If there is a current read request, decrement the timeout counter.
  1624. ;       If counter goes to zero, ProcRun the request.
  1625. ;       When the thread wakes up, it attempts to complete the request
  1626. ;       from the data available in the input queue
  1627. ;       and starts the next request.
  1628. ;
  1629. ;       ENTRY   (ds:si) -> ComInfo structure
  1630. ;
  1631. ;       EXIT
  1632. ;
  1633. ;       USES    ax bx di es
  1634.  
  1635. Procedure ReadTick,NEAR
  1636.         ASSUME  cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1637.  
  1638.         ChkComInfoPtr
  1639.  
  1640.         test    [si].ci_Flagx1,FX1_FLUSH_RX_IP ;;MF
  1641.         jnz     rtkx                           ;;MF
  1642.  
  1643.         cli
  1644.         cmp     [si].ci_r_rp._hi,0
  1645.         je      rtkx                    ; no current read request
  1646.  
  1647.         dec     [si].ci_r_to            ; record tick
  1648.         jnz     rtkx                    ; no time out
  1649.  
  1650.         les     di,[si].ci_r_rp         ; (es:di) -> request packet
  1651.         ASSUME  es:NOTHING
  1652.         ChkRPPtr
  1653.         ChkRPType     CMDINPUT
  1654.  
  1655.         sti
  1656.         call    ProcRun
  1657.  
  1658. rtkx:   sti
  1659.         ret
  1660.  
  1661. EndProc ReadTick
  1662.  
  1663. ;********************** START OF SPECIFICATIONS *********************
  1664. ;*
  1665. ;* SUBROUTINE NAME:  TellVCOMxx
  1666. ;*
  1667. ;* DESCRIPTIVE NAME: PCOM to VCOM Interrupt Notification Routine
  1668. ;*
  1669. ;* STATUS: RELEASE 2  LEVEL 0
  1670. ;*
  1671. ;* FUNCTION: Tells VCOM when an interrupt needs to be reflected to the
  1672. ;*           DOS app running in a VDM.
  1673. ;*
  1674. ;* NOTES:
  1675. ;*
  1676. ;* DEPENDENCIES:   ABIOS MUST BE PRESENT
  1677. ;*
  1678. ;* ENTRY POINTS:  TellVCOMMs, TellVCOMRx, TellVCOMTx
  1679. ;*
  1680. ;* LINKAGE:     NEAR
  1681. ;*
  1682. ;* INPUT:       DS:SI --> ComInfo data area for this port
  1683. ;*              BX = MSR to send to VDM(for TellVCOMMs)
  1684. ;*              ci_vdm_LastLSR = LSR to send to VDM(for TellVCOMRx)
  1685. ;*
  1686. ;* OUTPUT:    NONE
  1687. ;*
  1688. ;* EXIT-NORMAL: NONE
  1689. ;*
  1690. ;* EXIT_ERROR:  NONE
  1691. ;*
  1692. ;* EFFECTS:
  1693. ;*
  1694. ;* INTERNAL REFERENCES:
  1695. ;*
  1696. ;* EXTERNAL REFERENCES: NONE
  1697. ;*
  1698. ;*********************** END OF SPECIFICATIONS ***********************
  1699.  
  1700. Procedure TellVCOMxx,near
  1701.  
  1702. TellVCOMRx:                     ; tell VCOM about RX interrupt
  1703.         mov     ah,4
  1704.         mov     bl,[si].ci_vdm_LastLSR
  1705.         Jmp     short TellVCOM
  1706.  
  1707. TellVCOMTx:                     ; tell VCOM about TX interrupt
  1708.         mov     ah,2
  1709.         Jmp     short TellVCOM
  1710.  
  1711. TellVCOMMs:                     ; tell VCOM about Modem Status interrupt
  1712.         mov     ah,0
  1713.         mov     [si].ci_VDM_LastMSR,bl
  1714.         and     [si].ci_VDM_LastMSR, NOT MS_TERI ; RDW 80677 - Tell VCOM when
  1715.                                                  ; RI (TERI) is present
  1716.  
  1717. TellVCOM:
  1718.  
  1719.         mov     dl, [si].ci_port_number
  1720.         .386
  1721.         call    FWORD PTR [VCOMAddress]
  1722.         .286
  1723.  
  1724.         RET                     ; to Caller
  1725.  
  1726. EndProc  TellVCOMxx
  1727.  
  1728. ;********************** START OF SPECIFICATIONS *********************
  1729. ;*
  1730. ;* SUBROUTINE NAME:  Rx_Notify
  1731. ;*
  1732. ;* DESCRIPTIVE NAME: Check to see if VCOM should be notified about an
  1733. ;*                   Rx interrupt
  1734. ;*
  1735. ;* STATUS: RELEASE 2  LEVEL 0
  1736. ;*
  1737. ;* FUNCTION:
  1738. ;*
  1739. ;* NOTES:
  1740. ;*
  1741. ;* DEPENDENCIES:   ABIOS MUST BE PRESENT
  1742. ;*
  1743. ;* ENTRY POINTS:  Rx_Notify
  1744. ;*
  1745. ;* LINKAGE:     NEAR
  1746. ;*
  1747. ;* INPUT:       DS:SI --> ComInfo data area for this port
  1748. ;*              ci_LastLSR = LSR to send to VDM(for TellVCOMRx)
  1749. ;*
  1750. ;* OUTPUT:      NONE
  1751. ;*
  1752. ;* EXIT-NORMAL: NONE
  1753. ;*
  1754. ;* EXIT_ERROR:  NONE
  1755. ;*
  1756. ;* EFFECTS:
  1757. ;*
  1758. ;* INTERNAL REFERENCES:
  1759. ;*              TellVcomRx
  1760. ;*
  1761. ;* EXTERNAL REFERENCES: NONE
  1762. ;*
  1763. ;*********************** END OF SPECIFICATIONS ***********************
  1764. Procedure Rx_Notify,near
  1765.                                         ; if the notifiy flag is on
  1766.         test    [si].ci_vdm_flag,VDM_Flag_notify_the_VCOM_RX
  1767.         jz      rxn90
  1768.         cmp     [si].ci_vdm_Tx_State,1  ; if we are in TX state 1
  1769.         jne     rxn90
  1770.                                         ; if there is data in the rx queue
  1771.  
  1772.         mov     ax,[si].ci_qin.ioq_count        ; ax = size of input queue
  1773.         cmp     ax,0
  1774.         jz      rxn90
  1775.                                         ; set the notify flag off
  1776.         and     [si].ci_vdm_flag,NOT VDM_Flag_notify_the_VCOM_RX
  1777.         call    TellVCOMRx              ; notify VCOM
  1778. rxn90:
  1779.         ret
  1780.  
  1781. EndProc  Rx_Notify
  1782.  
  1783. ;********************** START OF SPECIFICATIONS *********************
  1784. ;*
  1785. ;* SUBROUTINE NAME:  Tx_Notify
  1786. ;*
  1787. ;* DESCRIPTIVE NAME: Check to see if VCOM should be notified about a
  1788. ;*                   Tx interrupt
  1789. ;*
  1790. ;* STATUS: RELEASE 2  LEVEL 0
  1791. ;*
  1792. ;* FUNCTION:
  1793. ;*
  1794. ;* NOTES:
  1795. ;*
  1796. ;* DEPENDENCIES:   ABIOS MUST BE PRESENT
  1797. ;*
  1798. ;* ENTRY POINTS:  Tx_Notify
  1799. ;*
  1800. ;* LINKAGE:     NEAR
  1801. ;*
  1802. ;* INPUT:       DS:SI --> ComInfo data area for this port
  1803. ;*
  1804. ;* OUTPUT:      NONE
  1805. ;*
  1806. ;* EXIT-NORMAL: NONE
  1807. ;*
  1808. ;* EXIT_ERROR:  NONE
  1809. ;*
  1810. ;* EFFECTS:
  1811. ;*
  1812. ;* INTERNAL REFERENCES:
  1813. ;*              TellVcomTx
  1814. ;*
  1815. ;* EXTERNAL REFERENCES: NONE
  1816. ;*
  1817. ;*********************** END OF SPECIFICATIONS ***********************
  1818. Procedure Tx_Notify,near
  1819.                                         ; if the notifiy flag is on
  1820.         test    [si].ci_vdm_flag,VDM_Flag_notify_the_VCOM_TX
  1821.         jz      txn90                        ; no goto end
  1822.  
  1823.         cmp     [si].ci_vdm_Rx_State,3  ; if we are in RX state 3
  1824.         je      txn10                   ; yes do processing
  1825.  
  1826.         cmp     [si].ci_vdm_Rx_State,1   ; if we are in RX state 1
  1827.         jne      txn90                  ; no goto end
  1828.                                         ; if there is data in the tx queue
  1829.         mov     ax,[si].ci_qout.ioq_count       ; ax = number of char in
  1830.                                                 ; output queue
  1831.         cmp     ax,0
  1832.         je      txn90                   ; no goto end
  1833. txn10:
  1834.                                          ; set the notify flag off
  1835.         and     [si].ci_vdm_flag,NOT VDM_Flag_notify_the_VCOM_TX
  1836.         call    TellVCOMTx               ; notify VCOM
  1837. txn90:
  1838.         ret
  1839.  
  1840. EndProc  Tx_Notify
  1841.  
  1842. ;********************** START OF SPECIFICATIONS *********************
  1843. ;*
  1844. ;* SUBROUTINE NAME:  Ms_Notify
  1845. ;*
  1846. ;* DESCRIPTIVE NAME: Check to see if VCOM should be notified about a
  1847. ;*                   Ms interrupt
  1848. ;*
  1849. ;* STATUS: RELEASE 2  LEVEL 0
  1850. ;*
  1851. ;* FUNCTION:
  1852. ;*
  1853. ;* NOTES:
  1854. ;*
  1855. ;* DEPENDENCIES:   ABIOS MUST BE PRESENT
  1856. ;*
  1857. ;* ENTRY POINTS:  Ms_Notify
  1858. ;*
  1859. ;* LINKAGE:     NEAR
  1860. ;*
  1861. ;* INPUT:       DS:SI --> ComInfo data area for this port
  1862. ;*
  1863. ;* OUTPUT:      NONE
  1864. ;*
  1865. ;* EXIT-NORMAL: NONE
  1866. ;*
  1867. ;* EXIT_ERROR:  NONE
  1868. ;*
  1869. ;* EFFECTS:
  1870. ;*
  1871. ;* INTERNAL REFERENCES:
  1872. ;*              TellVcomMs
  1873. ;*
  1874. ;* EXTERNAL REFERENCES: NONE
  1875. ;*
  1876. ;*********************** END OF SPECIFICATIONS ***********************
  1877. Procedure Ms_Notify,near
  1878. ;     Bl = ComInfo.msrshadow
  1879.         mov     bl,[si].ci_msrshadow
  1880. ; NOTE we are only interested in CTS, DSR, RI and DCD
  1881.         and     bl,MS_CTS+MS_DSR+MS_RI+MS_DCD+MS_TERI ;AA Fix added MS_TERI
  1882. ;     IF (Bl != ComInfo.VDM_lastMSR)
  1883.         mov     bh,[si].ci_vdm_LastMSR
  1884.         cmp     bl,bh
  1885. ;     THEN
  1886.         je      msn90
  1887. ;        IF (ComInfo.Rx_Queue empty)
  1888.         push    bx
  1889.         mov     ax,[si].ci_qin.ioq_count        ; ax = size of input queue
  1890.         pop     bx
  1891.         cmp     ax,0
  1892. ;        THEN
  1893.         jne     msn10
  1894. ;           call TellVCOMMs (Temp_MSR)
  1895.         call    TellVCOMMs
  1896.         jmp     short msn90
  1897. ;        ELSE
  1898. msn10:
  1899. ;           Bl.CTS = ComInfo.VDM_lastMSR.CTS
  1900. ;           Bl.DSR = ComInfo.VDM_lastMSR.DSR
  1901.         and     bh,MS_CTS+MS_DSR
  1902.         and     bl,NOT (MS_CTS+MS_DSR)
  1903.         or      bl,bh
  1904. ;           IF (Bl != ComInfo.VDM_lastMSR)
  1905.         cmp     bl,[si].ci_vdm_LastMSR
  1906. ;           THEN
  1907.         je      msn90
  1908. ;              call TellVCOMMs
  1909.         call    TellVCOMMs
  1910. msn90:
  1911.         ret
  1912.  
  1913. EndProc Ms_Notify
  1914.  
  1915. CSEG    ENDS
  1916.  
  1917. RSEG    SEGMENT
  1918.         ASSUME cs:RSEG
  1919.  
  1920. Procedure ComInt2,FAR
  1921.         setDS   DSEG
  1922.         mov     si,Com2         ; pointer to com2 info structure
  1923.         jmp     ComInt
  1924.  
  1925. Entry ComInt1,,,nocheck
  1926.         setDS   DSEG
  1927.         mov     si,Com1         ; pointer to com1 info structure
  1928.         jmp     ComInt
  1929.  
  1930. Entry ComInt3,,,nocheck
  1931.         setDS   DSEG
  1932.         mov     si,Com3         ; pointer to com3 info structure
  1933.         jmp     ComInt
  1934.  
  1935. Entry ComInt4,,,nocheck
  1936.         setDS   DSEG
  1937.         mov     si,Com4         ; pointer to com4 info structure
  1938.         jmp     ComInt
  1939.  
  1940. EndProc ComInt2
  1941.  
  1942. Procedure SComInt1,FAR
  1943.  
  1944.         setDS   DSEG
  1945.         lea     si, ShrdIRQ1            ; info. for this IRQ line
  1946.         jmp     short SComInt
  1947.  
  1948. Entry SComInt2,,,nocheck
  1949.  
  1950.         setDS   DSEG
  1951.         lea     si, ShrdIRQ2            ; info. for this IRQ line
  1952.         jmp     short SComInt
  1953.  
  1954. Entry SComInt3,,,nocheck
  1955.  
  1956.         setDS   DSEG
  1957.         lea     si, ShrdIRQ3            ; info. for this IRQ line
  1958.         jmp     short SComInt
  1959.  
  1960. Entry SComInt4,,,nocheck
  1961.  
  1962.         setDS   DSEG
  1963.         lea     si, ShrdIRQ4            ; info. for this IRQ line
  1964. ;;;;;   jmp     SComInt                 ; fall into SComInt
  1965.  
  1966. SComInt:
  1967.         mov     si, [si].si_firstCOM    ; first entry in the chain
  1968.  
  1969. sci10:
  1970.         push    si                      ; save our spot in the chain
  1971.         push    cs                      ; fake a far call
  1972.         call    [si].ci_isr             ; call an interrupt service routine
  1973.         pop     si                      ; get back our spot in the chain
  1974.         jc      sci20                   ; it claimed the interrupt, so exit
  1975.         ret                             ; CY is clear, indicating our interrupt
  1976.  
  1977. sci20:
  1978.         mov     si, [si].ci_next_COM    ; get next entry in the chain
  1979.         or      si, si                  ; end of the chain (null)?
  1980.         jnz     sci10                   ; N: process next COM port in chain
  1981.         stc                             ; indicate not our interrupt
  1982.         ret
  1983.  
  1984.  
  1985. EndProc SComInt1
  1986.  
  1987. Procedure Ticker,FAR
  1988.         setDS   DSEG
  1989.         jmp     SwapTicker
  1990. EndProc Ticker
  1991.  
  1992. RSEG    ENDS
  1993.  
  1994. END
  1995.