;
; MSXMBC - MS-DOS KERMIT MODULE FOR SANYO MBC-55x
;
;	THIS MODULE WAS CREATED BY EDITING THE GENERIC MS-DOS MODULE
; MSXGEN AND ADDING THE SANYO SPECIFIC CODE TO PERFORM THE NEEDED
; FUNCTIONS, MANY OF WHICH WERE GRACEFULLY BORROWED FROM THE MSXIBM
; MODULE. PLEASE NOTE THAT THE SANYO "AUX" DEVICE HARDWARE CONSISTS OF:
;
;		8251A	SERIAL COMMUNICATIONS DEVICE (DOES RS-232 STUFF)
;		8259A	SYSTEM INTERRUPT CONTROLLER
;		8253	TIMER DEVICE (FED TO 8251A AS BAUD RATE)
;
; DEFUALT SETTINGS ARE:
;
;		BAUD RATE	= 300
;		CHAR LENGTH	= 8 BITS
;		PARITY		= NONE
;		STOP BITS	= 1
;
; JOE SMILEY 1-5-85
;

	;
	; GLOBALLY ACCESSIBLE SUBROUTINES
	;
	PUBLIC	SERINI			; INITIALIZE AUX DEVICE FOR INPUT
	PUBLIC	SERRST			; RESTORE AUX DEVICE TO CALM STATE
	PUBLIC	CLRBUF			; CLEAR AUX DEVICE INPUT BUFFERS
	PUBLIC	OUTCHR			; OUTPUT CHARACTER ON AUX DEVICE
	PUBLIC	COMS			; SET COMM PORT (ONLY ONE ON SANYO)
	PUBLIC	VTS			; HEATH-19 NOT IMPLEMENTED
	PUBLIC	DODEL			; DELETE CHARACTER FROM SCREEN
	PUBLIC	CTLU			; ERASE CURRENT LINE
	PUBLIC	CMBLNK			; BLANK THE ENTIRE VIDEO SCREEN
	PUBLIC	LOCATE			; HOME CURSOR
	PUBLIC	LCLINI			; LOCAL SYSTEM INITIALIZATION
	PUBLIC	PRTCHR			; GET A CHARACTER (IF ONE) FROM AUX
	PUBLIC	DOBAUD			; SET AUX DEVICE BAUD RATE
	PUBLIC	CLEARL			; CLEAR A LINE ON VIDEO SCREEN
	PUBLIC	DODISK			; GET NO. OF SYSTEM DISK DRIVES
	PUBLIC	GETBAUD			; GET DEFAULT BAUD RATE
	PUBLIC	BEEP			; OUTPUT BEEP ON PC
	PUBLIC	PUTHLP			; DISPLAY HELP MESSAGE ON SCREEN
	PUBLIC	PUTMOD			; PUT MODE STRING ON LINE 24
	PUBLIC	CLRMOD			; CLEAR MODE LINE
	PUBLIC	POSCUR			; POSITION CURSOR ON VIDEO SCREEN
	PUBLIC	SENDBR			; SEND BREAK SIGNAL ON AUX DEVICE
	PUBLIC	TERM			; PERFORM TERMINAL EMULATION
	PUBLIC	SHOWKEY			; NOT IMPLEMENTED
	;
	; GLOBALLY ACCESSIBLE DATA
	;
	PUBLIC	COUNT			; NO. OF CHARACTERS IN INPUT BUFFER
	PUBLIC	XOFSNT			; FLAG INDICATING XOFF SENT OUT AUX
	PUBLIC	MACHNAM			; ASCII STRING CONTAINING MACHINE NAME
	PUBLIC	SETKTAB			; NOT USED
	PUBLIC	SETKHLP			; NOT USED

;
; INCLUDE STANDARD MS-DOS DEFINITIONS
;
	INCLUDE	MSDEFS.H

;
; ADDITIONAL EQUATES
;
FALSE	EQU	0			; BOOLEAN FALSE VALUE
TRUE	EQU	1			; BOOLEAN TRUE VALUE
MNTRGH	EQU	(BUFSIZ * 3) / 4	; HIGH POINT OF BUFFER FULL
VIDEO	EQU	010H			; VIDEO INTERRUPT

;
; EXTERNAL VARIABLES USED
;
;	DRIVES	- NO. OF DISK DRIVES ON SYSTEM
;	FLAGS	- GLOBAL FLAGS AS PER FLGINFO STRUCTURE
;	PORTVAL	- POINTER TO CURRENT PORTINFO STRUCTURE (ALWAYS PORT1)
;	PORT1	- PORTINFO STRUCTURE USED FOR SANYO
;

;
; DEFINE DATA SEGMENT
;
DATAS	SEGMENT	PUBLIC	'DATAS'
	EXTRN	DRIVES:BYTE		; NO. OF DISK DRIVES ON SYSTEM
	EXTRN	FLAGS:BYTE		; GLOBAL FLAGS USED
	EXTRN	PORTVAL:WORD		; POINTER TO PORTINFO STRUCTURE
	EXTRN	PORT1:BYTE		; PORTINFO STRUCTURE USED BY SANYO

;
; SANYO DEVICE DEFINITIONS (AND BAUD RATE TABLE)
;

;
; 8251A serial communications device
;
	BUF8251	EQU	028H		; I/O address of 8251A in/out buffer
	CMD8251	EQU	02aH		; I/O address of 8251A command buffer
	STS8251	EQU	02aH		; I/O address of 8251A status buffer
	VEC8251	EQU	03e8H		; 8251A interrupt vector location
	INT8251	EQU	0fbH		; 8259A interrupt enable mask (int 2)
