home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
archives
/
msr313src.zip
/
msxdm2.asm
< prev
next >
Wrap
Assembly Source File
|
1988-08-16
|
26KB
|
744 lines
name msxdm2
; File MSXDM2.ASM
; Last modification: 20 April 1986
; DECmate II MS DOS Kermit module
; Add global entry point vtstat for use by Status in mssset.
; Also trimmed off trailing commas from publics. Joe R. Doupnik 12 March 1986
; Add global procedures ihosts and ihostr to handle host initialization
; when packets are to be sent or received by us,resp. 24 March 1986
; Add global procedure dtrlow (without worker serhng) to force DTR & RTS low
; in support of Kermit command Hangup. Says Not Yet Implemented. [jrd]
; Add small fixups in procedure coms. [jrd]
; Revise procedure outchr to use dos 2.x file handles rather than "punout"
; which defaults to the Printer! Make proc Clrbuf read from the comms port.
; Add global procedure Dumpscr, called by Ter in file msster, to dump screen
; to a file. Just does a beep for now. 13 April 1986 [jrd]
; In proc Outchr add override of xon from chkxon sending routine.
; This makes a hand typed Xoff supress the xon flow control character sent
; automatically as the receiver buffer empties. 20 April 1986 [jrd]
PAGE 66,120
public serini, serrst, clrbuf, outchr, coms, vts, vtstat, dodel
public ctlu, cmblnk, locate, lclini, prtchr, dobaud, clearl
public dodisk, getbaud, beep
public count, xofsnt, puthlp, putmod, clrmod, poscur
public sendbr, term, machnam, setktab, setkhlp, showkey
public ihosts, ihostr, dtrlow, dumpscr ; [jrd]
include mssdef.h
false equ 0
true equ 1
instat equ 6
rddev equ 3fH
open equ 3dH
; 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 (currently either port1
; or port2)
; 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 public 'datas'
extrn drives:byte,flags:byte, trans:byte
extrn portval:word, port1:byte, port2:byte
extrn comand:byte, dmpname:byte ; [jrd]
machnam db 'DECmate II MS-DOS 2.0$'
erms20 db cr,lf,'?Warning: System has no disk drives$' ; [21a]
erms40 db cr,lf,'?Warning: Unrecognized baud rate$'
erms41 db cr,lf,'?Warning: Cannot open com port$'
erms50 db cr,lf,'Error reading from device$'
hnd1 db cr,lf,'Enter a file handle. Check your DOS manual if you are '
db cr,lf,'not certain what value to supply (generally 3).$'
hnd2 db cr,lf,'Handle: $'
hnderr db cr,lf,'Warning: Handle not known.'
deverr db cr,lf,'Any routine using the communications port will'
db cr,lf,'probably not work.$'
hndhlp db cr,lf,'A four digit file handle $'
dev1 db cr,lf,'Device: $'
devhlp db cr,lf,'Name for your systems auxiliary port $'
badbd db cr,lf,'Unimplemented baud rate$'
noimp db cr,lf,'Command not implemented.$'
hngmsg db cr,lf,' The phone should have hungup.',cr,lf,'$' ; [jrd]
hnghlp db cr,lf,' The modem control lines DTR and RTS for the current'
db ' port are forced low (off)'
db cr,lf,' to hangup the phone. Normally, Kermit leaves them'
db ' high (on) when it exits.'
db cr,lf,'$' ; [jrd]
rdbuf db 80 dup (?) ; temp buf [jrd]
shkmsg db 'Not implemented.'
shklen equ $-shkmsg
setktab db 0
setkhlp db 0
gopos db esc,'['
rowp db 20 dup (?)
crlf db cr,lf,'$'
delstr db BS,' ',BS,'$' ; Delete string. [21d]
clrlin db cr,'$' ; Clear line (just the cr part).
clreol db ESC,'[K$' ; Clear line.
clrseq db esc,'[H',esc,'[J$' ;clear screen home cursor.
telflg db 0 ; non-zero if we're a terminal.
xofsnt db 0 ; Say if we sent an XOFF.
xofrcv db 0 ; Say if we received an XOFF.
count dw 0 ; Number of chars in int buffer.
prthnd dw 0 ; Port handle.
prttab dw com2,com1
com1 db 'COM1',0
com2 db 'COM2',0
tmp db ?,'$'
temp dw 0
temp1 dw ? ; Temporary storage.
temp2 dw ? ; Temporary storage.
;;;[jrd]rdbuf db 20 dup(?) ; Buffer for input.
prtstr db 20 dup(?) ; Name of auxiliary device. [27d]
; Entries for choosing communications port. [19b]
comptab db 6 ; Number of options
mkeyw '1',01H
mkeyw '2',00H
mkeyw 'COM1',01H
mkeyw 'COM2',00H
mkeyw 'DEVICE',02H
mkeyw 'FILE-HANDLE',03H
ourarg termarg <>
datas ends
code segment public 'code'
extrn comnd:near, dopar:near, prserr:near, atoi:near, prompt:near
extrn sleep:near ; [jrd]
assume cs:code,ds:datas
; this is called by Kermit initialization. It checks the
; number of disks on the system, sets the drives variable
; appropriately. Returns normally.
DODISK PROC NEAR
mov ah,gcurdsk ; Current disk value to AL.
int dos
mov dl,al ; Put current disk in DL.
mov ah,seldsk ; Select current disk.
int dos ; Get number of drives in AL.
mov drives,al
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.
; Do nothing since we are not interrupt driven. Returns normally.
CLRBUF PROC NEAR
ret
CLRBUF ENDP
; Clear to the end of the current line. Returns normally.
CLEARL PROC NEAR
push ax ; save regs [jrd]
push dx
mov ah,prstr
mov dx,offset clreol
int dos
pop dx
pop ax
ret
CLEARL 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: mov bp,portval
cmp ds:[bp].floflg,0 ; Are we doing flow control.
je outch2 ; No, just continue.
xor cx,cx ; clear counter
cmp ah,byte ptr [bp].flowc ; sending xoff? [jrd]
jne outch1 ; ne = no
mov xofsnt,false ; supress xon from chkxon buffer routine
outch1: cmp xofrcv,true ; Are we being held?
jne outch2 ; No - it's OK to go on.
loop outch1 ; held, try for a while
mov xofrcv,false ; timed out, force it off and fall thru.
outch2: push dx ; Save register.
mov al,ah ; Parity routine works on AL.
call dopar ; Set parity appropriately.
; Begin revised output routine. [jrd]
cmp prthnd,0 ; Got a handle yet? [27d]
jne outch3 ; Yup just go on. [27d]
call opnprt ; Else 'open' the port. [27d]
outch3: push bx
mov bx,prthnd ; port handle
mov cx,1 ; one byte to write
mov dx,offset temp ; place where data will be found
mov byte ptr temp,al ; put data there
mov ah,write2 ; dos 2 write to file/device
int dos
pop bx ; end of revised routine
;;; mov dl,al
;;; mov ah,punout ; Output char in DL to comm port.
;;; int dos
pop dx
jmp rskp
; This routine blanks the screen. Returns normally.
CMBLNK PROC NEAR
mov ah,prstr
mov dx,offset clrseq ;erase the screen
int dos
ret
CMBLNK ENDP
; Homes the cursor. Returns normally.
LOCATE PROC NEAR
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 near
push dx ; preserve message
mov dx,1800h ; now address line 24
call poscur
pop dx ; get message back
mov ah,prstr
int dos ; write it out
ret ; and return
putmod endp
; clear the mode line written by putmod. Returns normally.
clrmod proc near
mov dx,1800h
call poscur ; Go to bottom row.
call clearl ; Clear to end of line.
ret
clrmod endp
; Put a help message on the screen.
; Pass the message in ax, terminated by a null. Returns normally.
puthlp proc near
push dx ; save regs [jrd]
push si
push ax ; preserve this
mov ah,prstr
mov dx,offset crlf
int dos
pop si ; point to string again
puthl3: lodsb ; get a byte
cmp al,0 ; end of string?
je puthl4 ; yes, stop
mov dl,al
mov ah,dconio
int dos ; else write to screen
jmp puthl3 ; and keep going
puthl4: mov ah,prstr
mov dx,offset crlf
int dos
pop si ; [jrd]
pop dx
ret
puthlp endp
; Set the baud rate for the current port, based on the value
; in the portinfo structure. Returns normally.
DOBAUD PROC NEAR
mov ah,prstr
mov dx,offset noimp ; Say it's not implemented.
int dos
push bx ; [jrd]
mov bx,portval
mov [bx].baud,0FFFFH ; So it's not a recognized value.
pop bx ; [jrd]
ret ; Must be set before starting Kermit.
DOBAUD ENDP
; Get the current baud rate from the serial card and set it
; in the portinfo structure for the current port. Returns normally.
; This is used during initialization.
GETBAUD PROC NEAR
ret ; Can't do this.
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.
; Minor patch by [jrd]
PRTCHR PROC NEAR
push bx
push cx
push si
push bp
cmp prthnd,0 ; Got a handle yet? [27d]
jne prtch0 ; Yup just go on. [27d]
call opnprt ; Else 'open' the port. [27d]
prtch0: call chkxon
mov bx,prthnd
mov al,instat
mov ah,ioctl
int dos
or al,al
jz prtch4 ; not ready...
mov bx,prthnd
mov ah,rddev
mov cx,1
mov dx,offset temp
int dos
jnc prtch1 ; nc = no error. [jrd]
cmp al,5 ; Error condition.
je prt3x
cmp al,6 ; Error condition
je prt3x
prtch1: mov al,byte ptr temp ; [jrd]
mov bp,portval
cmp ds:[bp].parflg,PARNON ; no parity?
je prtch3 ; then don't strip
and al,7fh ; else turn off parity
prtch3: pop bp
pop si
pop cx
pop bx
ret
prt3x: mov ah,prstr
mov dx,offset erms50
int dos
prtch4: pop bp
pop si
pop cx
pop bx
jmp rskp ; no chars...
PRTCHR ENDP
; Local routine to see if we have to transmit an xon
chkxon proc near
push bx
mov bx,portval
cmp [bx].floflg,0 ; doing flow control?
je chkxo1 ; no, skip all this
cmp xofsnt,false ; have we sent an xoff?
je chkxo1 ; no, forget it
mov ax,[bx].flowc ; ah gets xon
call outchr ; send it
nop
nop
nop ; in case it skips
mov xofsnt,false ; remember we've sent the xon.
chkxo1: pop bx ; restore register
ret ; and return
chkxon endp
; IHOSTS - Initialize the host by sending XON, or equivalent, and enter the
; cycle of clear input buffer, wait 1 second, 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 NEAR
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
call outchr ; send it (release Host's output queue)
nop ; outchr can do skip return
nop
nop
ihosts1:call clrbuf ; clear out interrupt buffer
mov ax,1 ; sleep for 1 second
call sleep ; procedure sleep is in msscom.asm
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 NEAR
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
call outchr ; send it (release Host's output queue)
nop ; outchr can do skip return
nop
nop
pop cx
pop bx
pop ax
ret
IHOSTR ENDP
DTRLOW PROC NEAR ; Global proc to Hangup the Phone by making
; DTR and RTS low.
mov ah,cmtxt ; allow text to be able to display help
mov bx,offset rdbuf ; dummy buffer
mov dx,offset hnghlp ; help message
call comnd ; get a confirm
jmp r
; not yet imp. call serhng ; drop DTR and RTS
mov ah,prstr ; give a nice message
; not yet imp. mov dx,offset hngmsg
mov dx,offset noimp ; for now
int dos
jmp rskp
DTRLOW ENDP
; Hang up the Phone. Similar to SERRST except it just forces DTR and RTS low
; to terminate the connection. 29 March 1986 [jrd]
; Calling this twice without intervening calls to serini should be harmless.
; Returns normally.
; SERHNG is Not Yet Implemented.
; Send a break out the current serial port. Returns normally.
SENDBR PROC NEAR
push dx ;save the register to be used
mov ah,03 ;class description 3 comm channel
mov al,0bH ;send break to port
mov dl,1cH ;send a 280 millisend break
int 05fH ;call extended bios to do it
pop dx
ret
SENDBR ENDP
; Position the cursor according to contents of DX:
; DH contains row, DL contains column. Returns normally.
POSCUR PROC NEAR
add dx,101H ;start at column 1,1
push ax ; [jrd]
push bx
push cx
push di
push es
push dx
cld
mov ax,ds
mov es,ax ;address right segment
mov di,offset rowp ;row comes first
mov al,dh
mov ah,0
call nout ;store the characters into di
mov al,';' ;separated with this
stosb
pop dx ;get back column number
mov al,dl
mov ah,0
call nout ;store as ascii data
mov al,'H' ;terminator for dca
stosb
mov byte ptr [di],'$' ;terminate the line
mov ah,prstr ;print string to msdos
mov dx,offset gopos
int dos
pop es ;clean up the stack and exit
pop di ; [jrd]
pop cx
pop bx
pop ax
ret
POSCUR ENDP
; Delete a character from the terminal. This works by printing
; backspaces and spaces. Returns normally.
DODEL PROC NEAR
mov ah,prstr
mov dx,offset delstr ; Erase weird character.
int dos
ret
DODEL ENDP
; Move the cursor to the left margin, then clear to end of line.
; Returns normally.
CTLU PROC NEAR
mov ah,prstr
mov dx,offset clrlin
int dos
call clearl
ret
CTLU ENDP
; Set the current port.
COMS PROC NEAR
mov dx,offset comptab
mov bx,0
mov ah,cmkey
call comnd
jmp r
push bx
mov ah,cmcfm
call comnd ; Get a confirm.
jmp comx ; Didn't get a confirm.
nop
pop bx
cmp bl,2 ; Do they want to set device name? [27d]
je coms2 ; Yes go get name. [27d]
jg coms3 ; Else pick up file handle. [27d]
mov flags.comflg,bl ; Set the comm port flag.
cmp flags.comflg,1 ; Using Com 1?
jne coms0 ; Nope.
mov ax,offset port1
mov portval,ax
ret
coms0: mov ax,offset port2
mov portval,ax
ret
comx: pop bx
ret
coms2: mov dx,offset dev1 ; Let user supply device name.
call prompt
mov ah,cmtxt
mov bx,offset prtstr ; Put name here
mov dx,offset devhlp
call comnd
jmp coms21 ; Did user type ^C.
nop
mov comand.cmstat,cmcfm ;simulate a confirm has been requested. [jrd]
;[jrd] mov al,0 ; Need a null
;[jrd] mov [bx],al ; To terminate string
mov dx,offset prtstr ; Point to string
mov ah,open ; Open port
mov al,2 ; For reading and writing
int dos
jnc coms22 ; Success
coms21: mov ah,prstr
mov dx,offset erms41
int dos
mov dx,offset deverr
int dos
ret
coms22: mov prthnd,ax ; Save handle.
ret
coms3: mov dx,offset hnd2 ; Let user supply file handle.
call prompt
mov ah,cmtxt
mov bx,offset rdbuf ; Where to put input.
mov dx,offset hndhlp ; In case user wants help.
call comnd
jmp coms31 ; No go.
nop
cmp ah,4 ; Right amount of data?
ja coms31 ; Too many chars.
mov si,offset rdbuf
call atoi ; Convert to real number
jmp coms31 ; Keep trying.
nop
mov prthnd,ax ; Value returned in AX
ret
coms31: mov ah,prstr ; Else, issue a warning.
mov dx,offset hnderr
int dos
ret ; Yes, fail.
COMS ENDP
; Set heath emulation on/off.
VTS PROC NEAR
jmp notimp
VTS 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 NEAR ; Dumps screen contents to a file. Just Beeps here
call beep ; [jrd]
ret
DUMPSCR ENDP
notimp: mov ah,prstr
mov dx,offset noimp
int dos
jmp prserr
VTSTAT PROC NEAR ; For Status display [jrd]
ret ; no emulator status to display
VTSTAT ENDP
; Initialize variables to values used by the generic MS DOS version.
lclini: mov flags.vtflg,0 ; Don't to terminal emulation.
mov prthnd,3 ; No handle yet. [27d][28a d.rice]
; call opnprt ; Get file handle for comm port.
ret
; Get a file handle for the communications port. Use DOS call to get the
; next available handle. If it fails, ask user what value to use (there
; should be a predefined handle for the port, generally 3). The open
; will fail if the system uses names other than "COM1" or "COM2".
opnprt: mov al,flags.comflg
mov ah,0
mov si,ax
shl si,1 ; double index
mov dx,prttab[si]
mov ah,open
mov al,2
int dos
jnc opnpr2
mov ah,prstr ; It didn't like the string.
mov dx,offset erms41
int dos
mov dx,offset hnd1
int dos
opnpr0: mov dx,offset hnd2 ; Ask user to supply the handle.
call prompt
mov ah,cmtxt
mov bx,offset rdbuf ; Where to put input.
mov dx,offset hndhlp ; In case user wants help.
call comnd
jmp opnpr3 ; Maybe user typed a ^C.
nop
mov si,offset rdbuf
call atoi ; Convert to real number
jmp opnpr0 ; Keep trying.
nop
mov prthnd,ax ; Value returned in AX
ret
opnpr2: mov prthnd,ax ; Call succeeded.
ret
opnpr3: cmp flags.cxzflg,'C' ; Did user type a ^C?
jne opnpr4 ; No, don't say anything.
mov ah,prstr ; Else, issue a warning.
mov dx,offset hnderr
int dos
opnpr4: ret ; Yes, fail.
showkey:
mov ax,offset shkmsg
mov cx,shklen
ret
; Initialization for using serial port. Returns normally.
SERINI PROC NEAR
cld ; Do increments in string operations
call clrbuf ; Clear input buffer.
ret ; We're done.
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 NEAR
ret ; All done.
SERRST ENDP
; Produce a short beep. The PC DOS bell is long enough to cause a loss
; of data at the port. Returns normally.
BEEP PROC NEAR
mov dl,bell
mov ah,dconio
int dos
ret
BEEP ENDP
;
;put the number in ax into the buffer pointed to by di. di is updated.
;
nout proc near
mov dx,0 ;high order is always zero
mov bx,10
div bx ;divide to get digit
push dx ;save remainder till later
or ax,ax ;test the quotient
jz noutl ;zero, no more number
call nout ;else call for rest of number
noutl: pop ax ;get digit back
add al,'0' ;make it displayable
stosb ;drop it off
ret ;and exit
nout endp
; Dumb terminal emulator. Doesn't work too well above 1200 baud (and
; even at 1200 baud you sometimes lose the first one or two characters
; on a line).
term proc near
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
rep movsb ; copy into our arg blk
term1: call prtchr
jmp short term2 ; have a char...
nop
nop
jmp short term3 ; no char, go on
term2: push ax
and al,7fh ; mask off parity for terminal
mov dl,al
mov ah,conout
int dos ; go print it
pop ax
test ourarg.flgs,capt ; capturing output?
jz term3 ; no, forget it
call ourarg.captr ; else call the routine
term3: mov ah,dconio
mov dl,0ffh
int dos
jz term1 ; no character, go on
cmp al,ourarg.escc ; escape char?
je term4 ; yes, exit
push ax ; save char
mov ah,al
;[jrd] or ah,80H ; turn on hi bit so DOS doesn't interfere
call outchr ; output the character
nop
nop
nop
pop ax
test ourarg.flgs,lclecho ; echoing?
jz term1 ; no, continue loop
mov dl,al
mov ah,dconio
int dos
jmp term1 ; else echo and keep going
term4: ret
term endp
; Jumping to this location is like retskp. It assumes the instruction
; after the call is a jmp addr.
RSKP PROC NEAR
pop bp
add bp,3
push bp
ret
RSKP ENDP
; Jumping here is the same as a ret.
R PROC NEAR
ret
R ENDP
code ends
end