	public	serini, serrst, clrbuf, outchr, coms, vts, dodel, ctlu
	public	cmblnk, locate, prtchr, dobaud, clearl, lclini
	public	dodisk, getbaud, beep, setkhlp, setktab
	public	machnam, xofsnt, count, term, poscur
	public	clrmod, putmod, puthlp, sendbr, showkey
	include msdefs.h

false	equ	0
true	equ	1

wrdev	equ	40H
rddev	equ	3fH
open	equ	3dH
close	equ	3eH
rdchan	equ	2
e_send_break equ 6
e_ioctl	equ	44h		; MSODS io control fct

datas 	segment	public 'datas'
	extrn	drives:byte, flags:byte, trans:byte
	extrn	portval:word, port1:byte, port2:byte
machnam	db	'HP-150$'
erms20	db	cr,lf,'?Warning: System has no disk drives$' ; [21a]
erms40	db	cr,lf,'?Warning: Unrecognized baud rate$'
erms41	db	cr,lf,'?Warning: Cannot open com port$'
noimp	db	cr,lf,'Command not implemented.$'
setktab	db	0
setkhlp	db	0
shkmsg	db	'Not implemented.'
shklen	equ	$-shkmsg
crlf    db      cr,lf,'$'
comphlp	db	cr,lf,'1 (COM1)   2 (COM2)$'		; [19b]
delstr  db      BS,BS,'  ',BS,BS,'$' 	; Delete string. [21d]
clrlin  db      cr,esc,'K$'
xofsnt	db	0		; Say if we sent an XOFF.
xofrcv	db	0		; Say if we received an XOFF.
invseq	db	esc,'&dB$'	; Reverse video.
nrmseq	db	esc,'&d@$'	; Normal mode.
ivlseq	db	80 dup (' '),cr,'$' 	; Make a line inverse video
tmp	db	?,'$'
temp	dw	0
temp1   dw      ?               ; Temporary storage.
temp2   dw      ?               ; Temporary storage.

; Entries for choosing communications port. [19b]

comptab	db	04H
	db	01H,'1$'
	dw	01H
	db	01H,'2$'
	dw	00H
	db	04H,'COM1$'
	dw	01H
 	db	04H,'COM2$'
	dw	00H

; variables for serial interrupt handler

source	db	bufsiz DUP(?)	; Buffer for data from port.
bufout	dw	0		; buffer removal ptr
count	dw	0		; Number of chars in int buffer.
bufin	dw	0		; buffer insertion ptr
telflg	db	0		; Are we acting as a terminal. [16] [17c]
clreol	db	esc,'K$'
prttab	dw	com2,com1
com1	db	'COM1',0
com2	db	'COM2',0
blank	db	esc,'H',esc,'J$'
movcur	db	esc,'&a'
colno	db	20 dup (?)
ten	db	10
prthnd	dw	0
tempbuf dw	10 dup(?)
ourarg	termarg	<>
datas	ends

code	segment	public
	extrn	comnd:near, dopar:near, prserr:near
	assume	cs:code,ds:datas

; See how many disk drives we have.
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 before sending a packet. [20e]

CLRBUF	PROC	NEAR
	cli
	mov ax,offset source
	mov bufin,ax
	mov bufout,ax
	mov count,0
	sti
clrb1:	call prtchr		; get a character
	 jmp clrb1		; until there aren't any more
	 nop
	ret
CLRBUF	ENDP

; Common routine to clear to end-of-line. [19a]

CLEARL	PROC	NEAR
	mov dx,offset clreol
	mov ah,prstr
	int dos
	ret
CLEARL	ENDP

dobaud	proc	near
	jmp notimp
dobaud	endp

; Send the break signal out data comm.
sendbr:	mov al,e_send_break
	jmp  dc_ioctl

; Set some data comm ioctl option.  AL has function code.
dc_ioctl proc	near
	mov ah,8h
	mov tempbuf,ax
	mov dx,offset tempbuf
	mov ah,e_ioctl
	mov al,3
	mov bx,prthnd
	mov cx,2
	int 21h
	ret
dc_ioctl endp


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.
	push cx
	push bx
	cmp prthnd,0		; do we have a port handle?
	jne outch3		; yes, go on
	push ax
	call opnprt		; open the port
	pop ax
outch3: mov byte ptr temp,ah	; save character
	mov bx,prthnd
	mov ah,wrdev
	mov cx,1
	mov dx,offset temp
	int dos
	pop bx
	pop cx
	pop dx
	jmp rskp

opnprt:	mov al,flags.comflg
	mov ah,0
	mov si,ax
	shl si,1		; double index
	mov dx,prttab[si]
	mov ah,open
	mov al,2
	int dos
	jnc opnpr1
	mov ah,prstr
	mov dx,offset erms41
	int dos
	ret
opnpr1:	mov prthnd,ax
	ret

; This routine blanks the screen.

CMBLNK	PROC	NEAR		; This is stolen from the IBM example.
	mov ah,prstr
	mov dx,offset blank
	int dos
	ret
CMBLNK  ENDP

LOCATE  PROC	NEAR
	mov dx,0		; Go to top left corner of screen.
	jmp poscur		; callret...
LOCATE  ENDP

GETBAUD	PROC	NEAR
	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
	push bx
	push cx
	push si
	push bp
	cmp count,0		; no characters?
	jne prtch2		; no, go fill buffer
	cmp prthnd,0		; have a handle yet?
	jne prtch1		; yes, keep going
	call opnprt