;
; 8251A Command Intruction Formats
;
	TxEN	EQU	001H		; 8251A transmit enable	
	DTR	EQU	002H		; 8251A data terminal ready high
	RxEN	EQU	004H		; 8251A receiver enable	
	SBRK	EQU	008H		; 8251A send break character	
	ER	EQU	010H		; 8251A error reset (must when RxEN)
	RTS	EQU	020H		; 8251A request to send high	
	IR	EQU	040H		; 8251A internal reset		
;
; 8251A Status Read Formats
;
	TxRDY	EQU	001H		; 8251A transmitter ready	
	RxRDY	EQU	002H		; 8251A receiver ready		
	TxEMPTY	EQU	004H		; 8251A transmit buffer empty	
	PE	EQU	008H		; 8251A parity error		
	OE	EQU	010H		; 8251A overrun error		
	FE	EQU	020H		; 8251A framing error		
	BRKDET	EQU	040H		; 8251A break detect		
	DSR	EQU	080H		; 8251A data set ready at zero level

;
; 8253 timer device
;
	CKA8253	EQU	020H		; I/O address of 8253 counter #0
	CKB8253	EQU	022H		; I/O address of 8253 counter #1
	CKC8253	EQU	024H		; I/O address of 8253 counter #2
	CMD8253	EQU	026H		; I/O address of 8253 command buffer
;
; 8253 Timer baud rate tables
;
; Note:
;	the 8251a is normally (by default) set up to a clock multiplier
; of 16x rather than 1x or 64x.  this is OK for most of the popular baud
; rates, however, the values programmed below may not work for some of the
; less popular rates without resetting the clock multiplier on the 8251a,
; and reprogramming the timer values below.
;
;	in other words, i was too lazy to verify that all of the timer
; values mentioned below would work for the specified baud rates.
;
BDDAT	LABEL	WORD
	DW	(29829/((45/30)*8))	; Timer value for baud rate 45.5
	DW	(29829/((50/30)*8))	; Timer value for baud rate 50
	DW	(29829/((75/30)*8))	; Timer value for baud rate 75
	DW	(29829/((110/30)*8))	; Timer value for baud rate 110
	DW	(29829/((134/30)*8))	; Timer value for baud rate 134.5
	DW	(29829/((150/30)*8))	; Timer value for baud rate 150
	DW	(29829/((300/30)*8))	; Timer value for baud rate 300
	DW	(29829/((600/30)*8))	; Timer value for baud rate 600
	DW	(29829/((1200/30)*8))	; Timer value for baud rate 1200
	DW	(29829/((1800/30)*8))	; Timer value for baud rate 1800
	DW	(29829/((2000/30)*8))	; Timer value for baud rate 2000
	DW	(29829/((2400/30)*8))	; Timer value for baud rate 2400
	DW	(29829/((4800/30)*8))	; Timer value for baud rate 4800
	DW	(29829/((9600/30)*8))	; Timer value for baud rate 9600
	DW	(29829/((19200/30)*8))	; Timer value for baud rate 19200
	DW	(29829/((38400/30)*8))	; Timer value for baud rate 38400

;
; 8259A interrupt controller
;
	CMA8259	EQU	000H		; I/O address of 8259A command buff 1
	CMB8259	EQU	002H		; I/O address of 8259A command buff 2

;
; ASCII MESSAGES
;
MACHNAM	DB	'Sanyo MBC-55x MS-DOS v2.11$'
ERMS20	DB	CR,LF,'?Warning: System has no disk drives$'
ERMS40	DB	CR,LF,'?Warning: Unrecognized baud rate$'
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
DELSTR  DB      BS,' ',BS,'$'
CLRLIN  DB      CR,'$'
RBTRN	DB	7FH			; RUBOUT CODE

;
; ADDITIONAL DATA STRUCTURES
;
TELFLG	DB	0			; TERMINAL EMULATION FLAG
XOFSNT	DB	0			; XOFF JUST SENT FLAG
XOFRCV	DB	0			; XOFF JUST RECEIVED FLAG
PORTIN	DB	0			; AUX PORT INITIALIZED FLAG

SAVSCI	DW	?			; SAVED AUX PORT INTERRUPT VECTOR
SAVSCS	DW	?			; SAVED AUX PORT INTERRUPT VECTOR

SOURCE	DB	BUFSIZ DUP(?)		; INPUT DATA BUFFER (FROM AUX)
SRCPNT	DW	0			; INPUT BUFFER POINTER
COUNT	DW	0			; NO. OF CHARACTERS IN BUFFER
SAVESI	DW	0			; SAVE SI REGISTER HERE

OURARG	TERMARG	<>			; TERMINAL EMULATOR ARG STORAGE

DATAS	ENDS				; END OD DATA SEGMENT

;
; START OF CODE SEGMENT
;
CODE	SEGMENT	PUBLIC
	EXTRN	DEFKEY:NEAR		; DEFINE A TRANSLATION ROUTINE
	EXTRN	PRSERR:NEAR		; EXTERNAL PRINT ERROR ROUTINE
	ASSUME	CS:CODE, DS:DATAS	; ASSUME CODE AND DATA SEGMENTS

