From ebb2ff2af569d5822b70ee555a32d27cf7494816 Mon Sep 17 00:00:00 2001 From: Jeff Armstrong Date: Sun, 25 Oct 2026 17:42:06 -0400 Subject: Initial import of 4.11 --- src/cpxpro.asm | 561 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 561 insertions(+) create mode 100644 src/cpxpro.asm (limited to 'src/cpxpro.asm') diff --git a/src/cpxpro.asm b/src/cpxpro.asm new file mode 100644 index 0000000..9099b04 --- /dev/null +++ b/src/cpxpro.asm @@ -0,0 +1,561 @@ +IF NOT lasm +.printx * CPXPRO.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. +; +; revision history: +; +;edit 2, 16-Oct-1990 by MF. Reformatted speed tables according to +; current usage and reworked sysspd routine accordingly. +; Also eliminated cursor-positioning routines as we now link to +; cpxvdu.asm. Reworked version message according to current usage. +;edit 1, 17 November, 1987, by OBSchou. Extracted Compupro code +; from CPMPRO.ASM and massaged fort CP/M kermit V4.09 +; +; Modifications to KERMIT-80 for use with Compupro Interfacer 3/4 "[gv]" +; +; Guy Valiquette, M.D. +; Black Bldg. Rm 322 +; Dept. of Neurology +; College of Physicians & Surgeons +; Columbia University +; 630 W. 168th Street +; New York, NY 10032 +; (212) 694-3965 +; +; I/O routines for Interfacer 3/4 board +; Allow sending break with B while CONNECTed +; Terminal control sequences for Wyse Technology WY-100 +; Add calls to "hangup" subroutine in EXIT and BYE to hang-up phone if +; using a smart modem by disabling UART (and withdrawing DTR signal) +; +; +; Using KERMIT with Compupro Interfacer 3/4: +; - Set compro below to TRUE, all other to FALSE +; - Select the ABSOLUTE USER number you want with the user EQUate +; - Select the terminal control string set needed (or write your +; own if not there) +; - Note that I had to use a kludge to get the signon message right. +; Code in KERMIT as I found it did not, nor could it, work. Search +; for the section of code under: IF compro AND wy100 and imitate. +; - If you have a smart modem, CONNECT puts you in contact with your +; modem. Use your usual "wake-up" character sequence to dial out. +; You can CONNECT and return to KERMIT repeateadly without hanging up +; UNLESS you change the baud rate, execute the BYE command or EXIT. +; - Baud rate set up in code to use 1200 baud as default. Can easily +; be changed to 300 (or whatever). The byte defined at label "baudrt" +; is the mode register 2 used to initialize the UART on first CONNECT. +; The low order nibble of this byte is the baud rate. Refer to the +; Compupro manual to set whatever default baud rate desired by changing +; this low nibble at baudrt db 0011$xxxxb. +; +; Note: "Wrapup" work (outlined below) to clean up code not done since +; new version of KERMIT is due out in a few weeks (says fdc) +; +; WRAPUP: +; - outchri modification done for IF inout ONLY +; - stchr routine implemented for IF inout ONLY +; and used by outchr only +; +; +; Keep module name, edit number, and last revision date in memory. +family: db 'CPXPRO.ASM (2) 16-Oct-1990 $' +; +; Assembly time message to let me know I'm building the right version. +; LASM generates an 'S' error along with the message, which is messy, but +; better than trying to put everything inside a IF m80 OR mac80 conditional, +; because LASM doesn't like nested IF's, either. + +IF compro +.printx * Assembling Kermit-80 for Compupro Interfacer 4 (or 3) * +ENDIF + +iobyte EQU 03H ;Location of I/O byte + +IF compro +if4 EQU 10H ;standard base address of Interfacer 4/3 board +datap EQU if4+0 ;data port (read/write) +stat EQU if4+1 ;status port (read/write) +mode EQU if4+2 ;mode registers (read/write) +command EQU if4+3 ;command register (read/write) +txint EQU if4+4 ;transmit interrupts status/mask (read/write) +rxint EQU if4+5 ;receive interrupts status/mask (read/write) +; if4+6 not used +usersel EQU if4+7 ;absolute user number select register +output EQU 1 +input EQU 2 +; Note: tested with CP/M Ver2.2, and Racal-Vadic Auto Dial VA212 modem +; and USRobotics Password modems. [gv] +user EQU 7 ;ABSOLUTE user number on IF4 or IF3 +; Also remember to select a terminal!!! +ENDIF;compro +; + +sysxin: ;system initialisation not covered by sysinit + ret ; return from system-dependent routine + +; +; +; system-dependent termination processing +; If we've changed anything, this is our last chance to put it back. +sysexit: + ret + +; +; system-dependent processing for start of CONNECT command +; +syscon: + ret + +; +; +; syscls - system-dependent close routine +; called when exiting transparent session. +; +syscls: + ret +; +; +; sysinh - help for system-dependent special functions. +; called in response to ?, after listing all the +; system-independent escape sequences. +; +sysinh: + lxi d,inhlps ; we got options... + call prtstr ; print them. + ret +inhlps: + + db cr,lf,'D - drop the line' + db cr,lf,'B - send a break' + db cr,lf + db '$' ;[hh] table 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: sequence was not recognized +sysint: + ani 137O ; convert lower case to upper, for testing... + + cpi 'D' ;Disconnect modem? + jnz intc00 ;no +hangup: xra a ;get a null byte + out command ;disable UART + sta ckdialf ;pull down flag to reinitialize UART + ret ;most smart modems will hang up on loosing DTR +intc00: + cpi 'B' ; Send a reak? + jz sendbr + ret + + +;send a break +sendbr: mvi a,user ;select our UART + di ;quiet + out usersel ;select it + in command ;get current command byte + ori 00001000b ;set "send break" bit + out command ;send to UART + ei + + ;now for 300 msec timing loop (at 4 MHz, 0 wait state) + mvi a,30 ;[obs] call delay for 300 ms + call delay + + mvi a,user ;now, go back to UART + di ;quiet + out usersel + in command ;get current command + ani 11110111b ;reset "send break" bit + ori 00010000b ;and set "reset errors" command bit (in case) + out command ;send back to UART + ei + jmp rskp + + +ckdial: + lda ckdialf ;check flag that forces reinitialization + ora a ;test it + jz ckdial0 ;must redo it + mvi a,user ;user number + di + out usersel ;select it + in command ;get current command register + ei + ani 00000111b ;mask for normal operating mode + ;(DTR on, RX and TX both enabled) + cpi 00000111b ;is it? + jz rskp ;UART is on, start terminal emulation +; else initialize UART... +ckdial0:di + mvi a,user ;select user + out usersel + mvi a,0001$0000b ;reset errors command + out command ;send to command register + out command + out command ;...make sure it got it + in command ;confirm + lda moderg1 ;get mode register 1 + out mode ;send it + lda moderg2 ;get mode register 2 + out mode ;send it + mvi a,0011$0111b ;command register to start things + out command ;send it + ei ;turn interrupts back on + mvi a,0ffh ;get a non-zero byte + sta ckdialf ;pull down flag +; + jmp rskp ;start terminal emulation + + +; sysflt - system-dependent filter. +; called with the character in E. +; preserves bc, de, hl. +; note: ,,, and are always discarded. +sysflt: + mov a,e ; get character for testing + ret + +; mdmflt - modem filter [30] +; 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 ;[30] get character to test + ret + + +; prtflt - printer filter [30] +; 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 ; [30] get character to test + ret + + +; +; +; system-dependent processing for BYE command. +; for apmmdm, heath, and lobo, hang up the phone. +sysbye: + + call hangup + ret +; +; This is the system-dependent command to change the baud rate. +; DE contains the two-byte value from the baud rate table; this +; value is also stored in 'speed'. +sysspd: + + +IF compro + lda speed ;[MF]Get requested baud-rate + mov b,a ;Save the number. + lxi h,baudrt ;point to current baud rate + mov a,m ;get it + ani 0f0h ;keep high nibble + ora b ;merge back baud rate + mov m,a ;store back + xra a ;clear A + sta ckdialf ;put up flag to force reinitialization + ret ;...at next connect + +ENDIF;compro + + +; + +; 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 identical bytes or 1 word) +; [Toad Hall] + +spdtbl: db 8 ;[MF]8 entries in speed table + db 3,'110$' + db 02h,02h ;[MF]110 baud + db 4,'1200$' + db 07h,07h ;[MF]1200 baud + db 5,'134.5$' + db 03h,03h ;[MF]134.5 baud + db 3,'150$' + db 04h,04h ;[MF]150 baud + db 4,'1800$' + db 08h,08h ;[MF]1800 baud + db 5,'19200$' + db 0fh,0fh ;[MF]19200 baud + db 4,'2000$' + db 09h,09h ;[MF]2000 baud + db 4,'2400$' + db 0ah,0ah ;[MF]2400 baud + db 3,'300$' + db 05h,05h ;[MF]300 baud + db 4,'3600$' + db 0bh,0bh ;[MF]3600 baud + db 4,'4800$' + db 0ch,0ch ;[MF]4800 baud + db 2,'50$' + db 00h,00h ;[MF]50 baud + db 3,'600$' + db 06h,06h ;[MF]600 baud + db 4,'7200$' + db 0dh,0dh ;[MF]7200 baud + db 2,'75$' + db 01h,01h ;[MF]75 baud + db 4,'9600$' + db 0eh,0eh ;[MF]9600 baud + +sphtbl: db cr,lf,'50 75 110 134 150 300 600 1200' + db cr,lf,'1800 2000 2400 3600 4800 7200 9600 19200$' + +ckdialf:db 0 ;force UART initialization on entry +baudrt: db 0011$0111b ;default baud rate: 1200 baud +moderg1:db 0100$1110b ;default mode register 1: + ; -asynch, 8 data bits, 1 stop bit, + ; -parity odd, disabled +moderg2 EQU baudrt +ENDIF;compro +; + +; +; The following conditionals were once a huge if not statement. There +; wasn't enough room to add the lobo to the list, so it had to be broken +; into 2, which you can't do with an if not. I redid it as two ifs and +; applied them to those that wouldn't set baud. [Hal Hostetler] +; This is the system-dependent SET PORT command. +; HL contains the argument from the command table. +sysprt: + ret +; +; +; Port table not applicable +prttbl EQU 0 +prhtbl EQU 0 ; + +; +; +; 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 Decision I, switches Multi I/O board to console or modem serial +; port. [Toad Hall] +; 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: +;************************System Dependent**************************** +; +; Addition by [gv], 16/7/84 +; Return the status of the modem port: +; Z flag set if NO input available +; C flag set in NOT output ready +; Destroys A and flags, preserves all other registers +; +stchr: + di + mvi a,user + out usersel + in stat + ani output + in stat + ei + jz outmdm ;not output ready, try again +; else... + di ;no interrupts + mvi a,user + out usersel + mov a,e ;get back character + out datap + ei + 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: +; + di + mvi a,user + out usersel + in stat + ei + ani input ;test for input status (C flag reset by ANI n) + rz ; no input available +; +;************************System Dependent**************************** +; +; Addition by [gv], 16/7/84 +; get a character "raw" (i.e. just get it in A) +; +; Note: MUST have character ready before call, use stchr + mvi a,user + di + out usersel + in datap + ei + 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: + xra a ; assume it is ok.. this may not be necessary + 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 ; [30] if a=0 do nothing + mvi c,lstout + call bdos ;Char to printer +outlp1: pop d ; restore saved register pair + + + +IF inout +prtout: +ENDIF ;inout +IF compro AND inout + di + mvi a,user + out usersel + in stat + ei +ENDIF;compro AND inout +IF (NOT compro) AND inout + in mnprts ;Get the output ready flag. +ENDIF;(NOT compro) AND inout +IF inout + ani output ;Is it set? + jz prtout ;If so, loop until it isn't. +ENDIF ;inout +IF compro AND inout + di + mvi a,user + out usersel + mov a,e + out datap + ei +ENDIF;compro AND inout +IF (NOT compro) AND inout + mov a,e ;Get the char to output. +prtou2: out mnport ;Output it. +ENDIF;(NOT compro) AND inout + ret + + +; + +; +; Screen manipulation routines +; +; 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) +; For Kaypro and Vector General, delete puts a blotch on the screen. +; For Apple and Osborne 1, delete moves but doesn't print. +delchr: + mvi e,bs + call 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 compro; [gv] +sysver: db '[Compupro IF4-',user+'0',']$' +ENDIF;compro + +IF lasm +LINK CPXVDU.ASM +ENDIF ;lasm -- cgit v1.2.3