;********************************************************
;*							*
;*	DISK I/O ROUTINES FOR XEBEC S1410 CONTROLLER	*
;*							*
;*	LAST EDIT DATE:  25-AUGUST-82			*
;*							*
;********************************************************
;
DMA	EQU	08CH		;Z80 DMA PORT ADDRESS
SELMUX	EQU	0CCH		;DRIVE SEL/READY MUX CONTROL PORT
SASI	EQU	0D8H		;SASI BUS BASE ADDRESS

COMAND	EQU	00100000B
DATA	EQU	00000000B
MSG	EQU	00001000B
BUSY	EQU	00000010B
INPUT	EQU	00000001B
OUTPUT	EQU	00000000B

SEL	EQU	3
RST	EQU	2
ON	EQU	00001000B
OFF	EQU	00000000B
;
;
;
DOWINCH:
	LD	HL,(HSTTRK)
	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,HL		;CREATE DISK ADDRESS BYTES FOR DCB
	LD	A,H
	LD	(DCB+2),A	;STORE MIDDLE ADDRESS BYTE
	LD	A,(HSTSEC)
	DEC	A		;REMOVE +1 BIAS FROM WINCHESTER SECTOR
	AND	00011111B
	OR	L
	LD	(DCB+3),A	;STORE LOW ADDRESS BYTE
	LD	A,(RWFLAG)
	OR	A
	JR	Z,DWIN3
DWIN2:	CALL	RD		;READ FROM WINCHESTER
	JR	DWIN4
;
DWIN3:	CALL	WRT		;WRITE TO WINCHESTER
DWIN4:	OR	A
	RET	Z		;EXIT IF NO ERRORS FROM SASI

	LD	HL,SASMSG
	CALL	PMSG		;PRINT SASI BUS ERROR MESSAGE
	LD	A,(ERRBUF)
	BIT	7,A		;TEST IF ADDRESS FIELD IS APPLICABLE
	JR	Z,DWINX		;PRINT ONLY FIRST STATUS BYTE IF NOT
	RES	7,A
	CALL	PUTHEX
	LD	A,(ERRBUF+1)
	CALL	PUTHEX
	LD	A,(ERRBUF+2)
	CALL	PUTHEX
	LD	A,(ERRBUF+3)
DWINX:	CALL	PUTHEX
	LD	A,1
	OR	A
	RET			;RETURN PERMANENT ERROR TO CP/M
;
;
;
PUTHEX:
	PUSH	AF
	RRA
	RRA
	RRA
	RRA
	CALL	PNYBBL		;PRINT HIGH NYBBLE OF HEX BYTE
	POP	AF
	CALL	PNYBBL		;PRINT LOW NYBBLE OF HEX BYTE
	CALL	PMSG		;PRINT DELIMITER CHARACTER @HL
	RET
;
;
PNYBBL:	AND	00001111B
	ADD	A,90H
	DAA
	ADC	A,40H
	DAA
	LD	C,A
	CALL	OVEC
	RET
;
;
SASMSG:	DEFB	CR,LF
	DEFB	'BIOS error on SASI  status=',NULL
	DEFB	'.',NULL
	DEFB	'.',NULL
	DEFB	'.',NULL
	DEFB	' ',NULL
;
;
;
;
DCB:	DEFB	0,0,0,0,0,0	;DEVICE CONTROL BLOCK
ERRBUF:	DEFB	0,0,0,0		;ERROR STATUS BUFFER
;
;
;
RD:
	LD	HL,RDDCB
	CALL	CMDOUT		;OUTPUT READ COMMAND TO XEBEC
RD1:	IN	A,(SASI+1)
	AND	00100001B
	CP	COMAND+INPUT
	JR	Z,RD3		;JUMP IF READ ERROR
	CP	DATA+INPUT
	JR	NZ,RD1		;ELSE LOOP UNTIL DATA READ
	CALL	REQ
	LD	HL,(HSTPTR)
	LD	B,0
	LD	C,SASI
	INIR			;INPUT SECTOR DATA FROM XEBEC
RD2:	IN	A,(SASI+1)
	AND	00100001B
	CP	COMAND+INPUT
	JR	NZ,RD2		;LOOP UNTIL COMPLETION STATUS RDY
RD3:	CALL	COMPLETE
	LD	A,B
	AND	00000010B
	RET	Z		;EXIT IF NO ERRORS

	CALL	ERROR		;ELSE READ ERROR STATUS
	RET

RDDCB:	DEFB	00001000B	;READ COMMAND OPCODE
	DEFB	0		;HIGH ADDRESS
	DEFB	0		;MIDDLE ADDRESS
	DEFB	0		;LOW ADDRESS
	DEFB	1		;BLOCK COUNT
	DEFB	0		;CONTROL FIELD
;
;
;
;
WRT:
	LD	HL,WRTDCB
	CALL	CMDOUT		;OUTPUT WRITE COMMAND TO XEBEC
WRT1:	IN	A,(SASI+1)
	AND	00100001B
	CP	DATA+OUTPUT
	JR	NZ,WRT1		;LOOP UNTIL WRITE DATA REQUESTED
	CALL	REQ
	LD	HL,(HSTPTR)
	LD	B,0
	LD	C,SASI
	OTIR			;BLAST DATA OUT TO XEBEC
WRT2:	IN	A,(SASI+1)
	AND	00100001B
	CP	COMAND+INPUT
	JR	NZ,WRT2		;LOOP UNTIL COMMAND COMPLETION
	CALL	COMPLETE
	LD	A,B
	AND	00000010B
	RET	Z		;EXIT IF NO ERRORS

	CALL	ERROR		;ELSE REQUEST-SENSE-STATUS
	RET