;
; DODISK - SET THE NUMBER OF DISK DRIVES ON THE HOST SYSTEM
;
; OUTPUTS:
;	DRIVES	- GLOBAL BYTE VARIABLE SET TO THE NUMBER OF DISK DRIVES
;
; NOTES:
;	RETURNS NORMALLY.
;
DODISK	PROC	NEAR
	MOV	AH,GCURDSK		; SET CODE TO GET CURRENT DISK DRIVE
	INT	DOS			; GET THE CURRENT DISK DRIVE
	MOV	DL,AL			; SET CURRENT DISK DRIVE
	MOV	AH,SELDSK		; SET CODE TO SELECT CURRENT DISK
	INT	DOS			; SELECT AND GET NO. OF DRIVES
	MOV	DRIVES,AL		; SET GLOBAL VARIABLE
	RET				; AND RETURN
DODISK	ENDP

;
; CLRBUF - CLEAR 8251A (AUX DEVICE) INPUT BUFFER
;
;	THIS ROUTINE CLEARS THE AUX DEVICE INPUT BUFFER SO THAT NO
; ACCUMULATED CHARACTERS (ESPECIALLY IMPORTANT WHEN TALKING TO
; SERVER KERMITS) INTEREFER WITH COMMUNICATION. IT ALSO SETS UP THE
; CIRCULAR INPUT BUFFER USED BY THE INPUT INTERRUPT ROUTINE.
;
; NOTES:
;	THIS ROUTINE RETURNS NORMALLY.
;
CLRBUF	PROC	NEAR
	PUSHF				; SAVE FLAGS
	CLI				; LOCK OUT INTERRUPTS
	PUSH	AX			;;; SAVE REGISTER
	IN	AL,STS8251		;;; READ STATUS REGISTER
	IN	AL,BUF8251		;;; READ INPUT BUFFER
	IN	AL,BUF8251		;;; READ AGAIN (DOUBLE BUFFERED INPUT)
	MOV	AX,OFFSET SOURCE	;;; GET START OF INPUT DATA BUFFER
	;
	; RESET CIRCULAR INPUT BUFFER POINTERS AND COUNT
	;
	MOV	SRCPNT,AX		;;; SET DATA BUFFER POINTER
	MOV	SAVESI,AX		;;; AND SET INITIAL SI POINTER
	MOV	COUNT,0			;;; INITIALIZE NO. OF CHARS IN BUFFER
	POP	AX			;;; RESTORE REGISTER
	POPF				;;; RESTORE FLAGS (RE-ENABLE INTS)
	RET				; RETURN
CLRBUF	ENDP

;
; CLEARL - CLEAR TO THE END OF THE CURRENT LINE ON THE VIDEO SCREEN
;
CLEARL	PROC	NEAR
	MOV	AH,3			; SET CODE TO GET CURSOR POSITION
	MOV	BH,0			; SET PAGE 0
	INT	VIDEO			; GET CURRENT CURSOR POSITION
	MOV	CX,DX			; COPY CURSOR POSITION
	MOV	DL,79			; SET COLUMN POSITION OF SCROLL
	MOV	AH,7			; SET CODE TO SCROLL PAGE DOWN
	MOV	AL,0			; SET NUMBER OF LINES (WHOLE WINDOW)
	MOV	BH,7			; BLANK LINE ATTRIBUTE
	INT	VIDEO			; AND NOW BLANK THE LINES
	RET				; AND RETURN
CLEARL	ENDP

;
; OUTCHR - OUTPUT CHARACTER TO AUX DEVICE DOING FLOW CONTROL
;
;	THIS SUBROUTINE WILL OUTPUT THE SPECIFIED CHARACTER ON THE AUX
; DEVICE WHILE HONORING XON/XOFF FLOW CONTROL.
;
; INPUTS:
;	AH	- CONTAINS CHARACTER TO BE OUTPUT
;
; NOTES:
;	THIS ROUTINE SKIPS RETURN ON SUCCESS.
;
OUTCHR:	MOV	BP,PORTVAL		; GET POINTER TO CURRENT PORT STRUCTURE
	CMP	DS:[BP].FLOFLG,FALSE	; DOING FLOW CONTROL?
	JE	OUTCH2			; IF E NO, JUST CONTINUE
	XOR	CX,CX			; CLEAR COUNTER REGISTER
OUTCH1:	CMP	XOFRCV,TRUE		; CURRENTLY BEING HELD?
	JNE	OUTCH2			; IF NE NO, OK TO PROCEED
	LOOP	OUTCH1			; ELSE WAIT A WHILE
	MOV	XOFRCV,FALSE		; TIMED OUT, FORCE XOFF OFF AND GO ON
	;
	; OUTCH2 - OUTPUT CHARACTER TO AUX DEVICE
	;
	; NOTES:
	;	- DESTROYS CONTENTS OF AX REGISTER
	;	- 8251A DEVICE HANDLES PARITY IN HARDWARE (SEE SETUP BELOW)
	;
OUTCH2:	PUSHF				; SAVE FLAGS
	CLI				; LOCK OUT INTERRUPTS
	PUSH	AX			;;; SAVE REGISTER 
	MOV	AL,(TxEN+DTR+RxEN+ER+RTS) ;;; GET OUTPUT ENABLE COMMAND
	OUT	CMD8251,AL		;;; COMMAND 8251 FOR OUTPUT
	CALL	DUMRET			;;; KILL SOME TIME
