]> cloudbase.mooo.com Git - kermit-80.git/blob - cpxpro.asm
Import of "Kermit 80 for CP/M-80 and CP/M-85" from http://www.columbia.edu/kermit...
[kermit-80.git] / cpxpro.asm
1 IF NOT lasm
2 .printx * CPXPRO.ASM *
3 ENDIF ;NOT lasm
4 ; KERMIT - (Celtic for "FREE")
5 ;
6 ; This is the CP/M-80 implementation of the Columbia University
7 ; KERMIT file transfer protocol.
8 ;
9 ; Version 4.0
10 ;
11 ; Copyright June 1981,1982,1983,1984,1985
12 ; Columbia University
13 ;
14 ; Originally written by Bill Catchings of the Columbia University Center for
15 ; Computing Activities, 612 W. 115th St., New York, NY 10025.
16 ;
17 ; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben,
18 ; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many
19 ; others.
20 ;
21 ; revision history:
22 ;
23 ;edit 2, 16-Oct-1990 by MF. Reformatted speed tables according to
24 ; current usage and reworked sysspd routine accordingly.
25 ; Also eliminated cursor-positioning routines as we now link to
26 ; cpxvdu.asm. Reworked version message according to current usage.
27 ;edit 1, 17 November, 1987, by OBSchou. Extracted Compupro code
28 ; from CPMPRO.ASM and massaged fort CP/M kermit V4.09
29 ;
30 ; Modifications to KERMIT-80 for use with Compupro Interfacer 3/4 "[gv]"
31 ;
32 ; Guy Valiquette, M.D.
33 ; Black Bldg. Rm 322
34 ; Dept. of Neurology
35 ; College of Physicians & Surgeons
36 ; Columbia University
37 ; 630 W. 168th Street
38 ; New York, NY 10032
39 ; (212) 694-3965
40 ;
41 ; I/O routines for Interfacer 3/4 board
42 ; Allow sending break with <ESC> B while CONNECTed
43 ; Terminal control sequences for Wyse Technology WY-100
44 ; Add calls to "hangup" subroutine in EXIT and BYE to hang-up phone if
45 ; using a smart modem by disabling UART (and withdrawing DTR signal)
46 ;
47 ;
48 ; Using KERMIT with Compupro Interfacer 3/4:
49 ; - Set compro below to TRUE, all other to FALSE
50 ; - Select the ABSOLUTE USER number you want with the user EQUate
51 ; - Select the terminal control string set needed (or write your
52 ; own if not there)
53 ; - Note that I had to use a kludge to get the signon message right.
54 ; Code in KERMIT as I found it did not, nor could it, work. Search
55 ; for the section of code under: IF compro AND wy100 and imitate.
56 ; - If you have a smart modem, CONNECT puts you in contact with your
57 ; modem. Use your usual "wake-up" character sequence to dial out.
58 ; You can CONNECT and return to KERMIT repeateadly without hanging up
59 ; UNLESS you change the baud rate, execute the BYE command or EXIT.
60 ; - Baud rate set up in code to use 1200 baud as default. Can easily
61 ; be changed to 300 (or whatever). The byte defined at label "baudrt"
62 ; is the mode register 2 used to initialize the UART on first CONNECT.
63 ; The low order nibble of this byte is the baud rate. Refer to the
64 ; Compupro manual to set whatever default baud rate desired by changing
65 ; this low nibble at baudrt db 0011$xxxxb.
66 ;
67 ; Note: "Wrapup" work (outlined below) to clean up code not done since
68 ; new version of KERMIT is due out in a few weeks (says fdc)
69 ;
70 ; WRAPUP:
71 ; - outchri modification done for IF inout ONLY
72 ; - stchr routine implemented for IF inout ONLY
73 ; and used by outchr only
74 ;
75 ;
76 ; Keep module name, edit number, and last revision date in memory.
77 family: db 'CPXPRO.ASM (2) 16-Oct-1990 $'
78 ;
79 ; Assembly time message to let me know I'm building the right version.
80 ; LASM generates an 'S' error along with the message, which is messy, but
81 ; better than trying to put everything inside a IF m80 OR mac80 conditional,
82 ; because LASM doesn't like nested IF's, either.
83
84 IF compro
85 .printx * Assembling Kermit-80 for Compupro Interfacer 4 (or 3) *
86 ENDIF
87
88 iobyte EQU 03H ;Location of I/O byte
89
90 IF compro
91 if4 EQU 10H ;standard base address of Interfacer 4/3 board
92 datap EQU if4+0 ;data port (read/write)
93 stat EQU if4+1 ;status port (read/write)
94 mode EQU if4+2 ;mode registers (read/write)
95 command EQU if4+3 ;command register (read/write)
96 txint EQU if4+4 ;transmit interrupts status/mask (read/write)
97 rxint EQU if4+5 ;receive interrupts status/mask (read/write)
98 ; if4+6 not used
99 usersel EQU if4+7 ;absolute user number select register
100 output EQU 1
101 input EQU 2
102 ; Note: tested with CP/M Ver2.2, and Racal-Vadic Auto Dial VA212 modem
103 ; and USRobotics Password modems. [gv]
104 user EQU 7 ;ABSOLUTE user number on IF4 or IF3
105 ; Also remember to select a terminal!!!
106 ENDIF;compro
107 ;\f
108
109 sysxin: ;system initialisation not covered by sysinit
110 ret ; return from system-dependent routine
111
112 ;
113 ;
114 ; system-dependent termination processing
115 ; If we've changed anything, this is our last chance to put it back.
116 sysexit:
117 ret
118
119 ;
120 ; system-dependent processing for start of CONNECT command
121 ;
122 syscon:
123 ret
124
125 ;
126 ;
127 ; syscls - system-dependent close routine
128 ; called when exiting transparent session.
129 ;
130 syscls:
131 ret
132 ;
133 ;
134 ; sysinh - help for system-dependent special functions.
135 ; called in response to <escape>?, after listing all the
136 ; system-independent escape sequences.
137 ;
138 sysinh:
139 lxi d,inhlps ; we got options...
140 call prtstr ; print them.
141 ret
142 inhlps:
143
144 db cr,lf,'D - drop the line'
145 db cr,lf,'B - send a break'
146 db cr,lf
147 db '$' ;[hh] table terminator
148
149 ;
150 ; sysint - system dependent special functions
151 ; called when transparent escape character has been typed;
152 ; the second character of the sequence is in A (and in B).
153 ; returns:
154 ; non-skip: sequence has been processed
155 ; skip: sequence was not recognized
156 sysint:
157 ani 137O ; convert lower case to upper, for testing...
158
159 cpi 'D' ;Disconnect modem?
160 jnz intc00 ;no
161 hangup: xra a ;get a null byte
162 out command ;disable UART
163 sta ckdialf ;pull down flag to reinitialize UART
164 ret ;most smart modems will hang up on loosing DTR
165 intc00:
166 cpi 'B' ; Send a reak?
167 jz sendbr
168 ret
169
170
171 ;send a break
172 sendbr: mvi a,user ;select our UART
173 di ;quiet
174 out usersel ;select it
175 in command ;get current command byte
176 ori 00001000b ;set "send break" bit
177 out command ;send to UART
178 ei
179
180 ;now for 300 msec timing loop (at 4 MHz, 0 wait state)
181 mvi a,30 ;[obs] call delay for 300 ms
182 call delay
183
184 mvi a,user ;now, go back to UART
185 di ;quiet
186 out usersel
187 in command ;get current command
188 ani 11110111b ;reset "send break" bit
189 ori 00010000b ;and set "reset errors" command bit (in case)
190 out command ;send back to UART
191 ei
192 jmp rskp
193
194
195 ckdial:
196 lda ckdialf ;check flag that forces reinitialization
197 ora a ;test it
198 jz ckdial0 ;must redo it
199 mvi a,user ;user number
200 di
201 out usersel ;select it
202 in command ;get current command register
203 ei
204 ani 00000111b ;mask for normal operating mode
205 ;(DTR on, RX and TX both enabled)
206 cpi 00000111b ;is it?
207 jz rskp ;UART is on, start terminal emulation
208 ; else initialize UART...
209 ckdial0:di
210 mvi a,user ;select user
211 out usersel
212 mvi a,0001$0000b ;reset errors command
213 out command ;send to command register
214 out command
215 out command ;...make sure it got it
216 in command ;confirm
217 lda moderg1 ;get mode register 1
218 out mode ;send it
219 lda moderg2 ;get mode register 2
220 out mode ;send it
221 mvi a,0011$0111b ;command register to start things
222 out command ;send it
223 ei ;turn interrupts back on
224 mvi a,0ffh ;get a non-zero byte
225 sta ckdialf ;pull down flag
226 ;
227 jmp rskp ;start terminal emulation
228
229
230 ; sysflt - system-dependent filter.
231 ; called with the character in E.
232 ; preserves bc, de, hl.
233 ; note: <xon>,<xoff>,<del>, and <nul> are always discarded.
234 sysflt:
235 mov a,e ; get character for testing
236 ret
237
238 ; mdmflt - modem filter [30]
239 ; called with character to be sent to printer in E
240 ; with parity set as appropriate.
241 ; return with accumulator = 0 do do nothing,
242 ; <> 0 to send char in E.
243 mdmflt:
244 mov a,e ;[30] get character to test
245 ret
246
247
248 ; prtflt - printer filter [30]
249 ; called with character to be sent to printer in E
250 ; returns with a = 0 to do nothing
251 ; a <> 0 to print it.
252 ;
253 ; this routine for those printer that automatically insert
254 ; a lf on cr, or cr for lf. Should this be shifted to
255 ; the system indep. stuff, in say 4.06?
256 prtflt:
257 mov a,e ; [30] get character to test
258 ret
259
260
261 ;
262 ;
263 ; system-dependent processing for BYE command.
264 ; for apmmdm, heath, and lobo, hang up the phone.
265 sysbye:
266
267 call hangup
268 ret
269 ;
270 ; This is the system-dependent command to change the baud rate.
271 ; DE contains the two-byte value from the baud rate table; this
272 ; value is also stored in 'speed'.
273 sysspd:
274
275
276 IF compro
277 lda speed ;[MF]Get requested baud-rate
278 mov b,a ;Save the number.
279 lxi h,baudrt ;point to current baud rate
280 mov a,m ;get it
281 ani 0f0h ;keep high nibble
282 ora b ;merge back baud rate
283 mov m,a ;store back
284 xra a ;clear A
285 sta ckdialf ;put up flag to force reinitialization
286 ret ;...at next connect
287
288 ENDIF;compro
289
290
291 ;\f
292
293 ; Speed tables
294 ; (Note that speed tables MUST be in alphabetical order for later
295 ; lookup procedures, and must begin with a value showing the total
296 ; number of entries. The speed help tables are just for us poor
297 ; humans.
298
299 ; db string length,string,divisor (2 identical bytes or 1 word)
300 ; [Toad Hall]
301
302 spdtbl: db 8 ;[MF]8 entries in speed table
303 db 3,'110$'
304 db 02h,02h ;[MF]110 baud
305 db 4,'1200$'
306 db 07h,07h ;[MF]1200 baud
307 db 5,'134.5$'
308 db 03h,03h ;[MF]134.5 baud
309 db 3,'150$'
310 db 04h,04h ;[MF]150 baud
311 db 4,'1800$'
312 db 08h,08h ;[MF]1800 baud
313 db 5,'19200$'
314 db 0fh,0fh ;[MF]19200 baud
315 db 4,'2000$'
316 db 09h,09h ;[MF]2000 baud
317 db 4,'2400$'
318 db 0ah,0ah ;[MF]2400 baud
319 db 3,'300$'
320 db 05h,05h ;[MF]300 baud
321 db 4,'3600$'
322 db 0bh,0bh ;[MF]3600 baud
323 db 4,'4800$'
324 db 0ch,0ch ;[MF]4800 baud
325 db 2,'50$'
326 db 00h,00h ;[MF]50 baud
327 db 3,'600$'
328 db 06h,06h ;[MF]600 baud
329 db 4,'7200$'
330 db 0dh,0dh ;[MF]7200 baud
331 db 2,'75$'
332 db 01h,01h ;[MF]75 baud
333 db 4,'9600$'
334 db 0eh,0eh ;[MF]9600 baud
335
336 sphtbl: db cr,lf,'50 75 110 134 150 300 600 1200'
337 db cr,lf,'1800 2000 2400 3600 4800 7200 9600 19200$'
338
339 ckdialf:db 0 ;force UART initialization on entry
340 baudrt: db 0011$0111b ;default baud rate: 1200 baud
341 moderg1:db 0100$1110b ;default mode register 1:
342 ; -asynch, 8 data bits, 1 stop bit,
343 ; -parity odd, disabled
344 moderg2 EQU baudrt
345 ENDIF;compro
346 ;\f
347
348 ;
349 ; The following conditionals were once a huge if not statement. There
350 ; wasn't enough room to add the lobo to the list, so it had to be broken
351 ; into 2, which you can't do with an if not. I redid it as two ifs and
352 ; applied them to those that wouldn't set baud. [Hal Hostetler]
353 ; This is the system-dependent SET PORT command.
354 ; HL contains the argument from the command table.
355 sysprt:
356 ret
357 ;
358 ;
359 ; Port table not applicable
360 prttbl EQU 0
361 prhtbl EQU 0 ;
362
363 ;
364 ;
365 ; selmdm - select modem port
366 ; selcon - select console port
367 ; selmdm is called before using inpmdm or outmdm;
368 ; selcon is called before using inpcon or outcon.
369 ; For iobyt systems, diddle the I/O byte to select console or comm port;
370 ; For Decision I, switches Multi I/O board to console or modem serial
371 ; port. [Toad Hall]
372 ; For the rest, does nothing.
373 ; preserves bc, de, hl.
374 selmdm:
375 ret
376
377 selcon:
378 ret
379 ;
380 ; Get character from console, or return zero.
381 ; result is returned in A. destroys bc, de, hl.
382 ;
383 inpcon:
384 mvi c,dconio ;Direct console I/O BDOS call.
385 mvi e,0FFH ;Input.
386 call BDOS
387 ret
388 ;
389 ;
390 ; Output character in E to the console.
391 ; destroys bc, de, hl
392 ;
393 outcon:
394 mvi c,dconio ;Console output bdos call.
395 call bdos ;Output the char to the console.
396 ret
397 ;
398 ;
399 ; outmdm - output a char from E to the modem.
400 ; the parity bit has been set as necessary.
401 ; returns nonskip; bc, de, hl preserved.
402 outmdm:
403 ;************************System Dependent****************************
404 ;
405 ; Addition by [gv], 16/7/84
406 ; Return the status of the modem port:
407 ; Z flag set if NO input available
408 ; C flag set in NOT output ready
409 ; Destroys A and flags, preserves all other registers
410 ;
411 stchr:
412 di
413 mvi a,user
414 out usersel
415 in stat
416 ani output
417 in stat
418 ei
419 jz outmdm ;not output ready, try again
420 ; else...
421 di ;no interrupts
422 mvi a,user
423 out usersel
424 mov a,e ;get back character
425 out datap
426 ei
427 ret
428
429 ;\f
430
431 ;
432 ;
433 ; get character from modem; return zero if none available.
434 ; for IOBYT systems, the modem port has already been selected.
435 ; destroys bc, de, hl.
436 inpmdm:
437 ;
438 di
439 mvi a,user
440 out usersel
441 in stat
442 ei
443 ani input ;test for input status (C flag reset by ANI n)
444 rz ; no input available
445 ;
446 ;************************System Dependent****************************
447 ;
448 ; Addition by [gv], 16/7/84
449 ; get a character "raw" (i.e. just get it in A)
450 ;
451 ; Note: MUST have character ready before call, use stchr
452 mvi a,user
453 di
454 out usersel
455 in datap
456 ei
457 ret
458 ;
459 ;\f
460
461 ;
462 ; flsmdm - flush comm line.
463 ; Modem is selected.
464 ; Currently, just gets characters until none are available.
465
466 flsmdm: call inpmdm ; Try to get a character
467 ora a ; Got one?
468 jnz flsmdm ; If so, try for another
469 ret ; Receiver is drained. Return.
470
471
472 ;
473 ;
474 ; lptstat - get the printer status. Return a=0 if ok, or 0ffh if not.
475 lptstat:
476 xra a ; assume it is ok.. this may not be necessary
477 ret
478 ;
479 ;
480 ; outlpt - output character in E to printer
481 ; console is selected.
482 ; preserves de.
483 outlpt:
484 push d ; save DE in either case
485 call prtflt ; go through printer filter [30]
486 ana a ; if A = 0 do nothing,
487 jz outlp1 ; [30] if a=0 do nothing
488 mvi c,lstout
489 call bdos ;Char to printer
490 outlp1: pop d ; restore saved register pair
491
492
493
494 IF inout
495 prtout:
496 ENDIF ;inout
497 IF compro AND inout
498 di
499 mvi a,user
500 out usersel
501 in stat
502 ei
503 ENDIF;compro AND inout
504 IF (NOT compro) AND inout
505 in mnprts ;Get the output ready flag.
506 ENDIF;(NOT compro) AND inout
507 IF inout
508 ani output ;Is it set?
509 jz prtout ;If so, loop until it isn't.
510 ENDIF ;inout
511 IF compro AND inout
512 di
513 mvi a,user
514 out usersel
515 mov a,e
516 out datap
517 ei
518 ENDIF;compro AND inout
519 IF (NOT compro) AND inout
520 mov a,e ;Get the char to output.
521 prtou2: out mnport ;Output it.
522 ENDIF;(NOT compro) AND inout
523 ret
524
525
526 ;\f
527
528 ;
529 ; Screen manipulation routines
530 ;
531 ; delchr - make delete look like a backspace. Unless delete is a printing
532 ; character, we just need to print a backspace. (we'll output clrspc
533 ; afterwards)
534 ; For Kaypro and Vector General, delete puts a blotch on the screen.
535 ; For Apple and Osborne 1, delete moves but doesn't print.
536 delchr:
537 mvi e,bs
538 call outcon
539
540 ; erase the character at the current cursor position
541 clrspc: mvi e,' '
542 call outcon
543 mvi e,bs ;get a backspace
544 jmp outcon
545
546 ; erase the current line
547 clrlin: lxi d,eralin
548 jmp prtstr
549
550 ; erase the whole screen, and go home. preserves b (but not c)
551 clrtop: lxi d,erascr
552 jmp prtstr
553
554
555 IF compro; [gv]
556 sysver: db '[Compupro IF4-',user+'0',']$'
557 ENDIF;compro
558
559 IF lasm
560 LINK CPXVDU.ASM
561 ENDIF ;lasm