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