DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T m

⟦1b48c2662⟧ TextFile

    Length: 36550 (0x8ec6)
    Types: TextFile
    Names: »msxrmx.a86«

Derivation

└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
    └─⟦71044c191⟧ »EurOpenD3/misc/kermit.ms-2.32.tar.Z« 
        └─⟦31f2d420d⟧ 
            └─⟦this⟧ »msxrmx.a86« 

TextFile

        NAME    MSXRMX
; RMX System dependent module derived from Generic MS DOS Kermit module

$INCLUDE(mssdef.h86)

        public  serini, serrst, clrbuf, outchr, coms, vts, dodel, termtb, bddat
        public  ctlu, cmblnk, locate, lclini, prtchr, dobaud, clearl, pcwait
        public  dodisk, getbaud, beep, srcptr, sendbl, dtrtime, shomodem
        public  xofsnt, puthlp, putmod, clrmod, poscur, savsi, portatt, sintok
        public  sendbr, term, setktab, setkhlp, showkey, dtrlow, serhng
        public  vtstat, ihosts, ihostr, dumpscr, comptab, costrt, coptr, spkout
        public  chrout, chang, klogof, klogon, snull, cquit, cstatus, cquery

false   equ     0
true    equ     1

; external variables used:
; drives - # of disk drives on system
; flags - global flags as per flginfo structure defined in pcdefs
; trans - global transmission parameters, trinfo struct defined in pcdefs
; portval - pointer to current portinfo structure
; port1, port2 - portinfo structures for the corresponding ports

; global variables defined in this module:
; xofsnt, xofrcv - tell whether we saw or sent an xoff.

datas   segment
PURGE   prstr, dconio
        extrn   drives:byte, flags:byte, trans:byte, citok:word, cotok:word
        extrn   portval:word, prtbase:byte, oneport:byte, trmstr:byte
        extrn   mbox:word, tmbox:word, sigpair:word, sematok:word, spkcnt:word
        extrn   data:byte, pack:byte, combx:word, cimbx:word, termatt:word
        extrn   trok:byte, rxtable:byte, kbdflg:byte, subpksz:word, source:byte
        extrn   bufill:word, temp:word

erms40  db      cr,lf,'?Warning: Unrecognized baud rate',cr,lf,'$'
erms60  db      cr,lf,'Port doesn''t exist, use RUN ATTACH . . .'
        db      cr,lf,'& try again$'
wrn1prt db
&       bell,cr,lf,'Warning: No ports found, port 0 being used',cr,lf,bell,'$'
badbd   db      cr,lf,'Unimplemented baud rate$'
noimp   db      cr,lf,'Command not implemented.$'
setktab db      0
setkhlp db      0
crlf    db      cr,lf,'$'
delstr  db      BS,BS,' ',BS,'$'        ; Delete string.
clrlin  db      cr                      ; Clear line (just the cr part).
clreol  db      ESCAPE,'[0K'            ; Clear line.
clscr   db      ESCAPE,'[2J'            ; clear screen

cursor  db      ESCAPE,'['              ; position cursor
row     dw      ?                       ;  part
        db      ';'                     ;   of
col     dw      ?                       ; above
        db      'H'                     ; last of above

mode    db      ESCAPE,'[24;1H',ESCAPE,'[0K'    ; put cursor on mode line & clea
model   db      80 dup(?)               ; mode line contents
huosc   db      ESCAPE,']M:H',ESCAPE,'\'        ; hangup OSC

xofsnt  db      0               ; Say if we sent an XOFF.
xofrcv  db      0               ; Say if we received an XOFF.
parmsk  db      ?               ; 8/7 bit parity mask, for reception
savrflg db      ?               ; save previous remflg
comstr  db      6,':COM_:'
tstr    db      4,':T_:'
devname db      14 dup(?)       ; :TERM:'s physical device name

; Entries for choosing communications port. [19b]
comptab db      10
        %mkeyw  (%('0 (TERM)'),0)
        %mkeyw  (%('1 (COM1 or T1)'),1)
        %mkeyw  (%('2 (COM2 or T2)'),2)
        %mkeyw  (%('3 (COM3 or T3)'),3)
        %mkeyw  (%('4 (COM4 or T4)'),4)
        %mkeyw  (%('5 (COM5 or T5)'),5)
        %mkeyw  (%('6 (COM6 or T6)'),6)
        %mkeyw  (%('7 (COM7 or T7)'),7)
        %mkeyw  (%('8 (COM8 or T8)'),8)
        %mkeyw  (%('9 (COM9 or T9)'),9)