OUTCH3:	IN	AL,STS8251		;;; READ DEVICE STATUS
	TEST	AL,TxRDY		;;; TRANSMITTER READY?
	JZ	OUTCH3			;;; IF ZERO NO
	POP	AX			;;; RESTORE REGISTER
	MOV	AL,AH			;;; GET CHARACTER TO OUTPUT
	OUT	BUF8251,AL		;;; OUTPUT CHARACTER
	CALL	DUMRET			;;; KILL SOME TIME
	MOV	AL,(DTR+RxEN+ER+RTS)	;;; GET INPUT ENABLE COMMAND
	OUT	CMD8251,AL		;;; RE-COMMAND 8251A FOR INPUT
	POPF				;;; RESTORE FLAGS (RE-ENABLE INTS)
	JMP	RSKP			; RETURN
DUMRET:	RET				; DUMMY RETURN

;
; CMBLNK - BLANK THE VIDEO SCREEN
;
; NOTES:
;	RETURN NORMALLY.
;
CMBLNK	PROC	NEAR
	MOV	CX,0			; SET HOME POSITION
	MOV	DX,0184FH		; SET LOWER RIGHT CORNER OF SCREEN
	MOV	BH,7			; SET BLANK ATTRIBUTE
	MOV	AX,0600H		; SET CODE FOR SCROLL PAGE UP
	INT	VIDEO			; AND CLEAR THE SCREEN
	RET				; AND RETURN
CMBLNK  ENDP

;
; LOCATE - HOME THE CURSOR
;
; NOTES:
;	RETURNS NORMALLY.
;
LOCATE  PROC	NEAR
	MOV	DX,0			; SET HOME POSITION
	JMP	POSCUR			; AND GO TO POSITION
LOCATE  ENDP

;
; PUTMOD - WRITE A LINE AT THE BOTTOM OF THE VIDEO SCREEN
;
; INPUTS:
;	DX	- ADDRESS OF LINE, TERMINATED BY '$'
;
; NOTES:
;	RETURNS NORMALLY.
;
PUTMOD	PROC	NEAR
	PUSH	DX			; SAVE REGISTER
	MOV	CX,01800H		; SET START ADDRESS
	MOV	DX,0184FH		; AND END ADDRESS
	MOV	AX,0600H		; SET CODE TO SCROLL PAGE UP
	MOV	BH,07H			; SET ATTRIBUTE
	INT	VIDEO			; CLEAR LINE
	MOV	DX,01800H		; RE-ADDRESS LINE 24
	CALL	POSCUR			; POSITION THE CURSOR
	POP	DX			; GET STRING ADDRESS
	MOV	AH,PRSTR		; SET CODE TO PRINT STRING
	INT	DOS			; PRINT THE STRING
	RET				; AND RETURN
PUTMOD	ENDP

;
; CLRMOD - CLEAR THE LINE WRITTEN BY PUTMOD
;
; NOTES:
;	RETURNS NORMALLY.
;
CLRMOD	PROC	NEAR
	MOV	CX,01800H		; ADDRESS START OF LINE 24
	MOV	DX,0184FH		; AND END ADDRESS
	MOV	AX,0600H		; SET CODE TO SCROLL PAGE UP
	MOV	BH,07H			; NORMAL ATTRIBUTE
	INT	VIDEO			; AND CLEAR LINE
	RET				; AND RETURN
CLRMOD	ENDP

;
; PUTHLP - PUT A HELP MESSAGE ON THE SCREEN
;
; INPUTS:
;	AX	- ADDRESS OF MESSAGE, TERMINATED BY NUL
;
; NOTES:
;	RETURNS NORMALLY.
;
PUTHLP	PROC	NEAR
	PUSH	AX			; SAVE THE STRING ADDRESS
	MOV	SI,AX			; SET STRING ADDRESS
	MOV	DH,1			; INITIALIZE COUNTER
PUTHL1:	LODSB				; GET NEXT BYTE
	CMP	AL,LF			; GET A LINE FEED?
	JNE	PUTHL2			; IF NE NO, CONTINUE
	INC	DH			; ELSE COUNT IT
	JMP	PUTHL1			; AND CONTINUE
PUTHL2:	CMP	AL,0			; AT END OF STRING?
	JNE	PUTHL1			; IF NE NO, CONTINUE COUNTING
	MOV	AX,0600H		; SET CODE TO SCROLL ACTIVE PAGE UP
	XOR	CX,CX			; SET HOME POSITION
	MOV	DL,04FH			; TO BOTTOM RIGHT OF NEEDED PIECE
	MOV	BH,070H			; SET INVERSE VIDEO ATTRIBUTE
	INT	VIDEO			; CLEAR SCREEN AREA
	CALL	LOCATE			; HOME CURSOR
	POP	SI			; RESTORE STRING ADDRESS
PUTHL3:	LODSB				; GET NEXT BYTE
	CMP	AL,0			; END OF STRING?
	JE	PUTHL4			; IF E YES
	MOV	AH,14			; SET CODE TO WRITE TO VIDEO
	INT	VIDEO			; AND DO IT
	JMP	PUTHL3			; AND DO NEXT CHARACTER
PUTHL4:	MOV	DX,24 * 100H		; SET ADDRESS OF LAST LINE
	JMP	POSCUR			; AND POSITION CURSOR THERE
PUTHLP	ENDP
 
