home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / mskermit / msxv90.asm < prev    next >
Assembly Source File  |  2020-01-01  |  42KB  |  1,444 lines

  1.        name msxv90
  2. ; File MSXV90.ASM
  3.     include mssdef.h
  4. ;       Copyright (C) 1982,1991, Trustees of Columbia University in the
  5. ;       City of New York.  Permission is granted to any individual or
  6. ;       institution to use, copy, or redistribute this software as long as
  7. ;       it is not sold for profit and this copyright notice is retained.
  8. ; Kermit system dependent module for VICTOR 9000/SIRIUS
  9. ; Edit History
  10. ; 2 March 1991 version 3.10
  11. ; Last edit: 17 Dec 1990 MS-DOS Kermit v3.02 editing. [jrd]
  12. ; 12 June 1988 Add error recovery if serial port fails to initialize. [jrd]
  13. ; 9 March 1988 Add procedure getmodem and global byte mdmhand for use by
  14. ;  scripts in sensing modem status. Add: ignore received XOFF if we have sent
  15. ;  an XOFF already (avoids lockouts from echoes). Add user/buffer xon/xoff
  16. ;  sensing. [jrd]
  17. ; 3 March 1988 Add shomodem routine to show status of DSR, CD, CTS lines
  18. ;   [bgp]
  19. ; 7 Sept 1987 Remove keep_delete, pass null, del chars to terminal section.
  20. ;   [jrd]
  21. ; 29 August 1987 Add capability for sending long break [bgp]
  22. ; 9 February 1987 Add flag for ignoring delete chars in SERINT - they must
  23. ;   be retained when emulating a Tektronix (graphics mode) - this is done
  24. ;   using global symbol keep_delete.
  25. ; 6 November 1986 Fix receiver overrun detection and miscellaneous minor
  26. ;   fixes
  27. ; 30 Sept 1986 Reject DEL char at serial port reception level to avoid
  28. ;   problems when DEL is used as a filler char (be Emacs). [jrd]
  29. ; 16 Sept 1986 Revise serial port routines prtchr, outchr, serini, serint
  30. ;   to use more efficient code from IBM version. [jrd]
  31. ; 4 Sept 1986 Add Bob Goeke's change to move comms port table to a system
  32. ;   dependent module (typ msx---) to allow 3+ ports and localized idents. [jrd]
  33. ; 26 August 1986 Use parity mask when testing for nulls & Xon/Xoff in serial
  34. ;   port interrupt routine. [jrd]
  35. ; 16 August 1986 Use observed screen attributes for mode line. [jrd]
  36. ; 9 August 1986 Revise SERINT to insert control-G for overrun chars, give
  37. ;  faster return of interrupts to system, remove use of BP in code. [jrd]
  38. ;   Original version, BGP, 23 November 1985
  39. ; Add global entry point vtstat for use by Status routine in mssset.
  40. ; Cleared terminal emulation flag, flags.vtflg, in procedure lclini.
  41. ; Add register save/restore in procedure getbaud.
  42. ; Joe R. Doupnik 12 March 1986
  43. ; Add some register save/restores here and there.
  44. ; Add global procedures ihosts and ihostr to handle host initialization
  45. ; when packets are to be sent or received by us,resp. 24 March 1986
  46. ; Add global procedure dtrlow to force DTR and RTS low in support of Kermit
  47. ; command Hangup.   B.G.Peterson 10 April 1986
  48. ; Add support of serial port settings through use of IOCTL DOS function
  49. ; code from Andreas Stumpf (ZRZS@DS0RUS1I), merged by B.G.Peterson 10 April 86
  50. ; Moved VTS and VTSTAT routines to MSYxxx.ASM where the terminal emulation
  51. ; is done anyway. B.G.Peterson 10 April 1986
  52. ; Last update 28 April 1986
  53. ; 30 July 1986 Corrected IHOSTS and IHOSTR to prevent sending null byte if
  54. ;  no flow control.
  55. ;  Modified SERHNG so it turns DTR and RTS off for 3 seconds and then back
  56. ;  on again so a new connection can be made easily.
  57. ;  Modified SERRST to wait until transmitter is empty before turning off
  58. ;  port.
  59. ;  Modified port controller access so that if opening it using the standard
  60. ;  Victor drivers fails, it will just go direct to the hardware. [bgp]
  61.  
  62.     public    serini, serrst, clrbuf, outchr, coms, dodel
  63.     public    ctlu, cmblnk, locate, lclini, prtchr, dobaud
  64.     public    clearl, getbaud, beep, puthlp, putmod
  65.     public    clrmod, poscur, sendbr, showkey, sendbl, pcwait
  66.     public    xofsnt, machnam, setktab, setkhlp, count
  67.     public    ihosts, ihostr, dtrlow, comptab, serhng, mdmhand
  68.     public    shomodem, getmodem, baudst, bdtab, portval
  69.     public    parmsk, flowon, flowoff, peekcom
  70.  
  71. FALSE    equ    0
  72. off    equ    0
  73. bufon    equ    1        ; buffer level xon/xoff on-state control flag
  74. usron    equ    2        ; user level xon/xoff on-state control flag
  75. MNTRGH    EQU    BUFSIZ*3/4    ; High point = 3/4 of buffer full.
  76. MNTRGL    EQU    BUFSIZ/4    ; Low point = 1/4 of buffer full.
  77. DEF_BAUD EQU    8        ; Default to 1200 baud
  78.  
  79. ; constants used by serial port handler
  80.  
  81. SEG_7201 EQU    0E004H        ; Segment for 7201 serial controller
  82. DATAA_7201 EQU    0        ; DATA A offset
  83. STATA_7201 EQU    2        ; STATUS A offset
  84. DATAB_7201 EQU    1        ; DATA B offset
  85. STATB_7201 EQU    3        ; STATUS B offset
  86.  
  87. ;   no interrupts, no waits
  88. REG1_7201 EQU    0        ; 7201 Register 1 value
  89. ENABLE_INT EQU    18H        ; Mask to turn on interrupts (OR)
  90. ;   non-DMA, non-vectored interrupts, priority type 1 (Ra>Rb>Ta>Tb)
  91. REG2_7201 EQU    14H        ; 7201 Register 2 value
  92. ;   8 bits/char, no CRC, receiver enabled
  93. REG3_7201 EQU    0C1H        ; 7201 Register 3 value
  94. ;   clock/16, 1.5 stop bit, no parity
  95. REG4_7201 EQU    48H        ; 7201 Register 4 value
  96. ;   DTR low (active), 8 bits/char, transmitter enabled, RTS low, no CRC
  97. REG5_7201 EQU    0EAH        ; 7201 Register 5 value
  98. BREAK_ON EQU    10H        ; Mask to turn on break bit (OR)
  99. DTR_RTS_OFF EQU 7DH        ; Mask to turn off DTR and RTS (AND)
  100.  
  101. MDMINP    EQU    1        ; Input ready bit. [jrd]
  102. MDMOVER EQU    32        ; Receiver overrun bit. [bgp]
  103.  
  104. SEG_8253 EQU    0E002H        ; Segment for 8253 timer
  105. SETA_8253 EQU    0        ; Speed for port A
  106. SETB_8253 EQU    1        ; Speed for port B
  107. CTRL_8253 EQU    3        ; Control for 8253 timer
  108.  
  109. SEG_8259 EQU    0E000H        ; Segment for 8259 int. controller
  110. CW1_8259 EQU    0        ; Offset for 8259 register 1
  111. CW2_8259 EQU    1        ; Offset for 8259 register 2
  112.  
  113. ; external variables used:
  114. ; drives - # of disk drives on system
  115. ; flags - global flags as per flginfo structure defined in pcdefs
  116. ; trans - global transmission parameters, trinfo struct defined in pcdefs
  117. ; portval - pointer to current portinfo structure (currently either port1
  118. ;     or port2)
  119. ; port1, port2 - portinfo structures for the corresponding ports
  120.  
  121. ; global variables defined in this module:
  122. ; xofsnt, xofrcv - tell whether we saw or sent an xoff.
  123. ; setktab - keyword table for redefining keys (should contain a 0 if
  124. ;     not implemented)
  125. ; setkhlp - help for setktab.
  126.  
  127. data    segment
  128.     extrn    flags:byte, trans:byte
  129.  
  130. setktab db    0
  131. setkhlp db    CR,LF,'Set Key not supported on VICTOR/SIRIUS Kermit$'
  132. sh_key_str db    'Set Key not supported on VICTOR/SIRIUS Kermit'
  133. sh_key_len dw    45
  134. machnam db    'VICTOR/SIRIUS$'
  135. clrlin    db    CR        ; clears full line with next line...
  136. clreol    db    ESCAPE,'K$'        ; clears from cursor to end of line
  137. home    db    ESCAPE,'H$'        ; homes cursor
  138. clrscr    db    ESCAPE,'E$'        ; clears screen and homes cursor
  139. delstr    db    BS,BS,'  ',BS,BS,'$' ; Delete string
  140. clr_25    db    ESCAPE,'j',ESCAPE,'x1',ESCAPE,'Y8 ',ESCAPE,'l',ESCAPE,'k'
  141.     db    ESCAPE,'y1$'
  142.     ;clr_25 does the entire operation of clearing the mode line
  143. start_25 db    ESCAPE,'j',ESCAPE,'x1',ESCAPE,'Y8 ',ESCAPE,'p$'
  144.     ; start_25 enables line 25 and moves to the start in reverse video
  145. end_25    db    ESCAPE,'q',ESCAPE,'k',ESCAPE,'y1$'
  146.     ; end_25 turns off reverse video and line 25 and returns the cursor
  147. mov_pfx db    ESCAPE,'Y$'        ; prefix for moves
  148. mdminfo    struc
  149. mddat    dw    0        ; data register
  150. mdiir    dw    0        ; interrupt identification register
  151. mdstat    dw    0        ; line status register
  152. mdcom    dw    0
  153. mden    db    0
  154. mddis    db    0
  155. mdmeoi    db    0
  156. mdintv    dw    0
  157. mdminfo    ends
  158. modem    mdminfo <DATAA_7201,0,STATA_7201,SETA_8253,0FDH,2,61H,104H>
  159. port1    prtinfo    <0FFFH,0,defpar,1,0,defhand,floxon,0>    ; UART ports
  160. port2    prtinfo    <0FFFH,0,defpar,1,0,defhand,floxon,0>
  161. portval    dw    port1            ; Default is to use port 1
  162. savsci    dw    ?        ; Save for serial port interrupt vector.
  163. savscs    dw    ?        ; Ditto.
  164. portin    db    FALSE        ; Has comm port been initialized.
  165. xofsnt    db    FALSE        ; Say if we sent an XOFF.
  166. xofrcv    db    FALSE        ; Say if we received an XOFF.
  167. parmsk    db    ?        ; parity mask, 0ffh for no parity, 07fh with.
  168. flowoff db    ?        ; flow-off char, Xoff or null (if no flow)
  169. flowon    db    ?        ; flow-on char, Xon or null
  170. overrun db    ?        ; holds status of receiver overrun
  171. mdmhand    db    0        ; Modem status register, current.
  172. erms20    db    CR,LF,'?Warning: System has no disk drives$'
  173. badbd    db    CR,LF,'Unimplemented baud rate$'
  174. hngmsg    db    CR,LF,' The phone should have hung up.',CR,LF,'$' ; [jrd]
  175. hnghlp    db    CR,LF,' The modem control lines DTR and RTS for the current'
  176.     db    ' port are forced low (off)'
  177.     db    CR,LF,' to hang up the phone.  Normally, Kermit leaves them'
  178.     db    ' high (on) when it exits.'
  179.     db    CR,LF,' They will return high after about 3 seconds.'
  180.     db    CR,LF,'$'                                       ; [jrd]
  181. shmdm0    db    CR,LF,' Modem is not ready:  DSR is off$'
  182. shmdm1    db    CR,LF,' Modem is ready:      DSR is on$'        ; [bgp]
  183. shmdm2    db    CR,LF,' no Carrier Detect:   CD is off$'
  184. shmdm3    db    CR,LF,' Carrier Detect:      CD is on$'
  185. shmdm4    db    CR,LF,' no Clear to Send:    CTS is off$'
  186. shmdm5    db    CR,LF,' Clear to Send:       CTS is on$'        ; [bgp]
  187. tmp    db    ?,'$'
  188. temp1    dw    ?        ; Temporary storage.
  189.  
  190. ontab    db    02H        ; Two entries.
  191.     mkeyw    'OFF',00H
  192.     mkeyw    'ON',01H
  193.  
  194. comptab db    0AH
  195.     mkeyw    '1',01H
  196.     mkeyw    '2',00H
  197.     mkeyw    'A',01H
  198.     mkeyw    'B',00H
  199.     mkeyw    'COM1',01H
  200.     mkeyw    'COM2',00H
  201.     mkeyw    'SERIALA',01H
  202.     mkeyw    'SERIALB',00H
  203.     mkeyw    'TTY',01H
  204.     mkeyw    'UL1',00H
  205.  
  206. bdtab    db    16            ; Baud rate table
  207.     mkeyw    '45.5',0
  208.     mkeyw    '50',1
  209.     mkeyw    '75',2
  210.     mkeyw    '110',3
  211.     mkeyw    '134.5',4
  212.     mkeyw    '150',5
  213.     mkeyw    '300',6
  214.     mkeyw    '600',7
  215.     mkeyw    '1200',8
  216.     mkeyw    '1800',9
  217.     mkeyw    '2000',10
  218.     mkeyw    '2400',11
  219.     mkeyw    '4800',12
  220.     mkeyw    '9600',13
  221.     mkeyw    '19200',14
  222.     mkeyw    '38400',15
  223.  
  224. ; This table is indexed by the baud rate definitions given above.
  225. ; Unsupported baud rates should contain FF.
  226. ;   This number is determined by 78125/(baud rate) (decimal values)
  227.  
  228. bddat    label    word
  229.     dw    6B4H        ; 45.5 baud
  230.     dw    61AH        ; 50 baud
  231.     dw    411H        ; 75 baud
  232.     dw    2C6H        ; 110 baud
  233.     dw    244H        ; 134.5 baud
  234.     dw    208H        ; 150 baud
  235.     dw    104H        ; 300 baud
  236.     dw    82H        ; 600 baud
  237.     dw    41H        ; 1200 baud
  238.     dw    2BH        ; 1800 baud
  239.     dw    26H        ; 2000 baud
  240.     dw    20H        ; 2400 baud
  241.     dw    10H        ; 4800 baud
  242.     dw    8H        ; 9600 baud
  243.     dw    4H        ; 19200 baud
  244.     dw    2H        ; 38400 baud
  245.  
  246. ; variables for serial interrupt handler
  247.  
  248. source    db    BUFSIZ DUP(?)    ; Buffer for data from port.
  249. srcpnt    dw    0        ; Pointer in buffer (DI).
  250. count    dw    0        ; Number of chars in int buffer.
  251.  
  252. ; variables for accessing portinfo from serial drivers using IOCTL function
  253. ;
  254. ; Structure is defined according to "Systems Programmers Toolkit II",
  255. ; Appendix A.        Structure contains baud rate and values of control registers
  256. ; 0 through 7.
  257.  
  258. pval    struc
  259. stype    dw    11H        ; port access
  260. status    dw    (?)
  261. blocktype dw    0        ; serial
  262. baudr    dw    (?)        ; baud rate to set or get
  263. CR0    db    (?)
  264. CR1    db    (?)
  265. CR2A    db    (?)
  266. CR2B    db    (?)
  267. CR3    db    (?)
  268. CR4    db    (?)
  269. CR5    db    (?)
  270. CR6    db    (?)
  271. CR7    db    (?)
  272. pval    ends
  273.  
  274. erms41    db    CR,LF,'?Warning:  Cannot open com port'
  275.     db    CR,LF,'  Going direct to serial controller hardware...$' ; [bgp]
  276. rdbuf    db    20 dup (?)    ; input buffer
  277.  
  278. plength equ    17        ; length of pval structure
  279. oldpval pval    <,,,41H,,,,,,,,,> ; default to 1200 baud
  280. newpval pval    <,,,41H,,,,,,,,,> ; value comes from bdtab above... [bgp]
  281.  
  282. prttab    dw    com2,com1    ; 0=com2, 1=com1 in flags.comflg
  283. com1    db    'SERIALA',0     ; name string for device
  284. com2    db    'SERIALB',0
  285.  
  286. IOread    equ    2        ; read status block
  287. IOwrite equ    3        ; write status block
  288.  
  289. prthnd    dw    0        ; handle for accessing port
  290.  
  291. data    ends
  292.  
  293. code    segment
  294.     extrn    comnd:near, dopar:near, defkey:near
  295.     extrn    lclyini:near
  296.     assume    cs:code,ds:data,es:nothing
  297.  
  298. ; local initialization
  299.  
  300. LCLINI    proc    near
  301.     mov    flags.vtflg,TTHEATH ; BIOS does HEATH, use as default
  302.     cmp    flags.comflg,1    ; using port 1?
  303.     jne    lclini2     ; no...
  304.     mov    portval,offset port1
  305.     mov    modem.mddat,DATAA_7201 ; set COM1 values
  306.     mov    modem.mdstat,STATA_7201
  307.     mov    modem.mdcom,SETA_8253
  308.     jmp    lclini0
  309. lclini2:            ; using port2
  310.     mov    portval,offset port2
  311.     mov    modem.mddat,DATAB_7201 ; set COM2 values
  312.     mov    modem.mdstat,STATB_7201
  313.     mov    modem.mdcom,SETB_8253
  314. lclini0:call    opnprt        ; get file handle and init port
  315.     call    lclyini     ; init term part too
  316.     ret
  317. LCLINI    endp
  318.  
  319. ; procedure to get a file handle for the port.    if it fails ask the user
  320. ; for some predefined handle (3 is the usual value) (Andreas Stumpf)
  321. ; 30 July 1986 If it fails, just warn the user and go direct to the
  322. ;  hardware [bgp]
  323.  
  324. OPNPRT    proc    near
  325.     cmp    prthnd,0    ; is one open?
  326.     jle    opnprta     ; no...
  327.     mov    bx,prthnd    ; better close this
  328.     mov    ah,CLOSE2    ; to be sure they don't accumulate
  329.     int    DOS
  330.     mov    prthnd,0    ; done...
  331. opnprta:
  332.     mov    al,flags.comflg
  333.     mov    ah,0
  334.     mov    si,ax
  335.     shl    si,1        ; double index
  336.     mov    dx,prttab[si]
  337.     mov    ah,OPEN2
  338.     mov    al,2
  339.     int    DOS        ; open port on handle
  340.     jnc    opnprt2
  341.     mov    ah,PRSTR    ; it didn't like the string...
  342.     mov    dx,offset erms41
  343.     int    DOS
  344.     mov    prthnd,-1    ; no port is open! [bgp]
  345.     push    es        ; better save this
  346.     mov    bx,SEG_7201    ; point at controller
  347.     mov    es,bx
  348.     mov    bx,modem.mdstat
  349.     mov    byte ptr es:[bx],1
  350.     mov    byte ptr es:[bx],18H ; Software reset of current port
  351.     push    ax        ; kill time for four 2.5 MHz cylces
  352.     pop    ax        ; 8 processor cycles
  353.     mov    bx,STATA_7201    ; First one is always port A
  354.     mov    byte ptr es:[bx],2 ; must be first one set
  355.     mov    byte ptr es:[bx],REG2_7201
  356.     mov    bx,modem.mdstat
  357.     mov    byte ptr es:[bx],4 ; must be second
  358.     mov    byte ptr es:[bx],REG4_7201
  359.     mov    byte ptr es:[bx],1 ; rest any order
  360.     mov    byte ptr es:[bx],REG1_7201
  361.     mov    byte ptr es:[bx],3
  362.     mov    byte ptr es:[bx],REG3_7201
  363.     mov    byte ptr es:[bx],5
  364.     mov    byte ptr es:[bx],REG5_7201
  365.     pop    es
  366.     call    getbaud     ; use this to be sure right value is used
  367.     call    dobaud        ; better set baud rate to the correct value too
  368.     jmp    opnprt2a    ; all init done... [bgp]
  369. opnprt2:
  370.     mov    prthnd,ax    ; call succeeded - save handle
  371.     mov    bx,ax
  372.     mov    ah,IOCTL
  373.     mov    al,IOread    ; get old values
  374.     mov    cx,plength
  375.     mov    dx,offset oldpval ; place for old values
  376.     int    DOS
  377.     mov    ah,IOCTL
  378.     mov    al,IOread
  379.     mov    dx,offset newpval ; one to work on
  380.     int    DOS
  381.  
  382. ; set registers to something neat
  383.  
  384.     cli            ; avoid interrupts here
  385.     mov    bx,offset newpval
  386.     mov    [bx].CR1,REG1_7201
  387.     mov    [bx].CR2A,REG2_7201
  388.     mov    [bx].CR3,REG3_7201
  389.     mov    [bx].CR4,REG4_7201
  390.     mov    [bx].CR5,REG5_7201
  391.     mov    bx,prthnd    ; get handle
  392.     mov    ah,IOCTL
  393.     mov    al,IOwrite    ; set new values
  394.     int    DOS
  395. opnprt2a:
  396.     push    es        ; save this for a flash
  397.     mov    bx,SEG_7201
  398.     mov    es,bx
  399.     mov    bx,modem.mdstat
  400.     mov    byte ptr es:[bx],10H ; clear external/status interrupts
  401.     mov    byte ptr es:[bx],30H ; clear special receive cond. int.
  402.     mov    byte ptr es:[bx],38H ; set to end of interupt
  403.     pop    es        ; back again
  404.     sti            ; interrupts are okay again
  405.     ret
  406. OPNPRT    endp
  407.  
  408. ; Show the definition of a key.  Since it isn't really necessary to redefine
  409. ; keys for the VICTOR/SIRIUS (assuming that KEYGEN is available), this isn't
  410. ; implemented, and the string returned to the calling sequence merely says so.
  411. ; Returns a string to print in AX, length of same in CX.
  412. ; Returns normally.
  413.  
  414. SHOWKEY proc    near
  415.     mov    ax,offset sh_key_str
  416.     mov    cx,sh_key_len
  417.     ret
  418. SHOWKEY endp
  419.  
  420. ; Clear the input buffer. This throws away all the characters in the
  421. ; serial interrupt buffer.    This is particularly important when
  422. ; talking to servers, since NAKs can accumulate in the buffer.
  423. ; Returns normally.
  424.  
  425. CLRBUF    proc    near
  426.     cli
  427.     mov    ax,offset source
  428.     mov    srcpnt,ax
  429.     mov    count,0
  430.     sti
  431.     ret
  432. CLRBUF    endp
  433.  
  434. ; Clear to the end of the current line.  Returns normally.
  435.  
  436. CLEARL    proc    near
  437.     mov    dx,offset clreol
  438.     mov    ah,PRSTR
  439.     int    DOS
  440.     ret
  441. CLEARL    endp
  442.  
  443. ; Put the char in AH to the serial port.  This assumes the
  444. ; port has been initialized. Skip returns on success, returns ret if the
  445. ; character cannot be written.
  446. ; Add entry point OUTCH2 for non-flow controlled sending to
  447. ; prevent confusion of flow control logic at top of outchr; used by receiver
  448. ; buffer high/low water mark flow control code. [jrd]
  449.  
  450. OUTCHR    proc    near
  451.     cmp    flowoff,0        ; Are we doing flow control.
  452.     je    outch2            ; No, just continue.
  453.     cmp    ah,flowoff        ; sending xoff?
  454.     jne    outch1            ; ne = no
  455.     mov    xofsnt,usron        ; indicate user level xoff being sent
  456.     jmp    outch1b
  457. outch1:    cmp    ah,flowon        ; user sending xon?
  458.     jne    outch1b            ; ne = no
  459.     mov    xofsnt,off         ; say an xon has been sent (cancels xoff)
  460. outch1b:cmp    xofrcv,off        ; Are we being held (xoff received)?
  461.     je    outch2            ; e = no - it's OK to go on.
  462.     cmp    flags.timflg,0        ; is timer off?
  463.     je    outch2            ; e = yes, no timeout period
  464.     push    cx            ; save reg
  465.     mov    ch,trans.rtime        ; receive timeout interval (sec)
  466.     mov    cl,0            ;  convert to 4 millsec increments
  467.     jcxz    outch1c            ; z = no timeout wanted.
  468.  
  469. outch1a:cmp    xofrcv,off        ; Are we being held (xoff received)?
  470.     je    outch1c            ; e = no - it's OK to go on.
  471.     push    ax
  472.     mov    ax,4            ; 4 millisec wait loop
  473.     call    pcwait
  474.     pop    ax
  475.     loop    outch1a            ; and try it again
  476.     mov    xofrcv,off        ; timed out, force it off and fall thru
  477. outch1c:pop    cx            ; end of flow control section
  478.              ; OUTCH2 is entry point for sending without flow control
  479. OUTCH2:    mov    al,ah            ; Parity routine works on AL.
  480.     call    dopar            ; Set parity appropriately.
  481.     mov    ah,al            ; Don't overwrite character with status
  482.     push    bx
  483.     push    cx
  484.     push    es
  485.     xor    cx,cx
  486.     mov    bx,SEG_7201    ; point at 7201
  487.     mov    es,bx
  488.     mov    bx,modem.mdstat
  489. outch3:
  490.     mov    al,es:[bx]
  491.     test    al,4        ; ready?
  492.     jnz    outch4        ; yes
  493.     loop    outch3
  494.     jmp    outch5        ; Timeout
  495. outch4:
  496.     mov    al,ah        ; Now send it out
  497.     mov    bx,modem.mddat
  498.     mov    es:[bx],al
  499.     pop    es
  500.     pop    cx
  501.     pop    bx
  502.     ret
  503. outch5:
  504.     pop    es
  505.     pop    cx
  506.     pop    bx
  507.     ret
  508. OUTCHR    endp
  509.  
  510. ; This routine blanks the screen.   Returns normally.
  511.  
  512. CMBLNK    proc    near
  513.     mov    dx,offset clrscr
  514.     mov    ah,PRSTR
  515.     int    DOS
  516.     ret
  517. CMBLNK    endp
  518.  
  519. ; Locate: homes the cursor.    Returns normally.
  520.  
  521. LOCATE    proc    near
  522.     mov    dx,offset home
  523.     mov    ah,PRSTR
  524.     int    DOS
  525.     ret
  526. LOCATE    endp
  527.  
  528. ; write a line in inverse video at the bottom of the screen...
  529. ; the line is passed in dx, terminated by a dollar sign.  Returns normally.
  530.  
  531. PUTMOD    proc    near
  532.     push    si        ; better save this
  533.     push    dx        ; preserve message
  534.     mov    dx,offset start_25 ; to set up for write to 25
  535.     mov    ah,PRSTR
  536.     int    DOS
  537.     mov    ah,DCONIO    ; output a char at a time
  538.     pop    si        ; get back message
  539.     cld            ; better increment
  540. putmod1:
  541.     lodsb            ; get byte
  542.     cmp    al,'$'          ; is it end of string?
  543.     je    putmod2
  544.     mov    dl,al
  545.     int    DOS
  546.     jmp    putmod1
  547. putmod2:
  548.     mov    dx,offset end_25 ; back to normal
  549.     mov    ah,PRSTR
  550.     int    DOS
  551.     pop    si        ; and restore it
  552.     ret
  553. PUTMOD    endp
  554.  
  555. ; clear the mode line written by putmod.  Returns normally.
  556.  
  557. CLRMOD    proc    near
  558.     mov    dx,offset clr_25 ; to clear line 25
  559.     mov    ah,PRSTR
  560.     int    DOS
  561.     ret
  562. CLRMOD    endp
  563.  
  564. ; put a help message on the screen.    This one uses reverse video...
  565. ; pass the message in ax, terminated by a null.  Returns normally.
  566.  
  567. PUTHLP    proc    near
  568.     push    si
  569.     mov    si,ax
  570.     mov    ah,DCONIO    ; don't check anything...
  571.     cld            ; better increment on strings
  572. puthlp1:
  573.     lodsb            ; get byte
  574.     cmp    al,0        ; is it null (null-terminated string)
  575.     je    puthlp2
  576.     mov    dl,al
  577.     int    DOS
  578.     jmp    puthlp1
  579. puthlp2:
  580.     mov    dl,13        ; want a crlf
  581.     int    DOS
  582.     mov    dl,10
  583.     int    DOS
  584.     pop    si
  585.     ret
  586. PUTHLP    endp
  587.  
  588. ; Set the baud rate for the current port, based on the value
  589. ; in the portinfo structure.  Returns carry clear.
  590.  
  591. BAUDST    PROC    NEAR
  592.     mov    dx,offset bdtab        ; baud rate table, ascii
  593.     xor    bx,bx            ; help is the table itself
  594.     mov    ah,cmkey        ; get keyword
  595.     call    comnd
  596.     jc    baudst1            ; c = failure
  597.     push    bx            ; save result
  598.     mov    ah,cmeol        ; get confirmation
  599.     call    comnd
  600.     pop    bx
  601.     jc    baudst1            ; c = failure
  602.     mov    si,portval
  603.     mov    ax,[si].baud        ; remember original value
  604.     mov    [si].baud,bx        ; set the baud rate
  605.     call    dobaud            ; use common code
  606.     clc
  607. baudst1:ret
  608. BAUDST    ENDP
  609. ; Set the baud rate for the current port, based on the value
  610. ; in the portinfo structure. Returns normally. Method of setting using
  611. ; IOCTL thanks to Andreas Stumpf
  612.  
  613. DOBAUD    proc    near
  614.     push    ax        ; these too [jrd]
  615.     push    bx
  616.     push    cx
  617.     push    dx
  618.     mov    bx,portval
  619.     mov    bx,[bx].baud
  620.     cmp    bx,0
  621.     jl    unk_baud    ; out of range
  622.     cmp    bl,bdtab    ; number of table entries
  623.     jge    unk_baud    ; out of range
  624.     shl    bx,1        ; get index into table
  625.     mov    ax,offset bddat ; start of table
  626.     add    bx,ax
  627.     mov    ax,[bx]     ; get divider
  628.     cmp    ax,0FFH     ; unimplemented baud rate?
  629.     je    unk_baud    ; that's right
  630.     mov    bx,offset newpval
  631.     mov    [bx].baudr,ax    ; set it in structure no matter what [bgp]
  632.     cmp    prthnd,0    ; anything open?
  633.     jge    dobaud0     ; yes, do it nice
  634.     push    es        ; better save this...
  635.     push    ax        ; save divider
  636.     mov    bx,SEG_8253    ; point at timer
  637.     mov    es,bx
  638.     mov    bx,CTRL_8253    ; set up function first
  639.     mov    ax,modem.mdcom    ; set up control byte
  640.     ror    al,1        ; need port number in high bits
  641.     ror    al,1
  642.     and    al,0C0H     ; keep only top 2 bits
  643.     add    al,36H        ; set both, Mode 3, binary
  644.     mov    es:[bx],al
  645.     mov    bx,modem.mdcom    ; Where to write the rate
  646.     pop    ax        ; get divider back
  647.     mov    es:[bx],al
  648.     mov    es:[bx],ah    ; done
  649.     pop    es
  650.     jmp    dobaud1
  651. dobaud0:            ; [bgp]
  652.     mov    ah,IOCTL
  653.     mov    al,IOwrite
  654.     mov    bx,prthnd    ; set the poor thing
  655.     mov    cx,plength
  656.     mov    dx,offset newpval
  657.     int    DOS
  658. dobaud1:
  659.     pop    dx
  660.     pop    cx
  661.     pop    bx
  662.     pop    ax
  663.     ret
  664. unk_baud:
  665.     mov    ah,PRSTR
  666.     mov    dx,offset badbd ; Give an error message.
  667.     int    DOS
  668.     pop    dx        ; restore regs [jrd]
  669.     pop    cx
  670.     pop    bx
  671.     pop    ax
  672.     ret
  673. DOBAUD    endp
  674.  
  675. ; Get the current baud rate from the serial card and set it
  676. ; in the portinfo structure for the current port.   Returns normally.
  677. ; This is used during initialization.        The method of getting the baud
  678. ; rate directly from the port handler is thanks to Andreas Stumpf.
  679. ; Note that this assumes that the thing has a defined baud rate to
  680. ; start with from the initialization and the opnprt has been called on
  681. ; the current port so that the values in newpval are defined.
  682.  
  683. GETBAUD proc    near
  684.     push    ax
  685.     push    bx
  686.     push    cx
  687.     push    dx
  688.     cmp    prthnd,0    ; opened?
  689.     jne    go_gb        ; yes, get the rate
  690.     call    opnprt        ; no, open it
  691. go_gb:
  692.     mov    bx,offset newpval
  693.     mov    ax,[bx].baudr
  694.     xor    ch,ch
  695.     mov    cl,bdtab    ; entries in baudtable
  696.     mov    bx,offset bddat-2
  697.     add    bx,cx
  698.     add    bx,cx
  699. loop_gb:
  700.     cmp    ax,[bx]
  701.     je    have_gb
  702.     dec    bx
  703.     dec    bx
  704.     dec    cx
  705.     jnz    loop_gb
  706. have_gb:
  707.     dec    cx        ; value is one greater than desired
  708.     mov    bx,portval    ; cx=-1 means unrecognized (dropped off bottom)
  709.     mov    [bx].baud,cx
  710.     pop    dx
  711.     pop    cx
  712.     pop    bx
  713.     pop    ax
  714.     ret
  715. GETBAUD endp
  716.  
  717. ; Skip returns if no character available at port,
  718. ; otherwise returns with char in al, # of chars in buffer in dx.
  719. ; Revised 22 May 1986, and again slightly 2 August 1986 by [jrd]
  720. ; Direct copy from msxibm.asm [jrd]
  721.  
  722. PRTCHR    proc    near
  723.     call    chkxon        ; see if we need to xon
  724.     cmp    count,0     ; any characters available?
  725.     jnz    prtch1        ; nz = yes, get one
  726.     xor    dx,dx        ; return count of zero
  727.     stc
  728.     ret            ; No data
  729. prtch1:
  730.     push    si        ; save si
  731.     cli            ; interrupts off, to keep srcpnt & count consistent
  732.     mov    si,srcpnt    ; address of next available slot in buffer
  733.     sub    si,count    ; minus number of unread chars in buffer
  734.     cmp    si,offset source ; located before start of buffer (wrapped)?
  735.     jae    prtch2        ; ae = no
  736.     add    si,BUFSIZ    ; else do arithmetic module bufsiz
  737. prtch2:
  738.     mov    al,byte ptr [si] ; get a character into si
  739.     dec    count        ; one less unread char now
  740.     sti            ; interrupts back on now.
  741.     pop    si
  742.     mov    dx,count    ; return # of chars in bufer
  743.     clc
  744.     ret
  745. PRTCHR    endp
  746.  
  747. ; Examine incoming communications stream for a packet SOP character.
  748. ; Return CX= count of bytes starting at the SOP character (includes SOP)
  749. ; and carry clear. Return CX = 0 and carry set if SOP is not present.
  750. ; Destroys AL.
  751. peekcom proc far
  752.     mov    cx,count        ; qty in circular buffer
  753.     cmp    cx,6            ; basic NAK
  754.     jb    peekc4            ; b = two few chars, get more
  755.     push    bx
  756.     cli        ; interrupts off, to keep srcpnt & count consistent
  757.     mov    bx,srcpnt        ; address of next available slot in buffer
  758.     sub    bx,cx            ; minus number of unread chars in buffer
  759.     cmp    bx,offset source    ; located before start of buf?
  760.     jae    peekc1            ; ae = no
  761.     add    bx,bufsiz        ; else do arithmetic modulo bufsiz
  762. peekc1:    mov    al,[bx]
  763.     cmp    al,trans.rsoh        ; packet receive SOP?
  764.     je    peekc3            ; e = yes
  765.     inc    bx
  766.     cmp    bx,offset source+bufsiz ; beyond end of buffer?
  767.     jb    peekc2            ; b = no
  768.     mov    bx,offset source    ; wrap around
  769. peekc2:    loop    peekc1            ; keep looking
  770.     sti
  771.     pop    bx
  772.     stc                ; set carry for no SOP
  773.     ret
  774. peekc3:    sti                ; interrupts back on now
  775.     pop    bx
  776.     inc    cx            ; include SOP in count
  777.     clc                ; say SOP found
  778.     ret                ; CX has count remaining
  779.     
  780. peekc4:    xor    cx,cx            ; return count of zero
  781.     stc                ; say no data
  782.     ret
  783. peekcom endp
  784.  
  785. ; local routine to see if we have to transmit an xon
  786. chkxon    proc    near
  787.     cmp    flowon,0        ; doing flow control?
  788.     je    chkxo1            ; no, skip all this
  789.     test    xofsnt,usron        ; did user send an xoff?
  790.     jnz    chkxo1            ; nz = yes, don't contradict it here
  791.     test    xofsnt,bufon        ; have we sent a buffer level xoff?
  792.     jz    chkxo1            ; z = no, forget it
  793.     cmp    count,mntrgl        ; below (low water mark) trigger?
  794.     jae    chkxo1            ; no, forget it
  795.     mov    ah,flowon        ; ah gets xon
  796.     and    xofsnt,off        ; remember we've sent the xon.
  797.     call    outch2            ; send via non-flow controlled entry point
  798. chkxo1:    ret
  799. chkxon    endp
  800.  
  801. ; IHOSTS - Initialize the host by sending XON, or equivalent, and enter the
  802. ; cycle of clear input buffer, wait 1 second, test if buffer empty then exit
  803. ; else repeat cycle. Requires that the port be initialized before hand.
  804. ; Ihosts is used by the local send-file routine just after initializing
  805. ; the serial port.
  806. ; 22 March 1986 [jrd]
  807. ; 30 July 1986 Avoid sending nulls if no flow control [bgp]
  808.  
  809. IHOSTS    proc    near
  810.     push    ax        ; save the registers
  811.     push    cx
  812.     push    dx
  813.     mov    xofrcv,off    ; clear old xoff received flag
  814.     mov    xofsnt,off    ; and old xoff sent flag
  815.     mov    ah,flowon    ; put Go-ahead flow control char in ah
  816.     or    ah,ah        ; check for null char
  817.     jz    ihosts1     ; z=null, don't send it
  818.     call    outchr        ; send it (release Host's output queue)
  819. ihosts1:call    clrbuf        ; clear out interrupt buffer
  820.     pop    dx        ; empty buffer. we are done here.
  821.     pop    cx
  822.     pop    ax
  823.     ret
  824. IHOSTS    endp
  825.  
  826. ; IHOSTR - initialize the remote host for our reception of a file by
  827. ; sending the flow-on character (XON typically) to release any held
  828. ; data. Called by receive-file code just after initializing the serial
  829. ; port.  22 March 1986 [jrd]
  830. ; 30 July 1986 Avoid sending null if no flow control [bgp]
  831.  
  832. IHOSTR    proc    near
  833.     push    ax        ; save reg
  834.     mov    xofrcv,off    ; clear old xoff received flag
  835.     mov    xofsnt,off    ; and old xoff sent flag
  836.     mov    ah,flowon    ; put Go-ahead flow control char in ah
  837.     or    ah,ah        ; check for null char
  838.     jz    ihostr1     ; z=null, don't send it
  839.     call    outchr        ; send it (release Host's output queue)
  840. ihostr1:pop    ax
  841.     ret
  842. IHOSTR    endp
  843.  
  844. ; Global proc to hang up the phone by making DTR and RTS low.
  845.  
  846. DTRLOW    proc    near
  847.     mov    ah,cmline    ; allow text to be able to display help
  848.     mov    bx,offset rdbuf ; dummy buffer
  849.     mov    dx,offset hnghlp ; help message
  850.     call    comnd        ; get a confirm
  851.     jnc    dtrlow1        ; nc = success
  852.     ret            ; carry set = failure
  853. dtrlow1:call    serhng        ; drop DTR and RTS
  854.     mov    ah,PRSTR    ; give a nice message
  855.     mov    dx,offset hngmsg
  856.     int    dos
  857.     clc
  858.     ret
  859. DTRLOW    endp
  860.  
  861. ; SERHNG us used to hang up the phone.    This resets the port (by calling
  862. ; serrst), and then forces DTR and RTS low to terminate the connection.
  863. ; 12 April 1986 [bgp]
  864. ; 30 July 1986 Turn them back on again after 3 seconds so new connection can
  865. ;  be made [bgp]
  866.  
  867. SERHNG    proc    near
  868.     call    serrst        ; reset the port to be sure
  869.     push    dx
  870.     push    cx
  871.     push    bx
  872.     push    ax
  873.     cmp    prthnd,0    ; nice method open? [bgp]
  874.     jge    serhng0     ; yes
  875.     push    es        ; better save this
  876.     mov    bx,SEG_7201    ; point at controller
  877.     mov    es,bx
  878.     mov    bx,modem.mdstat
  879.     cli            ; no interrupts please
  880.     mov    byte ptr es:[bx],5 ; register 5
  881.     mov    byte ptr es:[bx],REG5_7201 and DTR_RTS_OFF
  882.     sti            ; interrupts ok again
  883.     mov    ax,3000        ; sleep for 3 seconds
  884.     call    pcwait
  885.     mov    bx,SEG_7201
  886.     mov    es,bx
  887.     mov    bx,modem.mdstat
  888.     cli            ; no interrupts please
  889.     mov    byte ptr es:[bx],5
  890.     mov    byte ptr es:[bx],REG5_7201
  891.     sti            ; interrupts ok again
  892.     pop    es
  893.     jmp    short serhng1     ; [bgp]
  894. serhng0:
  895.     mov    bx,offset newpval
  896.     mov    [bx].CR5,REG5_7201 and DTR_RTS_OFF
  897.     mov    dx,bx        ; where the stuff is
  898.     mov    cx,plength    ; how long it is
  899.     mov    bx,prthnd    ; get handle
  900.     mov    ah,IOCTL
  901.     mov    al,IOwrite    ; set new values
  902.     int    DOS
  903.     mov    ax,3000        ; sleep for 3 seconds
  904.     call    pcwait
  905.     mov    bx,offset newpval ; turn them back on again...
  906.     mov    [bx].CR5,REG5_7201
  907.     mov    dx,bx
  908.     mov    cx,plength
  909.     mov    bx,prthnd
  910.     mov    ah,IOCTL
  911.     mov    al,IOwrite
  912.     int    DOS
  913. serhng1:
  914.     pop    ax
  915.     pop    bx
  916.     pop    cx
  917.     pop    dx
  918.     ret
  919. SERHNG    endp
  920.  
  921. ; SHOW MODEM, displays current status of lines DSR, CD, and CTS.
  922. ; Uses global byte mdmhand, the modem line status register. [jrd]
  923.  
  924. SHOMODEM proc    near
  925.     mov    ah,cmeol
  926.     call    comnd
  927.     jc    shomodem4        ; c = failure
  928.     mov    dx,offset shmdm0    ; assume DSR is not set
  929.     test    mdmhand,20h         ; is bit set?
  930.     jnz    shomodem1        ; z = no
  931.     mov    dx,offset shmdm1    ; DSR is asserted (line active)
  932. shomodem1:
  933.     mov    ah,PRSTR
  934.     int    DOS
  935.     test    mdmhand,80h        ; test for CD
  936.     jz    shomodem2        ; z = off
  937.     mov    dx,offset shmdm3    ; actually have CD
  938. shomodem2:
  939.     int    DOS
  940.     mov    dx,offset shmdm4    ; assume no CTS
  941.     test    mdmhand,10H        ; test for CTS
  942.     jz    shomodem3
  943.     mov    dx,offset shmdm5    ; actually have CTS
  944. shomodem3:
  945.     int    DOS
  946.     clc
  947. shomodem4:ret
  948. SHOMODEM endp
  949.  
  950.  
  951. ; Get modem status and set global byte mdmhand. Preserve all registers.
  952.  
  953. ; Check the status of the return control lines from the serial port.
  954. ; Since this function doesn't care if the port has been properly
  955. ; initialized or anything else we will always go directly to the
  956. ; hardware.  This is actually quite reasonable since the values
  957. ; returned in IOCTL from earlier will have no relation to the current
  958. ; state of reality. [bgp]
  959. ; Note that the method of getting DSR is a little weird.  There are
  960. ; no connections on the 7201 for DSR so we have to get it from one
  961. ; of the 6522s where there are a few free lines (specifically, the
  962. ; one that controls the keyboard interface and the CRT brightness/
  963. ; contrast.  This one is at E8040-E804F with line PA3 for DSRA and
  964. ; PA5 for DSRB.  Note that a zero is registered for an active line
  965. ; on the DSR sense.
  966.  
  967. getmodem proc    near            ; gets modem status upon request
  968.     mov    mdmhand,0        ; assume nothing is on
  969.     push    bx
  970.     push    es            ; better save these
  971.     mov    bx,0E804H        ; segment of 6522
  972.     mov    es,bx
  973.     mov    bl,8            ; assume looking at port A
  974.     cmp    flags.comflg,1
  975.     je    getmod1            ; e = it is A
  976.     mov    bl,20H            ; actually looking at B
  977. getmod1:test    es:[1],bl         ; is DSR bit set?
  978.     jnz    getmod2            ; nz = no
  979.     or    mdmhand,20h        ; DSR is asserted (line active)
  980. getmod2:mov    bx,SEG_7201        ; point at 7201
  981.     mov    es,bx
  982.     mov    bx,modem.mdstat
  983.     test    byte ptr es:[bx],8    ; test for CD
  984.     jz    getmod3            ; z = off
  985.     or    mdmhand,80h        ; actually have CD
  986. getmod3:test    byte ptr es:[bx],20H    ; test for CTS
  987.     jz    getmodx            ; z = off
  988.     or    mdmhand,10h        ; actually have CTS
  989. getmodx:pop    es
  990.     pop    bx
  991. getmodem endp
  992.  
  993. ; Send a break out the current serial port.    Returns normally.
  994. ; Changed to use IOCTL function 12 April 1986 [bgp]
  995. ; 30 July 1986 Direct to hardware if not opened right [bgp]
  996.  
  997. SENDBR    proc    near
  998.     push    es
  999.     push    dx
  1000.     push    cx
  1001.     push    bx
  1002.     push    ax
  1003.     mov    ax,250        ; break length in msec
  1004.     push    ax        ; for later use
  1005.     jmp    sendbrz
  1006.  
  1007. sendbl:
  1008.     push    es
  1009.     push    dx
  1010.     push    cx
  1011.     push    bx
  1012.     push    ax
  1013.     mov    ax,3500     ; break length in msec
  1014.     push    ax        ; for later use
  1015. sendbrz:
  1016.     cmp    prthnd,0    ; open ok? [bgp]
  1017.     jge    sendbr0     ; yes, do it nice
  1018.     mov    bx,SEG_7201    ; point at 7201
  1019.     mov    es,bx
  1020.     mov    bx,modem.mdstat
  1021.     cli            ; no interrupts please
  1022.     mov    byte ptr es:[bx],1 ; register 1
  1023.     mov    byte ptr es:[bx],REG1_7201
  1024.     mov    byte ptr es:[bx],5
  1025.     mov    byte ptr es:[bx],REG5_7201 or BREAK_ON
  1026.     sti            ; interrupts ok again
  1027.     pop    ax
  1028.     call    wait_msec
  1029.     cli            ; no interrupts
  1030.     mov    byte ptr es:[bx],5
  1031.     mov    byte ptr es:[bx],REG5_7201
  1032.     mov    byte ptr es:[bx],1
  1033.     mov    byte ptr es:[bx],REG1_7201 or ENABLE_INT
  1034.     sti            ; interrupts ok again
  1035.     jmp    sendbr1     ; [bgp]
  1036. sendbr0:
  1037.     mov    bx,offset newpval
  1038.     mov    [bx].CR1,REG1_7201 ; to disable interrupts
  1039.     mov    [bx].CR5,REG5_7201 or BREAK_ON
  1040.     mov    dx,bx        ; where the stuff is
  1041.     mov    cx,plength    ; how much there is
  1042.     mov    bx,prthnd    ; get handle
  1043.     mov    ah,IOCTL
  1044.     mov    al,IOwrite    ; set new values
  1045.     cli            ; avoid interrupts here
  1046.     int    DOS
  1047.     mov    bx,SEG_7201    ; have to explicitly do register 1
  1048.     mov    es,bx        ; IOCTL doesn't seem to touch it
  1049.     mov    bx,modem.mdstat
  1050.     mov    byte ptr es:[bx],1 ; Register 1
  1051.     mov    byte ptr es:[bx],REG1_7201
  1052.     sti            ; interrupts back on
  1053.     pop    ax
  1054.     call    wait_msec    ; kill time
  1055.     mov    bx,offset newpval
  1056.     mov    [bx].CR5,REG5_7201
  1057.     mov    bx,prthnd
  1058.     mov    ah,IOCTL
  1059.     mov    al,IOwrite
  1060.     cli            ; no interrupts please
  1061.     int    DOS
  1062.     mov    bx,SEG_7201    ; Point at 7201 serial controller
  1063.     mov    es,bx
  1064.     mov    bx,modem.mdstat
  1065.     mov    byte ptr es:[bx],1 ; Register 1 must be done explicitly
  1066.     mov    byte ptr es:[bx],REG1_7201 or ENABLE_INT
  1067.     sti            ; interrupts are okay again
  1068. sendbr1:
  1069.     pop    ax
  1070.     pop    bx
  1071.     pop    cx
  1072.     pop    dx
  1073.     pop    es
  1074.     clc            ; need to stay connected
  1075.     ret            ; And return.
  1076. SENDBR    endp
  1077.  
  1078. ; Wait for the # of milliseconds in ax.  The delay is set for a 5 MHz
  1079. ; clock rate.        Actual delay for ax=1 is 1.007 msec, plus 1.005 msec
  1080. ; for each increment in ax.
  1081.  
  1082. WAIT_MSEC proc    near
  1083. pcwait:             ; entry point for the outside world...
  1084.     push    cx        ; 10 cycles
  1085.     mov    cx,ax        ; 2 cycles
  1086. wait_msec1:
  1087.     push    cx        ; 10 cycles
  1088.     mov    cx,294        ; 4 cycles
  1089. wait_msec2:
  1090.     loop    wait_msec2    ; 5+17*(CX-1) cycles
  1091.     pop    cx        ; 8 cycles
  1092.     loop    wait_msec1    ; 17 cycles if jump, 5 cycles if no jump
  1093.     pop    cx        ; 8 cycles
  1094.     ret
  1095. WAIT_MSEC endp
  1096.  
  1097. ; Position the cursor according to contents of DX:
  1098. ; DH contains row, DL contains column.    Returns normally.
  1099.  
  1100. POSCUR    proc    near
  1101.     push    ax
  1102.     push    dx        ; save this
  1103.     mov    dx,offset mov_pfx ; move prefix string
  1104.     mov    ah,PRSTR
  1105.     int    DOS
  1106.     pop    dx
  1107.     push    dx
  1108.     mov    dl,dh
  1109.     add    dl,' '          ; this is the row
  1110.     mov    ah,DCONIO    ; no checking please
  1111.     int    DOS
  1112.     pop    dx
  1113.     push    dx
  1114.     add    dl,' '          ; this is the column
  1115.     int    DOS
  1116.     pop    dx
  1117.     pop    ax
  1118.     ret
  1119. POSCUR    endp
  1120.  
  1121. ; Delete a character from the terminal.  This works by printing
  1122. ; backspaces and spaces.  Returns normally.
  1123.  
  1124. DODEL    proc    near
  1125.     mov    dx,offset delstr     ; Erase character.
  1126.     mov    ah,PRSTR
  1127.     int    DOS
  1128.     ret
  1129. DODEL    endp
  1130.  
  1131. ; Move the cursor to the left margin, then clear to end of line.
  1132. ; Returns normally.
  1133.  
  1134. CTLU    proc    near
  1135.     mov    dx,offset clrlin
  1136.     mov    ah,PRSTR
  1137.     int    DOS
  1138.     ret
  1139. CTLU    endp
  1140.  
  1141. ; set the current port.
  1142.  
  1143. COMS    proc    near
  1144.     mov    dx,offset comptab
  1145.     mov    bx,0
  1146.     mov    ah,CMKEY
  1147.     call    comnd
  1148.     jnc    coms1        ; nc = success
  1149.     ret
  1150. coms1:    push    bx
  1151.     mov    ah,cmeol
  1152.     call    comnd        ; Get a confirm
  1153.     pop    bx
  1154.     jnc    coms2
  1155.     ret
  1156. coms2:    call    serrst        ; reset current port
  1157.     mov    flags.comflg,bl ; Set the comm port flag.
  1158.     cmp    flags.comflg,1    ; Using Com 1?
  1159.     jne    coms0        ; Nope.
  1160.     mov    ax,offset port1
  1161.     mov    portval,ax
  1162.     mov    modem.mddat,DATAA_7201 ; Set COM1 defaults.
  1163.     mov    modem.mdstat,STATA_7201
  1164.     mov    modem.mdcom,SETA_8253
  1165.     call    opnprt        ; open the handle
  1166.     ret
  1167. coms0:
  1168.     mov    ax,offset port2
  1169.     mov    portval,ax
  1170.     mov    modem.mddat,DATAB_7201 ; Set COM2 defaults.
  1171.     mov    modem.mdstat,STATB_7201
  1172.     mov    modem.mdcom,SETB_8253
  1173.     call    opnprt
  1174.     ret
  1175. COMS    endp
  1176.  
  1177. ; initialization for using serial port.  This routine performs
  1178. ; any initialization necessary for using the serial port, including
  1179. ; setting up interrupt routines, setting buffer pointers, etc.
  1180. ; Doing this twice in a row should be harmless (this version checks
  1181. ; a flag and returns if initialization has already been done).
  1182. ; SERRST below should restore any interrupt vectors that this changes.
  1183. ; Returns normally.    Modified to IOCTL function 12 April 1986 [bgp]
  1184.  
  1185. SERINI    proc    near
  1186.     push    es
  1187.     push    dx
  1188.     push    cx
  1189.     push    bx
  1190.     push    ax
  1191.     cmp    portin,FALSE    ; Did we initialize port already?
  1192.     je    serin0
  1193.     jmp    serin2        ; Yes, just leave
  1194. serin0:
  1195.     cli            ; Disable interrupts
  1196.     xor    ax,ax        ; Address low memory
  1197.     mov    es,ax
  1198.     mov    bx,modem.mdintv
  1199.     mov    ax,es:[bx]
  1200.     mov    savsci,ax
  1201.     mov    ax,offset serint ; Point at our routine
  1202.     mov    es:[bx],ax
  1203.     add    bx,2        ; Now for CS value
  1204.     mov    ax,es:[bx]
  1205.     mov    savscs,ax
  1206.     mov    es:[bx],cs
  1207.     mov    portin,1    ; Note that we are initialized
  1208.     mov    ax,offset source
  1209.     mov    srcpnt,ax
  1210.     mov    count,0
  1211.     mov    ax,SEG_8259    ; Point at 8259 interrupt controller
  1212.     mov    es,ax
  1213.     mov    bx,CW2_8259    ; Control word 2
  1214.     mov    al,es:[bx]
  1215.     and    al,modem.mden    ; Enable INT1 (all from 7201)
  1216.     mov    es:[bx],al    ; Save it
  1217.     mov    bx,CW1_8259    ; Control word 1
  1218.     mov    al,modem.mdmeoi ; Clear any outstanding requests
  1219.     mov    es:[bx],al
  1220.  
  1221. ;  Note that access to the serial controller here is only to register 1 which
  1222. ;  must be done explicitly anyway, so there is no reason to care about
  1223. ;  whether a port is open [bgp]
  1224.  
  1225.     mov    bx,SEG_7201    ; Point at 7201 serial controller
  1226.     mov    es,bx
  1227.     mov    bx,modem.mdstat
  1228.     mov    byte ptr es:[bx],1 ; Register 1 must be done explicitly
  1229.     mov    byte ptr es:[bx],REG1_7201 or ENABLE_INT
  1230.     mov    byte ptr es:[bx],10H ; Clear external/status interrupts
  1231.     mov    byte ptr es:[bx],30H ; Clear special receive cond. int.
  1232.     mov    byte ptr es:[bx],38H ; Set to end of interrupt
  1233.     sti            ; Allow interrupts
  1234.     mov    bx,portval    ; get port [jrd]
  1235.     mov    parmsk,0FFH    ; parity mask, assume parity is None. [jrd]
  1236.     cmp    [bx].parflg,PARNON ; is it None?
  1237.     je    serin1        ; e = yes
  1238.     mov    parmsk,07FH    ; no, pass lower 7 bits as data
  1239. serin1:
  1240.     mov    bx,[bx].flowc    ; get flow control chars
  1241.     mov    flowoff,bl    ; xoff or null
  1242.     mov    flowon,bh    ; xon or null
  1243. serin2:    pop    ax
  1244.     pop    bx
  1245.     pop    cx
  1246.     pop    dx
  1247.     pop    es
  1248.     clc            ; carry clear for success
  1249.     ret
  1250. SERINI    endp
  1251.  
  1252. ; Reset the serial port.  This is the opposite of serini.   Calling
  1253. ; this twice without intervening calls to serini should be harmless.
  1254. ; Returns normally.    Modified to use IOCTL function 12 April 1986 [bgp]
  1255. ; 30 July 1986 Make it go direct to hardware if handle open failed [bgp]
  1256. ;   Also, don't reset the port until the transmit buffer is empty
  1257.  
  1258. SERRST    proc    near
  1259.     push    es        ; preserve this
  1260.     push    dx
  1261.     push    cx
  1262.     push    bx
  1263.     push    ax
  1264.     cmp    portin,FALSE    ; Reset already?
  1265.     je    srst0        ; Yes, just leave.
  1266.     mov    bx,SEG_7201    ; point at 7201 [bgp]
  1267.     mov    es,bx
  1268.     mov    bx,modem.mdstat
  1269. sersta:
  1270.     cli
  1271.     mov    byte ptr es:[bx],1 ; want status register 1
  1272.     mov    al,es:[bx]    ; get status
  1273.     sti
  1274.     test    al,1        ; all sent? (transmitter and shift reg. empty)
  1275.     jz    sersta        ; no, wait...
  1276.     cli            ; Disable interrupts
  1277.     mov    bx,SEG_8259    ; Point at 8259 interrupt controller
  1278.     mov    es,bx
  1279.     mov    bx,CW2_8259
  1280.     mov    al,es:[bx]
  1281.     or    al,modem.mddis    ; Turn off INT1
  1282.     mov    es:[bx],al
  1283.     xor    bx,bx        ; Address low memory
  1284.     mov    es,bx
  1285.     mov    bx,modem.mdintv ; Restore the serial card int vector
  1286.     mov    ax,savsci
  1287.     mov    es:[bx],ax
  1288.     add    bx,2        ; Restore CS too.
  1289.     mov    ax,savscs
  1290.     mov    es:[bx],ax
  1291.  
  1292. ; As in SERINI, the only access to the serial controller is to register 1
  1293. ; which must be done explicitly anyway, so we don't care about the handle [bgp]
  1294.  
  1295.     mov    bx,SEG_7201    ; Point at 7201 serial controller
  1296.     mov    es,bx
  1297.     mov    bx,modem.mdstat
  1298.     mov    byte ptr es:[bx],1 ; Register 1 has to be done explicitly
  1299.     mov    byte ptr es:[bx],REG1_7201
  1300.     mov    portin,FALSE    ; Reset flag.
  1301.     sti
  1302. srst0:
  1303.     pop    ax
  1304.     pop    bx
  1305.     pop    cx
  1306.     pop    dx
  1307.     pop    es        ; All done.
  1308.     ret            ; All done.
  1309. SERRST    endp
  1310.  
  1311. ; serial port interrupt routine.  This is not accessible outside this
  1312. ; module, handles serial port receiver interrupts.
  1313. ; Revised on 22 May 1986, again 2 August 1986 to run at 38.4kb on PC's. [jrd]
  1314. ; Srcpnt holds offset, within buffer Source, where next rcv'd char goes.
  1315. ; Count is number of chars now in buffer, and oldest char is srcpnt-count
  1316. ; done modulo size of Source.  All pointer management is handled here.
  1317. ; Control-G char substituted for char(s) lost in overrun condition. [jrd]
  1318. ; Adapted from msxibm.asm code. [jrd]
  1319. ; Fixed test for receiver overrun. [bgp]
  1320.  
  1321. SERINT    proc      near
  1322.     push    ax        ; [jrd]
  1323.     push    ds        ; do ds and ax first [jrd]
  1324.     push    es
  1325.     push    bx
  1326.     push    dx
  1327.     mov    ax,seg data
  1328.     mov    ds,ax        ; address data segment
  1329.     mov    bx,SEG_7201    ; point at 7201
  1330.     mov    es,bx
  1331.     mov    bx,modem.mdstat
  1332.     mov    al,es:[bx]    ; get status (register 0)
  1333.     mov    byte ptr es:[bx],1 ; want status register 1 [bgp]
  1334.     mov    ah,es:[bx]    ; get status [bgp]
  1335.     mov    bx,STATA_7201    ; this one is always channel A
  1336.     mov    byte ptr es:[bx],38H ; Notify 7201 of end of interrupt
  1337.     mov    bx,SEG_8259    ; point at 8259
  1338.     mov    es,bx
  1339.     mov    bx,CW1_8259
  1340.     mov    dl,modem.mdmeoi
  1341.     mov    es:[bx],dl    ; Clear interrupt
  1342.     test    al,MDMINP    ; anything there (status register 0)?
  1343.     jnz    srint0        ; nz = yes
  1344.     jmp    retint        ; and exit now (common jump point)
  1345. srint0:
  1346.     mov    bx,SEG_7201
  1347.     mov    es,bx
  1348.     and    ah,MDMOVER    ; select overrun bit (status register 1)[jrd]
  1349.     mov    overrun,ah    ; save it for later [jrd]
  1350.     jz    srint0a     ; no overrun
  1351.     mov    bx,modem.mdstat
  1352.     mov    byte ptr es:[bx],30H ; Clear overrun error status
  1353. srint0a:
  1354.     mov    bx,modem.mddat
  1355.     mov    al,es:[bx]    ; get data byte
  1356.     cmp    flowoff,0    ; flow control active?
  1357.     je    srint4        ; e = no
  1358.     mov    ah,al        ; ah = working copy. Check flow cntl.
  1359.     and    ah,parmsk    ; strip parity temporarily, if any. [jrd]
  1360.     cmp    ah,flowoff    ; acting on Xoff?
  1361.     jne    srint3        ; ne = Nope, go on
  1362.     cmp    xofsnt,0    ; have we sent an outstanding XOFF? [jrd]
  1363.     jne    srint1        ; ne = yes, ignore (possible echo)
  1364.     mov    xofrcv,bufon    ; Set the flag saying XOFF received
  1365. srint1:    jmp    retint        ; and exit
  1366. srint3:
  1367.     cmp    ah,flowon    ; acting on Xon?
  1368.     jne    srint4        ; ne = Nope, go on
  1369.     mov    xofrcv,off    ; Clear the XOFF received flag.
  1370.     jmp    retint        ; and exit
  1371. srint4:
  1372.     mov    ah,overrun    ; get overrun flag [jrd]
  1373.     or    ah,ah        ; overrun?
  1374.     jz    srint5        ; z = no
  1375.     mov    ah,al        ; yes, save present char
  1376.     mov    al,BELL     ; insert control-G for missing character
  1377. srint5:
  1378.     mov    bx,srcpnt    ; address of buffer storage slot
  1379.     mov    byte ptr [bx],al ; store the new char in buffer "source"
  1380.     inc    srcpnt        ; point to next slot
  1381.     inc    bx
  1382.     cmp    bx,offset source+BUFSIZ ; beyond end of buffer?
  1383.     jb    srint6        ; b = not past end
  1384.     mov    srcpnt,offset source ; wrap buffer arount
  1385. srint6:
  1386.     cmp    count,BUFSIZ    ; filled already?
  1387.     jae    srint7        ; ae = yes
  1388.     inc    count        ; no, add a char
  1389. srint7:
  1390.     or    ah,ah        ; anything in overrun storage?
  1391.     jz    srint8        ; z = no
  1392.     mov    al,ah        ; recover any recent char from overrun
  1393.     xor    ah,ah        ; clear overrun storage
  1394.     jmp    srint5        ; yes, go store real second char
  1395. srint8:
  1396.     sti            ; ok to allow interrupts now, not before
  1397.     cmp    count,MNTRGH    ; past the high trigger point?
  1398.     jbe    retint        ; be = no, we're within our limit
  1399.     test    xofsnt,bufon    ; Has an XOFF been sent by buffer control?
  1400.     jnz    retint        ; nz = Yes.
  1401.     mov    al,flowoff    ; get the flow off char (Xoff or null)
  1402.     or    al,al        ; don't send null chars
  1403.     jz    retint        ; z = null, nothing to send
  1404.     call    dopar        ; set parity appropriately.
  1405.     mov    ah,al        ; Don't overwrite character with status
  1406.     push    cx        ; save reg [jrd]
  1407.     xor    cx,cx        ; loop counter [jrd]
  1408.     mov    bx,SEG_7201    ; point at 7201
  1409.     mov    es,bx
  1410.     mov    bx,modem.mdstat
  1411. srint9:
  1412.     mov    al,es:[bx]
  1413.     test    al,4        ; ready?
  1414.     jnz    srint10     ; yes
  1415.     loop    srint9
  1416.     jmp    srint11     ; Timeout
  1417. srint10:
  1418.     mov    al,ah        ; now send it out
  1419.     mov    bx,modem.mddat
  1420.     mov    es:[bx],al
  1421.     mov    xofsnt,bufon       ; Remember we sent an XOFF at buffer level
  1422. srint11:
  1423.     pop    cx        ; [jrd]
  1424. retint:
  1425.     sti            ; be sure that this made it on
  1426.     pop    dx
  1427.     pop    bx
  1428.     pop    es
  1429.     pop    ds
  1430.     pop    ax        ; [jrd]
  1431.     iret
  1432. SERINT    endp
  1433.  
  1434. ; Produce a beep.   Returns normally.
  1435.  
  1436. BEEP    proc    near
  1437.     mov    dl,BELL
  1438.     mov    ah,DCONIO    ; No checks, just do it
  1439.     int    DOS
  1440.     ret
  1441. BEEP    endp
  1442. CODE    ends
  1443.     end
  1444.