ourarg  termarg <>

termtb  db      1
        %mkeyw  (%('none'),ttgenrc)

        even

ten     dw      10
dtrtime dw      500
status  dw      ?
sostrt  dw      ?
soend   dw      ?
sofin   dw      ?
savsi   dw      source          ; points to next char in buffer
srcptr  dw      source          ; points to next quadrant of buffer
sintok  dw      0
soutok  dw      0
portptr dw      ?
costrt  dw      ?
coptr   dw      ?
argadr  dw      ?

portatt dw      4,4,0ffh,119h   ; serial I/O port attributes for rqaspecial
inbaud  dw      0,1             ; part of above

getptat dw      3,3,2 dup(?)    ; structure to read baud rate
getinbd dw      ?               ; part of above

dest    db      2 dup (?)       ; outchr's buffer

; This table is indexed by portinfo.baud.  Unsupported baud rates contain 0.
bddat   label   word
        dw      0               ;   45.5 baud  N/A
        dw      50              ;     50 baud
        dw      75              ;     75 baud
        dw      110             ;    110 baud
        dw      0               ;  134.5 baud  N/A
        dw      150             ;    150 baud
        dw      300             ;    300 baud
        dw      600             ;    600 baud
        dw      1200            ;   1200 baud
        dw      1800            ;   1800 baud
        dw      2000            ;   2000 baud
        dw      2400            ;   2400 baud
        dw      4800            ;   4800 baud
        dw      9600            ;   9600 baud
        dw      19200           ;  19200 baud
        dw      38400           ;  38400 baud
        dw      56800           ;  56800 baud
        dw      0               ; 113600 baud  N/A
datas   ends

code    segment
        extrn   comnd:near, dopar:near, prserr:near, keybd:near, msuinit:near
        extrn   delcon:near, crfile:near, opfile:near, writer:near
        extrn   aspcl:near, prstr:near, awrite:near, rqsleep:near, flushci:near
        extrn   waitio:near, sendms:near, aopen:near, aclose:near, special:near
        extrn   rcvmsg:near, delseg:near, dconio:near, gfilsta:near

; This is the HANGUP command.  It drops DTR momentarily, if the serial board
; and its driver support modem control.

dtrlow  PROC
serhng: call    serrst                  ; reset & reinitialize port
        call    serini
        mov     ax,soutok               ; enable OSC's on output
        mov     bx,offset portatt
        and     word ptr[bx+4],0bfh
        mov     cx,5
        call    aspcl
        mov     ax,soutok               ; send hangup OSC
        mov     bx,offset huosc
        mov     byte ptr[bx+4],'H'
        mov     cx,size huosc
        mov     dx,tmbox
        call    awrite
        mov     ax,soutok               ; wait for it
        mov     bx,tmbox
        call    waitio
        mov     ax,dtrtime                      ; kill time
        call    pcwait
        mov     ax,soutok
        mov     bx,offset huosc
        mov     byte ptr[bx+4],'A'
        mov     cx,size huosc           ; send answer OSC
        mov     dx,tmbox
        call    awrite
        mov     ax,soutok               ; wait for it
        mov     bx,tmbox
        call    waitio
        mov     ax,soutok               ; disable OSC's on output
        mov     bx,offset portatt
        or      word ptr[bx+4],40h
        mov     cx,5
        call    aspcl
        call    serrst                  ; reset port
        jmp     RSKP
dtrlow  ENDP

pcwait  PROC            ; sleep for ax milliseconds (rounded up to nearest 10)
        push    ax      ; too lazy to find out how much of this is necessary
        push    bx
        push    cx
        push    dx
        push    si
        push    di
        push    es
        sub     dx,dx
        add     ax,9
        div     ten
        push    ax
        push    ds
        mov     ax,offset status
        push    ax
        call    rqsleep
        pop     es
        pop     di
        pop     si
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        ret
pcwait  ENDP

; IHOSTS - Initialize the host by sending XON, or equivalent, and enter the
; cycle of clear input buffer, test if buffer empty then exit, else repeat
; cycle. Requires that the port be initialized before hand.
; Ihosts is used by the local send-file routine just after initializing
; the serial port.
; 22 March 1986 [jrd]