;
; DOBAUD SET THE CURRENT BAUD RATE
;
; NOTES:
;	RETURNS NORMALLY.
;
DOBAUD	PROC	NEAR
	PUSH	AX			; SAVE REGISTER
	PUSH	BX			; SAVE REGISTER
	PUSH	BP			; SAVE REGISTER
	MOV	BP,PORTVAL		; ADDRESS PORT STRUCTURE
	MOV	AX,DS:[BP].BAUD		; GET BAUD RATE INDEX
	SHL	AX,1			; CONVERT TO WORD INDEX
	MOV	BX,AX			; RE-GET OFFSET ADDRESS
	ADD	BX,OFFSET BDDAT		; ADD IN BASE ADDRESS OF TABLE
	;
	; SET TIMER VALUE FOR BAUD RATE GENERATION BY 8253 TIMER CHIP
	;
	MOV	AX,[BX]			; GET 8253 TIME COUNT FOR THIS RATE
	OUT	CKC8253,AL		; OUTPUT LOW BYTE OF VALUE
	MOV	AL,AH			; GET HIGH BYTE
	OUT	CKC8253,AL		; OUTPUT HIGH BYTE OF VALUE
	POP	BP			; RESTORE REGISTER
	POP	BX			; RESTORE REGISTER
	POP	AX			; RETSORE REGISTER
	RET				; AND RETURN
DOBAUD	ENDP

;
; GETBAUD - SET DEFAULT BAUD RATE TO 300
;
GETBAUD	PROC	NEAR
	PUSH	AX			; SAVE REGISTER
	PUSH	BP			; SAVE REGISTER
	MOV	AX,6			; GET INDEX FOR BAUD RATE OF 300
	MOV	BP,PORTVAL		; GET PORT INFO STRUCTURE
	MOV	DS:[BP].BAUD,AX		; SET INDEX
	POP	BP			; RESTORE REGISTER
	POP	AX			; RESTORE REGISTER
	RET
GETBAUD	ENDP

;
; SERINI - SERIAL (AUX) DEVICE INITIALIZATION
;
;	THIS FUNCTION IS CALLED TO SET UP THE SERIAL DEVICE INPUT
; INTERRUPT AND INITIALIZE THE SERIAL DEVICE BEFORE COMMUNICATIONS.
; NOTE THAT THIS FUNCTION SHOULD BE ABLE TO BE CALLED TWICE IN
; SUCCESSION WITHOUT DISASTEROUS RESULTS.
;
;	"SERRST" IS THE OPPOSITE OF THIS FUNCTION AND SHOULD RETURN
; THE DEVICE TO A QUESCIENT STATE.
;
; NOTES:
;	THE AUX DEVICE IS SET UP BY DEFAULT FOR 300 BAUD, 8 BITS
; PER CHARACTER, 1 STOP BIT, AND NO PARITY.
;
;	THIS FUNCTION RETURNS NORMALLY.
;
SERINI	PROC	NEAR
	CMP	PORTIN,0		; DEVICE ALREADY INITIALIZED?
	JNE	SERIN0			; IF NE YES
	;
	; RESET 8251A DEVICE AND SET DEFAULT OPERATING MODE
	;
	CLI				; DISABLE INTERRUPTS
	MOV	AL,IR			;;; GET 8251A INTERNAL RESET COMMAND
	OUT	CMD8251,AL		;;; RESET 8251A DEVICE
	CALL	DUMRET			;;; KILL SOME TIME
	MOV	AL,04EH			;;; GET MODE (8 BITS PER CHAR, NO
					;;;  PARITY, 1 STOP BIT, 16X CLOCK)
	OUT	CMD8251,AL		;;; SET OPERATING MODE ON 8251A
	CALL	DUMRET			;;; KILL SOME TIME
	MOV	AL,(DTR+RxEN+ER+RTS)	;;; GET INPUT ENABLE COMMAND
	OUT	CMD8251,AL		;;; ENABLE INPUT ON 8251A
	;
	; SET NEW INTERRUPT VECTOR AND UNMASK 8251A INTERRUPT LINE ON 8259A 
	;
	PUSH	ES			;;; SAVE SEGMENT REGISTER
	MOV	AX,0000			;;; GET SEGMENT OF VECTOR SPACE
	MOV	ES,AX			;;; SET SEGMENT ADDRESS
	MOV	BX,VEC8251		;;; GET ADDRESS OF AUX INT VECTOR
	MOV	AX,ES:[BX]		;;; GET OLD VECTOR OFFSET
	MOV	SAVSCI,AX		;;; AND SAVE IT
	MOV	AX,OFFSET SERINT	;;; GET NEW VECTOR OFFSET
	MOV	ES:[BX],AX		;;; AND SET IT
	ADD	BX,2			;;; GET TO NEXT WORD IN VECTOR
	MOV	AX,ES:[BX]		;;; AND GET IT
	MOV	SAVSCS,AX		;;; AND SAVE SECOND WORD
	MOV	ES:[BX],CS		;;; SET OUR SEGMENT ADDRESS
	IN	AL,CMB8259		;;; GET CURRENT INTERRUPT MASK
	AND	AL,INT8251		;;; UNMASK 8251A INTERRUPT
	OUT	CMB8259,AL		;;; SET NEW MASK VALUE
	POP	ES			;;; RESTORE SEGMENT REGISTER
	;
	; CLEAR THE INPUT DEVICE AND SET UP CIRCULAR INPUT BUFFER
	;
	CALL	CLRBUF			;;; CLEAR THE INPUT BUFFER
	CALL	DOBAUD			;;; SET BAUD RATE LOCALLY
	;
	; INITIALIZATION DONE.
	;
	MOV	PORTIN,1		;;; SET PORT IS INITIALIZED
	STI				;;; ENABLE INTERRUPTS
SERIN0:	RET				; RETURN
SERINI	ENDP

