home *** CD-ROM | disk | FTP | other *** search
/ Piper's Pit BBS/FTP: ibm 0020 - 0029 / ibm0020-0029 / ibm0028.tar / ibm0028 / GRLF-C-1.ZIP / GCOMM / ISR.ASM < prev    next >
Encoding:
Assembly Source File  |  1990-08-14  |  45.4 KB  |  1,225 lines

  1. ;
  2. ; The Greenleaf Comm Library
  3. ;
  4. ; Copyright (C) 1984-90 Greenleaf Software Inc.  All Rights Reserved.
  5. ;
  6. ;
  7. ; MODIFICATIONS
  8. ;
  9. ;  ""   21-SEP-1988  10:05:48.64  version 2.21
  10. ;       Near the end of psdigi interrupt routine si was not being popped
  11. ;       before ds (in large data model only) (#126)
  12. ;
  13. ;  ""      Mon 05-Jun-1989 14:25:15
  14. ;       Added support for 35 ports.
  15. ;
  16.         include model.h
  17.         include prologue.h
  18.         include asiports.equ
  19.  
  20.         RESTARTTX      macro
  21.          local rstnmt,restartxexit
  22.          test  [si+chst_bits],TXEMPTY
  23.          jnz   restartxexit
  24.          lea   di,[si+tx_cell]
  25.          cli
  26.          call  _remove
  27.          jnz   rstnmt
  28.          or    [si+chst_bits],TXEMPTY
  29. rstnmt:  or    [si+chst_bits],XCHRUN+TXIFLAG
  30.          sti
  31.          mov   dx,[si+base_8250]
  32.          out   dx,al
  33.          KILL_TIME
  34. restartxexit:
  35.          endm
  36. TABLEPORT       struc
  37.   ptb           dw      ptrsize dup(?)
  38.   as_shport     dw      ?
  39.   as_shbits     dw      ?
  40.   as_mask       dw      ?
  41.   as_xorv       dw      ?
  42. TABLEPORT       ends
  43.  
  44.  
  45. TABLESIZE       equ     size TABLEPORT
  46.  
  47.         dseg    _commlib
  48.  
  49.         public  ihdptr
  50.         public  inttbl
  51.         public  tblptr
  52.         public  serv0
  53.         public  pcdigi
  54.         public  psdigi
  55.  
  56. ihdptr  dw      offset pcdigi
  57.  
  58.  
  59. ;==>--  This table contains the starting addresses of all interrupt
  60. ;       service routines.
  61. ;
  62. inttbl  dw      offset serv0    ; offset of COM1: interrupt routine
  63.         dw      offset serv1    ; offset of COM2: interrupt routine
  64.         dw      offset serv2    ; offset of COM3: interrupt routine
  65.         dw      offset serv3    ; offset of COM4: interrupt routine
  66.         dw      offset serv4    ; offset of COM5: interrupt routine
  67.         dw      offset serv5    ; offset of COM6: interrupt routine
  68.         dw      offset serv6    ; offset of COM7: interrupt routine
  69.         dw      offset serv7    ; offset of COM8: interrupt routine
  70.         dw      offset serv8    ; offset of COM9: interrupt routine
  71.         dw      offset serv9    ; offset of COM10: interrupt routine
  72.         dw      offset serv10   ; offset of COM11: interrupt routine
  73.         dw      offset serv11   ; offset of COM12: interrupt routine
  74.         dw      offset serv12   ; offset of COM13: interrupt routine
  75.         dw      offset serv13   ; offset of COM14: interrupt routine
  76.         dw      offset serv14   ; offset of COM15: interrupt routine
  77.         dw      offset serv15   ; offset of COM16: interrupt routine
  78.         dw      offset serv16   ; offset of COM17: interrupt routine
  79.         dw      offset serv17   ; offset of COM18: interrupt routine
  80.         dw      offset serv18   ; offset of COM19: interrupt routine
  81.         dw      offset serv19   ; offset of COM20: interrupt routine
  82.         dw      offset serv20   ; offset of COM21: interrupt routine
  83.         dw      offset serv21   ; offset of COM22: interrupt routine
  84.         dw      offset serv22   ; offset of COM23: interrupt routine
  85.         dw      offset serv23   ; offset of COM24: interrupt routine
  86.         dw      offset serv24   ; offset of COM25: interrupt routine
  87.         dw      offset serv25   ; offset of COM26: interrupt routine
  88.         dw      offset serv26   ; offset of COM27: interrupt routine
  89.         dw      offset serv27   ; offset of COM28: interrupt routine
  90.         dw      offset serv28   ; offset of COM29: interrupt routine
  91.         dw      offset serv29   ; offset of COM30: interrupt routine
  92.         dw      offset serv30   ; offset of COM31: interrupt routine
  93.         dw      offset serv31   ; offset of COM32: interrupt routine
  94.         dw      offset serv32   ; offset of COM33: interrupt routine
  95.         dw      offset serv33   ; offset of COM34: interrupt routine
  96.         dw      offset serv34   ; offset of COM35: interrupt routine
  97.  
  98. dev_cnt         equ     (($ - inttbl)/2)        ; device count
  99.  
  100. srcher  db      0               ;set to 1 if interrupt routine has error
  101. icnt         dw 0                         ;These counters were added to work
  102. ecnt         dw 0                         ;with the C option in MULTLOOP.
  103.                                           ;In order for them to do anything,
  104.                                           ;define DEBUG_COUNTERS in ASIPORTS.EQU
  105.  
  106. tblptr  dd      ?               ;points to array of table pointers
  107.  
  108. ;==>--  Table for interrupt service routines
  109. ;
  110. injmptl dw      offset asicms   ; case 0 modem status
  111.         dw      offset asictx   ; case 2 transmit register empty
  112.         dw      offset asicrx   ; case 4 receive character ready
  113.         dw      offset asicrs   ; case 6 special condition
  114.  
  115.  
  116.         endds
  117.  
  118.         pseg    isr
  119.         cproc GetInterruptCount,,geticnt
  120.         mov  ax,icnt
  121.         cproce
  122.  
  123.         cproc GetInterruptErrorCount,,getecnt
  124.         mov  ax,ecnt
  125.         cproce
  126.  
  127. ;==>--  int _asigetc(p)  remove character & wide track status
  128. ;       from receive queue.  Character is returned in AL, status
  129. ;       (if enabled) is returned in AH.
  130. ;
  131.         cproc   _asigetc
  132.         if      _LDATA
  133.          push   ds
  134.          lds    si,parm1_
  135.         else
  136.          mov    si,parm1_
  137.         endif
  138.         lea     di,[si+rx_cell]
  139.         cli
  140.         and     [si+chst_bits],not RXFULL
  141.         call    _remove                  ;remove character
  142. ;**2.10 sti
  143.         jnz     _asgne                  ;if non zero, not empty
  144.         or      [si+chst_bits],RXEMPTY  ;say receive is empty
  145. _asgne: sti                             ;**2.10
  146.         test    [si+chmode_bits],IS_ASCII
  147.         jz      _asxxx
  148.         and     al,7FH
  149. _asxxx: test    [si+chst_bits],XOFFSENT ;see if xon was sent
  150.         jz      asirck                  ;if not don't check low water
  151.         push    ax                      ;save character (&status)
  152.         mov     ax,[si+rx_count]
  153.         cmp     ax,[si+rx_lowater]      ;see if down to low water yet
  154.         jnb     asixxt
  155.         mov     cx,[si+base_8250]       ;cx=8250 base
  156.         mov     dx,LSREG
  157.         add     dx,cx
  158. asiglp: in      al,dx
  159.         KILL_TIME
  160.         and     al,THRE                 ;wait for transmit holding register
  161.         jz      asiglp
  162.         mov     dx,cx
  163.         mov     ax,[si+start_rem_xmt]   ;get character to start it
  164.         out     dx,al
  165.         KILL_TIME
  166.         and     [si+chst_bits], not XOFFSENT    ;say it has been reversed
  167.         test    [si+chmode_bits],IS_TXINT       ;are tx interrupts enabled
  168.         jz      asixxt                          ;if not get out
  169.         or      [si+chst_bits],XCHRUN           ;else say xmit back on
  170.         mov     dx,LSREG        ; now wait for tx holding to empty
  171.         add     dx,cx
  172. wloop1: in      al,dx
  173.         KILL_TIME
  174.         and     al,THRE         ; is tx holding empty?
  175.         jz      wloop1
  176.         RESTARTTX
  177. asixxt: pop     ax                              ;get character back
  178. asirck: test    [si+chmode_bits],IS_RTSCONTROL  ;see if controlling RTS
  179.         jz      asiext                          ;if not exit _asigetc
  180.         test    [si+chst_bits],RTSACTIVE        ;is RTS asserted?
  181.         jnz     asiext                          ;if so then nothing to do
  182.         mov     cx,[si+rts_lowater]             ;see if down to low water yet
  183.         cmp     cx,[si+rx_count]
  184.         jb      asiext                          ;if not hop out
  185.         push    ax                              ;save character/status
  186.         cli                                     ;disable wolves while
  187.         or      [si+chst_bits],RTSACTIVE        ;updating shared variable
  188.         mov     dx,[si+base_8250]
  189.         add     dx,MCREG                        ;dx=modem control register
  190.         in      al,dx
  191.         KILL_TIME
  192.         or      al,RTS                          ;assert RTS
  193.         out     dx,al
  194.         KILL_TIME
  195.         sti                                     ;wolves o.k. again
  196.         pop     ax                              ;restore character/status
  197. asiext:
  198.         if      _LDATA
  199.          pop    ds
  200.         endif
  201.         cproce
  202.  
  203. ;==>--  int _asiputc(p,c) insert character in queue.
  204. ;
  205.         cproc   _asiputc
  206.         if      _LDATA
  207.          push   ds
  208.          lds    si,parm1_
  209.          mov    al,parm3_
  210.         else
  211.          mov    si,parm1_
  212.          mov    al,parm2_
  213.         endif
  214.         test    [si+chmode_bits],IS_ASCII
  215.         jz      _aspna
  216.         and     al,7fh
  217. _aspna: lea     di,[si+tx_cell]
  218.         cli
  219.         call    insert                  ;insert character
  220.         jnz     _aspnf                  ;if non zero not full
  221.         or      [si+chst_bits],TXFULL   ;say transmit is full
  222. _aspnf: sti
  223.         test    [si+chst_bits],TXEMPTY  ;is transmit empty?
  224.         jz      _asnmt                  ;if not skip out
  225.         and     [si+chst_bits],not TXEMPTY ;say it is now not empty
  226.         test    [si+chmode_bits],IS_TXINT       ;should xmit be running?
  227.         jz      _asnmt                  ;if not don't re-start
  228.         test    [si+chst_bits],TXWXON+TXWCTS+TXWALERT+XCHRUN
  229.         jnz     _asnmt                  ;if waiting for something else?
  230.         mov     cx,[si+base_8250]
  231.         mov     dx,LSREG        ; now wait for tx holding to empty
  232.         add     dx,cx
  233. wloop2: in      al,dx
  234.         KILL_TIME
  235.         and     al,THRE         ; is tx holding empty?
  236.         jz      wloop2
  237.         RESTARTTX
  238. _asnmt:
  239.         if      _LDATA
  240.          pop    ds
  241.         endif
  242.         xor     ax,ax
  243.         cproce
  244.  
  245. ;==>--  Offsets for the insert & remove routines
  246. ;
  247. CELL    equ     0
  248. BSIZE   equ     2
  249. COUNT   equ     4
  250. HEAD    equ     6
  251. TAIL    equ     8
  252. BUFFER  equ     10
  253.  
  254. ;==>--  int _asipekc(p)  read character & wide track status
  255. ;       from receive queue, do not adjust any pointers or flags.
  256. ;       DO NOT call this routine unless there is a character to read.
  257. ;       Character is returned in AL, status (if enabled) is returned in AH.
  258. ;
  259.         cproc   _asipekc
  260.         if      _LDATA
  261.          push   ds
  262.          lds    si,parm1_
  263.         else
  264.          mov    si,parm1_
  265.         endif
  266.         lea     di,[si+rx_cell]
  267.         if      _LDATA
  268.         push    es
  269.         les     si,[di+BUFFER]                  ;es:si=base of buffer
  270.         else
  271.         mov     si,[di+BUFFER]                  ;ds:si=base of buffer
  272.         endif
  273.         mov     bx,[di+HEAD]                    ;read the head
  274.         cmp     word ptr[di+CELL],2             ;see if word size buffer
  275.         jz      peword
  276.         xor     ah,ah
  277.         if      _LDATA
  278.          mov    al,es:[si+bx]                   ;remove character via ES:SI
  279.         else
  280.          mov    al,[si+bx]                      ;remove character via DS:SI
  281.         endif
  282.         jmp     short peend
  283. peword:
  284.         if      _LDATA
  285.          mov    ax,es:[si+bx]                   ;remove char/status via ES:SI
  286.         else
  287.          mov    ax,[si+bx]                      ;remove char/status via DS:SI
  288.         endif
  289. peend:
  290.         if      _LDATA
  291.          pop    es
  292.          pop    ds
  293.         endif
  294.         cproce
  295.  
  296.  
  297. ;==>--  insert character is to be called with ds:di pointing to the
  298. ;       cell size variable, upon return the Zero flag being set indicates
  299. ;       that the buffer is NOW FULL. When the buffer is full do not call
  300. ;       this routine again, until there is space for another character.
  301. ;       Call with character in AL, status in AH (if applicable).  This
  302. ;       routine does not test for a full buffer before inserting, only
  303. ;       after inserting.
  304. ;
  305. insert  PROC    NEAR                            ;DS:DX points to beginning
  306.         push    si
  307.         if      _LDATA
  308.          push   es
  309.          les    si,[di+BUFFER]                  ;es:si points to base of array
  310.         else
  311.          mov    si,[di+BUFFER]                  ;ds:si points to base of array
  312.         endif
  313.         inc     word ptr [di+COUNT]             ;bump counter
  314.         mov     bx,[di+TAIL]                    ;read the tail
  315.         mov     dx,bx
  316.         add     dx,[di+CELL]                    ;advance the tail for next
  317.         mov     cx,[di+BSIZE]                   ;get size of buffer to cx
  318.         cmp     word ptr[di+CELL],2             ;see if wide buffer
  319.         jnz     noiadj
  320.         shl     cx,1                            ;buffer is * 2
  321. noiadj: cmp     dx,cx                           ;check for wrap
  322.         jb      inwrap                          ;if no wrap take jump
  323.         xor     dx,dx                           ;reset subscript to 0
  324. inwrap: mov     [di+TAIL],dx                    ;save updated tail
  325.         cmp     word ptr [di+CELL],2            ;see if word size buffer
  326.         jz      inword
  327.         if      _LDATA
  328.          mov    es:[si+bx],al                   ;save character via ES:SI
  329.         else
  330.          mov    [si+bx],al                      ;save character via DS:SI
  331.         endif
  332.         jmp     short inend
  333. inword:
  334.         if      _LDATA
  335.          mov    es:[si+bx],ax                   ;save char/status via ES:SI
  336.         else
  337.          mov    [si+bx],ax                      ;save char/status via DS:SI
  338.         endif
  339. inend:  cmp     dx,[di+HEAD]                    ;see if buffer full
  340.         if      _LDATA
  341.          pop    es
  342.         endif
  343.         pop     si
  344.         ret
  345. insert  ENDP
  346.  
  347. ;==>--  remove character is to be called with ds:di pointing to the
  348. ;       cell size variable, upon return the Zero flag being set indicates
  349. ;       that the buffer is NOW EMPTY. When the buffer is empty DO NOT call
  350. ;       this routine again, until there is another character to remove.
  351. ;       Returns with character in AL, status in AH (if applicable).  This
  352. ;       routine does not test for an empty buffer before removing, only
  353. ;       after removing.
  354. ;
  355. _remove  PROC    NEAR
  356.         push    si
  357.         if      _LDATA
  358.         push    es
  359.         les     si,[di+BUFFER]                  ;es:si=base of buffer
  360.         else
  361.         mov     si,[di+BUFFER]                  ;ds:si=base of buffer
  362.         endif
  363.         dec     word ptr [di+COUNT]             ;decrement counter
  364.         mov     bx,[di+HEAD]                    ;read the head
  365.         mov     dx,bx
  366.         add     dx,[di+CELL]                    ;advance the head
  367.         mov     cx,[di+BSIZE]                   ;get size of buffer to cx
  368.         cmp     word ptr[di+CELL],2             ;see if wide buffer
  369.         jnz     noradj
  370.         shl     cx,1                            ;buffer is * 2
  371. noradj: cmp     dx,cx                           ;check for wrap
  372.         jb      rewrap                          ;if no wrap take jump
  373.         xor     dx,dx                           ;reset subscript to 0
  374. rewrap: mov     [di+HEAD],dx                    ;save updated head
  375.         cmp     word ptr[di+CELL],2             ;see if word size buffer
  376.         jz      reword
  377.         xor     ah,ah
  378.         if      _LDATA
  379.          mov    al,es:[si+bx]                   ;remove character via ES:SI
  380.         else
  381.          mov    al,[si+bx]                      ;remove character via DS:SI
  382.         endif
  383.         jmp     short reend
  384. reword:
  385.         if      _LDATA
  386.          mov    ax,es:[si+bx]                   ;remove char/status via ES:SI
  387.         else
  388.          mov    ax,[si+bx]                      ;remove char/status via DS:SI
  389.         endif
  390. reend:  cmp     dx,[di+TAIL]                    ;see if buffer empty
  391.         if      _LDATA
  392.          pop    es
  393.         endif
  394.         pop     si
  395.         ret
  396. _remove  ENDP
  397.  
  398. ;==>--  void _asiprime(p)
  399. ;       struct PORT_TABLE *p;
  400. ;
  401. ;       This function will re-start the 8250's transmit interrupt
  402. ;       process (if transmit interrupts are enabled)
  403. ;
  404.         cproc   _asiprime,,_asiprim,,,<DS,OKEXIT>
  405.         if      _LDATA
  406.          lds    si,parm1_
  407.         else
  408.          mov    si,parm1_
  409.         endif
  410.         test    [si+chmode_bits],IS_TXINT       ;see if app. has enabled
  411.         jnz     ok2p
  412.  
  413.         jmp     short ok_exit
  414. ok2p:   mov     cx,[si+base_8250]
  415.         mov     dx,LSREG        ; now wait for tx holding to empty
  416.         add     dx,cx
  417. wloop4: in      al,dx
  418.         KILL_TIME
  419.         and     al,THRE         ; is tx holding empty?
  420.         jz      wloop4
  421.         RESTARTTX
  422. ok_exit:
  423.         xor  ax,ax
  424.         cproce
  425. ;==>--  The psdigi routine gets control when the PS/2 digiboard is installed.
  426. ;       This code is enabled by calling asihsel(1)
  427. ;
  428. psdigi  LABEL   NEAR
  429.         lds     si,tblptr               ;ds:si points to first entry in table
  430.         add     si,ax                   ;ax has offset into table
  431.         mov     dx,[si+as_shport]       ;check shared port address
  432.         or      dx,dx                   ;if no shared port
  433.         jnz     psisshr
  434. ;
  435. ; This is a non-shared port interrupt.  This means I now have to call the
  436. ; service routine for this port and every other port on the same IRQ.
  437. ; I sit in a loop calling the interrupt handler.  CX is set to be the
  438. ; interrupt number for this port.  The first time through the loop, CX
  439. ; is set to 0, which means we don't know the interrupt number yet.
  440. ;
  441.         mov    cx,0
  442. testloop:
  443.  
  444.         push    si                     ;Save the pointer into the table
  445.         if      _LDATA
  446.          push   ds
  447.          lds    si,dword ptr[si]
  448.          mov    dx,ds
  449.         else
  450.          mov    si,[si]                 ;test for NULL pointer
  451.          mov    dx,0
  452.         endif
  453.  
  454.         or     dx,si
  455.         jz     loopdone                 ;if so then take interrupt error exit
  456.         mov     dx,[si+base_8250]
  457.         mov     ax,[si+intrpt_num]
  458.         or      cx,cx
  459.         jnz     skip
  460.         mov     cx,ax
  461. skip:   cmp     ax,cx
  462.         jnz     loopdone
  463.         push    cx
  464.         call    psdintlop
  465.         pop     cx
  466.         if      _LDATA
  467.          pop    ds
  468.         endif
  469.         pop     si
  470.         add     si,TABLESIZE
  471.         jmp     testloop
  472. loopdone:
  473.         if      _LDATA
  474.          pop    ds
  475.         endif
  476.         pop     si
  477.         mov     dx,[si+port_8259]
  478.         jmp     short psdout2
  479.  
  480. ;
  481. psisshr:
  482.         mov     bx,[si+as_mask]         ;mask to bx
  483.         or      bh,bh                   ;check bits 8-15
  484.         jz      ps8bit
  485.         in      ax,dx                   ;read 16 bit shared port
  486.         KILL_TIME
  487.         and     ax,bx                   ;mask unwanted bits
  488.         xor     ax,[si+as_xorv]         ;invert bits if needed
  489.         jnz     psnxt1
  490.         jmp     servexit
  491.  
  492. ps8bit: in      al,dx                   ;read shared port to al (8 bit)
  493.         KILL_TIME
  494.         xor     ah,ah                   ;clear ah
  495.         and     al,bl                   ;mask unwanted bits
  496.         xor     al,byte ptr [si+as_xorv] ;invert bits if needed
  497.         jnz     psnxt1
  498.         jmp     servexit
  499. psnxt1:
  500.         if      _LDATA
  501.          push   ds
  502.         endif
  503.         push    si                      ;save pointer to start
  504. psdloop:
  505.         shr     ax,1                    ;shift bit 0 to carry flag
  506.         jnc     psdnxt                  ;see if channel has int pending
  507.         push    si                      ;if so process it.
  508.         if      _LDATA
  509.          push   ds
  510.         endif
  511.         push    ax
  512.         call    psdfound
  513.         mov     dx,[si+port_8259]       ;dx = port of 8259 for serviced chnl.
  514.         pop     ax
  515.         if      _LDATA
  516.          pop    ds
  517.         endif
  518.         pop     si
  519. psdnxt: add     si,TABLESIZE            ;ds:si points to next entry
  520.         or      ax,ax                   ;check, are we finished?
  521.         jnz     psdloop                 ;if not process next one.
  522.  
  523.         pop     si                      ;get pointer to start back
  524.         if      _LDATA                  ; pop si before ds FIX
  525.          pop    ds
  526.         endif
  527.  
  528.         mov     cx,dx                   ;save dx away
  529.         mov     dx,[si+as_shport]       ;check shared port address
  530.         mov     bx,[si+as_mask]         ;mask to bx
  531.         or      bh,bh                   ;check bits 8-15
  532.         jz      ps8bit2
  533.         in      ax,dx                   ;read 16 bit shared port
  534.         KILL_TIME
  535.         and     ax,bx                   ;mask unwanted bits
  536.         xor     ax,[si+as_xorv]         ;invert bits if needed
  537.         mov     dx,cx
  538.         jz      psdout2
  539.         jmp     short psnxt2
  540. ps8bit2:
  541.         in      al,dx                   ;read shared port to al (8 bit)
  542.         KILL_TIME
  543.         xor     ah,ah                   ;clear ah
  544.         and     al,bl                   ;mask unwanted bits
  545.         xor     al,byte ptr [si+as_xorv] ;invert bits if needed
  546.         mov     dx,cx
  547.         jz      psdout2
  548. psnxt2:
  549.         if      _LDATA
  550.          push   ds
  551.         endif
  552.         push    si                      ;save pointer to start
  553.         jmp     psdloop
  554. psdout2:
  555.         or      dx,dx
  556.         jnz     dxvalid
  557.         mov     dx,20h
  558. dxvalid:
  559.         cmp     dx,20h                  ;See if the EOI is going to an
  560.         je      dx_skip                 ;8259 other than the system
  561.         mov     al,20h
  562.         out     dx,al
  563.         KILL_TIME
  564. dx_skip:
  565.         jmp     servexit
  566.  
  567. ;==>--  Now we have found the structure member that applies to this
  568. ;       interrupt, ds:si points to the variable that contains the
  569. ;       address of the ports data structure.
  570. ;
  571. psdfound:
  572.         if      _LDATA
  573.          lds    si,dword ptr[si]
  574.          mov    dx,ds
  575.          or     dx,si                   ;test for NULL pointer
  576.          jz     psdgobak                ;if so then take interrupt error exit
  577.         else
  578.          mov    si,[si]                 ;test for NULL pointer
  579.          mov    dx,si
  580.          or     si,si
  581.          jz     psdgobak                ;if so then take interrupt error exit
  582.         endif
  583.         mov     dx,[si+base_8250]
  584. psdintlop:
  585.         mov     cx,dx
  586.         add     dx,INTID        ;point to interrupt ID register
  587.         in      al,dx           ;read interrupt identification register
  588.         KILL_TIME
  589.         mov     dx,cx           ;leave pointing to base address
  590.         test    al,1            ;see if interrupt is pending
  591.         jnz     psdgobak        ;if no interrupt pending get out
  592.         xor     bh,bh
  593.         mov     bl,al
  594.         push    dx              ;save 8250 address for next pass
  595.         ifdef   DSNOTHING
  596.           mov     ax,__commlib_DATA
  597.           assume  es:__commlib_DATA
  598.         else
  599.           mov     ax,DGROUP
  600.           assume  es:DGROUP
  601.         endif
  602.         mov     es,ax
  603.         call    es:injmptl[bx]  ;take required 8250 action.
  604.         pop     dx
  605.         assume  es:NOTHING
  606.         jmp     psdintlop
  607. psdgobak:
  608.         ret
  609.  
  610.  
  611. ;==>--  The pcdigi routine gets control when either the PC digiboard
  612. ;       or an ordinary COM1/COM2 is installed.
  613. ;
  614. pcdigi  LABEL   NEAR
  615.         lds     si,tblptr               ;ds:si points to first entry in table
  616.         add     si,ax                   ;ax has offset into table
  617.         mov     dx,[si+as_shport]       ;check shared port address
  618.         or      dx,dx                   ;if no shared port take jump
  619.         jz      pcdfound
  620.         in      al,dx                   ;read shared port
  621.         KILL_TIME
  622.         and     al,byte ptr [si+as_mask]
  623.         xor     ah,ah
  624.         mov     dx,TABLESIZE            ;incrementer
  625. pcdsrchl:
  626.         cmp     ax,[si+as_shbits]       ;is this the one?
  627.         jz      pcdfound
  628.         add     si,dx
  629.         loop    pcdsrchl                ;if cx!=0 do it again
  630. pcdinerex:
  631.         jmp    servexit
  632.  
  633. ;==>--  Now we have found the structure member that applies to this
  634. ;       interrupt, ds:si points to the variable that contains the
  635. ;       address of the ports data structure.
  636. ;
  637. pcdfound:
  638.         if      _LDATA
  639.          lds    si,dword ptr[si]
  640.          mov    dx,ds
  641.          or     dx,si                   ;test for NULL pointer
  642.          jnz    pcd_continue
  643.          jmp    servexit                ;if so then take interrupt error exit
  644.         else
  645.          mov    si,[si]                 ;test for NULL pointer
  646.          or     si,si
  647.          jnz    pcd_continue
  648.          jmp    servexit                ;if so then take interrupt error exit
  649.         endif
  650. pcd_continue:
  651.         mov     dx,[si+base_8250]
  652. pcdintlop:
  653.         mov     cx,dx
  654.         add     dx,INTID        ;point to interrupt ID register
  655.         in      al,dx           ;read interrupt identification register
  656.         KILL_TIME
  657.         mov     dx,cx           ;leave pointing to base address
  658.         test    al,1            ;see if interrupt is pending
  659.         jnz     pcdgobak        ;if no interrupt pending get out
  660.         xor     bh,bh
  661.         mov     bl,al
  662.         push    dx              ;save 8250 address for next pass
  663.         ifdef   DSNOTHING
  664.           mov     ax,__commlib_DATA
  665.           assume  es:__commlib_DATA
  666.         else
  667.           mov     ax,DGROUP
  668.           assume  es:DGROUP
  669.         endif
  670.         mov     es,ax
  671.         call    es:injmptl[bx]  ;take required 8250 action.
  672.         pop     dx
  673.         jmp     pcdintlop
  674. pcdgobak:
  675.         pop     bp
  676.         pop     di
  677.         pop     es
  678.         pop     bx
  679.         mov     dx,[si+port_8259]       ;send generic 8259 eoi
  680.         pop     si
  681.         pop     ds
  682.         mov     al,20h
  683.         out     dx,al
  684.         KILL_TIME
  685.         cmp     dx,20h                  ;see if system board
  686.         jz      pcdaround
  687.         out     20h,al                  ;and to system board
  688.         KILL_TIME
  689. pcdaround:
  690.         pop     dx
  691.         pop     cx
  692.         pop     ax
  693.         iret
  694.  
  695. ;
  696. ;==>--  Common Interrupt routines  --<==;
  697. ;
  698.  
  699. ;==>--  Modem status change interrupt handler
  700. ;
  701. asicms: mov     cx,dx                   ;save 8250 base in cx for speed
  702.         add     dx,MSREG                ;dx = Modem status register
  703.         in      al,dx                   ;read the reason we are here
  704.         KILL_TIME
  705.         mov     dx,cx                   ;dx back to 8250 base
  706.         mov     ah,al
  707.         not     ah
  708.         add     dx,INTER                ;dx=interrupt enable register
  709.         or      [si+modem_stat],ax      ;update static status byte
  710.         not     ah
  711.         mov     bx,[si+wide_stat]       ;save status bits for wide track
  712.         and     bl,0fh                  ;mask off bits 4-7
  713.         and     ah,0f0h
  714.         or      bl,ah
  715.         mov     ah,al                   ;refresh ah with 8250 status
  716.         mov     [si+wide_stat],bx
  717.         or      [si+chst_bits],MODCHG   ;say we had a modem status change
  718.         mov     bp,[si+chmode_bits]     ;let bp hold these for speed
  719.         test    bp,IS_IGMSTAT+IS_IGALERT+IS_CTSMODE  ;**2.10 eliminate
  720.                                         ;time-consuming test/jump sequences
  721. ;;      jz      mstout
  722.         jnz     mst001
  723.         jmp     mstout
  724. mst001: test    bp,IS_IGMSTAT           ;see if we are ignoring modem
  725.         jz      mstiga                  ;status changes?
  726.         or      [si+chst_bits],ALERT    ;set alert bit if not
  727. mstiga: test    bp,IS_IGALERT           ;are we ignoring alert conditions?
  728.         jz      mstcts                  ;if so check for cts
  729.         in      al,dx                   ;come here to stop tx & rx interrupts
  730.         KILL_TIME
  731.         and    [si+chst_bits],not TXIFLAG
  732.         and    al,not ENRX
  733.         out    dx,al
  734.         KILL_TIME
  735.         and     [si+chst_bits],not XCHRUN+RCHRUN  ;say interrupts both stopped
  736.         or      [si+chst_bits],TXWALERT ;and we are waiting for alert
  737.         jmp     short mstout
  738. mstcts: test    bp,IS_CTSMODE           ;see if CTS flow control enabled?
  739.         jz      mstout
  740.         test    bp,IS_TXINT             ;see if transmit interrupts
  741.         jz      mstout                  ;are enabled?
  742.         test    ah,DCTS                 ;did CTS change?
  743.         jz      mstout                  ;if so disable or enable tx interrupts
  744.         test    ah,CTS                  ;did it just go true
  745.         jz      stoptx                  ;if not stop xmit ints
  746.         mov     dx,LSREG        ; now wait for tx holding to empty
  747.         add     dx,cx
  748. wloop3: in      al,dx
  749.         KILL_TIME
  750.         and     al,THRE         ; is tx holding empty?
  751.         jz      wloop3
  752.         RESTARTTX
  753.         and     [si+chst_bits],not TXWCTS ;and not waiting for CTS
  754.         jmp     short mstout                  ;leave modem status change
  755. stoptx: in      al,dx                   ;come here to stop tx-interrupts
  756.         KILL_TIME
  757.         and    [si+chst_bits],not TXIFLAG
  758.         and     [si+chst_bits],not XCHRUN       ;say tx interrupts stopped
  759.         or      [si+chst_bits],TXWCTS           ;and we are waiting for CTS
  760. mstout: ret
  761.  
  762. ;==>--  Transmit holding register empty interrupt handler
  763. ;
  764. asictx:
  765.         if      TXIFLAG
  766.          test   [si+chst_bits],TXIFLAG
  767.          jz     stopxm
  768.         endif
  769.         test    [si+chst_bits],TXEMPTY          ;see if TX buffer empty
  770.         jnz     stopxm                          ;if transmit is empty stop it
  771.         test    [si+chst_bits],TXWXON           ;tx waiting for xon?
  772.         jnz     txout
  773.         lea     di,[si+tx_cell]                 ;else go get next character
  774.         call    _remove                          ;to al
  775.         jnz     txnomt                          ;if not empty take jump
  776.         or      [si+chst_bits],TXEMPTY          ;say it is now empty
  777. txnomt: and     [si+chst_bits],not TXFULL
  778.         mov     dx,[si+base_8250]               ;dx=8250 base address
  779.         out     dx,al                           ;send character
  780.         KILL_TIME
  781.         jmp     short txout
  782. stopxm:
  783.         and    [si+chst_bits],not XCHRUN+TXIFLAG ;say not running any more
  784. txout:  ret
  785.  
  786. ;==>--  Receive character ready interrupt handler
  787. ;
  788. asicrx: mov     cx,dx                           ;save 8250 base in cx
  789.         in      al,dx                           ;clear condition
  790.         KILL_TIME
  791.         inc     [si+rx_accum]                   ;increment accumulator
  792.         test    [si+chst_bits],RXFULL           ;see if rx buffer is full
  793.         jz      rx0                             ;if not full take jump
  794.         or      [si+chst_bits],RXOVFLOW         ;else say overflow
  795.         jmp     rxrts
  796. rx0:    mov     bp,[si+chmode_bits]             ;put in bp for speed
  797.         test    bp,IS_IGCD+IS_IGDSR+IS_IGALERT+IS_XOFFMODE+IS_RCHKING ;**2.10
  798. ;;;     jz      rx5                             ;**2.10 skip numerous test
  799.         jnz     rx0a                            ;jump sequences if features
  800.         jmp     rx5                             ;are not used
  801.  
  802. rx0a:   test    bp,IS_IGCD                      ;are we ignoring CD
  803.         jz      rx1                             ;if so take jump
  804.         test    [si+wide_stat],RLSD             ;see if it is active
  805.         jnz     rx1
  806.         jmp     rxout
  807. ;;;     jz      rxout                           ;if not get out
  808. rx1:    test    bp,IS_IGDSR                     ;are we ignoring DSR?
  809.         jz      rx2                             ;if so don't test it
  810.         test    [si+wide_stat],DSR              ;is it active
  811.         jnz     rx2
  812.         jmp     rxout
  813. ;;;     jz      rxout                           ;if not get out
  814. rx2:    test    bp,IS_IGALERT                   ;are we ignoring alert?
  815.         jz      rx3                             ;if so get out
  816.         test    [si+chst_bits],ALERT            ;see if alert set
  817.         jz      rx3
  818.         jmp     rxout
  819. ;;;     jnz     rxout                           ;if so get out
  820. rx3:    test    bp,IS_XOFFMODE                  ;see if in xon/xoff mode
  821.         jz      rx4                             ;if not skip around
  822.         add     dx,INTER                        ;dx=interrupt enable register
  823.         cmp     al,byte ptr[si+stop_xmt]        ;is this the stop character
  824.         jnz     rx3a                            ;if not check for on character
  825.         and    [si+chst_bits],not TXIFLAG
  826.         or      [si+chst_bits],TXWXON           ;set status bit
  827.         and     [si+chst_bits],not XCHRUN       ;say transmit not running
  828.         jmp     rxout                           ;get out
  829. rx3a:   cmp     al,byte ptr[si+start_xmt]       ;is this the start character
  830.         jnz     rx4                             ;if not take jump
  831.         test    bp,IS_TXINT                     ;should tx interrupts be on
  832.         jz      rx4                             ;if not don't re-enable them
  833.         mov     dx,LSREG        ; now wait for tx holding to empty
  834.         add     dx,cx
  835. wloop5: in      al,dx
  836.         KILL_TIME
  837.         and     al,THRE         ; is tx holding empty?
  838.         jz      wloop5
  839.         RESTARTTX
  840.         and     [si+chst_bits],not TXWXON       ;reset status bit
  841.         jmp     rxout                           ;get out
  842. rx4:    test    bp,IS_RCHKING                   ;are we rchking
  843.         jz      rx5                             ;if not take quick way out
  844.         lea     di,[si+chkchr_1]                ;start with #1
  845.         mov     cx,3                            ;and check 3 characters
  846. rchlop: mov     bx,[di]                         ;read value from structure
  847.         test    bx,RCHKENABLED                  ;is this position checking
  848.         jz      rchnom                          ;if not do next
  849.         cmp     al,bl                           ;do characters match
  850.         jnz     rchnom
  851.         and     bh,high RCHKVAL                 ;mask out all but mode
  852.         jnz     rx4a
  853.         jmp     rxout
  854. ;;;     jz      rxout                           ;if discarding just get out
  855. rx4a:   or      [di],RCHKFLAG                   ;1&2 both set flags so set now
  856.         dec     bh
  857.         jnz     rx5
  858.         jmp     rxout
  859. ;;;     jz      rxout                           ;if 1 discard
  860. ;;;     jmp     rx5
  861. rchnom: add     di,2                            ;check next character
  862.         loop    rchlop                          ;till all 3 checked
  863. rx5:    lea     di,[si+rx_cell]                 ;put character in queue
  864.         and     [si+chst_bits],not RXEMPTY      ;say rx not empty
  865.         mov     ah,byte ptr[si+wide_stat]
  866.         and     byte ptr[si+wide_stat],0f0h     ;**2.04
  867.         call    insert
  868.         jnz     rnfull                          ;if not full
  869.         or      [si+chst_bits],RXFULL           ;else say full
  870. rnfull: test    bp,IS_XOFFMODE+IS_RTSCONTROL    ;**2.10 eliminate test/jumps
  871. ;;;     jz      rxout                           ;**2.10 and get out if
  872.         jnz     cxorts                          ;possible
  873.         jmp     short rxout
  874. cxorts: test    bp,IS_XOFFMODE                  ;are we in xon/xoff mode?
  875.         jz      rxrts                           ;if not skip this
  876.         test    [si+chst_bits],XOFFSENT         ;has it already been sent?
  877.         jnz     rxrts
  878.         mov     ax,[si+rx_count]                ;get rx character count
  879.         cmp     ax,[si+rx_hiwater]              ;see if below high water mark
  880.         jnb     rxsxof
  881.         jmp     short rxout                           ;if so don't send xoff
  882. rxsxof: mov     cx,[si+base_8250]
  883.         mov     dx,LSREG
  884.         add     dx,cx
  885.         or      [si+chst_bits],XOFFSENT         ;say XOFF sent
  886. xoflop: in      al,dx                           ;wait till transmitter empty
  887.         KILL_TIME
  888.         and     al,THRE
  889.         jz      xoflop
  890.         mov     dx,cx
  891.         mov     ax,[si+stop_rem_xmt]            ;get character to send
  892.         out     dx,al                           ;and send it out
  893.         KILL_TIME
  894. rxrts:  test    bp,IS_RTSCONTROL                ;are we controlling RTS?
  895.         jz      rxout
  896.         test    [si+chst_bits],RTSACTIVE        ;is RTS asserted?
  897.         jz      rxout                           ;if not then nothing to do
  898.         mov     cx,[si+rx_count]                ;get rx character count
  899.         cmp     cx,[si+rts_hiwater]
  900.         jb      rxout                           ;if rx_count<rts_hiwater
  901.         and     [si+chst_bits],not RTSACTIVE    ;say RTS de-asserted
  902.         mov     dx,[si+base_8250]               ;and de-assert RTS
  903.         add     dx,MCREG
  904.         in      al,dx
  905.         KILL_TIME
  906.         and     al,not RTS
  907.         out     dx,al
  908.         KILL_TIME
  909. rxout:  ret
  910.  
  911. ;==>--  Special receive condition interrupt handler
  912. ;
  913. asicrs: mov     cx,dx
  914.         add     dx,LSREG                ;point to line status
  915.         in      al,dx                   ;read the reason we are here
  916.         KILL_TIME
  917.         mov     ah,al
  918.         not     ah
  919.         mov     dx,INTER
  920.         add     dx,cx                   ;dx = interrupt enable register
  921.         or      [si+line_stat],ax       ;update static status byte
  922.         not     ah
  923.         mov     bx,[si+wide_stat]       ;save status bits for wide track
  924.         and     bl,0f0h                 ;set bits 0-3 to 0
  925.         and     ah,0eh                  ;strip unwanted bits in ah
  926.         or      bl,ah                   ;and merge into bl
  927.         mov     [si+wide_stat],bx       ;and save it back
  928.         or      [si+chst_bits],LINERRG  ;say we had a line status change
  929.         mov     bp,[si+chmode_bits]     ;let bp hold these for speed
  930.         test    bp,IS_IGRCVER           ;see if we are ignoring modem
  931.         jz      lstout                  ;status changes?
  932.         or      [si+chst_bits],ALERT    ;set alert bit if not
  933.         test    bp,IS_IGALERT           ;are we ignoring alert conditions?
  934.         jz      lstout                  ;if so get out
  935.         in      al,dx                   ;come here to stop tx & rx interrupts
  936.         KILL_TIME
  937.         and    al,not ENRX
  938.         out    dx,al
  939.         KILL_TIME
  940.         and    [si+chst_bits],not TXIFLAG
  941.         out     dx,al
  942.         KILL_TIME
  943.         and     [si+chst_bits],not XCHRUN+RCHRUN  ;say interrupts both stopped
  944.         or      [si+chst_bits],TXWALERT ;and we are waiting for alert
  945. lstout: ret
  946.  
  947. ;==>--  Defined below is the entry point for 16 interrupt service
  948. ;       routines.
  949. ;
  950. serv0:  push    ax              ;COM1:
  951.         push    cx              ;**2.04
  952.         xor     ax,ax
  953.         mov     cx,35           ;**2.04
  954.         jmp     servcommon
  955.  
  956. serv1:  push    ax              ;COM2:
  957.         push    cx              ;**2.04
  958.         mov     ax,1 * TABLESIZE
  959.         mov     cx,34           ;**2.04
  960.         jmp     servcommon
  961.  
  962. serv2:  push    ax              ;COM3:
  963.         push    cx              ;**2.04
  964.         mov     ax,2 * TABLESIZE
  965.         mov     cx,33           ;**2.04
  966.         jmp     servcommon
  967.  
  968. serv3:  push    ax              ;COM4:
  969.         push    cx              ;**2.04
  970.         mov     ax,3 * TABLESIZE
  971.         mov     cx,32           ;**2.04
  972.         jmp     servcommon
  973.  
  974. serv4:  push    ax              ;COM5:
  975.         push    cx              ;**2.04
  976.         mov     ax,4 * TABLESIZE
  977.         mov     cx,31           ;**2.04
  978.         jmp     servcommon
  979.  
  980. serv5:  push    ax              ;COM6:
  981.         push    cx              ;**2.04
  982.         mov     ax,5 * TABLESIZE
  983.         mov     cx,30           ;**2.04
  984.         jmp     servcommon
  985.  
  986. serv6:  push    ax              ;COM7:
  987.         push    cx              ;**2.04
  988.         mov     ax,6 * TABLESIZE
  989.         mov     cx,29           ;**2.04
  990.         jmp     servcommon
  991.  
  992. serv7:  push    ax              ;COM8:
  993.         push    cx              ;**2.04
  994.         mov     ax,7 * TABLESIZE
  995.         mov     cx,28           ;**2.04
  996.         jmp     servcommon
  997.  
  998. serv8:  push    ax              ;COM9:
  999.         push    cx              ;**2.04
  1000.         mov     ax,8 * TABLESIZE
  1001.         mov     cx,27           ;**2.04
  1002.         jmp     servcommon
  1003.  
  1004. serv9:  push    ax              ;COM10:
  1005.         push    cx              ;**2.04
  1006.         mov     ax,9 * TABLESIZE
  1007.         mov     cx,26           ;**2.04
  1008.         jmp     servcommon
  1009.  
  1010. serv10: push    ax              ;COM11:
  1011.         push    cx              ;**2.04
  1012.         mov     ax,10 * TABLESIZE
  1013.         mov     cx,25           ;**2.04
  1014.         jmp     servcommon
  1015.  
  1016. serv11: push    ax              ;COM12:
  1017.         push    cx              ;**2.04
  1018.         mov     ax,11 * TABLESIZE
  1019.         mov     cx,24           ;**2.04
  1020.         jmp     servcommon
  1021.  
  1022. serv12: push    ax              ;COM13:
  1023.         push    cx              ;**2.04
  1024.         mov     ax,12 * TABLESIZE
  1025.         mov     cx,23           ;**2.04
  1026.         jmp     servcommon
  1027.  
  1028. serv13: push    ax              ;COM14:
  1029.         push    cx              ;**2.04
  1030.         mov     ax,13 * TABLESIZE
  1031.         mov     cx,22           ;**2.04
  1032.         jmp     servcommon
  1033.  
  1034. serv14: push    ax              ;COM15:
  1035.         push    cx              ;**2.04
  1036.         mov     ax,14 * TABLESIZE
  1037.         mov     cx,21           ;**2.04
  1038.         jmp     servcommon
  1039.  
  1040. serv15: push    ax              ;COM16:
  1041.         push    cx              ;**2.04
  1042.         mov     ax,15 * TABLESIZE
  1043.         mov     cx,20           ;**2.04
  1044.         jmp     servcommon
  1045.  
  1046. serv16: push    ax              ;COM17:
  1047.         push    cx              ;**2.04
  1048.         mov     ax,16 * TABLESIZE
  1049.         mov     cx,19           ;**2.04
  1050.         jmp     servcommon
  1051.  
  1052. serv17: push    ax              ;COM18:
  1053.         push    cx              ;**2.04
  1054.         mov     ax,17 * TABLESIZE
  1055.         mov     cx,18           ;**2.04
  1056.         jmp     servcommon
  1057.  
  1058. serv18: push    ax              ;COM19:
  1059.         push    cx              ;**2.04
  1060.         mov     ax,18 * TABLESIZE
  1061.         mov     cx,17           ;**2.04
  1062.         jmp     servcommon
  1063.  
  1064. serv19: push    ax              ;COM20:
  1065.         push    cx              ;**2.04
  1066.         mov     ax,19 * TABLESIZE
  1067.         mov     cx,16           ;**2.04
  1068.         jmp     servcommon
  1069.  
  1070. serv20: push    ax              ;COM21:
  1071.         push    cx              ;**2.04
  1072.         mov     ax,20 * TABLESIZE
  1073.         mov     cx,15           ;**2.04
  1074.         jmp     servcommon
  1075.  
  1076. serv21: push    ax              ;COM22:
  1077.         push    cx              ;**2.04
  1078.         mov     ax,21 * TABLESIZE
  1079.         mov     cx,14           ;**2.04
  1080.         jmp     servcommon
  1081.  
  1082. serv22: push    ax              ;COM23:
  1083.         push    cx              ;**2.04
  1084.         mov     ax,22 * TABLESIZE
  1085.         mov     cx,13           ;**2.04
  1086.         jmp short servcommon
  1087.  
  1088. serv23: push    ax              ;COM24:
  1089.         push    cx              ;**2.04
  1090.         mov     ax,23 * TABLESIZE
  1091.         mov     cx,12           ;**2.04
  1092.         jmp short servcommon
  1093.  
  1094.  
  1095. serv24: push    ax              ;COM25:
  1096.         push    cx              ;**2.04
  1097.         mov     ax,24 * TABLESIZE
  1098.         mov     cx,11           ;**2.04
  1099.         jmp short servcommon
  1100.  
  1101. serv25: push    ax              ;COM26:
  1102.         push    cx              ;**2.04
  1103.         mov     ax,25 * TABLESIZE
  1104.         mov     cx,10           ;**2.04
  1105.         jmp short servcommon
  1106.  
  1107. serv26: push    ax              ;COM27:
  1108.         push    cx              ;**2.04
  1109.         mov     ax,26 * TABLESIZE
  1110.         mov     cx,9            ;**2.04
  1111.         jmp short servcommon
  1112.  
  1113. serv27: push    ax              ;COM28:
  1114.         push    cx              ;**2.04
  1115.         mov     ax,27 * TABLESIZE
  1116.         mov     cx,8            ;**2.04
  1117.         jmp short servcommon
  1118.  
  1119. serv28: push    ax              ;COM29:
  1120.         push    cx              ;**2.04
  1121.         mov     ax,28 * TABLESIZE
  1122.         mov     cx,7            ;**2.04
  1123.         jmp short servcommon
  1124.  
  1125. serv29: push    ax              ;COM30:
  1126.         push    cx              ;**2.04
  1127.         mov     ax,29 * TABLESIZE
  1128.         mov     cx,6            ;**2.04
  1129.         jmp short servcommon
  1130.  
  1131. serv30: push    ax              ;COM31:
  1132.         push    cx              ;**2.04
  1133.         mov     ax,30 * TABLESIZE
  1134.         mov     cx,5            ;**2.04
  1135.         jmp short servcommon
  1136.  
  1137. serv31: push    ax              ;COM32:
  1138.         push    cx              ;**2.04
  1139.         mov     ax,31 * TABLESIZE
  1140.         mov     cx,4            ;**2.04
  1141.         jmp short servcommon
  1142.  
  1143. serv32: push    ax              ;COM33:
  1144.         push    cx              ;**2.04
  1145.         mov     ax,32 * TABLESIZE
  1146.         mov     cx,3            ;**2.04
  1147.         jmp short servcommon
  1148.  
  1149. serv33: push    ax              ;COM34:
  1150.         push    cx              ;**2.04
  1151.         mov     ax,33 * TABLESIZE
  1152.         mov     cx,2            ;**2.04
  1153.         jmp short servcommon
  1154.  
  1155. serv34: push    ax              ;COM35:
  1156.         push    cx              ;**2.04
  1157.         mov     ax,34 * TABLESIZE
  1158.         mov     cx,1            ;**2.04
  1159.         jmp short servcommon
  1160.  
  1161. servcommon:
  1162.         sti
  1163.         push    dx
  1164.         push    ds
  1165.         push    si
  1166.         push    bx
  1167.         push    es
  1168.         push    di
  1169.         push    bp
  1170.         ifdef   DSNOTHING
  1171.           mov     bx,__commlib_DATA
  1172.         else
  1173.           mov     bx,DGROUP
  1174.         endif
  1175.         mov     ds,bx
  1176.         ifdef   DEBUG_COUNTERS
  1177.         inc     icnt                    ;This is normally not compiled, only
  1178.         endif                           ;to save overhead
  1179.         jmp     [ihdptr]
  1180. ;
  1181. ; After the interrupts have all been serviced, the ISR branches back
  1182. ; here to return to the program that was interrupted.
  1183. ;
  1184. servexit:
  1185.         ifdef   DSNOTHING
  1186.           mov     bx,__commlib_DATA
  1187.         else
  1188.           mov     bx,DGROUP
  1189.         endif
  1190.         mov     ds,bx
  1191.         ifdef   DEBUG_COUNTERS
  1192.         inc        ecnt                 ;This is normally not compiled
  1193.         endif
  1194.         mov     srcher,al               ;if we get here, we could not
  1195.                                         ;identify the port so we set a
  1196.                                         ;variable and get out
  1197.         pop     bp
  1198.         pop     di
  1199.         pop     es
  1200.         pop     bx
  1201.         pop     si
  1202.         pop     ds
  1203.         pop     dx
  1204.         pop     cx
  1205.         mov     al,20h
  1206.         out     20h,al
  1207.         KILL_TIME
  1208.         pop     ax
  1209.         iret
  1210.  
  1211.  
  1212.  
  1213.  
  1214. ;==>--  interror()      - see if interrupt routines have had an error
  1215. ;                         searching for match in shared hardware.
  1216. ;
  1217.         cproc   interror,,,,,<NOSI,NODI>
  1218.         xor     ax,ax
  1219.         xchg    al,srcher
  1220.         cproce
  1221.  
  1222.         endps
  1223.         end
  1224.  
  1225.