; B5MH-5.INS - BYE5 insert for Morrow MD5, MD11, MD16, MD34 - 08/26/86
;
;		Z80 SIO and 8253 baudrate generator
;
;		 This is an insert, not an overlay
;
; This insert adapts the Morrow computers using hard disk and CP/M+
; with bank memory to BYE5.
;
;
;=   =	 =   =	 =   =	 =   =	 =   =	 =   =	 =   =	 =   =	 =   =
;
; 08/26/86  Changed SETINV routine.  Added comment of where to reinstall
;    v5     MDPREP and MDPOSP calls in the main program.
;					- George Reding
;
; 07/18/86  Removed bank switching code for compatibility with BYE510
;    v4     or greater. 		- Stuart Rose
;
; 10/10/85  Reorganized and simplified. - Ed Meyer
;    v3
;
; 08/25/85  Fixed BUG in the Morrow BIOS INTER-BANK routine.
;    v2 				- Paul Bartholomew
;
; 08/17/85  Updated for compatibility with BYE501.
;    v1 				- George Peace
;
;=   =	 =   =	 =   =	 =   =	 =   =	 =   =	 =   =	 =   =	 =   =
;
; To get this to work correctly with a Morrow MD-HD, you must configure
; your cable in accord with the setting of jumpers inside your computer.
; Pins 2 and 3 may or may not need to be crossed. Carrier detect (pin 8)
; from the modem will connect to pin 8 (or pin 4) on the computer, in
; accord with the setting of the jumpers.
;
; ** Consult your MD-## Users Guide, Appendix D, figures D-5 and D-6. **
;
;-----------------------------------------------------------------------
;
;
; Set ONE of the following to YES, the other to NO
;
PMPORT	EQU	NO		; Yes, using "Printer/Modem" port
AUXPORT	EQU	YES		; Yes, using "Auxilliary" port
;
PORT	EQU	060H		; Port for local console output
CONST	EQU	PORT+1		; Local console status
;
;
	 IF	PMPORT
BPORT	EQU	062H
BAUDS	EQU	051H
MODEW	EQU	07EH
	 ENDIF			; PMPORT

	 IF	AUXPORT
BPORT	EQU	070H
BAUDS	EQU	050H
MODEW	EQU	03EH
	 ENDIF			; AUXPORT
;
;
; The following define the port addresses to use.
;
DPORT	EQU	BPORT		; Data port
MDCTL1	EQU	BPORT+1		; Status/control port
BRPORT	EQU	053H
;
;
; The following are MDCTL1 status masks
;
MDRCV	EQU	1		; Data available
MDSND	EQU	4		; Transmit buffer empty
DCD	EQU	8		; Data carrier detect
;
;-----------------------------------------------------------------------
;
;
; See if we still have a carrier - if not, return with the zero flag set
;
MDCARCK:MVI	A,10H		; Reset status
	OUT	MDCTL1
	IN	MDCTL1		; Get status
	ANI	DCD		; Check for data carrier
	RET			; Return
;.....
;
;
; Disconnect and wait for an incoming call
;
MDINIT:	MVI	A,18H		; Reset channel
	OUT	MDCTL1
	MVI	A,4		; Setup to write register 4
	OUT	MDCTL1
	MVI	A,44H		; No parity, 1 stop, 16x
	OUT	MDCTL1
	MVI	A,1		; Setup to write register 1
	OUT	MDCTL1
	MVI	A,0
	OUT	MDCTL1
	MVI	A,5		; Setup to write register 5
	OUT	MDCTL1
	MVI	A,0		; DTR, RTS both off
	OUT	MDCTL1
	PUSH	B		; Save in case it's being used elsewhere
	MVI	B,20		; 2 second delay
;
OFFTI:	CALL	DELAY		; 0.1 second delay
	DCR	B
	JNZ	OFFTI		; Keep looping until finished
	POP	B		; Restore bc
	MVI	A,3		; Setup to write register 3
	OUT	MDCTL1
	MVI	A,0C1H		; 8 bits, enable receive
	OUT	MDCTL1
	MVI	A,5		; Setup to write register 5
	OUT	MDCTL1
	MVI	A,0EAH		; DTR, RTS, TX on, 8 bits
	OUT	MDCTL1

	 IF	IMODEM		; If using intelligent modem
	CALL	IMINIT		; Go initialize modem now
	 ENDIF			; IMODEM
;
	RET			; Return
;.....
;
;
; Input a character from the modem port
;
MDINP:	IN	DPORT		; Get character
	RET			; Return
;.....
;
;
; Check the status to see if a character is available.	If not, return
; with the zero flag set.  If yes, use 0FFH to clear the flag.
;
MDINST:	IN	MDCTL1		; Get status
	ANI	MDRCV		; Got a character?
	RZ			; Return if none
	ORI	0FFH		; Otherwise, set the proper flag
	RET			; And return