;
; SERRST - RESTORE SERIAL PORT INTERRUPT
;
SERRST	PROC	NEAR
	CMP	PORTIN,0		; NEED TO RESET?
	JE	SERRS0			; IF EQUAL NO
	CLI				; DISABLE INTERRUPTS
	PUSH	ES			;;; SAVE SEGMENT REGISTER
	MOV	AX,0000			;;; GET SEGMENT OF VECTOR SPACE
	MOV	ES,AX			;;; SET SEGMENT ADDRESS
	MOV	BX,VEC8251		;;; GET ADDRESS OF AUX INT VECTOR
	MOV	AX,SAVSCI		;;; GET OLD VECTOR OFFSET
	MOV	ES:[BX],AX		;;; AND SET IT
	ADD	BX,2			;;; GET TO NEXT WORD IN VECTOR
	MOV	AX,SAVSCS		;;; GET SECOND WORD SAVED
	MOV	ES:[BX],AX		;;; SET OLD SEGMENT ADDRESS
	POP	ES			;;; RESTORE SEGMENT REGISTER
	STI				;;; RE-ENABLE INTERRUPTS
	MOV	PORTIN,0		; SET DEVICE NOT INITIALIZED
SERRS0:	RET				; RETURN
SERRST	ENDP

;
; SERINT - SERIAL PORT (AUX DEVICE) INPUT INTERRUPT SERVICE ROUTINE
;
SERINT  PROC  NEAR
	PUSH	AX			;;; SAVE REGISTER
	PUSH	BX			;;; SAVE REGISTER
	PUSH	CX			;;; SAVE REGISTER
	PUSH	DX			;;; SAVE REGISTER
	PUSH	DI			;;; SAVE REGISTER
	PUSH	BP			;;; SAVE FRAME POINTER
	PUSH	DS			;;; SAVE SEGMENT REGISTER
	PUSH	ES			;;; SAVE SEGMENT REGISTER
	CLD				;;; DO AUTO-INCREMENT ON STRINGS
	MOV	AX,SEG DATAS		;;; GET DATA SEGEMENT ADDRESS
	MOV	DS,AX			;;; SET DATA SEGMENT ADDRESS
	MOV	ES,AX			;;; AND SET AS EXTRA SEGMENT
	MOV	DI,SRCPNT		;;; GET POINTER TO INPUT DATA BUFFER
	IN	AL,STS8251		;;; GET 8251A STATUS
	TEST	AL,RxRDY		;;; RECEIVER READY (GOT A CHARACTER)?
	JZ	RETINT			;;; IF Z NO
	IN	AL,BUF8251		;;; ELSE GET CHARACTER INPUT
	CMP	TELFLG,0		;;; TERMINAL EMULATION MODE?
	JZ	SRINT0			;;; IF Z NO
	AND	AL,07FH			;;; ELSE TERMINAL MODE 7 BITS ONLY 
SRINT0:	OR	AL,AL			;;; IS THIS A NUL CHARACTER?
	JZ	RETINT			;;; IF Z YES, IGNORE NULS
	CMP	AL,07FH			;;; CHARACTER A RUBOUT?
	JZ	RETINT			;;; IF Z YES, IGNORE THEM TOO
	MOV	BP,PORTVAL		;;; GET ADDRESS OF PORT STRUCTURE
	CMP	DS:[BP].FLOFLG,0	;;; ARE WE DOING FLOW CONTROL?
	JE	SRINT2			;;; IF E NO
	MOV	BX,DS:[BP].FLOWC	;;; FLOW CONTROL (BH = XON, BL = XOFF)
	CMP	AL,BL			;;; IS INPUT CHARACTER AN XOFF?
	JNE	SRINT1			;;; IF NE NO, SO CONTINUE
	MOV	XOFRCV,TRUE		;;; SET RECEIVED XOFF
	JMP	RETINT			;;; AND EXIT FOR NOW
SRINT1:	CMP	AL,BH			;;; GET AN XON?
	JNE	SRINT2			;;; IF NE NO, CONTINUE
	MOV	XOFRCV,FALSE		;;; CANCEL XOFF
	JMP	RETINT			;;; AND EXIT INTERRUPT
SRINT2:	STOSB				;;; STORE CHARACTER IN BUFFER
	CMP	DI,OFFSET SOURCE + BUFSIZ ;;; TIME TO WRAP BUFFER BACK TO START
	JB	SRINT3			;;; IF B NO
	MOV	DI,OFFSET SOURCE	;;; ELSE WRAP BUFFER BACK TO START
SRINT3:	INC	COUNT			;;; COUNT CHARACTER INPUT
	CMP	DS:[BP].FLOFLG,0	;;; DOING FLOW CONTROL?
	JE	RETINT			;;; IF E NO, JUST LEAVE INTERRUPT
	CMP	XOFSNT,TRUE		;;; HAVE WE SENT AN XOFF?
	JE	RETINT			;;; IF E YES, JUST EXIT
	CMP	COUNT,MNTRGH		;;; PAST THE HIGH TRIGGER POINT?
	JBE	RETINT			;;; IF BE NO, WITHIN LIMIT
	MOV	AH,BL			;;; GET THE XOFF CHARACTER
	CALL	OUTCHR			;;; AND SEND IT
	NOP				;;; ALLOW FOR RSKP RETURN ON ERROR
	NOP				;;;	"
	NOP				;;;	"
	MOV	XOFSNT,TRUE		;;; SET SENT XOFF CHARACTER
