home *** CD-ROM | disk | FTP | other *** search
/ Beijing Paradise BBS Backup / PARADISE.ISO / software / BBSDOORW / SMAILSRC.ZIP / UUPC.ZIP / COMM.ZIP / COMM.ASM next >
Encoding:
Assembly Source File  |  1990-04-03  |  29.5 KB  |  1,067 lines

  1.     TITLE   COM_PKG2 -- Last updated 10/6/85
  2.         PAGE    75,132
  3. ;
  4. ;    modified to use MSC calling sequence.
  5. ;    jrr 3/86
  6. ;
  7. ; Communications Package for the IBM PC, XT, AT and PCjr
  8. ; and strict compatibles.
  9. ; May be copied and used freely -- This is a public domain program
  10. ; Developed by Richard Gillmann, John Romkey, Jerry Saltzer,
  11. ; Craig Milo Rogers, Dave Mitton and Larry Afrin.
  12. ;
  13. ; We'd sure like to see any improvements you might make.
  14. ; Please send all comments and queries about this package
  15. ; to GILLMANN@USC-ISIB.ARPA
  16. ;
  17. ; o Supports both serial ports simultaneously
  18. ; o All speeds to 19200 baud
  19. ; o Compatible with PC, XT, AT and PCjr.
  20. ; o Built in XON/XOFF flow control option
  21. ; o Assembly language calling conventions
  22. ; o Logs all comm errors
  23. ; o Direct connect or modem protocol
  24. ;
  25. ; MAXIMUM BUFFER SIZES
  26. R_SIZE    EQU     2048        ; SIZE OF RECEIVE BUFFERS skl/88-05-13
  27. S_SIZE    EQU     500        ; SIZE OF TRANSMIT BUFFERS rhl/4/86
  28. ; INTERRUPT NUMBERS
  29. INT_COM1 EQU    0CH        ; COM1: FROM 8259
  30. INT_COM2 EQU    0BH        ; COM2: FROM 8259
  31. ; 8259 PORTS
  32. INTA00  EQU     20H             ; 8259A PORT, A0 = 0
  33. INTA01  EQU     21H             ; 8259A PORT, A0 = 1
  34. ; COM1: LEVEL 4
  35. IRQ4    EQU    2*2*2*2            ; 8259A OCW1 MASK, M4=1, A0=0
  36. NIRQ4    EQU    NOT IRQ4 AND 0FFH    ; COMPLEMENT OF ABOVE
  37. EOI4    EQU    4 OR 01100000B        ; 8259A OCW2 SPECIFIC IRQ4 EOI, A0=0
  38. ; COM2: LEVEL 3
  39. IRQ3    EQU    2*2*2            ; 8259A OCW1 MASK, M3=1, A0=0
  40. NIRQ3    EQU    NOT IRQ3 AND 0FFH    ; COMPLEMENT OF ABOVE
  41. EOI3    EQU    3 OR 01100000B        ; 8259A OCW2 SPECIFIC IRQ3 EOI, A0=0
  42. ; FLOW CONTROL CHARACTERS
  43. CONTROL_Q EQU    11H        ; XON
  44. CONTROL_S EQU    13H        ; XOFF
  45. ; MISC.
  46. DOS    EQU    21H        ; DOS FUNCTION CALLS
  47.     PAGE
  48. ;
  49. ; ROM BIOS Data Area
  50. ;
  51. RBDA    SEGMENT    AT 40H
  52. RS232_BASE DW    4 DUP(?)    ; ADDRESSES OF RS232 ADAPTERS
  53. RBDA    ENDS
  54. ;
  55. ; ROM PC-Type IDENT
  56. ;
  57. ROM    SEGMENT    AT 0F000H
  58.     ORG    0FFFEH
  59. ROMID    DB    ?        ; 0FFH=PC OR EARLY XT, 0FEH=XT, 0FDH=JR
  60. ROM    ENDS
  61.         PAGE
  62. ;
  63. ; TABLE FOR EACH SERIAL PORT
  64. ;
  65. SP_TAB        STRUC
  66. PORT        DB    ?    ; 1 OR 2
  67. ; PARAMETERS FOR THIS INTERRUPT LEVEL
  68. INT_COM        DB    ?    ; INTERRUPT NUMBER
  69. IRQ        DB    ?    ; 8259A OCW1 MASK
  70. NIRQ        DB    ?    ; COMPLEMENT OF ABOVE
  71. EOI        DB    ?    ; 8259A OCW2 SPECIFIC END OF INTERRUPT
  72. ; INTERRUPT HANDLERS FOR THIS LEVEL
  73. INT_HNDLR    DW    ?    ; OFFSET TO INTERRUPT HANDLER
  74. OLD_COM_OFF    DW    ?    ; OLD HANDLER'S OFFSET
  75. OLD_COM_SEG    DW    ?    ; OLD HANDLER'S SEGMENT
  76. ; ATTRIBUTES
  77. INSTALLED    DB    ?    ; IS PORT INSTALLED ON THIS PC? (1=YES,0=NO)
  78. BAUD_RATE    DW    ?    ; 19200 MAX
  79. CONNECTION    DB    ?    ; M(ODEM), D(IRECT)
  80. PARITY        DB    ?    ; N(ONE), O(DD), E(VEN), S(PACE), M(ARK)
  81. STOP_BITS    DB    ?    ; 1, 2
  82. XON_XOFF    DB    ?    ; E(NABLED), D(ISABLED)
  83. ; FLOW CONTROL STATE
  84. HOST_OFF    DB    ?    ; HOST XOFF'ED (1=YES,0=NO)
  85. PC_OFF        DB    ?    ; PC XOFF'ED (1=YES,0=NO)
  86. ; ERROR COUNTS
  87. ERROR_BLOCK    DW    8 DUP(?)    ; EIGHT ERROR COUNTERS
  88. ; 8250 PORTS
  89. DATREG        DW    ?    ; DATA REGISTER
  90. IER        DW    ?    ; INTERRUPT ENABLE REGISTER
  91. IIR        DW      ?    ; INTERRUPT IDENTIFICATION REGISTER
  92. LCR        DW      ?    ; LINE CONTROL REGISTER
  93. MCR        DW      ?    ; MODEM CONTROL REGISTER
  94. LSR        DW      ?    ; LINE STATUS REGISTER
  95. MSR        DW      ?    ; MODEM STATUS REGISTER
  96. ; BUFFER POINTERS
  97. START_TDATA     DW      ?       ; INDEX TO FIRST CHARACTER IN X-MIT BUFFER
  98. END_TDATA       DW      ?       ; INDEX TO FIRST FREE SPACE IN X-MIT BUFFER
  99. START_RDATA     DW      ?       ; INDEX TO FIRST CHARACTER IN REC. BUFFER
  100. END_RDATA       DW      ?       ; INDEX TO FIRST FREE SPACE IN REC. BUFFER
  101. ; BUFFER COUNTS
  102. SIZE_TDATA      DW      ?       ; NUMBER OF CHARACTERS IN X-MIT BUFFER
  103. SIZE_RDATA      DW      ?       ; NUMBER OF CHARACTERS IN REC. BUFFER
  104. ; BUFFERS
  105. TDATA           DB      S_SIZE DUP(?)    ; SEND BUFFER
  106. RDATA           DB      R_SIZE DUP(?)    ; RECEIVE BUFFER
  107. SP_TAB        ENDS
  108. ; SP_TAB EQUATES
  109. ; WE HAVE TO USE THESE BECAUSE OF PROBLEMS WITH STRUC
  110. EOVFLOW        EQU    ERROR_BLOCK    ; BUFFER OVERFLOWS
  111. EOVRUN        EQU    ERROR_BLOCK+2    ; RECEIVE OVERRUNS
  112. EBREAK        EQU    ERROR_BLOCK+4    ; BREAK CHARS
  113. EFRAME        EQU    ERROR_BLOCK+6    ; FRAMING ERRORS
  114. EPARITY        EQU    ERROR_BLOCK+8    ; PARITY ERRORS
  115. EXMIT        EQU    ERROR_BLOCK+10    ; TRANSMISSION ERRORS
  116. EDSR        EQU    ERROR_BLOCK+12    ; DATA SET READY ERRORS
  117. ECTS        EQU    ERROR_BLOCK+14    ; CLEAR TO SEND ERRORS
  118. DLL        EQU    DATREG        ; LOW DIVISOR LATCH
  119. DLH        EQU    IER        ; HIGH DIVISOR LATCH
  120.     PAGE
  121. ;    put the data in the DGROUP segment
  122. ;    far calls enter with DS pointing to DGROUP
  123. ;
  124. DGROUP    GROUP _DATA
  125. _DATA    SEGMENT PUBLIC 'DATA'
  126. ;
  127. DIV50PC        EQU    2304        ; DIVISOR FOR 50 BAUD (PC,XT)
  128. DIV50JR        EQU    2237        ; DIVISOR FOR 50 BAUD (JR)
  129. DIV50        DW    2304        ; ACTUAL DIVISOR FOR 50 BAUD IN USE
  130. CURRENT_AREA    DW    AREA1        ; CURRENTLY SELECTED AREA
  131. ; DATA AREAS FOR EACH PORT
  132. AREA1    SP_TAB    <1,INT_COM1,IRQ4,NIRQ4,EOI4>    ; COM1 DATA AREA
  133. AREA2    SP_TAB    <2,INT_COM2,IRQ3,NIRQ3,EOI3>    ; COM2 DATA AREA
  134. _DATA    ENDS
  135.         PAGE
  136. COM_TEXT    SEGMENT PARA PUBLIC 'CODE'
  137.         ASSUME  CS:COM_TEXT,DS:DGROUP,ES:NOTHING
  138.  
  139.     PUBLIC    _select_port
  140.     PUBLIC    _save_com
  141.     PUBLIC    _install_com
  142.     PUBLIC    _restore_com
  143.     PUBLIC    _open_com
  144.     PUBLIC    _close_com
  145.     PUBLIC    _dtr_on
  146.     PUBLIC    _dtr_off
  147.     PUBLIC    _r_count
  148.     PUBLIC    _s_count
  149.     PUBLIC    _receive_com
  150.     PUBLIC    _send_com
  151.     PUBLIC    _sendi_com
  152.     PUBLIC    _send_local
  153.     PUBLIC    _break_com
  154.     PUBLIC    _com_errors
  155.     PAGE
  156. ;
  157. ; SELECT WHICH PORT IS TO BE "ACTIVE"
  158. ;    [bp+6] = port number
  159. _select_port    PROC FAR
  160.     push bp
  161.     mov bp,sp
  162.     mov AX,[bp+6]    ; get aguement
  163.     TEST    AL,1        ; FIRST PORT?
  164.     JZ    SP1        ; IF NOT, IT MUST BE SECOND PORT
  165.     MOV    AX,OFFSET DGROUP:AREA1    ; SELECT COM1 DATA AREA
  166.     JMP    SHORT SPX    ; CONTINUE
  167. SP1:    MOV    AX,OFFSET DGROUP:AREA2    ; SELECT COM2 DATA AREA
  168. SPX:    MOV    CURRENT_AREA,AX    ; SET SELECTION IN MEMORY
  169.     mov sp,bp
  170.     pop bp
  171.     RET            ; DONE
  172. _select_port    ENDP
  173.     PAGE
  174. ;
  175. ; SAVE ORIGINAL COM VECTOR
  176. ;
  177. _save_com    PROC FAR
  178.     push bp
  179.     mov bp,sp
  180.     push si
  181.     MOV    SI,CURRENT_AREA    ; SI POINTS TO DATA AREA
  182.     PUSH    ES        ; SAVE EXTRA SEGMENT
  183.     MOV    AREA1.INT_HNDLR,OFFSET INT_HNDLR1
  184.     MOV    AREA2.INT_HNDLR,OFFSET INT_HNDLR2
  185.     MOV    AH,30H        ; GET DOS VERSION NUMBER
  186.     INT    DOS        ; DOS FUNCTION
  187.     CMP    AL,2        ; AT LEAST DOS 2?
  188.     JB    SVC1        ; JUMP IF DOS 1
  189. ; SAVE OLD VECTOR WITH DOS 2 CALLS
  190.     MOV    AH,35H        ; FETCH INTERRUPT VECTOR CONTENTS
  191.     MOV    AL,INT_COM[SI]    ; INTERRUPT NUMBER
  192.     INT    DOS        ; DOS 2 FUNCTION
  193.     MOV    OLD_COM_OFF[SI],BX    ; SAVE
  194.     MOV    BX,ES            ; ES:BX
  195.     MOV    OLD_COM_SEG[SI],BX    ; FOR LATER RESTORATION
  196.     JMP    SHORT SVCX    ; DONE
  197. ; SAVE OLD VECTOR WITH DOS 1 CALLS
  198. SVC1:    MOV    AX,0        ; ZERO SEGMENT
  199.     MOV    ES,AX        ; ES POINTS TO INTERRUPT VECTORS
  200.     MOV    BL,INT_COM[SI]    ; OUR INTERRUPT NUMBER
  201.     MOV    BH,0        ; BL -> BX
  202.     SHL    BX,1        ; TIMES FOUR
  203.     SHL    BX,1        ; IS OFFSET OF VECTOR IN MEMORY
  204.     MOV    AX,WORD PTR ES:[BX]    ; SAVE
  205.     MOV    OLD_COM_OFF[SI],AX    ; THE
  206.     ADD    BX,2            ; OLD
  207.     MOV    AX,WORD PTR ES:[BX]    ; INTERRUPT
  208.     MOV    OLD_COM_SEG[SI],AX    ; VECTOR
  209. SVCX:    POP    ES        ; RESTORE ES
  210.     pop si
  211.     mov sp,bp
  212.     pop bp
  213.     RET            ; DONE
  214. _save_com    ENDP
  215.     PAGE
  216. ;
  217. ; INSTALL_COM:  INSTALL THE ACTIVE PORT
  218. ;
  219. ; SET 8250 PORTS FROM RS-232 BASE IN ROM BIOS DATA AREA
  220. ; INITIALIZE PORT CONSTANTS AND ERROR COUNTS
  221. ; INSTALL INTERRUPT VECTOR
  222. ;
  223. ;    return ax=1 on success ax=0 on failure
  224. ;
  225. _install_com    PROC FAR
  226.     push bp
  227.     mov bp,sp
  228.     push si
  229.     MOV    SI,CURRENT_AREA    ; SI POINTS TO DATA AREA
  230.     PUSH    ES        ; SAVE EXTRA SEGMENT
  231.     CMP    INSTALLED[SI],1    ; ALREADY INSTALLED?
  232.     JNE    INSTOK        ; NO, CONTINUE
  233.     JMP    INSTX        ; ELSE JUMP IF ALREADY INSTALLED
  234. ; CLEAR ERROR COUNTS
  235. INSTOK:    MOV    WORD PTR EOVFLOW[SI],0    ; BUFFER OVERFLOWS
  236.     MOV    WORD PTR EOVRUN[SI],0    ; RECEIVE OVERRUNS
  237.     MOV    WORD PTR EBREAK[SI],0    ; BREAK CHARS
  238.     MOV    WORD PTR EFRAME[SI],0    ; FRAMING ERRORS
  239.     MOV    WORD PTR EPARITY[SI],0    ; PARITY ERRORS
  240.     MOV    WORD PTR EXMIT[SI],0    ; TRANSMISSION ERRORS
  241.     MOV    WORD PTR EDSR[SI],0    ; DATA SET READY ERRORS
  242.     MOV    WORD PTR ECTS[SI],0    ; CLEAR TO SEND ERRORS
  243. ; SENSE PC TYPE AND SET DIVISOR ACCORDINGLY
  244.     MOV    BX,ROM        ; HIGH ROM SEGMENT
  245.     MOV    ES,BX        ; TO ES
  246.     ASSUME    ES:ROM
  247.     MOV    DIV50,DIV50PC    ; ASSUME PC OR XT
  248.     CMP    ROMID,0FDH    ; IS IT A PCjr?
  249.     JNE    INST0        ; JUMP IF NOT
  250.     MOV    DIV50,DIV50JR    ; ELSE SET JR DIVISOR
  251. ; SET 8250 PORT ADDRESSES
  252. INST0:    MOV    BX,RBDA        ; ROM BIOS DATA AREA
  253.     MOV    ES,BX        ; TO ES
  254.     ASSUME    ES:RBDA
  255.     TEST    PORT[SI],1    ; PORT 1?
  256.     JZ    INST1        ; JUMP IF NOT
  257.     MOV    AX,3F8H        ; COM1 BASE PORT ADDRESS
  258.     JMP    SHORT INST2    ; CONTINUE
  259. INST1:    MOV    AX,2F8H        ; COM2 BASE PORT ADDRESS
  260. INST2:    CMP    AX,RS232_BASE    ; INSTALLED?
  261.     JE    INST2A        ; JUMP IF SO
  262.     CMP    AX,RS232_BASE+2    ; INSTALLED?
  263.     JNE    INST666        ; JUMP IF NOT
  264. INST2A:    MOV    BX,DATREG    ; OFFSET OF TABLE OF PORTS
  265.     MOV    CX,7        ; LOOP SIX TIMES
  266. INST3:    MOV    WORD PTR [SI][BX],AX ; SET PORT ADDRESS
  267.     INC    AX        ; NEXT PORT
  268.     ADD    BX,2        ; NEXT WORD ADDRESS
  269.     LOOP    INST3        ; RS232 BASE LOOP
  270. ; RESET VECTOR TO POINT TO OUR HANDLER
  271.     MOV    AREA1.INT_HNDLR,OFFSET INT_HNDLR1
  272.     MOV    AREA2.INT_HNDLR,OFFSET INT_HNDLR2
  273.     MOV    AH,25H        ; SET INTERRUPT VECTOR CONTENTS
  274.     MOV    AL,INT_COM[SI]    ; INTERRUPT NUMBER
  275.     MOV    DX,OFFSET DGROUP:INT_HNDLR[SI] ; OUR INTERRUPT HANDLER
  276.     PUSH    DS              ; SAVE DATA SEGMENT
  277.     PUSH    CS        ; COPY CS
  278.     POP    DS        ; TO DS
  279.     INT    DOS        ; DOS FUNCTION
  280.     POP     DS              ; RECOVER DATA SEGMENT
  281. ; PORT INSTALLED
  282. INSTX:    MOV    INSTALLED[SI],1    ; PORT INSTALLED
  283.     POP    ES        ; RESTORE ES
  284.     mov ax,1
  285.     pop si
  286.     mov sp,bp
  287.     pop bp
  288.         RET            ; DONE
  289. ; PORT NOT INSTALLED
  290. INST666:MOV    INSTALLED[SI],0    ; PORT NOT INSTALLED ON THIS PC
  291.     POP    ES        ; RESTORE ES
  292.     mov ax,0
  293.     pop si
  294.     mov sp,bp
  295.     pop bp
  296.     RET            ; DONE
  297. _install_com    ENDP
  298.     PAGE
  299. ;
  300. ; RESTORE ORIGINAL INTERRUPT VECTOR
  301. ;
  302. _restore_com    PROC FAR
  303.     push bp
  304.     mov bp,sp
  305.     push si
  306.     MOV    SI,CURRENT_AREA    ; SI POINTS TO DATA AREA
  307.     MOV    INSTALLED[SI],0    ; PORT IS NO LONGER INSTALLED
  308.     MOV    AH,25H        ; SET INTERRUPT VECTOR FUNCTION
  309.     MOV    AL,INT_COM[SI]    ; INTERRUPT NUMBER
  310.     MOV    DX,OLD_COM_OFF[SI] ; OLD OFFSET TO DX
  311.     MOV    BX,OLD_COM_SEG[SI] ; OLD SEG
  312.     PUSH    DS        ; SAVE DS
  313.     MOV    DS,BX        ; TO DS
  314.     INT    DOS        ; DOS FUNCTION
  315.     POP    DS        ; RECOVER DS
  316.     pop si
  317.     mov sp,bp
  318.     pop bp
  319.         RET            ; DONE
  320. _restore_com    ENDP
  321.         PAGE
  322. ;
  323. ; OPEN_COM ON CURRENT PORT
  324. ;
  325. ; CLEAR BUFFERS
  326. ; RE-INITIALIZE THE INTEL 8250 UART
  327. ; ENABLE INTERRUPTS ON THE INTEL 8259 INTERRUPT CONTROL CHIP
  328. ;
  329. ; [bp+6] = BAUD RATE
  330. ; [bp+8] = CONNECTION: M(ODEM), D(IRECT)
  331. ; [bp+10] = PARITY:     N(ONE), O(DD), E(VEN), S(PACE), M(ARK)
  332. ; [bp+12] = STOP BITS:  1, 2
  333. ; [bp+14] = XON/XOFF:   E(NABLED), D(ISABLED)
  334. ;
  335. _open_com    PROC FAR
  336.     push bp
  337.     mov bp,sp
  338.     push si
  339.     MOV    SI,CURRENT_AREA        ; SI POINTS TO DATA AREA
  340.  
  341.     CLI                ; INTERRUPTS OFF
  342.     mov ax,[bp+6]
  343.     MOV    BAUD_RATE[SI],AX    ; SET
  344.     mov bh,[bp+8]
  345.     MOV    CONNECTION[SI],BH    ;     ARGS
  346.     mov bl,[bp+10]
  347.     MOV    PARITY[SI],BL        ;          IN
  348.     mov ch,[bp+12]
  349.     MOV    STOP_BITS[SI],CH    ;             MEMORY
  350.     mov cl,[bp+14]
  351.     MOV    XON_XOFF[SI],CL    
  352.  
  353. ; RESET FLOW CONTROL
  354.     MOV    HOST_OFF[SI],0        ; HOST FLOWING
  355.     MOV    PC_OFF[SI],0        ; PC FLOWING
  356.  
  357. ; RESET BUFFER COUNTS AND POINTERS
  358.     MOV    START_TDATA[SI],0
  359.     MOV    END_TDATA[SI],0
  360.     MOV    START_RDATA[SI],0
  361.     MOV    END_RDATA[SI],0
  362.     MOV    SIZE_TDATA[SI],0
  363.     MOV    SIZE_RDATA[SI],0
  364.  
  365.     TEST    INSTALLED[SI],1        ; PORT INSTALLED?
  366.     JNZ    OC1            ; SKIP IF SO
  367.     JMP    OCX            ; ELSE ABORT
  368. OC1:
  369. ; RESET THE 8250
  370.         MOV     AL,0
  371.         MOV     DX,MCR[SI]
  372.         OUT     DX,AL
  373.     JMP    $+2        ; I/O DELAY FOR JR
  374.  
  375.         MOV     DX,LSR[SI]    ; RESET LINE STATUS CONDITION
  376.         IN      AL,DX
  377.     JMP    $+2        ; I/O DELAY FOR JR
  378.         MOV     DX,DATREG[SI]    ; RESET RECSIVE DATA CONDITION
  379.         IN      AL,DX
  380.     JMP    $+2        ; I/O DELAY FOR JR
  381.         MOV     DX,MSR[SI]    ; RESET MODEM DELTAS AND CONDITIONS
  382.         IN      AL,DX
  383.  
  384. ; CONVERT PASSED BAUD RATE TO 8250 DIVISOR
  385.     MOV    AX,50        ; 50 BAUD
  386.     MUL    DIV50        ; TIMES ITS DIVISOR
  387.     DIV    BAUD_RATE[SI]    ; OTHER SPEEDS ARE PROPORTIONAL
  388.     MOV    BX,AX        ; RESULT TO BX
  389.  
  390. ; SET 8250 DIVISOR
  391.         MOV     DX,LCR[SI]    ; LINE CONTROL REGISTER
  392.         MOV     AL,80H          ; HI BIT ON
  393.         OUT     DX,AL           ; SET DLAB = 1
  394.     JMP    $+2        ; I/O DELAY FOR JR
  395.         MOV     DX,WORD PTR DLL[SI]    ; LEAST SIGNIFICANT BYTE
  396.         MOV     AL,BL        ; LSB FROM TABLE
  397.         OUT     DX,AL           ; SET LSB ON 8250
  398.     JMP    $+2        ; I/O DELAY FOR JR
  399.         MOV     DX,WORD PTR DLH[SI]    ; MOST SIGNIFICANT BYTE
  400.         MOV     AL,BH        ; MSB FROM TABLE
  401.         OUT     DX,AL           ; SET MSB ON 8250
  402.     JMP    $+2        ; I/O DELAY FOR JR
  403.  
  404. ; SET PARITY AND NUMBER OF STOP BITS
  405.     MOV    AL,03H        ; NONE OR SPACE PARITY IS THE DEFAULT
  406.     CMP    PARITY[SI],'O'    ; ODD PARITY REQUESTED?
  407.     JNE    P1        ; JUMP IF NOT
  408.     MOV    AL,0AH        ; SELECT ODD PARITY
  409.     JMP    SHORT P3    ; CONTINUE
  410. P1:    CMP    PARITY[SI],'E'    ; EVEN PARITY REQUESTED?
  411.     JNE    P2        ; JUMP IF NOT
  412.     MOV    AL,1AH        ; SELECT EVEN PARITY
  413.     JMP    SHORT P3    ; CONTINUE
  414. P2:    CMP    PARITY[SI],'M'    ; MARK PARITY REQUESTED?
  415.     JNE    P3        ; JUMP IF NOT
  416.     MOV    AL,2AH        ; SELECT MARK PARITY
  417. P3:    TEST    STOP_BITS[SI],2    ; 2 STOP BITS REQUESTED?
  418.     JZ    STOP1        ; NO
  419.     OR    AL,4        ; YES
  420. STOP1:    MOV     DX,LCR[SI]    ; LINE CONTROL REGISTER
  421.         OUT     DX,AL           ; SET 8250 PARITY MODE AND DLAB=0
  422.  
  423. ; ENABLE INTERRUPTS ON 8259 AND 8250
  424.         IN      AL,INTA01    ; SET ENABLE BIT ON 8259
  425.         AND     AL,NIRQ[SI]
  426.         OUT     INTA01,AL
  427.         MOV     DX,IER[SI]    ; ENABLE INTERRUPTS ON 8250
  428.         MOV     AL,5        ; RECEIVE & LINE ERROR
  429.         OUT     DX,AL
  430.     JMP    $+2        ; I/O DELAY FOR JR
  431.         MOV     DX,MCR[SI]    ; SET DTR AND ENABLE INT DRIVER
  432.         MOV     AL,0BH
  433.         OUT     DX,AL
  434.  
  435. OCX:    STI            ; INTERRUPTS ON
  436.     pop si
  437.     mov sp,bp
  438.     pop bp
  439.     RET            ; DONE
  440. _open_com    ENDP
  441.     PAGE
  442. ;
  443. ; CLOSE_COM - TURNS OFF INTERRUPTS FROM THE COMMUNICATIONS PORT
  444. ;
  445. _close_com    PROC FAR
  446.     push bp
  447.     mov bp,sp
  448.     push si
  449.     MOV    SI,CURRENT_AREA    ; SI POINTS TO DATA AREA
  450.     TEST    INSTALLED[SI],1    ; PORT INSTALLED?
  451.     JZ    CCX        ; ABORT IF NOT
  452.  
  453. ; TURN OFF 8250
  454.         MOV     DX,IER[SI]
  455.         MOV     AL,0
  456.         OUT     DX,AL
  457.  
  458. ; TURN OFF 8259
  459.         MOV     DX,INTA01
  460.         IN      AL,DX
  461.         OR      AL,IRQ[SI]
  462.     JMP    $+2        ; DELAY FOR AT
  463.         OUT     DX,AL
  464.  
  465. CCX:    pop si
  466.     mov sp,bp
  467.     pop bp
  468.     RET
  469. _close_com    ENDP
  470.         PAGE
  471. ;
  472. ; DTR_OFF - TURNS OFF DTR TO TELL MODEMS THAT THE TERMINAL HAS GONE AWAY
  473. ;           AND TO HANG UP THE PHONE
  474. ;
  475. _dtr_off    PROC FAR
  476.     push bp
  477.     mov bp,sp
  478.     push si
  479.     PUSHF            ; SAVE FLAGS
  480.     PUSH    AX        ; SAVE REGS
  481.     PUSH    DX
  482.     PUSH    SI
  483.     MOV    SI,CURRENT_AREA    ; SI POINTS TO DATA AREA
  484.     TEST    INSTALLED[SI],1    ; PORT INSTALLED?
  485.     JZ    DFX        ; ABORT IF NOT
  486.  
  487.         MOV     DX,MCR[SI]
  488.         MOV     AL,08H        ; DTR OFF, RTS OFF, OUT2 ON
  489.         OUT     DX,AL
  490. DFX:    POP    SI        ; RECOVER REGS
  491.     POP    DX
  492.     POP    AX
  493.     POPF            ; RECOVER FLAGS
  494.     pop si
  495.     mov sp,bp
  496.     pop bp
  497.     RET
  498. _dtr_off    ENDP
  499. ;
  500. ; DTR_ON - TURNS DTR ON
  501. ;
  502. _dtr_on    PROC FAR
  503.     push bp
  504.     mov bp,sp
  505.     push si
  506.     PUSHF            ; SAVE FLAGS
  507.     PUSH    AX        ; SAVE REGS
  508.     PUSH    DX
  509.     PUSH    SI
  510.     MOV    SI,CURRENT_AREA    ; SI POINTS TO DATA AREA
  511.     TEST    INSTALLED[SI],1    ; PORT INSTALLED?
  512.     JZ    DNX        ; ABORT IF NOT
  513.  
  514.         MOV     DX,MCR[SI]
  515.         MOV     AL,0BH
  516.         OUT     DX,AL
  517. DNX:    POP    SI        ; RECOVER REGS
  518.     POP    DX
  519.     POP    AX
  520.     POPF            ; RECOVER FLAGS
  521.     pop si
  522.     mov sp,bp
  523.     pop bp
  524.     RET            ; DONE
  525. _dtr_on    ENDP
  526.         PAGE
  527. ;
  528. ; R_COUNT - RETURNS NUMBER OF BYTES IN THE RECEIVE BUFFER IN AX
  529. ;             total in DX
  530. ;
  531. _r_count    PROC FAR
  532.     push bp
  533.     mov bp,sp
  534.     push si
  535.     PUSHF            ; SAVE FLAGS
  536.     PUSH    SI        ; SAVE SI
  537.     MOV    SI,CURRENT_AREA    ; SI POINTS TO DATA AREA
  538.     MOV    AX,0        ; NOTHING RECEIVED IF NOT INSTALLED
  539.     mov dx,R_SIZE
  540.  
  541.     TEST    INSTALLED[SI],1    ; PORT INSTALLED?
  542.     JZ    RCX        ; ABORT IF NOT
  543.  
  544.         MOV     AX,SIZE_RDATA[SI] ; GET NUMBER OF BYTES USED
  545. RCX:    POP    SI        ; RESTORE SI
  546.     POPF            ; RESTORE FLAGS
  547.     pop si
  548.     mov sp,bp
  549.     pop bp
  550.     RET
  551. _r_count    ENDP
  552.     PAGE
  553. ;
  554. ; RECEIVE - RETURNS THE NEXT CHARACTER FROM THE RECEIVE BUFFER IN AL
  555. ;            AND REMOVES IT FROM THE BUFFER
  556. ;            THE PARITY BIT IS STRIPPED OFF
  557. ;
  558. _receive_com    PROC FAR
  559.     push bp
  560.     mov bp,sp
  561.     push si
  562.     PUSHF                ; SAVE FLAGS
  563.     PUSH    BX            ; SAVE REGS
  564.     PUSH    SI
  565.     MOV    SI,CURRENT_AREA        ; SI POINTS TO DATA AREA
  566.     mov    ax,-1 ; -1 if bad call
  567.     TEST    INSTALLED[SI],1        ; PORT INSTALLED?
  568.     JZ    RCVX            ; ABORT IF NOT
  569.     CMP    SIZE_RDATA[SI],0    ; ANY CHARACTERS?
  570.     JE    RCVX            ; ABORT IF NOT
  571.  
  572. ; GOOD CALL
  573.     mov ah,0    ; good call
  574.         MOV     BX,START_RDATA[SI]    ; GET POINTER TO OLDEST CHAR
  575.         MOV     AL,RDATA[SI][BX]    ; GET CHAR FROM BUFFER
  576. ; MOD BY LBA, 10/6/85 FOR PROPER SUPPORT OF NO PARITY COMMUNICATIONS
  577.     CMP    PARITY[SI],'N'        ; ARE WE RUNNING WITH NO PARITY?
  578.     JE    L11            ; IF SO, DON'T STRIP HIGH BIT
  579. ; END OF MOD
  580.     AND    AL,7FH            ; STRIP PARITY BIT
  581. L11:    INC     BX                  ; BUMP START_RDATA
  582.         CMP     BX,R_SIZE        ; SEE IF PAST END
  583.         JB      L12                 ; IF NOT THEN SKIP
  584.         MOV    BX,0            ; ADJUST TO BEGINNING
  585. L12:    MOV     START_RDATA[SI],BX    ; SAVE THE NEW START_RDATA VALUE
  586.         DEC     SIZE_RDATA[SI]        ; ONE LESS CHARACTER
  587.     CMP    XON_XOFF[SI],'E'    ; FLOW CONTROL ENABLED?
  588.     JNE    RCVX            ; DO NOTHING IF DISABLED
  589.     CMP    HOST_OFF[SI],1        ; HOST TURNED OFF?
  590.     JNE    RCVX            ; JUMP IF NOT
  591.     CMP    SIZE_RDATA[SI],R_SIZE/20 ; RECEIVE BUFFER NEARLY EMPTY?
  592.     JGE    RCVX            ; DONE IF NOT
  593.     MOV    HOST_OFF[SI],0        ; TURN ON HOST IF SO
  594.     PUSH    AX            ; SAVE RECEIVED CHAR
  595.     MOV    AL,CONTROL_Q        ; TELL HIM TO TALK
  596.     CLI                ; TURN OFF INTERRUPTS
  597.     CALL    SENDII            ; SEND IMMEDIATELY INTERNAL
  598.     STI                ; INTERRUPTS BACK ON
  599.     POP    AX            ; RESTORE RECEIVED CHAR
  600. RCVX:    POP    SI            ; RECOVER REGS
  601.     POP    BX
  602.     POPF                ; RECOVER FLAGS
  603.     pop si
  604.     mov sp,bp
  605.     pop bp
  606.     RET                ; DONE
  607. _receive_com    ENDP
  608.         PAGE
  609. ;
  610. ; S_COUNT - RETURNS IN AX THE AMOUNT OF FREE SPACE
  611. ;              REMAINING IN THE TRANSMIT BUFFER
  612. ;     DX total size
  613. ;
  614. _s_count    PROC FAR
  615.     push bp
  616.     mov bp,sp
  617.     push si
  618.     PUSHF            ; SAVE FLAGS
  619.     PUSH    SI        ; SAVE SI
  620.     MOV    SI,CURRENT_AREA    ; SI POINTS TO DATA AREA
  621.     MOV    AX,0        ; NO SPACE LEFT IF NOT INSTALLED
  622.     mov dx,S_SIZE
  623.  
  624.     TEST    INSTALLED[SI],1    ; PORT INSTALLED?
  625.     JZ    SCX        ; ABORT IF NOT
  626.  
  627.         MOV     AX,S_SIZE    ; GET THE SIZE OF THE X-MIT BUFFER
  628.         SUB     AX,SIZE_TDATA[SI] ; SUBTRACT THE NUMBER OF BYTES USED
  629. SCX:    POP    SI        ; RECOVER SI
  630.     POPF            ; RESTORE FLAGS
  631.     pop si
  632.     mov sp,bp
  633.     pop bp
  634.     RET
  635. _s_count    ENDP
  636.         PAGE
  637. ;
  638. ; SEND - SEND A CHARACTER
  639. ;    [bp+6] = char
  640. ;
  641. _send_com    PROC FAR
  642.     push bp
  643.     mov bp,sp
  644.     push si
  645.     mov al,[bp+6]
  646.     PUSHF                ; SAVE FLAGS
  647.     PUSH    AX            ; SAVE REGS
  648.     PUSH    BX
  649.     PUSH    DX
  650.     PUSH    SI
  651.     MOV    SI,CURRENT_AREA        ; SI POINTS TO DATA AREA
  652.     TEST    INSTALLED[SI],1        ; PORT INSTALLED?
  653.     JZ    L44            ; ABORT IF NOT
  654.  
  655.     CMP    SIZE_TDATA[SI],S_SIZE    ; BUFFER FULL?
  656.     JL    L4A            ; JUMP IF NOT
  657.     INC    WORD PTR EOVFLOW[SI]    ; BUMP ERROR COUNT
  658.     JMP    SHORT L44        ; PUNT
  659. L4A:    MOV     BX,END_TDATA[SI]    ; BX POINTS TO FREE SPACE
  660.         MOV     TDATA[SI][BX],AL    ; MOVE CHAR TO BUFFER
  661.         INC     BX                  ; INCREMENT END_TDATA
  662.         CMP     BX,S_SIZE        ; SEE IF PAST END
  663.         JL      L4                  ; IF NOT THEN SKIP
  664.     MOV    BX,0            ; ADJUST TO BEGINNING
  665. L4:     MOV     END_TDATA[SI],BX    ; SAVE NEW END_TDATA
  666.         INC     SIZE_TDATA[SI]        ; ONE MORE CHARACTER IN X-MIT BUFFER
  667.     MOV     DX,IER[SI]        ; INTERRUPT ENABLE REGISTER
  668.         IN      AL,DX            ; GET IT
  669.     TEST    AL,2            ; SEE IF TX INTERRUPTS ARE ENABLED
  670.         JNZ     L44            ; JUMP IF SO
  671.         MOV     AL,7            ; IF NOT THEN RCV, TX, LINE ERROR
  672.         OUT     DX,AL            ; ARE ENABLED
  673. L44:    POP    SI            ; RESTORE REGS
  674.     POP    DX
  675.     POP    BX
  676.     POP    AX
  677.     POPF                ; RESTORE FLAGS
  678.     pop si
  679.     mov sp,bp
  680.     pop bp
  681.     RET                ; DONE
  682. _send_com    ENDP
  683.         PAGE
  684. ;
  685. ; SENDI - SEND A CHARACTER IMMEDIATELY
  686. ; [bp+6] = char to send
  687. ;
  688. _sendi_com    PROC FAR
  689.     push bp
  690.     mov bp,sp
  691.     push si
  692.     mov al,[bp+6]
  693.     PUSHF                ; SAVE FLAGS
  694.     PUSH    AX            ; SAVE REGS
  695.     PUSH    BX
  696.     PUSH    DX
  697.     PUSH    SI
  698.     MOV    SI,CURRENT_AREA        ; SI POINTS TO DATA AREA
  699.     TEST    INSTALLED[SI],1        ; PORT INSTALLED?
  700.     JZ    LQ44            ; ABORT IF NOT
  701.  
  702.     CLI                ; MASK INTERRUPTS
  703.     CALL    SENDII            ; CALL INTERNAL SEND IMMEDIATE
  704.     STI                ; INTERRRUPTS BACK ON
  705.  
  706. LQ44:    POP    SI            ; RESTORE REGS
  707.     POP    DX
  708.     POP    BX
  709.     POP    AX
  710.     POPF                ; RESTORE FLAGS
  711.     pop si
  712.     mov sp,bp
  713.     pop bp
  714.     RET                ; DONE
  715. _sendi_com    ENDP
  716.         PAGE
  717. ;
  718. ; INTERNAL ROUTINE
  719. ; DEPENDS ON CALLER TO KEEP INTERRUPTS CLEARED AND SET SI
  720. ; SENDI - SEND A CHARACTER IMMEDIATELY (PUT AT BEGINNING OF QUEUE)
  721. ; AL = CHAR TO WRITE
  722. ;
  723. SENDII    PROC    NEAR
  724.     PUSH    DX            ; SAVE DX
  725.     CMP    SIZE_TDATA[SI],S_SIZE    ; BUFFER FULL?
  726.     JB    LI4A            ; JUMP IF NOT
  727.     INC    WORD PTR EOVFLOW[SI]    ; BUMP ERROR COUNT
  728.     MOV    BX,START_TDATA[SI]    ; BX POINTS TO FIRST CHAR IN BUFFER
  729.     MOV     TDATA[SI][BX],AL     ; CLOBBER FIRST CHAR IN BUFFER
  730.     JMP    SHORT LI4B        ; CONTINUE
  731. LI4A:    MOV    BX,START_TDATA[SI]    ; BX POINTS TO FIRST CHAR IN BUFFER
  732.     DEC    BX            ; BACKUP THE PTR
  733.     CMP    BX,-1            ; BEFORE BEGINNING?
  734.     JNE    LI4            ; JUMP IF NOT
  735.     MOV    BX,S_SIZE-1        ; POINT TO END IF SO
  736. LI4:    MOV     TDATA[SI][BX],AL     ; MOVE CHAR TO BUFFER
  737.     MOV     START_TDATA[SI],BX    ; SAVE NEW START_TDATA
  738.     INC     SIZE_TDATA[SI]        ; ONE MORE CHARACTER IN X-MIT BUFFER
  739. LI4B:    MOV     DX,IER[SI]        ; INTERRUPT ENABLE REGISTER
  740.         IN      AL,DX            ; GET IT
  741.     TEST    AL,2            ; SEE IF TX INTERRUPTS ARE ENABLED
  742.         JNZ     LI44            ; JUMP IF SO
  743.         MOV     AL,7            ; IF NOT THEN RCV, TX, LINE ERROR
  744.         OUT     DX,AL            ; ARE ENABLED
  745. LI44:    POP    DX            ; RECOVER DX
  746.     RET                ; DONE
  747. SENDII    ENDP
  748.     PAGE
  749. ;
  750. ; S_LOCAL
  751. ;
  752. _send_local    PROC FAR
  753.     push bp
  754.     mov bp,sp
  755.     push si
  756.     mov al,[bp+6]
  757.     PUSHF                ; SAVE FLAGS
  758.     PUSH    AX            ; SAVE REGS
  759.     PUSH    BX
  760.     PUSH    SI
  761.     MOV    SI,CURRENT_AREA        ; SI POINTS TO DATA AREA
  762.     TEST    INSTALLED[SI],1        ; PORT INSTALLED?
  763.     JZ    SLX            ; ABORT IF NOT
  764.  
  765.         CLI                ; INTERRUPTS OFF
  766.         CMP     SIZE_RDATA[SI],R_SIZE    ; SEE IF ANY ROOM
  767.     JB    L13A            ; SKIP IF ROOM
  768.     INC    WORD PTR EOVFLOW[SI]    ; BUMP OVERFLOW COUNT
  769.     JMP    SHORT L14        ; PUNT
  770. L13A:    MOV     BX,END_RDATA[SI]    ; BX POINTS TO FREE SPACE
  771.         MOV     RDATA[SI][BX],AL    ; SEND DATA TO BUFFER
  772.         INC     BX                     ; INCREMENT END_RDATA POINTER
  773.         CMP     BX,R_SIZE        ; SEE IF GONE PAST END
  774.         JL      L13                 ; IF NOT THEN SKIP
  775.         MOV    BX,0            ; ELSE ADJUST TO BEGINNING
  776. L13:    MOV     END_RDATA[SI],BX     ; SAVE VALUE
  777.         INC     SIZE_RDATA[SI]        ; GOT ONE MORE CHARACTER
  778. L14:    STI                ; INTERRUPTS BACK ON
  779.  
  780. SLX:    POP    SI            ; RECOVER REGS
  781.     POP    BX
  782.     POP    AX
  783.     POPF                ; RECOVER FLAGS
  784.     pop si
  785.     mov sp,bp
  786.     pop bp
  787.     RET                ; DONE
  788. _send_local    ENDP
  789.         PAGE
  790. ;
  791. ; BREAK - CAUSES A BREAK TO BE SENT OUT ON THE LINE
  792. ;
  793. _break_com    PROC FAR
  794.     push bp
  795.     mov bp,sp
  796.     push si
  797.     PUSHF            ; SAVE FLAGS
  798.     PUSH    AX        ; SAVE REGS
  799.     PUSH    CX
  800.     PUSH    DX
  801.     MOV    SI,CURRENT_AREA    ; SI POINTS TO DATA AREA
  802.     TEST    INSTALLED[SI],1    ; PORT INSTALLED?
  803.     JZ    BRX        ; ABORT IF NOT
  804.  
  805.     MOV    DX,LCR[SI]    ; LINE CONTROL REGISTER
  806.     IN    AL,DX        ; GET CURRENT SETTING
  807.     JMP    $+2        ; I/O DELAY FOR JR
  808.     OR    AL,40H        ; TURN ON BREAK BIT
  809.     OUT    DX,AL        ; SET IT ON THE 8250
  810.     MOV    CX,0C000H    ; WAIT APPROX. 1/4 SEC.
  811. BREAK1:    LOOP    BREAK1        ; BUSY WAIT
  812.     AND    AL,0BFH        ; TURN OFF BREAK BIT
  813.     OUT    DX,AL        ; RESTORE LINE CONTROL REGISTER
  814. BRX:    POP    DX        ; RECOVER REGS
  815.     POP    CX
  816.     POP    AX
  817.     POPF            ; RECOVER FLAGS
  818.     pop si
  819.     mov sp,bp
  820.     pop bp
  821.     RET            ; DONE
  822. _break_com    ENDP
  823.     PAGE
  824. ;
  825. ; COM_ERRORS - RETURN POINTER IN dx:ax TO ERROR COUNTS
  826. ;
  827. _com_errors    PROC FAR
  828.     push bp
  829.     mov bp,sp
  830.     mov ax,OFFSET DGROUP:CURRENT_AREA
  831.     add ax,ERROR_BLOCK
  832.     mov dx,ds
  833.     mov sp,bp
  834.     pop bp
  835.     RET            ; DONE
  836. _com_errors    ENDP
  837.         PAGE
  838. ;
  839. ; INTERNAL ROUTINE
  840. ; BUMP ERROR COUNTS FROM LINE STATUS IN AL
  841. ;
  842. E_BUMP    PROC    NEAR
  843.     TEST    AL,2        ; OVERRUN ERROR?
  844.     JZ    LSI1        ; JUMP IF NOT
  845.     INC    WORD PTR EOVRUN[SI]    ; ELSE BUMP ERROR COUNT
  846. LSI1:    TEST    AL,4        ; PARITY ERROR?
  847.     JZ    LSI2        ; JUMP IF NOT
  848.     INC    WORD PTR EPARITY[SI]    ; ELSE BUMP ERROR COUNT
  849. LSI2:    TEST    AL,8        ; FRAMING ERROR?
  850.     JZ    LSI3        ; JUMP IF NOT
  851.     INC    WORD PTR EFRAME[SI]    ; ELSE BUMP ERROR COUNT
  852. LSI3:    TEST    AL,16        ; BREAK RECEIVED?
  853.     JZ    LSI4        ; JUMP IF NOT
  854.     INC    WORD PTR EBREAK[SI]    ; ELSE BUMP ERROR COUNT
  855. LSI4:    RET            ; DONE
  856. E_BUMP    ENDP
  857.     PAGE
  858. ;
  859. ; INTERNAL ROUTINE
  860. ; MODEM SEND PROTOCOL
  861. ;
  862. M_PROTOCOL PROC    NEAR
  863.         CMP     CONNECTION[SI],'M' ; MODEM CONNECTION?
  864.         JNE     S3        ; IF NOT, SKIP DSR & CTS PROTOCOL
  865.  
  866. ; TELL MODEM WE'RE READY TO SEND
  867.         MOV     DX,MCR[SI]    ; MODEM CONTROL REGISTER
  868.         MOV     AL,00001011B    ; OUT 2, RTS, DTR
  869.         OUT     DX,AL           ; TERMINAL READY, REQUEST TO SEND
  870.     JMP    $+2        ; I/O DELAY FOR JR
  871.  
  872. ; WAIT UNTIL MODEM SAYS DATA SET READY
  873.     MOV     CX,1000        ; TIMEOUT COUNT
  874.         MOV     DX,MSR[SI]    ; MODEM STATUS REGISTER
  875. S1:     IN      AL,DX           ; GET MODEM STATUS
  876.         TEST    AL,20H          ; DATA SET READY?
  877.         JNZ     S1X        ; YES, TEST CLEAR TO SEND
  878.         LOOP    S1              ; NO, BUSY WAIT
  879.         INC    WORD PTR EDSR[SI]    ; BUMP ERROR COUNT
  880.     JMP    SHORT S3    ; WE TIMED OUT
  881. S1X:
  882. ; WAIT UNTIL MODEM SAYS IT'S CLEAR TO SEND
  883.     MOV    CX,1000        ; TIMEOUT COUNT
  884. S2:    IN      AL,DX           ; GET MODEM STATUS
  885.         TEST    AL,10H          ; CLEAR TO SEND?
  886.         JNZ     S2X        ; YES
  887.         LOOP    S2        ; NO, KEEP TRYING
  888.         INC    WORD PTR ECTS[SI]    ; BUMP ERROR COUNT - WE TIMED OUT
  889. S2X:
  890. ; TEST FOR TRANSMITTER READY
  891. S3:    MOV     DX,LSR[SI]    ; LINE STATUS REGISTER
  892.     IN      AL,DX           ; GET LINE STATUS
  893.         TEST    AL,20H          ; TRANSMITTER READY?
  894.         JNZ     S4        ; SKIP IF SO
  895.     INC    WORD PTR EXMIT[SI]    ; ELSE BUMP ERROR COUNT
  896. S4:    RET            ; DONE
  897. M_PROTOCOL ENDP
  898.     PAGE
  899. ;
  900. ; INTERNAL ROUTINES FOR FLOW CONTROL
  901. ;
  902. ; FLOW_IN - RESPOND TO FLOW CONTROL COMMANDS FROM HOST
  903. ; FLOW_OUT - ISSUE FLOW CONTROL COMMANDS TO HOST
  904. ;
  905. FLOW_IN    PROC    NEAR
  906.     PUSH    AX        ; SAVE CHAR
  907.     CMP    XON_XOFF[SI],'E'; FLOW CONTROL ENABLED?
  908.     JNE    FI_2        ; DO NOTHING IF DISABLED
  909.     AND    AL,7FH        ; STRIP PARITY
  910.     CMP    AL,CONTROL_S    ; STOP COMMAND RECEIVED?
  911.     JNE    FI_1        ; JUMP IF NOT
  912.     MOV    PC_OFF[SI],1    ; WE MUST SHUT UP
  913.     JMP    SHORT FI_2    ; CONTINUE
  914. FI_1:    CMP    AL,CONTROL_Q    ; GO COMMAND RECEIVED?
  915.     JNE    FI_2        ; NO, MUST BE NORMAL CHAR
  916.     MOV    PC_OFF[SI],0    ; WE START TALKING AGAIN
  917. FI_2:    POP    AX        ; RESTORE CHAR
  918.     RET            ; DONE
  919. FLOW_IN    ENDP
  920. ;
  921. FLOW_OUT PROC    NEAR
  922.     CMP    XON_XOFF[SI],'E'; FLOW CONTROL ENABLED?
  923.     JNE    FO_X        ; DO NOTHING IF DISABLED
  924.     CMP    HOST_OFF[SI],1    ; HOST TURNED OFF?
  925.     JE    FO_X        ; JUMP IF SO
  926.     CMP    SIZE_RDATA[SI],R_SIZE/2    ; RECEIVE BUFFER NEARLY FULL?
  927.     JLE    FO_X        ; DONE IF NOT
  928.     MOV    AL,CONTROL_S    ; TURN OFF HOST IF SO
  929.     CALL    SENDII        ; SEND IMMEDIATELY INTERNAL
  930.     MOV    HOST_OFF[SI],1    ; HOST IS NOW OFF
  931. FO_X:    RET            ; DONE
  932. FLOW_OUT ENDP
  933.         PAGE
  934. ;
  935. ; INT_HNDLR1 - HANDLES INTERRUPTS GENERATED BY COM1:
  936. ;
  937. INT_HNDLR1 PROC  FAR
  938.     PUSH    SI        ; SAVE SI
  939.     MOV    SI,OFFSET AREA1    ; DATA AREA FOR COM1:
  940.     JMP    SHORT INT_COMMON ; CONTINUE
  941. ;
  942. ; INT_HNDLR2 - HANDLES INTERRUPTS GENERATED BY COM2:
  943. ;
  944. INT_HNDLR2 PROC  FAR
  945.     PUSH    SI        ; SAVE SI
  946.     MOV    SI,OFFSET AREA2    ; DATA AREA FOR COM2:
  947. ;
  948. ; BODY OF INTERRUPT HANDLER
  949. ;
  950. INT_COMMON:
  951.     PUSH    AX        ; SAVE REGS
  952.     PUSH    BX
  953.     PUSH    CX
  954.     PUSH    DX
  955.     PUSH    BP
  956.     PUSH    DI
  957.     PUSH    DS
  958.     PUSH    ES
  959.  
  960.     MOV    AX,SEG _DATA        ; OUR DATA SEG
  961.     MOV    DS,AX        ; TO DS
  962.  
  963. ; CLEAR THE INTERRUPT CONTROLLER FLAG
  964.     MOV    DX,INTA00    ; 8259 CONTROL PORT
  965.     MOV    AL,EOI[SI]    ; SPECIFIC END OF INTERRUPT
  966.     OUT    DX,AL        ; CLEAR FLAG
  967.  
  968. ; FIND OUT WHERE INTERRUPT CAME FROM AND JUMP TO ROUTINE TO HANDLE IT
  969. REPOLL:
  970.         MOV     DX,IIR[SI]    ; READ INTERRUPT STATUS REGISTER
  971.         IN      AL,DX
  972.         CMP     AL,4
  973.         JE    RX_INT        ; IF FROM THE RECEIVER
  974.     CMP     AL,2
  975.         JE      TX_INT          ; IF FROM THE TRANSMITTER
  976.         CMP     AL,6
  977.         JE    LSTAT_INT       ; INTERRUPT BECAUSE OF LINE STATUS
  978.         CMP     AL,0
  979.         JE    MSTAT_INT       ; INTERRUPT BECAUSE OF MODEM STATUS
  980.         JMP     FAR PTR INT_END    ; DONE, EXIT (DON'T FIX FAR PTR STUFF)
  981.  
  982. LSTAT_INT:
  983.         MOV     DX,LSR[SI]    ; READ AND IGNORE LINE STATUS
  984.         IN      AL,DX        ;
  985.     CALL    E_BUMP        ; JUST BUMP ERROR COUNTS
  986.     JMP     REPOLL          ; SEE IF ANY MORE INTERRUPTS
  987.  
  988. MSTAT_INT:
  989.         MOV     DX,MSR[SI]    ; READ AND IGNORE MODEM STATUS
  990.         IN      AL,DX        ;
  991.         JMP     REPOLL          ; SEE IF ANY MORE INTERRUPTS
  992.  
  993. TX_INT:
  994.     CMP    PC_OFF[SI],1    ; HAVE WE BEEN TOLD TO SHUT UP?
  995.     JNE    GOODTX1        ; JUMP IF NOT
  996.     CMP    HOST_OFF[SI],1    ; HAS HOST ALSO SHUT UP?
  997.     JNE    SEND_NO_MORE    ; JUMP IF NOT
  998.  
  999. ; CLEAR XON/XOFF DEADLOCK
  1000.     MOV    PC_OFF[SI],0    ; WE SPEAK
  1001.     MOV    HOST_OFF[SI],0    ; THEY REPLY
  1002.     MOV    AL,CONTROL_Q    ; BUT ONLY WHEN
  1003.     CALL    SENDII        ; WE LET THEM
  1004.  
  1005. GOODTX1:
  1006.     CMP     SIZE_TDATA[SI],0 ; SEE IF ANY MORE DATA TO SEND
  1007.     JG    HAVE_DATA       ; IF POSITIVE THEN THERE IS DATA TO SEND
  1008.  
  1009. ; IF NO DATA TO SEND THEN RESET TX INTERRUPT AND RETURN
  1010. SEND_NO_MORE:
  1011.         MOV     DX,IER[SI]        ;
  1012.         MOV     AL,5            ; JUST RCV AND LINE ERROR
  1013.         OUT     DX,AL            ; ARE SET
  1014.         JMP     REPOLL            ;
  1015.  
  1016. HAVE_DATA:
  1017.     CALL    M_PROTOCOL        ; DO MODEM PROTOCOL IF NECESSARY
  1018.  
  1019.         MOV     BX,START_TDATA[SI]    ; BX POINTS TO NEXT CHAR. TO BE SENT
  1020.         MOV     AL,TDATA[SI][BX]    ; GET DATA FROM BUFFER
  1021.         MOV     DX,DATREG[SI]        ; DX EQUALS PORT TO SEND DATA TO
  1022.         OUT     DX,AL               ; SEND DATA
  1023.         INC     BX                  ; INCREMENT START_TDATA
  1024.         CMP     BX,S_SIZE        ; SEE IF GONE PAST END
  1025.         JB      NTADJ               ; IF NOT THEN SKIP
  1026.     MOV    BX,0            ; RESET TO BEGINNING
  1027. NTADJ:  MOV     START_TDATA[SI],BX    ; SAVE START_TDATA
  1028.         DEC     SIZE_TDATA[SI]        ; ONE LESS CHARACTER IN X-MIT BUFFER
  1029.         JMP     REPOLL
  1030.  
  1031. RX_INT:
  1032.         MOV     DX,DATREG[SI]        ; 8250 DATA REGISTER
  1033.         IN      AL,DX            ; GET DATA
  1034.     CALL    FLOW_IN            ; RESPOND TO F.C. COMMANDS FROM HOST
  1035.         CMP     SIZE_RDATA[SI],R_SIZE    ; SEE IF ANY ROOM
  1036.         JL    GOOD_RX1        ; CONTINUE IF SO
  1037.     INC    WORD PTR EOVFLOW[SI]    ; BUMP OVERFLOW ERROR COUNT
  1038.     JMP    REPOLL            ; PUNT
  1039. GOOD_RX1:
  1040.         MOV     BX,END_RDATA[SI]    ; BX POINTS TO FREE SPACE
  1041.         MOV     RDATA[SI][BX],AL    ; MOVE DATA TO BUFFER
  1042.         INC    SIZE_RDATA[SI]        ; GOT ONE MORE CHARACTER
  1043.         INC     BX                  ; INCREMENT END_RDATA POINTER
  1044.         CMP     BX,R_SIZE        ; SEE IF GONE PAST END
  1045.     JB    NRADJ               ; IF NOT THEN SKIP
  1046.         MOV     BX,0            ; ELSE ADJUST TO BEGINNING
  1047. NRADJ:  MOV     END_RDATA[SI],BX    ; SAVE VALUE
  1048.     CALL    FLOW_OUT        ; ISSUE FLOW CONTROL COMMANDS TO HOST
  1049.     JMP    REPOLL            ;
  1050.  
  1051. INT_END:
  1052.     POP    ES        ; RESTORE REGS
  1053.     POP    DS
  1054.     POP    DI
  1055.     POP    BP
  1056.         POP     DX
  1057.         POP     CX
  1058.         POP     BX
  1059.         POP     AX
  1060.  
  1061.     POP    SI        ; RESTORE SI, TOO
  1062.         IRET
  1063. INT_HNDLR2 ENDP
  1064. INT_HNDLR1 ENDP
  1065. COM_TEXT    ENDS
  1066.         END
  1067.