; Kermit system dependent module for ACT Apricot public serini, serrst, clrbuf, outchr, coms, vts, dodel, public ctlu, cmblnk, locate, lclini, prtchr, dobaud, clearl, public dodisk, getbaud, beep public count, xofsnt, puthlp, putmod, clrmod, poscur public sendbr, term, machnam, setktab, setkhlp, showkey include msdefs.h false equ 0 true equ 1 instat equ 6 rddev equ 3FH open equ 3DH control equ 0FCH ; System Control Device ; 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. datas segment public 'datas' extrn drives:byte,flags:byte, trans:byte extrn portval:word, port1:byte, port2:byte machnam db 'ACT Apricot$' erms20 db cr,lf,'?Warning: System has no disk drives$' erms40 db cr,lf,'?Warning: Unrecognized baud rate$' erms41 db cr,lf,'?Warning: Cannot open com port$' erms50 db cr,lf,'Error reading from device$' badbd db cr,lf,'Unimplemented baud rate$' noimp db cr,lf,'Command not implemented.$' shkmsg db 'Not implemented.' shklen equ $-shkmsg setktab db 0 setkhlp db 0 crlf db cr,lf,'$' delstr db BS,' ',BS,'$' ; Delete string. clrlin db cr,esc,'K$' ; Clear line. clreol db esc,'K$' ; Clear line. clrscr db esc,'H',esc,'J$' ; Home and clear screen. ; Use high/low intensity rather than inverse video. ; It is kinder on the eyes.... invseq db esc,'($' ; High intensity mode. nrmseq db esc,')$' ; Low intensity mode. telflg db 0 ; non-zero if we're a terminal. xofsnt db 0 ; Say if we sent an XOFF. count dw 0 ; Number of chars in int buffer. tmp db ?,'$' temp dw 0 temp1 dw ? ; Temporary storage. temp2 dw ? ; Temporary storage. ; This table is indexed by the baud rate definitions given in msdefs.h. ; Unsupported baud rates should contain FF. bddat label word dw -1 ; 45.5 Unsupported dw 1 ; 50 dw 2 ; 75 dw 3 ; dw 4 ; 134.5 dw 5 ; 150 dw 6 ; 300 dw600 dw 8 ; 1200 dw 9 ; 1800 dw -1 ; 2000 ted dw 10 ; 2400 dw 12 ; 4800 (Have to skip 3600) dw 14 ; 9600 (Have to skip 7200) dw 15 ; 19200 dw -1 Unsupported ourarg termarg <> datas ends code segment public extrn comnd:near, dopar:near, prserr:near, atoi:near, prompt:near assume cs:code,ds:datas ; 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 ; Get number of drives in AL. mov drives,al ret DODISK 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 mov bx,34H ; Serial Device Driver mov cx,2 ; Read serial port clrbf1: int control ; call System Control Device cmp ax,-1 ; Read anything ? jne clrbf1 ; Yes, try again ret CLRBUF ENDP ; Clear to the end of the current line. Returns normally. CLEARL PROC NEAR mov dx,offset clreol jmp tmsg ; Send terminal message CLEARL ENDP ; Put the char in AH to the serial port. This assumes the ; port has been initialized. XON/XOFF are handled by the port ; driver. Skip returns on success, returns normally if the ; character cannot be written. OUTCHR: push bx push cx push dx ; Save register. sub cx,cx mov al,ah ; Parity routine works on AL. call dopar ; Set parity appropriately. mov dl,al mov dh,0 mov cx,1 ; Transmit char mov bx,34H ; Serial Device Driver int control ; System Control Device pop dx pop cx pop bx jmp rskp ; This routine blanks the screen. Returns normally. CMBLNK PROC NEAR mov dx,offset clrscr jmp tmsg ; Send terminal message. CMBLNK ENDP ; Homes the cursor. Returns normally. LOCATE PROC NEAR mov dx,0000H ; Go to top left corner of screen. jmp poscur 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 pointer. mov dx,1700H ; now address line 24 call poscur mov dx,offset invseq ; Use high intensity rather than inverse video call tmsg pop dx ; get message back call tmsg ; write it out mov dx,offset nrmseq ; Normal (low) intensity again call tmsg ret ; and return PUTMOD endp ; clear the mode line written by putmod. Returns normally. CLRMOD proc near mov dx,1700H call poscur ; Go to bottom row. call clearl ; Clear to end of line. ret CLRMOD endp ; Put a help message on the screen. ; Pass the message in ax, terminated by a null. Returns normally. PUTHLP proc near push ax ; preserve this mov dx,offset crlf call tmsg mov dx,offset invseq ; High intensity rather than inverse video call tmsg 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 ; else write to screen jmp puthl3 ; and keep going puthl4: mov dx,offset nrmseq ; Back to normal (low) intensity video call tmsg mov dx,offset crlf call tmsg 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 ; Save new rate, don't zap old rate yet... mov ax,ds:[bp].baud ; Check if new rate is valid. 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 the port cmp ax,0FFH ; Unimplemented baud rate. jne dobd0 mov ax,temp1 ; Get back original value. mov ds:[bp].baud,ax ; Leave rate as is. mov dx,offset badbd ; Give an error message. call tmsg ret ; dobd0: mov dx,ax mov bx,34H ; Serial Device Driver mov cx,4 ; Set transmit baud rate int control mov cx,5 ; Set receive baud rate int control mov dx,1 ; Turn on XON/XOFF just in case... mov cx,10 ; Transmit XON/XOFF int control mov cx,11 ; Receive XON/XOFF int control mov cx,3 ; Install changes, zap line, etc... 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,34H ; Serial Device Driver mov cx,4 ; Transmit baud rate mov dx,-1 ; Fetch data int control ; Go speak to Control Device Driver mov bx,offset bddat ; -> baud rate table mov cl,0 ; Keep track of index getb0: cmp ax,[bx] je getb1 inc cl cmp cl,baudsiz ; At the end of the list jge getb2 add bx,2 jmp getb0 getb1: mov ch,0 mov bp,portval mov ds:[bp].baud,cx ; Save rate index in port structure ret getb2: mov dx,offset erms40 call tmsg ret GETBAUD ENDP ; Use for DOS 2.0 and above. Check the port status. If no data, skip ; return. Else, read in a char and return. PRTCHR PROC NEAR push bx push cx push si push bp mov bx,34H mov cx,2 int control ; Read serial port cmp ax,-1 ; Character there ? jnz prtch1 ; Yes, process it... pop bp pop si pop cx pop bx jmp rskp ; No character, skip return. prtch1: mov bp,portval cmp ds:[bp].parflg,PARNON ; no parity? je prtch3 ; then don't strip and al,7fh ; else turn off parity prtch3: pop bp pop si pop cx pop bx ret PRTCHR ENDP ; Send a break out to the serial port. Returns normally. ; Need to handle port directly since ACT's Control Device doesn't ; have a 'send break' facility. SENDBR PROC NEAR mov al,5 out 62H,al ; Select SIO write register 5 mov al,0FAH out 62H,al ; Start break mov bx,-1 sendb0: dec bx jnz sendb0 mov al,5 out 62H,al ; Select SIO write register 5 mov al,0EAH out 62H,al ; Finished sending break ret SENDBR ENDP ; Position the cursor according to contents of DX: ; DH contains row, DL contains column. Origin (top left) = 0, 0 ; Returns normally. POSCUR PROC NEAR push dx ; Save row & column position mov dl,esc ; Start cursor positioning sequence call tchr mov dl,'Y' call tchr pop dx ; Retrieve row position mov al,dh call poscr1 mov al,dl poscr1: push dx add al,' ' mov dl,al call tchr pop dx ret POSCUR ENDP ; Delete a character from the terminal. This works by printing ; backspaces and spaces. Returns normally. DODEL PROC NEAR mov dx,offset delstr ; Erase weird character. jmp tmsg DODEL ENDP ; Move the cursor to the left margin, then clear to end of line. ; Returns normally. CTLU PROC NEAR mov dx,offset clrlin jmp tmsg CTLU ENDP ; Set the current port. COMS PROC NEAR jmp notimp COMS ENDP ; Set heath emulation on/off. VTS PROC NEAR jmp notimp VTS ENDP NOTIMP: mov dx,offset noimp call tmsg jmp prserr ; Initialize local variables and communications port. LCLINI: mov flags.vtflg,0 ; Don't do terminal emulation. mov bx,34H ; Control Device Driver mov cx,6 ; Set transmit bits per character mov dx,8 ; to 8-bit bytes int control mov cx,8 ; Set receive bits per character mov dx,7 ; to 8-bit bytes int control mov cx,8 ; Set number of stop bits mov dx,1 ; to 1 stop bit int control mov cx,9 ; Set parity type mov dx,0 ; to no parity. Parity handled internally. int control mov cx,10 ; Transmit XON/XOFF mov dx,1 ; Enabled int control mov cx,11 ; Receive XON/XOFF mov dx,1 ; Enabled int control mov cx,3 ; Install changes int control ret SHOWKEY: mov ax,offset shkmsg mov cx,shklen ret ; Initialization for using serial port. XON/XOFF has already been set by ; the local initialization routine. Returns normally. SERINI PROC NEAR cld ; Do increments in string operations call clrbuf ; Clear input buffer. 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 ; Produce a short beep. The PC DOS bell is long enough to cause a loss ; of data at the port. Returns normally. BEEP PROC NEAR mov dl,bell mov ah,dconio int dos ret BEEP ENDP ; Dumb terminal emulator. TERM proc near mov si,ax ; this is source mov di,offset ourarg ; place to store arguments mov ax,ds mov es,ax ; address destination segment mov cx,size termarg cld rep movsb ; copy into our arg blk mov bx,34H mov dx,1 mov cx,12 ; Turn on RTS int control mov cx,13 ; Turn on DTR int control term1: call prtchr jmp short term2 ; have a char... nop nop jmp short term3 ; no char, go on term2: and al,7FH push ax mov dl,al mov ah,conout int dos ; go print it pop ax test ourarg.flgs,capt ; capturing output? jz term3 ; no, forget it call ourarg.captr ; else call the routine term3: mov ah,dconio mov dl,0ffh int dos jz term1 ; no character, go on cmp al,ourarg.escc ; escape char? je term4 ; yes, exit push ax ; save char mov ah,al call outchr ; output the character nop nop nop pop ax test ourarg.flgs,lclecho ; echoing? jz term1 ; no, continue loop mov dl,al mov ah,dconio int dos jmp term1 ; else echo and keep going term4: ret TERM endp ; Print a message to the screen. Returns normally. TMSG proc near push ax push bx push cx push dx mov ah,prstr int dos pop dx pop cx pop bx pop ax ret TMSG endp ; Print a character to the screen. Returns normally. TCHR proc near push ax push bx push cx push dx mov ah,conout int dos pop dx pop cx pop bx pop ax ret TCHR 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