IHOSTS  PROC
        push    ax              ; save the registers
        push    bx
        push    cx
        push    dx
        mov     bx,portval      ; port indicator
        mov     ax,[bx].flowc   ; put Go-ahead flow control char in ah
        test    ah,ah           ; don't send null if flow=null
        jz      ihosts1         ; z=null
        call    outchr          ; send it (release Host's output queue)
         nop                    ; outchr can do skip return
         nop
         nop
ihosts1:call    clrbuf          ; clear out interrupt buffer
        call    prtchr          ; check for char at port
         jmp    ihosts1         ; have a char in al, repeat wait/read cycle
         nop                    ; prtchr does skip return on empty buffer
        pop     dx              ; empty buffer. we are done here.
        pop     cx
        pop     bx
        pop     ax
        ret
IHOSTS  ENDP

; IHOSTR - initialize the remote host for our reception of a file by
; sending the flow-on character (XON typically) to release any held
; data. Called by receive-file code just after initializing the serial
; port.         22 March 1986 [jrd]
IHOSTR  PROC
        push    ax              ; save regs
        push    bx
        push    cx
        mov     bx,portval      ; port indicator
        mov     ax,[bx].flowc   ; put Go-ahead flow control char in ah
        test    ah,ah           ; don't send null if flow=null
        jz      ihostr1         ; z=null
        call    outchr          ; send it (release Host's output queue)
         nop                    ; outchr can do skip return
         nop
         nop
ihostr1:pop     cx
        pop     bx
        pop     ax
        ret
IHOSTR  ENDP

; this is called by Kermit initialization.  It checks the
; number of disks on the system, sets the drives variable
; appropriately.  Returns normally.

DODISK  PROC
        mov drives,1            ; 1 "disk".  It's $, which can be reattachfiled
        ret
DODISK  ENDP

; Clear the input buffer. This throws away all the characters in the
; serial interrupt buffer.  This is particularly important when
; talking to servers, since NAKs can accumulate in the buffer.
; Returns normally.

CLRBUF  PROC
        push    es
        mov     ax,ds
        mov     es,ax
        cld
        cli
        mov     di,savsi                ; scan from current ptr
        mov     cx,offset source+bufsiz
        sub     cx,di                   ; to end of buffer for fill char
        mov     al,byte ptr bufill
        repne scasb
        je      CLRB1                   ; jump if found
        mov     di,offset source        ; scan from the beginning, if not
        mov     cx,bufsiz
        repne scasb
CLRB1:  dec     di
        mov     savsi,di                ; current ptr points to fill char
        sti
        pop     es
        ret
CLRBUF  ENDP

; Put the char in AH to the serial port.  This assumes the
; port has been initialized.  Should honor xon/xoff.  Skip returns on
; success, returns normally if the character cannot be written.

outchr  PROC
        push    bx
        push    cx
        push    dx
        push    es
        mov     al,ah
        call    dopar           ; set parity, as req'd
        mov     dest,al
        mov     ax,soutok
        mov     bx,offset dest  ; write it
        mov     cx,1
        sub     dx,dx
        call    awrite
        pop     es
        pop     dx
        pop     cx
        pop     bx
        cmp     status,0
        jne     OUTCH1
        jmp     RSKP            ; OK return
OUTCH1: ret                     ; NG return
outchr  ENDP

; Set the baud rate for the current port, based on the value in the portinfo
; structure.  Returns normally.  Entered w/current baud rate in ax.

DOBAUD  PROC
        push    bx
        mov     bx,portval              ; see if new baud rate is OK
        mov     si,[bx].baud
        shl     si,1
        mov     cx,bddat[si]
        jcxz    DOBD1                   ; nope
        call    serrst                  ; yeah, force serini to set it
        pop     bx
        ret
DOBD1:  mov     [bx].baud,ax            ; restore previous baud rate
        mov     dx,offset badbd         ; send bad baud msg
        call    prstr
        pop     bx
        ret
DOBAUD  ENDP

; Get the current baud rate from the serial card and set it
; in the potinfo structure for the current port.  Returns normally.
; This is used during initialization.

GETBAUD PROC
        ret                     ; It's all taken care of, so what's to do?
GETBAUD ENDP


; Use for DOS 2.0 and above.  Check the port status.  If no data, skip return.
; Else, read in a char and return.  DX returns # chars (0 or 1 for us).
PRTCHR  PROC
        push    si
        cmp     xofsnt,true             ; if XOF has been sent,
        je      PRTCH4                  ; see if there's room in buffer for XON
PRTCH1: sub     dx,dx                   ; # of chars
        mov     si,savsi                ; current serial input buffer ptr
        cld
        lodsb
        cmp     al,byte ptr bufill      ; got one?
        jne     PRTCH2
        pop     si                      ; nope
        jmp     RSKP
PRTCH2: cmp     si,offset source+bufsiz ; edge of the universe?
        jb      PRTCH3                  ; no
        mov     si,offset source        ; yeah, point to beginning
PRTCH3: mov     savsi,si                ; update current ptr
        inc     dx                      ; # chars=1
        pop     si
        ret                             ; got one return
PRTCH4: mov     ax,srcptr               ; if next quadrant & current ptr are
        sub     ax,savsi                ; 2 quadrants apart
        jns     PRTCH5                  ; there's room to XON
        add     ax,bufsiz
PRTCH5: cmp     ax,bufsiz/2
        jg      PRTCH1                  ; they aren't
        push    bx                      ; send XON
        mov     bx,portval
        mov     ax,[bx].flowc
        call    outchr
         nop
         nop
         nop
        mov     xofsnt,false            ; reset
        pop     bx
        jmp     PRTCH1
PRTCHR  ENDP

; Send a break out the current serial port.  Returns normally.
SENDBR  PROC
sendbl: mov     dx,offset noimp ; send intel's appologies
        call    prstr           ; for not having OS support
        ret                     ; for their hardware's capabilities

SENDBR  ENDP

; Show modem command.  Not implemented.
SHOMODEM PROC
        mov     ah,cmcfm        ; get a confirm
        call    comnd
         ret                    ; no confirm
         nop
         nop
        call    SENDBR          ; send not imp. msg
        jmp     RSKP
SHOMODEM ENDP

; Clear to the end of the current line.  Returns normally.

CLEARL  PROC
        push    bx
        mov     bx,offset clreol        ; send ESC[0K
SCRO1:  mov     cx,4                    ; to clear to end of line
SCRO2:  push    ax
SCRO3:  mov     ax,cotok
        push    es
        push    dx
        push    si
        call    writer
        pop     si
        pop     dx
        pop     es
        pop     ax
        pop     bx
        ret
CLEARL  ENDP

; This routine blanks the screen.  Returns normally.

CMBLNK  PROC
        push    bx
        mov     bx,offset clscr         ; send ESC[2J for clear screen
        jmp     SCRO1
CMBLNK  ENDP

; Position the cursor according to contents of DX:
; DH contains row, DL contains column.  Returns normally.
POSCUR  PROC
        push    bx
        push    ax
        add     dx,101h         ; KERMIT starts w/0, RMX w/1
        mov     al,dh           ; convert row to decimal
        sub     ah,ah
        mov     cl,10
        div     cl
        add     ax,'00'         ; covert to ASCII
        mov     row,ax          ; stash in row portion of escape sequence
        mov     al,dl           ; convert column to decimal
        sub     ah,ah
        div     cl
        add     ax,'00'         ; convert to ASCII
        mov     col,ax          ; to column portion of escape sequence
        mov     bx,offset cursor
        mov     cx,8            ; send ESC[row;colH to position cursor
        jmp     SCRO3
POSCUR  ENDP

; Move the cursor to the left margin, then clear to end of line.
; Returns normally.

CTLU    PROC
        push    bx
        mov     bx,offset clrlin        ; send CR,ESC[0K to clear entire line
        mov     cx,5
        jmp     SCRO2
CTLU    ENDP

; Homes the cursor.  Returns normally.

LOCATE  PROC
        mov     dx,0            ; Go to top left corner of screen.
        jmp     poscur
LOCATE  ENDP

; Write a line at the bottom of the screen...
; the line is passed in dx, terminated by a $.  Returns normally.
putmod  PROC
        push    bx
        push    ax
        mov     bx,es           ; save es
        mov     ax,ds
        mov     es,ax
        mov     di,dx
        mov     cx,0ffffh       ; compute # bytes in line
        mov     al,'$'
        repne scasb
        neg     cx
        add     cx,0fffeh
        mov     si,dx
        mov     di,offset model
        mov     dx,cx           ; save # bytes
        rep movsb               ; move line after mode line escape sequence
        mov     cx,size mode    ; mode line escape sequence length
        add     cx,dx           ; plus line length
        mov     es,bx           ; restore es
        mov     bx,offset mode  ; write line prefixed w/escape sequence
        jmp     SCRO3
putmod  ENDP

; clear the mode line written by putmod.  Returns normally.
clrmod  PROC
        push    bx
        mov     bx,offset mode  ; mode line escape sequence
        mov     cx,size mode    ; ESC[24;1HESC[0K
        jmp     SCRO2           ; clears mode line
clrmod  ENDP

; Put a help message on the screen.
; Pass the message in ax, terminated by a null.  Returns normally.
puthlp  PROC
        push    dx
        push    si
        push    ax              ; preserve this
        mov     dx,offset crlf
        call    prstr
        pop     si              ; point to string again
puthl3: cld
        lodsb                   ; get a byte
        cmp     al,0            ; end of string?
        je      puthl4          ; yes, stop
        mov     dl,al
        call    dconio          ; else write to screen
        jmp     puthl3          ; and keep going
puthl4: mov     dx,offset crlf
        call    prstr
        pop     si
        pop     dx
        ret
puthlp  ENDP

; Delete a character from the terminal.  This works by printing
; backspaces and spaces.  Returns normally.

DODEL   PROC
        mov     dx,offset delstr
        call    prstr           ; Erase weird character.
        ret
DODEL   ENDP

; Set the current port.
COMS    PROC
        call    serrst          ; reset the old port
        mov     dx,offset comptab
        sub     bx,bx
        mov     ah,cmkey
        call    comnd           ; parse for the new one
         ret
         nop
         nop
        push    bx              ; save port #
        mov     ah,cmcfm
        call    comnd           ; Get a confirm.
         jmp    short COMX      ; Didn't get a confirm.
         nop
        pop     cx              ; get port #
        mov     ax,size prtinfo ; compute address of prtinfo structure
        mul     cl
        add     ax,offset prtbase
        mov     temp,ax         ; save it
        jcxz    COMS1           ; jmp if port 0 (:TERM:)
        call    COMSR           ; crfile :COMn: or :Tn:
        jz      COMS2           ; jmp if successful
        mov     dx,offset erms60
        call    prstr           ; no luck, bitch
        ret
COMX:   pop     bx
        ret
COMS1:  mov     di,offset trmstr
        mov     temp+2,di       ; port name string pointer
        call    crfile
COMS2:  mov     bx,temp
        mov     portval,bx      ; set prtinfo ptr
COMS3:  mov     flags.comflg,cl ; remember port #
        mov     sintok,ax       ; open port
        mov     bx,1
        call    aopen
        call    rdbaud          ; read it's baud rate
        mov     bx,portval
        mov     [bx].baud,cx    ; memorize it
        call    serrst          ; reset port
        mov     di,temp+2       ; port name string pointer
        mov     portptr,di
        call    gfilsta         ; puts physical device name @temp+10
        mov     ax,ds
        mov     es,ax
        mov     si,offset devname
        mov     di,offset temp+10
        mov     cx,size devname
        repe cmpsb              ; is it the same as :TERM:?
        je      COMS5           ; eq = yes
        cmp     oneport,true    ; was it oneport?
        jne     COMS4           ; ne = no, exit
        mov     al,savrflg      ; yes, restore remflg to what it was before
        mov     flags.remflg,al
        mov     oneport,cl      ; clear oneport
COMS4:  ret
COMS5:  mov     al,dquiet       ; get current remflg & set to quiet mode
        xchg    al,flags.remflg
        cmp     oneport,true    ; if not previously one port
        je      COMS4           ; save previous remflg & set oneport
        mov     savrflg,al
        mov     oneport,true    ; set oneport
        ret

COMSR   proc
        push    cx              ; save port #
        add     cl,'0'          ; charify
        mov     di,offset comstr
        mov     temp+2,di       ; temp+2 is port name string pointer
        mov     [di+5],cl       ; setup :COMn: & :Tn: strings
        mov     tstr+3,cl
        call    crfile          ; try COMn
        jcxz    CSR1            ; OK
        mov     di,offset tstr  ; try Tn
        mov     temp+2,di
        call    crfile
CSR1:   test    cx,cx           ; return zero flag, if successful
        pop     cx              ; restore port #
        ret
COMSR   endp
COMS    ENDP

; Reads serial port's baud rate.  Returns baud rate index in cx if recognizable
; by KERMIT, if not, cx=0ffffh.

rdbaud  PROC
        push    es
        mov     ax,sintok       ; use aspecial function 4 to read baud rate
        mov     bx,offset getptat
        mov     cx,4
        call    aspcl
        mov     ax,ds
        mov     es,ax
        mov     ax,getinbd      ; search bddat table for it
        mov     cx,baudsiz
        mov     di,offset bddat+2*(baudsiz-1)
        std
        repne scasw
        cld
        je      RDB1            ; found it, cx=index
        mov     dx,offset erms40
        call    prstr           ; not found, say so
        mov     cx,0ffffh       ; return unrecognizable
RDB1:   pop     es
        ret
rdbaud  ENDP

; Set heath emulation on/off.

VTS     PROC
        mov     dx,offset noimp
        call    prstr
        jmp     prserr
VTS     ENDP

; Initialize variables & find port

lclini: mov     flags.vtflg,0           ; Don't do terminal emulation.
        call    msuinit

        mov     di,offset trmstr        ; get :TERM:'s physical devive name
        call    gfilsta
        mov     ax,ds
        mov     es,ax
        mov     si,offset temp+10       ; move it to devname
        mov     di,offset devname
        mov     cx,size devname
        rep movsb

        mov     ax,offset prtbase       ; base value of prtinfo struc ptr
        mov     ax,portval
        mov     temp,ax                 ; save in case it ends up port 0
LCL1:   add     portval,size prtinfo    ; loop thru looking for 1st of 1 to max
        inc     cx                      ; 0 1st time thru
        call    COMSR                   ; try crfile COMn or Tn
        jz      LCL2                    ; z = success
        cmp     cl,portmax-1            ; done?
        jl      LCL1                    ; l = no
        call    COMS1                   ; yes, go use :TERM:
        mov     dx,offset wrn1prt       ; and give one port warning
        call    prstr
        ret
LCL2:   jmp     COMS3                   ; join common code
        ret

showkey:ret     ; obsolete, for ext def only

; Initialization for using serial port.  Returns normally.
SERINI  PROC
        cmp     sintok,0        ; is this trip necessary?
        jne     SIN3            ; no
        push    bx
        push    es
        cmp     oneport,true    ; is it oneport?
        jne     SIN1            ; ne = no
        mov     ax,citok        ; yes, shut down citsk
        sub     cx,cx
        call    aclose
        mov     ax,citok        ; reopen
        mov     bx,3
        call    aopen
        call    flushci         ; necessary for 386
SIN1:   mov     di,portptr      ; get port ptr
        push    di              ; save for 2nd crfile
        call    crfile          ; create it
        mov     sintok,ax       ; set serial input token
        mov     bx,1            ; open for reading
        call    aopen

        pop     di              ; port ptr
        call    crfile          ; create it
        mov     soutok,ax       ; set serial output token
        mov     bx,2            ; open for writing
        call    aopen

        mov     bx,portval      ; prtinfo struc ptr
        mov     parmsk,0ffh     ; set parmsk according to this port
        cmp     [bx].parflg,parnon
        je      SIN2
        mov     parmsk,7fh
SIN2:   mov     bx,[bx].baud    ; set baud rate according to this prot
        shl     bx,1
        mov     ax,bddat[bx]
        mov     inbaud,ax

        mov     ax,soutok       ; set baud rate & attributes
        mov     bx,offset portatt
        mov     cx,5
        call    aspcl

        mov     ax,mbox         ; when the message sent to mbox
        mov     bx,ax           ; is the mbox token itself
        call    sendms          ; it tells the serial input task
        pop     es              ; to initialize & start input
        pop     bx
SIN3:   ret
SERINI  ENDP

; Reset the serial port.  This is the opposite of serini.  Calling
; this twice without intervening calls to serini should be harmless.
; Returns normally.

SERRST  PROC
        push    bx
        mov     bx,sintok       ; serial input token
        test    bx,bx
        jz      SERST1          ; unecessary
        mov     sintok,0        ; MUST be done 1st, cuz siotsk is gonna get ints
        call    delcon          ; before we get back from delete connection
SERST1: mov     ax,soutok       ; serial output token
        test    ax,ax
        jz      SERST2          ; don't bother
        push    ax              ; save for delcon
        mov     cx,tmbox
        push    cx              ; save for rcvmsg
        call    aclose          ; let I/O complete before delcon
        pop     ax
        mov     bx,0ffffh
        call    rcvmsg
        call    delseg
        pop     bx              ; soutok
        mov     soutok,0        ; see above
        call    delcon          ; ditto
        cmp     oneport,true
        jne     SERST2
        call    flushci         ; necessary for 386
        mov     ax,citok
        mov     bx,offset termatt
        mov     cx,5

        call    aspcl
        mov     ax,cimbx        ; restart citsk
        mov     bx,ax
        call    sendms
SERST2: pop     bx
        ret
SERRST  ENDP

; Bell ringer

BEEP    PROC
        mov     dl,bell
        call    dconio
        ret
BEEP    ENDP

VTSTAT  PROC    ; For Status display [jrd]
        ret             ; no emulator status to display
VTSTAT  ENDP

; Save the screen to a buffer and then append buffer to a disk file. [jrd]
; Default filename is Kermit.scn; actual file can be a device too. Filename
; is determined by mssset and is passed as pointer dmpname.

DUMPSCR PROC    ; Dumps screen contents to a file. Just Beeps here
        jmp     beep    ; [jrd]
DUMPSCR ENDP

; Dumb terminal emulator.
TERM    PROC
        cmp     oneport,true            ; if oneport
        jne     TERM1
        mov     kbdflg,'C'              ; force exit connect mode
        jmp     BEEP
TERM1:  mov     si,ax                   ; this is source
        mov     di,offset ourarg        ; place to store arguments
        mov     ax,ds
        mov     es,ax                   ; address destination segment
        mov     cx,size termarg
        cld
        rep movsb                       ; copy into our arg blk
        mov     parmsk,0ffh
        cmp     ourarg.parity,parnon
        je      TERM2
        mov     parmsk,7fh
TERM2:  mov     ax,citok                ; shut down citsk & reopen citok
        call    aclose
        mov     ax,citok
        mov     bx,3
        call    aopen

        sub     ax,ax                   ; turn off control C trap
        mov     sigpair,ax
        mov     ax,citok
        mov     bx,offset sigpair
        mov     cx,6
        call    aspcl

        push    termatt+6               ; save
        cmp     trok,true
        je      TERM3
        and     termatt+6,0fdffh        ; turn off translation
TERM3:  push    termatt+4               ; save
        or      termatt+4,0e0h          ; disable OSC's & output ctrl chars
        mov     ax,cotok                ; make it transparent as all get out
        mov     bx,offset termatt       ; during terminal emulation
        mov     cx,5
        call    special
        mov     ax,citok
        mov     bx,offset termatt
        mov     cx,5
        call    aspcl

        mov     ax,cimbx                ; start citsk & cotsk
        mov     bx,ax
        call    sendms
        mov     ax,combx
        mov     bx,ax
        call    sendms

        mov     ax,ds
        mov     es,ax

TERM4:  call    PORTCHR                 ; get char from port
         call   OUTTTY                  ; if char, output it
        call    KEYBD                   ; check keyboard
        jnc     TERM4                   ; carry=exit Connect mode

        pop     termatt+4               ; restore
        pop     termatt+6               ; restore

        mov     ax,combx                ; shut down cotsk
        mov     bx,ax
        call    sendms

        mov     ax,citok                ; shut down citsk & reopen citok
        call    aclose
        mov     ax,citok
        mov     bx,3
        call    aopen

        mov     ax,sematok              ; restore control C trap
        mov     sigpair,ax
        mov     ax,citok
        mov     bx,offset sigpair
        mov     cx,6
        call    aspcl

        mov     ax,cotok                ; reopen cotok
        mov     bx,3
        mov     cx,bx
        call    opfile

        mov     ax,citok                ; restore terminal attributes
        mov     bx,offset termatt
        mov     cx,5
        call    aspcl
        mov     ax,cotok
        mov     bx,offset termatt
        mov     cx,5
        call    special

        mov     ax,cimbx                ; restart citsk
        mov     bx,ax
        call    sendms

        ret
TERM    ENDP

;; keyboard translator action routines, system dependent, called from msurmx.
; These are invoked by a jump instruction. Return carry clear for normal
; processing, return carry set exit Connect mode (kbdflg has transfer char).

klogon  proc                            ; resume logging (if any)
        test    flags.capflg,logses     ; session logging enabled?
        jz      klogn                   ; z = no, forget it
        or      argadr.flgs,capt        ; turn on capture flag
        or      ourarg.flgs,capt        ; turn on local capture flag as well
klogn:  clc
        ret
klogon  endp

klogof  proc                            ; suspend logging (if any)
        and     argadr.flgs,not capt    ; stop capturing
        and     ourarg.flgs,not capt    ; rest local as well
        clc
        ret
klogof  endp

snull:  mov     ah,0                    ; send a null
        call    outchr                  ; send without echo or logging
         nop
         nop
         nop
        clc
        ret

cmdcom: mov     kbdflg,al               ; pass char to msster.asm via kbdflg
        stc                             ; say exit Connect mode
        ret
cstatus:mov     al,'S'                  ; these commands exit Connect mode
        jmp     cmdcom
cquit:  mov     al,'C'
        jmp     cmdcom
cquery: mov     al,'?'
        jmp     cmdcom
chang:  mov     al,'H'
        jmp     cmdcom

;; end of action routines

OUTTTY  PROC
        cmp     rxtable+256,0           ; translation turned off?
        je      OTY1                    ; e = yes, no translation
        push    bx
        mov     bx,offset rxtable       ; address of translate table [jrd]
        xlatb                           ; new char is in al
        pop     bx
OTY1:   test    ourarg.flgs,capt        ; capturing output?
        jz      OTY2                    ; no, forget it
        push    ax
        call    ourarg.captr            ; else call the routine
        pop     ax
OTY2:   test    ourarg.flgs,trnctl      ; debugging?  nz=yes
        jnz     OTY3                    ; bypass translation & do debug display
        test    flags.remflg,d8bit      ; keep 8 bits for displays?
        jnz     OUTONE                  ; nz = yes, 8 bits if possible
        and     al,7fh                  ; remove high bit

OUTONE  PROC
        mov     di,coptr                ; CO buffer pointer
        sub     di,costrt               ; is buffer full?
        cmp     di,cobufl
        je      OUTONE                  ; eq=yes, wait for room

        cli                             ; disable ints during
        mov     di,coptr                ; these 3
        stosb                           ; critical
        mov     coptr,di                ; instructions
        sti

        ret
OUTONE  ENDP

OTY3:   test    al,al                   ; is high bit on?
        jns     OTY4                    ; ns=no
        mov     ah,al                   ; save it
        mov     al,'~'                  ; output tilde
        call    OUTONE
        mov     al,ah                   ; restore it & turn off high bit
        and     al,7fh
OTY4:   cmp     al,7fh                  ; is it rubout?
        jne     OTY5                    ; ne=no
        and     al,3fh                  ; convert to ?
        jmp     short OTY6              ; to display ^? for rubout
OTY5:   cmp     al,' '                  ; is it a control character?
        jae     OUTONE                  ; ae=no, just output it
        add     al,'@'                  ; make printable
OTY6:   mov     ah,al                   ; save
        mov     al,'^'                  ; output ^
        call    OUTONE
        mov     al,ah                   ; restore & output
        jmp     OUTONE
OUTTTY  ENDP

CHROUT  PROC
        test    ourarg.flgs,lclecho     ; echoing?
        jz      CHRO1                   ; no, don't bother
        push    ax
        call    OUTTTY
        pop     ax
CHRO1:  mov     ah,al
        call    outchr                  ; output the character
         nop
         nop
         nop
        ret
CHROUT  ENDP

SPKOUT  PROC
        inc     spkcnt          ; bump ctr
        cmp     ah,trans.ssoh
        je      SPK4            ; eq = start of packet
        cmp     bx,soend
        je      SPK1            ; eq = enough to write
        clc
        ret

SPK1:   push    cx
        push    bx
        push    ax
        push    dx
        mov     cx,bx           ; bx is last byte+1
        xchg    bx,sostrt       ; bx = current 1st byte, sostrt = next 1st byte
        sub     cx,bx           ; cx = # bytes

        mov     ax,soutok       ; call rqawrite(soutok,ds:bx,cx,0,@status)
        sub     dx,dx
        call    awrite
        pop     dx
        pop     ax
        mov     bx,sostrt
        mov     cx,sofin
SPK2:   add     bx,subpksz      ; next time to write (soend) =
        cmp     bx,cx           ; min{sofin,(sostrt + subpksz)}
        jb      SPK3
        mov     bx,cx
SPK3:   mov     soend,bx
        pop     bx
        pop     cx
        clc
        ret

SPK4:   push    cx
        push    bx              ; start of packet
        dec     bx              ; point to soh
        mov     sostrt,bx       ; set sub-packet start ptr
        sub     cx,cx
        mov     cl,trans.chklen
        add     cx,offset data
        add     cx,pack.argbk1
        inc     cx
        mov     sofin,cx        ; sofin = end of packet ptr
        jmp     SPK2
SPKOUT  ENDP

PORTCHR PROC
        call    prtchr          ; get char from port
         jmp    short PORCH1    ; got one
         nop
        jmp     short RSKP      ; don't got
PORCH1: and     al,parmsk       ; apply 8/7 bit parity mask
        jz      RSKP            ; filter nulls
        cmp     al,del          ; filter rubouts
        je      RSKP
        ret
PORTCHR ENDP

; Jumping to this location is like retskp.  It assumes the instruction
;   after the call is a jmp addr.

RSKP    PROC
        pop     bp
        add     bp,3
        jmp     bp
RSKP    ENDP

code    ends
        end