WRTDCB:	DEFB	00001010B	;WRITE COMMAND OPCODE
	DEFB	0		;HIGH ADDRESS
	DEFB	0		;MIDDLE ADDRESS
	DEFB	0		;LOW ADDRESS
	DEFB	1		;BLOCK COUNT
	DEFB	0		;CONTROL FIELD
;
;
;
COMPLETE:
	IN	A,(SASI)	;READ FIRST COMPLETION BYTE
	LD	B,A
COMP2:	IN	A,(SASI+1)
	AND	00001000B
	JR	Z,COMP2		;LOOP UNTIL MSG INPUT BECOMES ACTIVE
	IN	A,(SASI)	;READ SECOND COMPLETION BYTE
	LD	C,A
COMP3:	IN	A,(SASI+1)
	AND	00001000B
	JR	NZ,COMP3	;LOOP UNTIL MSG INPUT GOES AWAY AGAIN
	RET
;
;
;
ERROR:	LD	HL,RSSDCB
	CALL	CMDOUT		;ISSUE READ-SENSE-STATUS COMMAND
ERR1:	IN	A,(SASI+1)
	AND	00100001B
	CP	DATA+INPUT
	JR	NZ,ERR1		;LOOP UNTIL STATUS BYTES AVAILABLE
	CALL	REQ
	LD	HL,ERRBUF
	LD	B,4
	LD	C,SASI
	INIR			;READ STATUS BYTES INTO BUFFER
ERR2:	IN	A,(SASI+1)
	AND	00100001B
	CP	COMAND+INPUT
	JR	NZ,ERR2		;LOOP UNTIL COMMAND COMPLETION
	CALL	REQ
	CALL	COMPLETE
	LD	A,1
	OR	A
	RET			;RETURN PERMANENT ERROR INDICATION

RSSDCB:	DEFB	00000011B	;REQUEST SENSE STATUS OPCODE
	DEFB	0
	DEFB	0
	DEFB	0
	DEFB	0
	DEFB	0
;
;
;
CMDOUT:
	LD	A,1
	OUT	(SASI),A
	LD	A,SEL+ON
	OUT	(SASI+1),A	;SELECT XEBEC CONTROLLER #1
	LD	A,SEL+OFF
	OUT	(SASI+1),A
CMD1:	IN	A,(SASI+1)
	AND	00101011B	;MASK TO STATUS INPUT BITS FROM SASI
	CP	COMAND+BUSY+OUTPUT
	JR	NZ,CMD1		;LOOP UNTIL XEBEC ENTERS COMMAND MODE

	LD	DE,DCB
	LD	BC,2
	LDIR			;COPY XEBEX COMMAND BYTES TO BUFFER
	INC	HL
	INC	HL
	INC	DE
	INC	DE		;BUMP PAST MIDDLE/LOW ADDRESS BYTES
	LD	BC,2
	LDIR
	LD	HL,DCB
	LD	B,6
	LD	C,SASI
	OTIR			;PUT COMMAND BYTES OUT TO XEBEC
CMD2:	IN	A,(SASI+1)
	AND	00101011B
	CP	COMAND+BUSY+OUTPUT
	JR	Z,CMD2		;LOOP UNTIL XEBEC LEAVES COMMAND MODE
	RET
;
;
;
REQ:
	DI
	LD	HL,INUSE
	LD	A,(HL)
	LD	(HL),1
	EI
	PUSH	AF
	OR	A		;TEST IF FOLPPYS WERE SELECTED OR NOT
	LD	A,(SELCPY)
	JR	Z,REQ1
	AND	00001111B
REQ1:	PUSH	AF
	OR	00001111B	;SELECT SASI REQ/ACK HANDSHAKE FLIPFLOP
	OUT	(SELMUX),A	; THROUGH DMA READY MULTIPLEXOR
	LD	A,10001010B
	OUT	(DMA),A		;PROGRAM DMA READY ACTIVE HIGH
REQ2:	LD	A,10111111B
	OUT	(DMA),A		;ISSUE READ-DMA-STATUS COMMAND
	IN	A,(DMA)
	BIT	1,A
	JR	NZ,REQ2		;LOOP TILL READY IS ACTIVE
	POP	AF
	OUT	(SELMUX),A
	POP	AF
	LD	(INUSE),A	;RESTORE IN-USE FLAG TO PREVIOUS STATE
	RET
;
;
;
;
;
;	DISK PARAMETER BLOCK FOR SEAGATE ST-506 WINCHESTER
;
MAXBLK	EQU	1224		;NUMBER OF BLOCKS ON DISK

WINSTUFF:
	DEFW	0		;NO SECTOR SKEW TABLE

	DEFW	64		;SECTORS PER TRACK
	DEFB	5		;BLOCK SHIFT
	DEFB	00011111B	;BLOCK MASK
	DEFB	00000001B	;EXTENT MASK
	DEFW	MAXBLK-1	;MAX BLOCK#
	DEFW	511		;MAX DIRECTORY ENTRY#
	DEFB	11110000B	;ALLOCATION MASK MSB
	DEFB	00000000B	;'             ' LSB
	DEFW	0		;CHECK SIZE (NOT REMOVABLE MEDIA)
	DEFW	0		;RESERVED TRACKS

	DEFB	1		;DEBLOCK SHIFT COUNT
	DEFB	00000001B	;DEBLOCK MASK
	DEFW	256		;BYTES PER SECTOR
;
;
;
;