RETINT:	MOV	SRCPNT,DI		;;; SAVE UPDATED BUFFER POINTER
	POP	ES			;;; RESTORE SEGMENT REGISTER
	POP	DS			;;; RESTORE SEGMENT REGISTER
	POP	BP			;;; RESTORE FRAME POINTER
	POP	DI			;;; RESTORE REGISTER
	POP	DX			;;; RESTORE REGISTER
	POP	CX			;;; RESTORE REGISTER
	POP	BX			;;; RESTORE REGISTER
	POP	AX			;;; RESTORE REGISTER
INTRET:	IRET				;;; RETURN FROM INTERRUPT
SERINT	ENDP

;
; PRTCHR - CHECK FOR CHARACTER AT AUX DEVICE
;
; OUTPUTS:
;	AL	- CHARACTER IF ONE AVAILABLE
;	DX	- NUMBER OF CHARACTERS IN BUFFER
; NOTES:
;	SKIPS RETURN IF NO CHARACTER AVAILABLE.
;
PRTCHR  PROC	NEAR
	CALL	CHKXON			; CHECK TO SEE IF XON NEEDED
	CMP	COUNT,0			; ANY CHARACTERS IN BUFFER?
	JNZ	PRTCH1			; IF NZ YES
	JMP	RSKP			; ELSE NO DATA, JUST RETURN
PRTCH1:	MOV	SI,SAVESI		; GET SAVED BUFFER POINTER
	LODSB				; GET NEXT BYTE FROM BUFFER
	CMP	SI,OFFSET SOURCE + BUFSIZ ; TIME TO WRAP BUFFER?
	JB	PRTCH2			; IF B NO
	MOV	SI,OFFSET SOURCE	; WRAP BUFFER BACK TO START
PRTCH2:	DEC	COUNT			; COUNT CHARACTER REMOVED
	MOV	SAVESI,SI		; SAVE BUFFER POINTER
	MOV	DX,COUNT		; RETURN NO. OF CHARS IN BUFFER
	RET				; AND RETURN
PRTCHR  ENDP

;
; CHKXON - CHECK TO SEE IF AN XON IS NEEDED
;
CHKXON	PROC	NEAR
	PUSH	BX			; SAVE REGISTER
	MOV	BX,PORTVAL		; GET ADDRESS OF PORT STRUCTURE
	CMP	[BX].FLOFLG,FALSE	; ARE WE DOING FLOW CONTROL?
	JE	CHKXO1			; IF E NO, JUST RETURN
	CMP	XOFSNT,FALSE		; HAVE WE ALREADY SENT AN XOFF?
	JE	CHKXO1			; IF E NO, JUST RETURN
	CMP	COUNT,MNTRGH		; ARE WE BELOW THE TRIGGER?
	JAE	CHKXO1			; IF AE NO, JUST RETURN
	MOV	AX,[BX].FLOWC		; GET XON INTO AH
	CALL	OUTCHR			; AND OUTPUT CHARACTER
	NOP				; IGNORE ERROR RETURN
	NOP				;	"
	NOP				;	"
	MOV	XOFSNT,FALSE		; SAY WE SENT AN XON NOW
CHKXO1:	POP	BX			; RESTORE REGISTER
	RET				; AND RETURN
CHKXON	ENDP

;
; SENDBR - SEND A BREAK OUT THE AUX DEVICE (SERIAL PORT)
;
SENDBR	PROC	NEAR
	PUSH	AX			; SAVE REGISTER
	PUSH	CX			; SAVE REGISTER
	XOR	CX,CX			; CLEAR LOOP VALUE
	MOV	AL,(TxEN+DTR+RxEN+RTS)	; GET OUTPUT 8251A ENABLE BYTE
	OUT	CMD8251,AL		; AND ENABLE 8251A
	MOV	AL,(TxEN+DTR+RxEN+SBRK+RTS) ; GET SEND BREAK ENABLE BYTE
	OUT	CMD8251,AL		; AND SEND BREAK
PAUSE:	LOOP	PAUSE			; KILL SOME TIME
	MOV	AL,(TxEN+DTR+RxEN+RTS)	; GET OUTPUT 8251A ENABLE BYTE
	OUT	CMD8251,AL		; STOP BREAK
	MOV	AL,(DTR+RxEN+ER+RTS)	; GET INPUT ENABLE BYTE
	OUT	CMD8251,AL		; AND RE-ENABLE INPUT
	POP	CX			; RESTORE REGISTER
	POP	AX			; RESTORE REGISTER
	RET				; RETURN
SENDBR	ENDP

;
; POSCUR - POSITION THE CURSOR
;
; INPUTS:
;	DH	- CONTAINS THE ROW
;	DL	- CONTAINS THE COLUMN
;
; NOTES:
;	RETURNS NORMALLY.
;
POSCUR	PROC	NEAR
	MOV	AH,2			; SET CODE TO POSITION CURSOR
	MOV	BH,0			; SET PAGE NUMBER
	INT	VIDEO			; AND POSITION THE CURSOR
	RET				; AND RETURN
POSCUR	ENDP

;
; DODEL - DELETE A CHARACTER FROM VIDEO SCREEN
;
; NOTES:
;	RETURNS NORMALLY.
;
DODEL	PROC	NEAR
	MOV	AH,PRSTR		; SET CODE TO PRINT STRING
	MOV	DX,OFFSET DELSTR	; SET ERASE STRING
	INT	DOS			; AND ERASE CHARACTER
	RET				; AND RETURN
DODEL	ENDP

;
; CTLU - CLEAR CURRENT LINE
;
; NOTES:
;	RETURNS NORMALLY.
;
CTLU	PROC	NEAR
	MOV	AH,PRSTR		; SET CODE TO PRINT STRING
	MOV	DX,OFFSET CLRLIN	; SET STRING ADDRESS
	INT	DOS			; OUTPUT STRING
	CALL	CLEARL			; NOW CLEAR THE LINE
	RET				; AND RETURN
