home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
KERMIT
/
CP411SRC.ARK
/
cpxsb.asm
< prev
next >
Wrap
Assembly Source File
|
1991-04-23
|
15KB
|
697 lines
IF NOT lasm
.printx * CPXSB.ASM *
ENDIF ;NOT lasm
; KERMIT - (Celtic for "FREE")
;
; This is the CP/M-80 implementation of the Columbia University
; KERMIT file transfer protocol.
;
; Version 4.0
;
; Copyright June 1981,1982,1983,1984,1985
; Columbia University
;
; Originally written by Bill Catchings of the Columbia University Center for
; Computing Activities, 612 W. 115th St., New York, NY 10025.
;
; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben,
; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many
; others.
;
; This file created 16 July, 1987 by OBSchou from code submitted
; by William Rose for the Micromint SB180 systems (as featured in
; BYTE magazine, 1986). This file has been modified to fit in with
; Kermit-80 V4.08 etc. His file KERSYS.ASM is a stripped down version
; of CPXSYS.ASM (formerly CP4SYS.ASM).
;
; revision history:
; KERSYS.ASM - version 0.8 dated 13 Jul 87.
;
; Cutdown CP4SYS.ASM for SB-180/Ampro 230.
;
;
; While this is a single CPU version (to ease editing) the assembler
; conditionals have been kept to identify machine specific code.
;
; Note that the baud setting routine also sets parity, but this does not
; change the parity given by Kermit's 'stat' command. I assume that the
; main body of the program does its own parity check.
;
; Revision history (last entry first)
;
; edit 2, 22 July by OBSchou to massage file to fit with CPXCOM.ASM.
;
; edit 1, 15 July, 1987 by OBSchou for William Rose who submitted
; the code for Kermit-80 V 4.05. Modified code as appropriate
; for 4.08 compatability.
;
delfac EQU 150 ; Delay factor in SB-180 input loop - a fudge
;
; Keep module name, edit number, and last revision date in memory.
;
;sysedt: db 'KERSYS.ASM (03) 12-FEB-87 $' ; last SB-180 revision
;sysedt: db 'KERSYS.ASM (04) 12-APR-87 $' ; Telecom Merlin added
;sysedt: db 'KERSYS.ASM (5) 9-May-87 $' ; Minor tidying
;sysedt: db 'KERSYS.ASM (6A) 17-Jun-87 $' ; BT Merlin M2215 only
;sysedt: db 'KERSYS.ASM (7) 19-Jun-87 $' ; SB-180 only
;sysedt: db 'KERSYS.ASM (8) 13-Jul-87 $' ; 6/9 MHz version
family: db 'CPXSB.ASM (2) 22-Jul-87$' ; First entry for V4.08/9
;
; Assembly time message to let me know I'm building the right version.
;
IF sb180
.printx * Assembling Kermit-80 for Micromint SB-180 *
ENDIF
IF sb180
mnctrla EQU 000H ;Modem control port - CNTLA0
mnctrlb EQU 002H ;Modem control port - CNTLB0
mnstat EQU 004H ;Modem status port - STAT0
mntxdat EQU 006H ;Modem output port - TDR0
mnrddat EQU 008H ;Modem input port - RDR0
output EQU 002H ;Transmit data register empty mask - TDRE
input EQU 080H ;Receive data register full mask - RDRF
z80 EQU TRUE ;This one's an HD64180, but Z80 will do
ENDIF
sysxin: ; continuation of system initialisation from sysinit
IF sb180
lxi h, porbuf ; park the original settings
db 0EDh, 038h, mnctrla ; HD64180 code IN0 g,(m)
mov m, a
inx h
db 0EDh, 038h, mnctrlb
mov m, a
inx h
db 0EDh, 038h, mnstat
mov m, a
ENDIF
; re-initialise for KERMIT
IF sb6
mvi h, 08h ; 0000$1001 - 9600 baud, (even) parity
mvi l, 08h ; 'speed' is two bytes
ENDIF
IF sb9
mvi h, 21h ; 0010$0001 - 9600 baud, (even) parity
mvi l, 21h ; 'speed' is two bytes
ENDIF
IF sb180
shld speed
lxi h, parind
mvi m, 8 ; index for 8 bits, no parity, 2 stop
call setpor
ENDIF
ret
porbuf: ds 3 ; original port settings
;
; system-dependent KERMIT termination processing
; If we've changed anything, this is our last chance to put it back.
;
sysexit:
IF sb180
lxi h, porbuf
mov a, m ; output parity
db 0EDh, 039h, mnctrla ; HD64180 code OUT0 (m),g
inx h
mov a, m ; output baud rate
db 0EDh, 039h, mnctrlb
inx h
mov a, m ; output to clear error flags
db 0EDh, 039h, mnstat
; read twice to reset DCD0 ?
db 0EDh, 038h, mnstat
db 0EDh, 038h, mnstat
ENDIF
ret
;
; system-dependent processing for start of CONNECT command
;
syscon:
ret
conmsg: ; Messages printed when entering transparent (CONNECT) mode:
db '$'
;
; syscls - system-dependent close routine
; called when exiting transparent session.
;
syscls:
ret
;
; sysinh - help for system-dependent special functions.
; called in response to <escape>?, after listing all the
; system-independent escape sequences.
;
sysinh:
IF sb180
lxi d, inhlps
call prtstr
ENDIF
ret
; Additional, system-dependent help for transparent mode
; (two-character escape sequences)
inhlps:
IF sb180
db cr, lf, 'V Cycle port parameters'
ENDIF
db '$' ; string terminator
;
; sysint - system dependent special functions
; called when transparent escape character has been typed;
; the second character of the sequence is in A (and in B).
; returns:
; non-skip: sequence has been processed
; skip: seqence was not recognized
;
sysint:
; ani 137O ; convert lower case to upper, for testing...
; does this work?
IF sb180
cpi 'V' ; cycle port ?
jz pcycl
cpi 'v'
jz pcycl
ENDIF
jmp rskp ; take skip return - command not recognised
; Actual commands
IF sb180
pcycl:
lxi h, parind ; increment parval, modulo 12
mov a, m
adi 1
cpi 13
jnz pcy1
mvi a, 1
pcy1: mov m, a ; update the storage
; get index of name in parstr
ora a ; clear flags
dcr a
rlc
rlc
mov c, a
mvi b, 0
lxi h, parstr
inx h
dad b
push h
lxi d, cgmsg1
call prtstr
pop d
call prtstr
lxi d, cgmsg2
call prtstr
call setpor ; reset the port
ret
cgmsg1: db '<$'
cgmsg2: db '>$'
ENDIF
ret
;
; Delay routine. Called with time (hundredths of seconds) in A.
; The inner loop delays 1001 T-states, assuming no wait states are
; inserted; this is repeated CPUSPD times, for a total delay of just
; over 0.01 second. (CPUSPD should be set to the system clock rate,
; in units of 100KHz: for an unmodified Kaypro II, that's 25 for
; 2.5 MHz. Some enterprising soul could determine whether or not the
; Kaypro actually inserts a wait state on instruction fetch (a common
; practice); if so, the magic number at delay2 needs to be decreased.
; (We also neglect to consider time spent at interrupt level).
;
; called by: sendbr
; destroys BC
;
;delay: mvi c,cpuspd ; Number of times to wait 1000 T-states to
; ; make .01 second delay
;delay2: mvi b,70 ; Number of times to execute inner loop to
; ; make 1000 T-state delay
;delay3: dcr b ; 4 T-states (* 70 * cpuspd)
; jnz delay3 ; 10 T-states (* 70 * cpuspd)
; dcr c ; 4 T-states (* cpuspd)
; jnz delay2 ; 10 T-states (* cpuspd)
; ; total delay: ((14 * 70) + 14) * cpuspd
; ; = 1001 * cpuspd
; dcr a ; 4 T-states
; jnz delay ; 10 T-states
;
; ret ; grand total: ((1001 * cpuspd) + 14) * a
;
; sysflt - system-dependent filter
; called with character in E.
; if this character should not be printed, return with A = zero.
; preserves bc, de, hl.
; note: <xon>,<xoff>,<del>, and <nul> are always discarded.
;
sysflt:
mov a,e ; get character for testing
ret
;
; mdmflt - modem filter
; called with character to be sent to printer in E
; with parity set as appropriate.
; return with accumulator = 0 do do nothing,
; <> 0 to send char in E.
mdmflt:
mov a,e ; get character to test
ret
;
; prtflt - printer filter
; called with character to be sent to printer in E
; returns with a = 0 to do nothing
; a <> 0 to print it.
;
; this routine for those printer that automatically insert
; a lf on cr, or cr for lf. Should this be shifted to
; the system indep. stuff, in say 4.06?
;
prtflt:
mov a,e ; get character to test
IF FALSE ; strip out lf from printer stream
ani 7fh ; make sure it is parity less
cpi lf ; is it a line feed?
rnz ; no, print it
; xra a ; yes, don't.
ENDIF
ret
;
; system-dependent processing for BYE command.
;
sysbye:
ret
;
; This is the system-dependent command to change the baud rate.
; DE contains the two-byte value from the baud rate table; both
; bytes of this value are also stored in 'speed'.
;
sysspd:
IF sb180
lxi d, prtmsg ; ask for variables
call prtstr
lxi d, tbuf ; get suitable string
mvi c, 10
call bdos
lxi h, tbuf1
mov a, m
ora a
jz setpor ; leave unchanged if string zero length
cpi 3 ; check given length
jnz spd1 ; error - wrong length
inx h
inx h
mov a, m
ani 137O ; convert parity code to upper case
mov m, a
lxi d, tbuf1 ; get index of given parameter
lxi h, parstr
call sposn
ora a
jnz spd2 ; or fall through if error
spd1: lxi d, invmsg ; invalid input - try again
call prtstr
jmp sysspd
spd2: adi 3 ; get index to parval table
rrc ; by dividing by 4
rrc
ani 15 ; mask out high bits
lxi h, parind
mov m, a ; and store it
call setpor ; set up port iaw index and speed bytes
ret
prtmsg: db cr,lf,'Enter bit/char, parity, and stop bits required.'
db cr,lf,'(Bit 7/8 Parity N/O/E Stop 1/2 - CR same) : $'
invmsg: db cr,lf,'Invalid parameters$'
parind: db 8 ; default <8N2> index
parstr: db 48,'7N1$7N2$7O1$7O2$7E1$7E2$'
db '8N1$8N2$8O1$8O2$8E1$8E2$'
parval: db 0,1,16+2,16+3,2,3
db 4,5,16+6,16+7,6,7
tbuf db 6
tbuf1 db 3,'8N2','$$$$'
;
; Set up the port using the table index in parind and the speed byte
;
setpor:
lxi h, parind
mov a, m
dcr a
lxi h, parval ; table base
mvi b, 0
mov c, a
dad b ; HL points at parameter value
mov a, m
mov b, a ; park parval
ani 16 ; the parity switch bit
lxi h, speed
add m ; this is now the baud rate byte
mov c, a ; park it
mov a, b ; sort out the parameter byte
ani 7 ; b/p/s only wanted
adi 96 ; RE, TE enable
db 0EDh,039h,mnctrla ; output parity etc.
mov a, c
db 0EDh,039h,mnctrlb ; output baud rate
mvi a, 0
db 0EDh,039h,mnstat ; clear status
db 0EDh,038h,mnstat ; read twice to reset DCD0
db 0EDh,038h,mnstat
ret
;
; Find substring position - Leventhal page 293, modified
; enter with subtring in DE and string in HL
; returns index in A or 0 for failure
;
sposn:
mov a, m ; exit if either string length zero
ora a
jz notfnd
sta slen
mov b, a
inx h
shld string
xchg
mov a, m
ora a
jz notfnd
sta sublen
mov c, a
inx h
shld substg
mov a, b
; no of searches = stringlen - substrlen + 1
; if substr longer than string quit immediately
sub c
jc notfnd
inr a
mov c, a
xra a
sta index
; search until remaining string shorter than substring
slp1: lxi h, index
inr m
lda sublen
mov b, a
lhld substg
xchg
lhld string
; try to match substring starting at index
cmplp: ldax d
cmp m
jnz slp2
dcr b
jz found
inx h
inx d
jmp cmplp
; arrive here if match fails
slp2: dcr c
jz notfnd
lhld string
inx h
shld string
jmp slp1
; found, return index
found: lda index
ret
; not found, return zero
notfnd: sub a
ret
string: ds 2
substg: ds 2
slen: ds 1
sublen: ds 1
index: ds 1
ENDIF
ret
;
; Speed tables
; (Note that speed tables MUST be in alphabetical order for later
; lookup procedures, and must begin with a value showing the total
; number of entries. The speed help tables are just for us poor
; humans.
;
; db string length, string, divisor (2 bytes or 1 word, ab)
; the data byte a is return in A and E, and b in D
; only byte 'a' is the key for the table
IF sb6
spdtbl: db 9 ; 9 entries
db 04h,'1200$', 0Bh,0Bh
db 03h,'150$', 0Eh,0Eh
db 05h,'19200$', 01h,01h
db 04h,'2400$', 0Ah,0Ah
db 03h,'300$', 0Dh,0Dh
db 05h,'38400$', 00h,00h
db 04h,'4800$', 09h,09h
db 03h,'600$', 0Ch,0Ch
db 04h,'9600$', 08h,08h
sphtbl: db cr,lf
db ' 150 300 600 1200 2400 4800 9600 19200 38400$'
ENDIF
IF sb9
spdtbl: db 7 ; 7 entries
db 04h,'1200$', 24h,24h
db 05h,'19200$', 20h,20h
db 04h,'2400$', 23h,23h
db 03h,'300$', 26h,26h
db 04h,'4800$', 22h,22h
db 03h,'600$', 25h,25h
db 04h,'9600$', 21h,21h
sphtbl: db cr,lf
db ' 300 600 1200 2400 4800 9600 19200$'
ENDIF
;
; This is the system-dependent SET PORT command.
; HL contains the argument from the command table.
;
sysprt:
ret
IF sb180
prttbl EQU 0 ; SET PORT is not supported
prhtbl EQU 0
ENDIF
;
; selmdm - select modem port
; selcon - select console port
; selmdm is called before using inpmdm or outmdm;
; selcon is called before using inpcon or outcon.
; For iobyt systems, diddle the I/O byte to select console or comm port;
; For the rest, does nothing.
; preserves bc, de, hl.
;
selmdm:
ret
selcon:
ret
;
; Get character from console, or return zero.
; result is returned in A. destroys bc, de, hl.
;
inpcon:
mvi c,dconio ;Direct console I/O BDOS call.
mvi e,0FFH ;Input.
call BDOS
ret
;
; Output character in E to the console.
; destroys bc, de, hl
;
outcon:
mvi c,dconio ;Console output bdos call.
call bdos ;Output the char to the console.
ret
;
; outmdm - output a char from E to the modem.
; the parity bit has been set as necessary.
; returns nonskip; bc, de, hl preserved.
;
outmdm:
IF sb180
db 0EDh,038h,mnstat
ani output ; check status
jz outmdm ; wait until port is available
mov a, e
db 0EDh,039h,mntxdat ; transmit
ENDIF
ret
;
; get character from modem; return zero if none available.
; for IOBYT systems, the modem port has already been selected.
; destroys bc, de, hl.
;
inpmdm:
IF sb180
lxi h, delfac ; loops to give delay
inpm1: db 0EDh,038h,mnstat
ani input ; check status
jz inpm2
db 0EDh,038h,mnrddat ; get a byte
ret
inpm2: dcx h ; no data
mov h, a
ora l
jnz inpm1 ; still tries left
ret ; with zero in A
ENDIF
ret
;
; flsmdm - flush comm line.
; Modem is selected.
; Currently, just gets characters until none are available.
;
flsmdm:
call inpmdm ; Try to get a character
ora a ; Got one?
jnz flsmdm ; If so, try for another
ret ; Receiver is drained. Return.
;
;
; lptstat - get the printer status. Return a=0 if ok, or 0ffh if not.
lptstat:
IF iobyte ;[33]
call bprtst ; get status
ENDIF ;iobyte[33]
IF NOT iobyte ;[33]
xra a ; assume it is ok.. this may not be necessary
ENDIF ;iobyte [33]
ret
;
; outlpt - output character in E to printer
; console is selected.
; preserves de.
;
outlpt:
push d ; save DE in either case
call prtflt ; go through printer filter [30]
ana a ; if A = 0 do nothing,
jz outlp1 ; if a=0 do nothing
outlp1: pop d ; restore saved register pair
ret
; delchr - make delete look like a backspace. Unless delete is a printing
; character, we just need to print a backspace. (we'll output clrspc
; afterwards)
delchr:
mvi e,bs ;get a backspace
jmp outcon
; erase the character at the current cursor position
clrspc: mvi e,' '
call outcon
mvi e,bs ;get a backspace
jmp outcon
; erase the current line
clrlin: lxi d,eralin
jmp prtstr
; erase the whole screen, and go home. preserves b (but not c)
clrtop: lxi d,erascr
jmp prtstr
IF sb180
sysver: db 'MicroMint SB 180 '
ENDIF
IF sb6
db ' (6 MHz)'
ENDIF
IF sb9
db ' (9 MHz)'
ENDIF
db '$'
IF lasm
LINK CPXVDU.ASM ; get terminal defs etc
ENDIF ;lasm