;.....
;
;
; Send a character to the modem
;
MDOUTP:	OUT	DPORT		; Send it
	RET			; Return
;.....
;
;
; See if the output is ready for another character
;
MDOUTST:IN	MDCTL1
	ANI	MDSND		; Mask it
	RET			; Return
;.....
;
;
; Reinitialize the modem and hang up the phone by dropping DTR and
; leaving it inactive.
;
MDQUIT:	 IF	IMODEM		; If using an intelligent modem
	CALL	IMQUIT		; Tell it to shut down
	 ENDIF			; IMODEM
;
;
; Called by the main program after caller types BYE.
;
MDSTOP:	MVI	A,5		; Setup to write register 5
	OUT	MDCTL1
	MVI	A,0		; Clear DTR, RTS causing shutdown
	OUT	MDCTL1
	RET
;.....
;
;
; The following routine sets the baudrate.  BYE5 asks for the maximum
; speed you have available.
;
SETINV:	ORI	0FFH		; Make sure zero flag is not set
	RET
;.....
;
;
SET300:	LXI	H,BD300
	JMP	SETBAUD
;
SET1200:LXI	H,BD1200
	JMP	SETBAUD
;
SET2400:LXI	H,BD2400
	JMP	SETBAUD
;
SETBAUD:MVI	A,MODEW
	OUT	BRPORT
	MOV	A,L
	OUT	BAUDS
	MOV	A,H
	OUT	BAUDS
	XRA	A		; Say rate is ok
	RET			; Return
;.....
;
;
; The following are baud rates for BPORT -- they will have to be changed
; for your particular CTC.
;
BD300	EQU	833
BD1200	EQU	208
BD2400	EQU	104
BD9600	EQU	26
;.....
;
;
;Find address of INTER-BANK BUG in Morrow's BIOS
;
FINDBUG:LDA	FNDBUG		; See if we already found the address
	ORA	A
	JZ	FBUG0		; No, go find it
	LHLD	BUGADR		; Yes, return with address
	RET
;.....
;
;
FBUG0:	LHLD	1
	INX	H
	MOV	E,M
	INX	H
	MOV	D,M
	XCHG			; Hl points to warm boot code
;
;
; The warm boot in common memory is as follows:
;
; loc  opcodes	mneumonics
; ---- -------	--------------------
; xxxx 21 yyyy	LD	HL,BNK-WBOOT ;WARM BOOT code in SYSTEM bank
; xxxx 18 zz	JR	INTER-BANK
;
; We will find the address of INTER-BANK and modify it to fix the BUG.
;
; The INTER-BANK code in COMMON memory is as follows:
;
; loc  opcodes	mneumonics
; ---- -------	--------------------
; xxxx 3A yyyy	LD	A,(SYSMTE-BANK-BITS)
; xxxx CB 47	BIT	0,A	;Should be BIT 1,A (CB 4F)
;
;
FBUG1:	MOV	A,M
	CPI	18H		; Look for JR to INTER-BANK
	JZ	FBUG2
	INX	H
	JMP	FBUG1
;
FBUG2:	INX	H
	MOV	A,M		; Get JR offset
	INX	H
	MOV	E,A
	MVI	D,0
	DAD	D		; HL now points to INTER-BANK
;
FBUG3:	MOV	A,M
	CPI	0CBH		; Look for bit opcode
	JZ	FBUG4
	INX	H
	JMP	FBUG3
;
FBUG4:	INX	H
	SHLD	BUGADR
	MVI	A,0FFH
	STA	FNDBUG
	RET
;.....
;
;
FNDBUG:	DB	0
BUGADR:	DW	0
BUGVAL:	DB	0
;
;.....
;
; In the main program, CALL to MDPREP and MDPOSP should be at the
; following locations.	If not present, they may be re-installed.
; CALL MDPREP should be in the PATCH: routine, before CALL TBLADDR.
; CALL MDPOSP should be in the EXCPM: routine, before CALL RSXCLR.
;
;.....
;
; Perform system or hardware dependent PRE-processing.	The following
; code will be executed by the PATCH subroutine before the BIOS jump
; table is overwritten.  This will allow the BIOS intercept routines to
; operate as early as the initial signon message display.
;
MDPREP:	CALL	FINDBUG		; Get address of BIOS bug
	MOV	A,M
	STA	BUGVAL		; Save old value
	MVI	M,04FH		; Change the bit 0,A to a bit 1,A
;
; OK, the BIOS BUG is now fixed.
;
	RET
;.....
;
;
; Perform system or hardware dependent POST-processing.  The following
; code will be executed by the EXCPM routine before returning control to
; CP/M Plus when the BYE5 program is terminated.
;
MDPOSP:	CALL	FINDBUG		; Get address of BIOS bug
	LDA	BUGVAL		; Get old value
	MOV	M,A		; Un-fix the BIOS bug (make it a bit 0)
	RET
;.....
;
;			       end
;-----------------------------------------------------------------------