CTLU	ENDP

;
; COMS - SET THE CURRENT PORT (ONLY ONE ON SANYO)
;
COMS	PROC	NEAR
	MOV	AX,OFFSET PORT1		; GET ADDRESS OF PORT STRUCTURE
	MOV	PORTVAL,AX		; AND SET IT
	RET				; WE'RE DONE
COMS	ENDP

;
; VTS - WE DON'T DO HEATH EMULATION, SANYO BIOS DOES VT-100 (SOMEWHAT)
;
VTS	PROC	NEAR
	MOV	AH,PRSTR		; SET CODE TO PRINT STRING
	MOV	DX,OFFSET NOIMP		; SET ADDRESS OF ERROR MESSAGE
	INT	DOS			; AND PRINT IT
	JMP	PRSERR			; AND EXIT
VTS	ENDP

;
; LCLINI - DO LOCAL INITIALIZATION
;
LCLINI:	MOV	FLAGS.VTFLG,0		; DON'T KNOW EXACTLY WHAT THIS DOES
	MOV	AX,0EH			; SET SCAN CODE FOR ARROW KEY
	MOV	SI,OFFSET RBTRN		; SET TRANSLATED CODE ADDRESS
	MOV	CX,1			; SET SIZE OF TRANSLATION
	CALL	DEFKEY			; AND DEFINE THE KEY
	RET				; AND RETURN

;
; SHOWKEY - DON'T DO THIS EITHER
;
SHOWKEY:
	MOV	AX,OFFSET SHKMSG	; SET ADDRESS OF MESSAGE
	MOV	CX,SHKLEN		; AND LENGTH OF MESSAGE
	RET

;
; BEEP - PRODUCE A BEEP
;
BEEP	PROC	NEAR
	MOV	DL,BELL			; SET ADDRESS OF BELL
	MOV	AH,DCONIO		; SET CODE FOR OUPUT
	INT	DOS			; OUTPUT BELL
	RET				; AND RETURN
BEEP	ENDP 
 
;
; TERM - TERMINAL EMULATOR (DUMB)
;
; INPUTS:
;	AX - POINTER TO ARGUMENT BLOCK
;
; NOTES:
;	THE SANYO BIOS WILL EMULATE (SOMEWHAT) A VT-100.
;
TERM	PROC	NEAR
	MOV	TELFLG,1		; SET TERMINAL EMULATION MODE
	MOV	SI,AX			; SET ADDRESS OF ARGUMENT BLOCK
	MOV	DI,OFFSET OURARG	; PLACE TO STORE ARGUMENTS
	MOV	AX,DS			; GET DATA SEGMENT ADDRESS
	MOV	ES,AX			; AND SET IN EXTRA SEGMENT
	MOV	CX,SIZE TERMARG		; AND SET SIZE OF MOVE
	REP	MOVSB			; COPY ARGUMENT BLOCK TO LOCAL STORE
TERM1:	CALL	PRTCHR			; GET NEXT CHAR FROM AUX, ABLE?
	JMP	SHORT TERM2		; YES, WE HAVE A CHAR
	NOP				; SPACE FOR RSKP RETURN
	NOP				;	"
	JMP	SHORT TERM3		; NO CHARACTER, SO CONTINUE
TERM2:	PUSH	AX			; SAVE CHARACTER
	MOV	DL,AL			; COPY CHARACTER
	MOV	AH,CONOUT		; SET CODE FOR CONSOLE OUTPUT
	INT	DOS			; AND GO PRINT IT
	POP	AX			; RESTORE REGISTER
	TEST	OURARG.FLGS,CAPT	; CAPTURING OUTPUT?
	JZ	TERM3			; IF Z NO, CONTINUE
	CALL	OURARG.CAPTR		; ELSE CALL THE CAPTURE ROUTINE
TERM3:	MOV	AH,DCONIO		; SET CODE FOR INPUT
	MOV	DL,0FFH			; AND CODE
	INT	DOS			; CHECK FOR CHARACTER, WELL?
	JZ	TERM1			; IF Z NO CHARACTER, GO ON
	CMP	AL,OURARG.ESCC		; ESCAPE CHARACTER?
	JE	TERM4			; YES, EXIT
	PUSH	AX			; SAVE CHARACTER
	MOV	AH,AL			; COPY THE CHARACTER
	CALL	OUTCHR			; OUTPUT CHARACTER TO AUX DEVICE
	NOP				; IGNORE ERRORS
	NOP				;	"
	NOP				;	"
	POP	AX			; RESTORE CHARACTER
	TEST	OURARG.FLGS,LCLECHO	; LOCAL ECHO REQUIRED?
	JZ	TERM1			; IF Z NO, CONTINUE
	MOV	DL,AL			; ELSE COPY CHARACTER
	MOV	AH,DCONIO		; SET CODE
	INT	DOS			; AND ECHO IT
	JMP	TERM1			; AND CONTINUE
TERM4:	MOV	TELFLG,0		; CLEAR TERMINAL EMULATION MODE
	RET
TERM	ENDP

;
; RSKP - JUMP RETURN WITH SKIPPING
;
RSKP    PROC    NEAR
	POP	BP			; GET TOP OF STACK
	ADD	BP,3			; ADD SKIP RANGE
	PUSH	BP			; AND RESTORE IT
	RET
RSKP    ENDP
 
CODE	ENDS
	END
