; Kermit system dependent module for Heath/Zenith Z100 public serini, serrst, clrbuf, outchr, coms, vts, dodel, public ctlu, cmblnk, locate, prtchr, dobaud, clearl, public dodisk, getbaud, beep, public count, xofsnt, puthlp, putmod, clrmod, poscur public sendbr, machnam, setktab, setkhlp, lclini, showkey include msdefs.h false equ 0 true equ 1 mntrgh equ bufsiz*3/4 ; High point = 3/4 of buffer full. ; constants used by serial port handler BRKBIT EQU 048H ; Send-break bit. MDMCOM1 EQU 00EFH ; Address of modem port command. [19b] ; 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. ; setktab - keyword table for redefining keys (should contain a 0 if ; not implemented) ; setkhlp - help for setktab. BIOS_SEG SEGMENT AT 40H ; Define segment where BIOS really is ORG 6*3 BIOS_AUXOUT LABEL FAR ; AUX output routine ORG 26*3 BIOS_AUXFUNC LABEL FAR ; AUX: function ORG 27*3 BIOS_CONFUNC LABEL FAR ; CON: function BIOS_SEG ENDS ; Function codes for BIOS_xxxFUNC CHR_WRITE EQU 0 ; Write character CHR_READ EQU 1 ; Read character CHR_STATUS EQU 2 ; Get status CHR_SFGS EQU 0 ; Get status subfunction CHR_SFGC EQU 1 ; Get config subfunction CHR_CONTROL EQU 3 ; Control function CHR_CFSU EQU 0 ; Set new configuration parameters CHR_CFCI EQU 1 ; Clear input buffer datas segment public 'datas' extrn drives:byte, flags:byte, trans:byte extrn portval:word, port1:byte, port2:byte setktab db 13 mkeyw 'F0',96h mkeyw 'F1',97h mkeyw 'F2',98h mkeyw 'F3',99h mkeyw 'F4',9ah mkeyw 'F5',9bh mkeyw 'F6',9ch mkeyw 'F7',9dh mkeyw 'F8',9eh mkeyw 'F9',9fh mkeyw 'F10',0a0h mkeyw 'F11',0a1h mkeyw 'SCAN',-1 setkhlp db cr,lf,'Keyname: f0, ... f11, "HELP" or "SCAN" follwed by ' db 'decimal scan code$' brkval db 0 ; What to send for a break. brkadr dw 0 ; Where to send it. badbd db cr,lf,'Unimplemented baud rate$' noimp db cr,lf,'Not implemented$' machnam db 'Heath-Zenith Z-100$' crlf db cr,lf,'$' delstr db BS,' ',BS,'$' ; Delete string. [21d] home db ESC,'H$' eeolstr db ESC,'K$' ; Erase to end of line clrstr db ESC,'E$' ; Erase entire display enamod db ESC,'x1$' ; Enable 25th line dismod db ESC,'y1$' ; Disable 25th line enascan db ESC,'y?$' ; Enable scan codes disscan db ESC,'x?$' ; Disable scan codes begrev db ESC,'p$' ; Enter reverse video endrev db ESC,'q$' ; Exit reverse video lin25 db ESC,'Y8 $' ; Column 1 row 25 savcur db ESC,'j$' ; Save current cursor position precur db ESC,'k$' ; Restore cursor to previous position clrlin db cr,'$' ; Clear line (just the cr part). xofsnt db 0 ; Say if we sent an XOFF. xofrcv db 0 ; Say if we received an XOFF. tmp db ?,'$' temp1 dw ? ; Temporary storage. ontab db 02H ; Two entries. db 03H,'OFF$' ; Should be alphabetized. [19a] dw 00H db 02H,'ON$' dw 01H ; this table is indexed by the baud rate definitions given in ; pcdefs. Unsupported baud rates should contain FF. bddat label word dw 0 ; 45.5 baud dw 1 ; 50 baud dw 2 ; 75 baud dw 3 ; 110 baud dw 4 ; 134.5 baud dw 5 ; 150 baud dw 6 ; 300 baud dw 7 ; 600 baud dw 8 ; 1200 baud dw 9 ; 1800 baud dw 10 ; 2000 baud dw 11 ; 2400 baud dw 12 ; 4800 baud dw 13 ; 9600 baud dw 14 ; 19200 baud dw 15 ; 38400 baud ; storage for port configuration cfginfo struc cfclass db 0 cfattr db 0 cfport dw 0 cfbaud db 0 cfhshk db 0 cfbctl db 0 cfecnt db 0 cfncnt db 0 cfnchr db 0 cfres db 6 dup(?) cfsize db 0 cfginfo ends auxconf cfginfo <> ; variables for serial interrupt handler count dw 0 ; Number of chars in int buffer. ourarg termarg <> shkbuf db 300 dup (?) ; room for definition shkmsg db ' Scan code: ' shkmln equ $-shkmsg shkms1 db cr,lf,' Definition: ' shkm1ln equ $-shkms1 datas ends code segment public extrn comnd:near, dopar:near, defkey:near assume cs:code,ds:datas ; local initialization lclini proc near mov brkval,BRKBIT ; What to send for a break. mov brkadr,MDMCOM1 mov flags.vtflg,0 ; Turn off true Heath mode (allows key macros) ret lclini endp ; 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 mov drives,al ret DODISK ENDP ; show the definition of a key. The terminal argument block (which contains ; the address and length of the definition tables) is passed in ax. ; Returns a string to print in AX, length of same in CX. ; Returns normally. showkey proc near push es push ax ; save the ptr mov bx,ds mov es,bx ; address data segment cld showk1: mov ah,prstr mov dx,offset enascan ; enable scan codes int dos mov ah,0ch ; char input with buffer flush mov al,7 int dos ; mov ah,chr_control ; mov al,chr_cfci ; clear input ; call bios_confunc ; mov ah,chr_read ; call bios_confunc ; read a char push ax mov ah,prstr mov dx,offset disscan ; disable scan codes int dos pop ax ; push ax ; save the character ; call gss ; get shift state ; pop bx mov ah,0 ; shift state to ah ; mov al,bh ; scan code to al push ax ; remember scan code mov di,offset shkbuf mov si,offset shkmsg mov cx,shkmln rep movsb ; copy in initial message call nout ; write out scan code mov si,offset shkms1 mov cx,shkm1ln ; second message rep movsb pop ax ; get scan code back pop bx ; and terminal arg block mov cx,[bx].klen ; and length jcxz showk2 ; no table, not defined push di ; remember output ptr mov di,[bx].ktab ; get key table repne scasw ; search for a definition for this mov si,di ; remember result ptr pop di ; get output ptr back jne showk2 ; not defined, forget it sub si,[bx].ktab ; compute offset from beginning sub si,2 ; minus 2 for pre-increment add si,[bx].krpl ; get index into replacement table mov si,[si] ; pick up replacement mov cl,[si] ; get length mov ch,0 inc si rep movsb ; copy into buffer showk2: mov ax,offset shkbuf ; this is buffer mov cx,di sub cx,ax ; length pop es ret ; and return showkey 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. ; Returns normally. CLRBUF PROC NEAR cli mov ah,chr_control mov al,chr_cfci call bios_auxfunc mov count,0 sti ret CLRBUF ENDP ; Clear to the end of the current line. Returns normally. CLEARL PROC NEAR mov ah,prstr mov dx,offset eeolstr ; Erase to end of line int dos 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 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. call bios_auxout pop dx jmp rskp ; This routine blanks the screen. Returns normally. CMBLNK PROC NEAR mov ah,prstr mov dx,offset clrstr int dos ret CMBLNK ENDP ; Locate: homes the cursor. Returns normally. LOCATE PROC NEAR mov ah,prstr mov dx,offset home ; Go to top left corner of screen. int dos LOCATE ENDP ; write a line in inverse video 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 ah,prstr mov dx,offset savcur int dos mov dx,offset enamod int dos mov dx,offset lin25 int dos mov dx,offset begrev int dos pop dx ; get message back int dos ; write it out mov dx,offset endrev int dos mov dx,offset precur int dos ret ; and return putmod endp ; clear the mode line written by putmod. Returns normally. clrmod proc near mov ah,prstr mov dx,offset dismod int dos ret clrmod endp BEEP PROC NEAR mov dl,07 ; ASCII BEL mov ah,dconio int dos ; Ring it ret BEEP ENDP ; put a help message on the screen. This one uses reverse video... ; pass the message in ax, terminated by a null. Returns normally. puthlp proc near 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 jmp puthl3 ; and keep going puthl4: mov ah,prstr mov dx,offset crlf int dos 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 bp,portval mov temp1,ax ; Don't overwrite previous rate. [25] mov ax,ds:[bp].baud ; Check if new rate is valid. [25] mov tmp,2 mul tmp ; Get index into baud table. mov bx,offset bddat ; Start of table. add bx,ax mov ax,[bx] ; The data to output to port. cmp ax,0FFH ; Unimplemented baud rate. jne dobd0 mov ax,temp1 ; Get back orginal value. mov ds:[bp].baud,ax ; Leave baud rate as is. mov ah,prstr mov dx,offset badbd ; Give an error message. int dos ret dobd0: push ax ; Save it mov bx,ds ; Set up pointer to config info mov es,bx ; . . . mov bx,offset auxconf ; . . . mov ah,chr_status mov al,chr_sfgc ; get current config info call bios_auxfunc pop ax ; get baud back mov auxconf.cfbaud,al mov ah,chr_control ; Function is control mov al,chr_cfsu ; Subfunction is set new config call bios_auxfunc ; Set the configuration ret 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 mov bx,ds mov es,bx mov bx,offset auxconf mov ah,chr_status mov al,chr_sfgc ; Status function get config info call bios_auxfunc mov ch,0 mov cl,auxconf.cfbaud mov bp,portval mov ds:[bp].baud,cx ret GETBAUD ENDP ; skip returns if no character available at port, ; otherwise returns with char in al, # of chars in buffer in dx. PRTCHR PROC NEAR call chkxon ; see if we need to xon push bx mov ah,chr_status mov al,chr_sfgs ; Status function get status call bios_auxfunc cmp bl,0 jnz prtch2 pop bx jmp rskp ; No data - check console. prtch2: mov dh,0 mov dl,bl ; Place # of chars in dx mov ah,chr_read call bios_auxfunc dec dl ; Decrement number of chars mov count,dx ; Save count for posterity pop bx ret 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 cmp count,mntrgh ; below trigger? jae 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 ; Send a break out the current serial port. Returns normally. SENDBR PROC NEAR push cx push dx push ax xor cx,cx ; Clear loop counter. mov dx,brkadr ; Port address. [19b] in al,dx ; Get current setting. or al,brkval ; Set send-break bit(s). out dx,al ; Start the break. pause: loop pause ; Wait a while. xor al,brkval ; Clear send-break bit(s). out dx,al ; Stop the break. pop ax pop dx pop cx ret ; And return. SENDBR ENDP ; Position the cursor according to contents of DX: ; DH contains row, DL contains column. Returns normally. POSCUR PROC NEAR push dx mov ah,CONOUT mov dl,ESC int dos mov dl,'Y' int dos pop dx push dx mov dl,dh add dl,' ' int dos pop dx add dl,' ' int dos 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 jmp notimp COMS ENDP ; Set heath emulation on/off. VTS PROC NEAR mov dx,offset ontab mov bx,0 mov ah,cmkey call comnd jmp r push bx mov ah,cmcfm call comnd ; Get a confirm. jmp vt0 ; didn't get a confirm. nop pop bx mov flags.vtflg,bl ; Set the Heath emulation flag ret vt0: pop bx ret VTS ENDP notimp: mov ah,prstr mov dx,offset noimp int dos jmp rskp ; initialization for using serial port. This routine performs ; any initialization necessary for using the serial port, including ; setting up interrupt routines, setting buffer pointers, etc. ; Doing this twice in a row should be harmless (this version checks ; a flag and returns if initialization has already been done). ; SERRST below should restore any interrupt vectors that this changes. ; Returns normally. SERINI PROC NEAR 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 ; 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 0. mov bx,10 div bx ; divide to get digit push dx ; save remainder digit or ax,ax ; test quotient jz nout1 ; zero, no more of number call nout ; else call for rest of number nout1: pop ax ; get digit back add al,'0' ; make printable stosb ; drop it off ret ; and return nout 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