prtch1:	mov bx,prthnd
	mov al,rdchan
	mov ah,ioctl
	mov dx,offset source	; buffer to read into
	mov cx,bufsiz		; length of buffer
	int dos
	mov count,ax		; reset count
	or ax,ax
	jz prtch4		; still no chars
	mov bufout,offset source ; this is output ptr
prtch2:	dec count
	mov dx,count		; return count in dx
	mov si,bufout
	lodsb			; get character
	mov bufout,si		; update ptr
	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
prtch4:	pop bp
	pop si
	pop cx
	pop bx
	jmp rskp		; no chars...
PRTCHR  ENDP

; Position the cursor according to contents of DX.

POSCUR	PROC	NEAR
	mov	ax,ds
	mov	es,ax			; address data segment!!!
	cld
	mov	di,offset colno
	mov	al,dl			; column
	call	nout
	mov	al,'c'
	stosb
	mov	al,dh			; row
	call	nout
	mov	al,'Y'
	stosb
	mov	al,'$'
	stosb
	mov	dx,offset movcur
	mov	ah,prstr
	int	dos			; print the sequence
	ret
POSCUR	ENDP

NOUT	PROC	NEAR
	cbw			; extend to word
	div	byte ptr ten	; divide by 10
	or	al,al		; any quotient?
	jz	nout1		; no, forget this
	push	ax		; save current result
	call	nout		; output high order
	pop	ax		; restore
nout1:	mov	al,ah		; get digit
	add	al,'0'		; make printable
	stosb
	ret			; put in buffer and return
NOUT	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	dx,24 * 100H	; line 24
	call	poscur
	mov	dx,offset invseq ; put into inverse video
	mov	ah,prstr
	int	dos
	pop	dx
	int 	dos
	mov	dx,offset nrmseq ; normal videw
	int	dos
	ret			; and return
putmod	endp

; Clear the mode line written by putmod.  Returns normally.
clrmod	proc	near
	mov	dx,24 * 100H
	call	poscur
	call	clearl
	ret
clrmod	endp

; Put a help message one the screen in reverse video.  Pass
; the message in AX, terminated by a null.  Returns normally.
; The message is put wherever the cursor currently is located.
puthlp	proc	near
	push ax
	mov ah,prstr		; Leave some room before the message.
	mov dx,offset crlf
	int dos
	pop si			; Put message address here.
puth0:	mov ah,prstr
	mov dx,offset invseq	; Put into reverse video.
	int dos
	mov ah,prstr
	mov dx,offset ivlseq	; Make line inverse video
	int dos
puth1:	lodsb
	cmp al,0		; Terminated with a null.
	je puth2
	mov dl,al
	mov ah,conout
	int dos	
	cmp al,lf		; Line feed?
	je puth0		; Yes, clear the next line.
	jmp puth1		; Else, just keep on writing.
puth2:	mov dx,offset crlf
	mov ah,prstr
	int dos
	mov dx,offset nrmseq	; Normal video.
	int dos
	ret
puthlp	endp

; Perform a delete.

DODEL	PROC	NEAR
	mov ah,prstr
	mov dx,offset delstr	; Erase weird character.
	int dos			
	ret
DODEL	ENDP

; Perform a Control-U.

CTLU	PROC	NEAR
	mov ah,prstr
	mov dx,offset clrlin
	int dos
	ret
CTLU	ENDP

COMS	PROC	NEAR
        mov dx,offset comptab
        mov bx,offset comphlp
        mov ah,cmkey
        call comnd
         jmp r
        push bx
        mov ah,cmcfm
        call comnd              ; Get a confirm.
         jmp comx		;  Didn't get a confirm.
	 nop
        pop bx
        mov flags.comflg,bl     ; Set the comm port flag.
	cmp flags.comflg,1	; Using Com 1?
	jne coms0		; Nope.
	mov ax,offset port1
	mov portval,ax
	ret
coms0:	mov ax,offset port2
	mov portval,ax
	ret
comx:	pop bx
	ret
COMS	ENDP

VTS	PROC	NEAR
	jmp notimp
VTS	ENDP

notimp:	mov ah,prstr
	mov dx,offset noimp
	int dos
	jmp prserr

lclini:	ret

showkey:
	mov ax,offset shkmsg
	mov cx,shklen
	ret

;  Common initialization for using serial port.

SERINI	PROC	NEAR
	call opnprt
	call clrbuf		; Clear input buffer. [20e]
	ret			; We're done. [21c]
SERINI	ENDP

SERRST	PROC	NEAR
	mov bx,prthnd
	cmp bx,0		; none there?
	je serrs1		; no, don't try to close.
	mov ah,close
	int dos			; close handle
	mov prthnd,0
serrs1:	ret			; All done. [21c]
SERRST	ENDP

; Generate a short beep.

BEEP	PROC	NEAR
	mov dl,bell
	mov ah,conout
	int dos	
	ret
BEEP	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

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
	rep movsb		; copy into our arg blk
term1:	call prtchr
	jmp short term2		; have a char...
	nop
	nop
	jmp short term3		; no char, go on
term2:	push ax
	mov dl,al
	and dl,7fh		; mask off parity for terminal
	mov ah,dconio
	int dos			; write out the character
	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
	or ah,80H		; turn on hi bit so DOS doesn't interfere
	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
code	ends 
	end
