	TITLE	INTELLIGENT SASI HOST ADAPTOR (ISHA) FIRMWARE
	LIST	NOCOND
;**************************************************************************
;
;	THIS MODULE CONTAINS THE INTELLIGENT HOST ADAPTER FIRMWARE.
;
;**************************************************************************
;
;	IOPB CONFIGURATION:
;
; DRIVE		USAGE
;   0		SASI physical drive 0
;   1		SASI physical drive 1
;   2		SASI physical drive 2	(OPTIONAL)
;   3		SASI physical drive 3	(OPTIONAL)
;
;**************************************************************************
;
;	REVISIONS:
; 1.0 -	28 DEC 83   GRH
;	DIAGNOSTIC VERSION FOR TESTING THE BOARD.
; 1.1 -	2 JAN 84   GRH
;	ADD HARD DISK CONTROLLER FIRMWARE.
; 1.2 -	1 APR 84   GRH
;	Fix Bug in host xfer subr. that caused problems on 32k boundary
;	crossings. Enable parity checking for received data. Enable
;	controller retrys.
; 1.3 -	2 APR 84   GRH
;	Fix Bug in read buffer routine which caused 1st 4 bytes of sector
;	to be 0 and read not retryed but sense status to be issued instead.
;	The CDB had to be re-initialized with the read command after getting
;	results command issued.
;
; 1.4 -	28 APR 84   GRH
;	Add Jade FDC routines. Change host block move subrs into general
;	 purpose subrs.
;
; 1.5 -	30 APR 84   GRH
;	Change hardware to reflect the state of the interrupt flip-flop
;	as the busy bit (D0). Hardware will now allow software setting of
;	the interrupt flip-flop to allow passing a busy state if required.
;	Normally this change will allow transparent operation of the soft-
;	ware, without concern to the busy status. All other status bits
;	reflect the software status register contents (D1..7).
;
; 1.6 - 3 MAY 84   GRH
;	Change block move subroutine to allow for 1..65,536 byte moves.
;	Fix bugs in Jade driver. Add printer output diagnostic.
;
; 1.7 -	2 JUN 84   GRH
;	Fix bug in HSTIN & HSTOUT macros outputting bit 7 data to XADDR
;	  register instead of to HXAD15 register.
;	Add JADE FDC dump to dump diagnostic command.
;
; 1.8 -	2 JUN 84   GRH
;	Change floppy disk read/write sector to logical sector for uniformity
;	   in IOPB parameters. (0..N-1 now changed to 1..N)
;
; 1.9 -	3 OCT 84   GRH
;	Fix bug in Jade driver which allowed errors to go undetected.
;
; 1.A -	18 APR 85   GRH
;	Fix logon problem. Code is only now showing bugs with 2nd hard
;	  disk installed.
; 1.B -	6 DEC 85   GRH
;	Changed code to return new values for logon.
; 2.0 -	31 JAN 86   GRH
;	1. Remove SASI floppy driver.
;	2. Streamline code for speed & structure.
;	3. Modify error reporting (separate IOPB errors).
;	4. Modify Jade code to talk to new Jade firmware.
;	5. Modify diagnostics to pass address data in IOPB_PTR.
;	6. Add reset (power on) diagnostics.
;
VERSN	EQU	20H
;**************************************************************************
FALSE	EQU	0
TRUE	EQU	NOT FALSE
DEBUG	EQU	FALSE

;
;*INCLUDE JDDCONT.DEF
;*INCLUDE JDDDISK.DEF
;
	LIST	OFF
*INCLUDE JDDCONT.DEF
*INCLUDE JDDDISK.DEF
	LIST	ON

	SUBTTL	DEFINITIONS
;===============================
;
;   ASSEMBLY TIME CONSTANTS
;
;===============================
S100D	EQU	0D8H		;DATA PORT VISIBLE TO S100 BUS
S100S	EQU	S100D + 1	;STATUS PORT VISIBLE TO S100 BUS
S100C	EQU	S100S		;COMMAND PORT VISIBLE TO S100 BUS
;
LOCPRTS	EQU	0		;BASE ADDRESS OF LOCAL PORTS
LOCMEM	EQU	0		;BASE ADDRESS OF LOCAL RAM
;
S1PRTS	EQU	80H		;BASE ADDRESS OF S100 PORTS
;
S1MEM	EQU	8000H		;BASE ADDRESS OF S100 MEMORY WINDOW
;
LOCROM	EQU	LOCMEM		;BASE ADDRESS OF LOCAL ROM
LOCRAM	EQU	LOCMEM + 4000H	;BASE ADDRESS OF LOCAL RAM
RAMSIZE	EQU	2048		;SIZE OF LOCAL RAM
ROMSIZE	EQU	2048		;SIZE OF LOCAL ROM


;============================================================================
;			SASI BUS DATA LOCAL PORT
;============================================================================
SASIDATA EQU	LOCPRTS


;============================================================================
;			SASI BUS CONTROL LOCAL PORT
;============================================================================
SASICMD	EQU	LOCPRTS + 1
;
;  7 6 5 4 3 2 1 0
; |X|X|X| | | | | |
;	 ^ ^ ^ ^ ^__ INTERRUPT SELECT; 0: HOST, 1: ON SASI REQUEST
;	 | | | |____ 1: SASI RESET
;	 | | |______ 1: SASI DEVICE SELECT STROBE
;	 | |________ 0: SASI PARITY ERROR CLEAR
;	 |__________ 1: HOST VECTORED INTERRUPT
;
;   BIT #S:
SINTE	EQU	0	;SASI INTERRUPT
SRESET	EQU	1	;SASI RESET
SSELECT	EQU	2	;SASI DEVICE SELECT STROBE
SERRCLR	EQU	3	;SASI PARITY ERROR CLEAR*
HINT	EQU	4	;HOST VECTORED INTERRUPT


;============================================================================
;			SASI BUS STATUS LOCAL PORT
;============================================================================
SASIST	EQU	LOCPRTS + 1
;
;  7 6 5 4 3 2 1 0
; | |X|X| | | | | |
;  ^     ^ ^ ^ ^ ^__ 1: BUSY
;  |     | | | |____ 1: MESSAGE
;  |     | | |______ 1: COMMAND, 0: DATA
;  |     | |________ 0: REQUEST
;  |     |__________ 0: INPUT TO ISASI, 1: OUTPUT (TO CONTROLLER)
;  |________________ 1: PARITY ERROR
;
; BIT #S:
SBUSY	EQU	0		;BUSY BIT
SMSG	EQU	1		;MESSAGE BIT
SCD	EQU	2		;C/D BIT
SREQ	EQU	3		;REQUEST* BIT
SIO	EQU	4		;I/O* BIT
SPERR	EQU	7		;PARITY ERROR DETECTED BIT
; MASKS:
SSTMSK	EQU	10011111B	;STATUS BIT MASK
SSTINV	EQU	00011000B	;STATUS BIT INVERSION MASK
SSXMSK	EQU	00010110B	;XFER CONTROL MASK
SGTCMD	EQU	1 SHL SCD	;GET COMMAND FROM H/A
SGTDAT	EQU	0		;GET DATA FROM H/A
SSNDDAT	EQU	1 SHL SIO	;SEND DATA TO H/A
SSNDST	EQU	(1 SHL SIO) + (1 SHL SCD)	;SEND STATUS TO H/A
SCMDDN	EQU	(1 SHL SIO) + (1 SHL SCD) + (1 SHL SMSG)	;COMMAND DONE


;============================================================================
;		HOST'S INTERRUPT CLEAR LOCAL OUTPUT PORT
;	 		(DATA= DON'T CARE)
;============================================================================
HINTC	EQU	LOCPRTS + 2


;============================================================================
;		HOST'S INTERRUPT SET LOCAL OUTPUT PORT
;			(DATA= DON'T CARE)
;============================================================================
HINTS	EQU	LOCPRTS + 3


;============================================================================
;		HOST STATUS LOCAL OUTPUT PORT
;============================================================================
HSTAT	EQU	LOCPRTS + 4
;
;  7 6 5 4 3 2 1 0
; | |0|0|0|0|0| | |
;  ^           ^ ^__ 1: ISASI BUSY
;  |           |____ 1: FIRMWARE ERROR
;  |________________ 1: ERROR
;
; BIT #S:
HBUSY	EQU	0		;HOST BUSY STATUS BIT
HFERRB	EQU	1		;HOST FIRMWARE ERROR BIT
HSERRB	EQU	7		;HOST ERROR STATUS BIT
; MASKS:
HFERR	EQU	(1 SHL HSERRB) + (1 SHL HFERRB)	;FIRMWARE ERROR BYTE


;============================================================================
;			HOST COMMAND LOCAL INPUT PORT
;============================================================================
HCMD	EQU	LOCPRTS + 4	;HOST COMMAND PORT
;
;  7 6 5 4 3 2 1 0
; | | |0| | | | | |
;  ^ ^   \_____/ ^__ 1: HOST INTERRUPT
;  | |      |_______ NON-IOPB COMMAND CODE (0..F)
;  | |______________ 1: EXECUTE HOST IOPB
;  |________________ 1: HARDWARE LOCAL RESET
;
; BIT #S:
HINTRB	EQU	0		;HOST INTERRUPT REQUEST BIT
HIOPBB	EQU	6		;HOST EXECUTE IOPB BIT
HRESB	EQU	7		;HOST RESET LOCAL PROCESSOR BIT


;============================================================================
;		HOST DATA TRANSFER LOCAL I/O PORT
;============================================================================
HDATA	EQU	LOCPRTS + 5	;HOST DATA TRANSFER PORT


;============================================================================
;		HOST ACCESS ADDRESS BIT 15 LOCAL OUTPUT PORT
;============================================================================
HXAD15	EQU	LOCPRTS + 6	;HOST A15 SET PORT
;
;  7 6 5 4 3 2 1 0
; | |X|X|X|X|X|X|X|
;  ^________________ BIT APPLIED TO HOST BUS A15 WHEN ACCESSING ITS MEMORY
;			AND BIT 7 WHEN ACCESSING ITS I/O
;
; BIT #S:
A15B	EQU	7		;HOST A15 BIT


;============================================================================
;		HOST EXTENDED ADDRESS LOCAL OUTPUT PORT
;============================================================================
HXADDR	EQU	LOCPRTS + 7	;EXTENDED ADDRESS PORT (A16..A23)
;
;  7 6 5 4 3 2 1 0
; | | | | | | | | |
;  ^ ^ ^ ^ ^ ^ ^ ^__ A16
;  | | | | | | |____ A17
;  | | | | | |______ A18
;  | | | | |________ A19
;  | | | |__________ A20
;  | | |____________ A21
;  | |______________ A22
;  |________________ A23


;============================================================================
;
;	FIRMWARE ERROR CODES IN HOST DATA REGISTER IF HOST STATUS
; BIT 1 IS SET
;
;============================================================================
FERR00	EQU	-1	;UNKNOWN ERROR
FERR02	EQU	-2	;ROM TEST FAILURE
FERR03	EQU	-3	;ILLEGAL COMMAND
FERR04	EQU	-4	;ILLEGAL INTERRUPT
FERR07	EQU	-7	;CONTROLLER HANDSHAKE TIMOUT
FERR08	EQU	-8	;CONTROLLER SYNC ERROR ???
FERR09	EQU	-9	;CONTROLLER SENSE STATUS ERROR
FERR10	EQU	-10	;ILLEGAL IOPB PARAMETER
FERR11	EQU	-11	;PARITY ERROR


;============================================================================
;
;	HARD DISK DEFINITIONS
;
;============================================================================
HDCONT	EQU	0		;THIS CONTROLLER'S ADDRESS BIT
HDBASD	EQU	0		;BASE DRIVE # OF HD CONTROLLER
HDNDRV	EQU	4		;NUMBER OF PHYSICAL DRIVES SUPPORTED
HDNLUN	EQU	HDNDRV
INLEV	EQU	6		;INTERLEAVE FACTOR FOR FORMAT


;============================================================================
;
;	SASI DEFINITIONS
;
;============================================================================
SCRDY	EQU	0	;TEST DRIVE READY COMMAND
SCREC	EQU	1	;RECALIBRATE
SCSNSE	EQU	3	;REQUEST SENSE
SCFMTD	EQU	4	;FORMAT ENTIRE DRIVE
SCFMTT	EQU	6	;FORMAT TRACK
SCFMTBT	EQU	7	;FORMAT BAD TRACK
SCREAD	EQU	8	;READ SECTOR(S)
SCWRIT	EQU	10	;WRITE SECTOR(S)
SCSEEK	EQU	11	;SEEK TRACK

SCCOPY	EQU	20H	;COPY BLOCK(S)


;============================================================================
;
;	JADE DEFINITIONS
;
;============================================================================
JADBASD	EQU	4		;BASE DRIVE # OF JADE CONTROLLER
JADNDRV	EQU	4		;NUMBER OF LOGICAL JADE CONTROLLER DRIVES

	SUBTTL	MACROS
;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
;
;	GET DATA MACRO
;
;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
GETDATA	MACRO
AA#SYM:	CALL	GETSTAT		;IF REQUEST FALSE THEN WAIT
	BIT	SREQ,A
	JR	Z,AA#SYM
;
	INI			;GET DATA
;
	ENDM


;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
;
;	PUTDATA MACRO
;
;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
PUTDATA	MACRO
AC#SYM:	CALL	GETSTAT		;IF REQUEST NOT TRUE THEN WAIT
	BIT	SREQ,A
	JR	Z,AC#SYM
;
	OUTI			;ASSUME CALLER SET UP
;				DON'T WAIT
	ENDM

;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
;
;	BUFFER HALF SELECT MACRO
;
;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
SELCTBUF MACRO
	LD	HL,HDSECB	;ASSUME 1ST HALF
	LD	A,(IOPB + PBSECO) ;IF SECTOR IS ODD THEN SELECT UPPER HALF
	AND	1
	JR	Z,BB#SYM
;
	LD	HL,HDSECB + 128
BB#SYM:
	ENDM

;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
;
;	HOST OUTPUT MACRO
;
;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
HSTOUT:	MACRO	#PORT, #DATA
   IF	#PORT < 80H
	XOR	A
   ELSE
	LD	A,#PORT		;SET UP BIT 7
   ENDIF
	OUT	(HXAD15),A
;
   IF	(#DATA = 0) AND (#PORT >= 80H)
	XOR	A
   ENDIF
   IF	#DATA <> 0
	LD	A,#DATA		;OUTPUT DATA
   ENDIF
	OUT	(#PORT OR 80H),A
	ENDM

;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
;
;	HOST INPUT MACRO
;
;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
HSTIN:	MACRO	#PORT
   IF	#PORT < 80H
	XOR	A
   ELSE
	LD	A,#PORT		;SET UP BIT 7
   ENDIF
	OUT	(HXAD15),A
;
	IN	A,(#PORT OR 80H)	;FETCH DATA
	ENDM

	SUBTTL	CODE
;************************************************
;
;	PROCESSOR REGISTER USAGE:
;	IY= PTR TO CURRENT COMMAND DESCRIPTOR BLOCK
;
;************************************************
	ORG	LOCROM
;
RESETV:
;
;   INIT SOME THINGS
;
	OUT	(HINTS),A	;SET BUSY FLAG
;
	XOR	A		;PASS NOT -1 TO BOOT
	OUT	(HSTAT),A
;
	IM	1		;ONLY 1 INTERRUPT
;
	LD	SP,STACK	;INIT STACK
;
;   TEST RAM
;
	LD	HL,LOCRAM	;DO RAM TEST
	LD	BC,RAMSIZE
;
MTLP:	LD	A,(HL)		;COMPLEMENT & TEST
	CPL
	LD	(HL),A
	CP	(HL)
	JR	NZ,MEMERR	;IF NO COMPARE THEN ERROR
;
	CPL			;RESTORE
	LD	(HL),A
;
	INC	HL		;NEXT LOCATION
	DEC	BC
	LD	A,B
	OR	C
	JR	NZ,MTLP
;
;   DO RESET TESTS
;
	CALL	PUTEST
;
;   INIT THE REMAINDER
;
	CALL	INIT		;ANY OTHER INITIALIZATION
;
;   GO WAIT FOR HOST COMMAND
;
	LD	HL,0		;FORCE NO TIMEOUT
	LD	(TIMOUT),HL
;
	OUT	(HINTC),A	;TELL HOST IT'S OK NOW
;
	JP	HWAIT		;GO WAIT FOR HOST INTERRUPT
;
;
;   RAM ERROR ENCOUNTERED
;
MEMERR:	LD	A,RAMERR	;PASS ERROR TO HOST & HALT
	CALL	FERR
	HALT			;FATAL!

	IF	$ > 38H
	CONMSG	**** ERROR! RESET CODE OVERLAPS INTERRUPT CODE! ****
	ENDIF
;----------------------------------------------------------------------------
;
;	INTERRUPT ENTRY VECTOR FOR MODE 1
;
;----------------------------------------------------------------------------
	ORG	LOCROM + 38H
;
;   CHECK FOR SASI INTERRUPT
;
	IN	A,(HCMD)	;GET COMMAND
	BIT	HINTRB,A	;IF NOT HOST INTERRUPT THEN MUST BE SASI
	JP	Z,SASINT
;
;   CHECK FOR IOPB EXECUTE INTERRUPT
;
	BIT	HIOPBB,A	;IF IOPB BIT SET THEN EXECUTE IOPB
	JP	NZ,EXIOPB
;
;   COMMAND INTERRUPT
;
	AND	00011110B	;MASK OFF UNUSED COMMANDS
;
	CP	NUMCMDS * 2	;IF COMMAND ERROR THEN RETURN FIRMWARE ERR
	JR	C,CMDOK
;
;   ILLEGAL COMMAND, RETURN ERROR
;
	LD	A,FERR03
	JP	FERR
;
;
;   EXECUTE THE COMMAND
;
CMDOK:	LD	E,A		;SAVE COMMAND
;
	XOR	A,A		;ASSUME NO ERRORS
	OUT	(HSTAT),A
;
	LD	HL,CMDTBL	;CALCULATE THE TABLE ENTRY FROM THE COMMAND
	LD	D,0
	ADD	HL,DE		;VALUE ALREADY *2 (BIT 0 = 0)
;
	LD	E,(HL)		;FETCH THE COMMAND HANDLER ADDRESS FROM TABLE
	INC	HL
	LD	D,(HL)
	EX	DE,HL
;
	IN	A,(HDATA)	;PREFETCH THE DATA FOR THE COMMAND
;
;   CALL THE COMMAND HANDLER
;
	LD	DE,CMDRET	;PUT RETURN ADDRESS ON STACK
	PUSH	DE
	JP	(HL)
;
;----------------------------------------------------------------------------
;
;	ALL COMMANDS RETURN HERE WITH ERROR STATUS ALREADY SET FOR HOST
;
;----------------------------------------------------------------------------
CMDRET:	OUT	(HINTC),A	;TELL HOST WE'RE DONE
	RET			;RETURN TO THE INTERRUPTED ROUTINE


;----------------------------------------------------------------------------
;
;   MAIN INTERRUPTED LOOP
;
;----------------------------------------------------------------------------
HWAIT:
;
;   TO PRESERVE DATA, ALLOW INTERRUPT HERE ONLY
;
	EI
	NOP
	DI
;
;   IF TIMED OUT THEN CONTINUE TO WAIT
;
	LD	HL,(TIMOUT)	;IF TIMED OUT THEN JUST WAIT
	LD	A,H
	OR	L
	JR	Z,HWAIT
;
;   ELSE DELAY SOME MORE
;
	DEC	HL
	LD	(TIMOUT),HL
	LD	A,H		;IF TIME OUT JUST WENT TO 0 THEN
	OR	L
	JR	NZ,HWAIT
;
;   TIMED OUT, DESELECT SASI BUS
;
	CALL	DESELECT
;
;   SAFE TO ALLOW INTERRUPT HERE ALSO
;
	EI
	JR	HWAIT


;############################################################################
;
;	COMMAND TABLE FOR NON-IOPB COMMANDS
;
;############################################################################
CMDTBL:	DW	IOPBLO		;(1) SET IOPB LO COMMAND
	DW	IOPBHI		;(3) SET IOPB HI COMMAND
	DW	IOPBX		;(5) SET IOPB XADDR COMMAND
	DW	DIAG0		;(7) DUMP LOCAL MEMORY DIAGNOSTIC CMD
	DW	DIAG1		;(9) SET OUTPUT PORTS DIAG. COMMAND
	DW	DIAG2		;(B) TEST S100 MEMORY ACCESS COMMAND
	DW	DIAG3		;(D) BLOCK MOVE 01000H TO 02000H COMMAND
	DW	PRINT		;(F) PRINT ASCII STRING TO PORT COMMAND
	DW	RETVERS		;(11) RETURN FIRMWARE VERSION
NUMCMDS	EQU	($ - CMDTBL) / 2	;NUMBER OF COMMANDS


;****************************************************************************
;
;	FIRMWARE ERROR ENCOUNTERED, SET THE ERROR FLAGS SUBR
;	ENTRY-	A= ERROR CODE
;
;****************************************************************************
FERR:	OUT	(HDATA),A	;OUTPUT THE ERROR CODE
;
	LD	A,HFERR		;PASS ERROR FLAGS TO HOST
	OUT	(HSTAT),A
;
	OUT	(HINTC),A	;CLEAR ANY PENDING INTERRUPT
	RET

	SUBTTL	FIRMWARE COMMANDS
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	SET IOPB LOW ADDRESS COMMAND 1
; MUST BE INITIALIZED BEFORE DISK ACCESS
;	ENTRY-	A= LOW BYTE OF IOPB ADDRESS
;	EXIT -	HDATA= OLD DATA
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
IOPBLO:	LD	HL,IOPBL	;POINT TO LOW BYTE TO ALTER
	JR	IOPBST


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	SET IOPB HIGH ADDRESS COMMAND 3
; MUST BE INITIALIZED BEFORE DISK ACCESS
;	ENTRY-	A= HIGH BYTE OF IOPB ADDRESS
;	EXIT -	HDATA= OLD DATA
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
IOPBHI:	LD	HL,IOPBH	;POINT TO HIGH BYTE TO ALTER
	JR	IOPBST


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	SET IOPB EXTENDED ADDRESS COMMAND 5
; MUST BE INITIALIZED BEFORE DISK ACCESS
;	ENTRY-	A= EXTENDED ADDRESS BYTE OF IOPB ADDRESS
;	EXIT -	HDATA= OLD DATA
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
IOPBX:	LD	HL,IOPBXA	;POINT TO EXTENDED BYTE TO ALTER
;
;   COMMON CODE
;
IOPBST:	LD	C,(HL)		;SAVE OLD DATA
	LD	(HL),A		;SET NEW DATA
	LD	A,C		;PASS OLD DATA TO HOST
	OUT	(HDATA),A
;
	RET


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	DIAGNOSTIC DUMP COMMAND 7 LOADS HOST MEMORY WITH RAM IMAGE
;	EXIT -	(IOPB_PTR) OFFSETS:
;		+0000H..+07FFH= RAM IMAGE
;		+0800H..+0FFFH= ROM IMAGE
;		+1000H..+17FFH= JADE FDC IMAGE
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DIAG0:
;
;   DUMP LOCAL RAM 1ST
;
   IF	0
	LD	HL,LOCRAM
	LD	DE,(IOPBL)
	LD	A,(IOPBXA)
	LD	BC,RAMSIZE
	CALL	MOV2HST
   ELSE
	XOR	A,A
	OUT	(HXADDR),A
	OUT	(HXAD15),A
	LD	HL,LOCRAM
	LD	DE,S1MEM OR 4000H
	LD	BC,RAMSIZE
	LDIR
   ENDIF
;
;   FOLLOW WITH ROM IMAGE
;
   IF	0
	LD	A,(IOPBXA)		;MUST RESTORE BANK ADDRESS
   ENDIF
	LD	HL,LOCROM
	LD	BC,ROMSIZE
	JP	MOV2HST


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	DIAGNOSTIC 1 COMMAND 9 LOADS DATA INTO DATA OUT & STATUS REGS
;	ENTRY-	A= DATA
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DIAG1:	OUT	(HDATA),A
	OUT	(HSTAT),A
	RET


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;  DIAG2 COMMAND 11 TESTS S100 MEMORY READS & WRITES FROM (IOPB_PTR) TO +FFFH
;	EXIT-	(IOPBL)= LAST LOCATION CHECKED
;		(IOPBXA)= DATA READ FROM LAST LOCATION
;		STATUS PORT= 0: NO ERRORS, -1 ERROR
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DIAG2:
;
;   SET UP FOR TEST
;
	CALL	SETPTRS
;
;   TEST THE S100 ACCESS
;
D2LP:	LD	A,(HL)
	CPL
	LD	(HL),A
	CP	(HL)
	CPL			;RESTORE
	LD	(HL),A
	JR	NZ,D2ERR
;
	CALL	BUMPHL
	DEC	BC
	LD	A,B
	OR	C
	JR	NZ,D2LP
;
;   ERROR OR DONE, PASS BACK THE DATA
;
D2ERR:	LD	(IOPBL),HL	;FAILURE LOCATION
	LD	(IOPBXA),A	;ORIGINAL DATA
	RET	Z		;RETURN IF NO ERROR
;
;   TEST ERROR, PASS BACK TO HOST
;
	LD	A,FERR00
	JP	FERR


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	DIAG3 COMMAND 13 DOES S100 MEMORY ACCESSES DEPENDING ON DATA
; NOTE:	SCOPING TESTS CONTINUE UNTIL ANOTHER DATA WORD IS WRITTEN TO THE DATA
;	 REGISTER BY THE HOST.
;
;	ENTRY-	A= 0: BLOCK MOVE FROM 1000H TO 2000H
;		   1: READ FROM 1000H (SCOPING TEST)
;		   2: WRITE TO 1000H  (SCOPING TEST)
;		   3: BLOCK MOVE FROM E000H TO E800H
;		   ALL OTHERS: NOP
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DIAG3:
;
;   IF SUBCOMMAND 0 THEN GO DO MOVE
;
	OR	A
	JR	Z,DOMOVE
;
;   LOOP ON COMMAND
;
D3LP:	IN	A,(HDATA)		;IF DATA CHANGED THEN CHECK
;
	CP	2
	JR	C,DOREAD	   ;IF SUBCOMMAND == READ ADDRESS THEN EXIT
;
	JR	Z,DOWRITE		;IF SUBCOMMAND == WRITE THEN THEN EXIT
	CP	3
	JR	Z,DOBLKH	   ;IF SUBCOMMAND == HIGH BLOCK MOVE THEN EXIT
;
	RET
;
;
;   WRITE TO SINGLE LOCATION SUBCOMMAND
;
DOWRITE:
	LD	(S1MEM + 1000H),A
	JR	D3LP
;
;
;   READ FROM SINGLE LOCATION SUBCOMMAND
;
DOREAD:
	LD	A,(S1MEM + 1000H)
	JR	D3LP
;
;
;   BLOCK MOVE IN LOW HOST MEMORY THEN RETURN SUBCOMMAND
;
DOMOVE:	XOR	A,A			;DO IN LOW 32K
	OUT	(HXAD15),A
;
	LD	HL,S1MEM + 1000H
	LD	DE,S1MEM + 2000H
	LD	BC,1000H
	LDIR
;
	RET
;
;
;   BLOCK MOVE IN HIGH HOST MEMORY THEN RETURN SUBCOMMAND
;
DOBLKH:	LD	A,1 SHL A15B		;SET HIGH PAGE
	OUT	(HXAD15),A
	LD	HL,0E000H
	LD	DE,0E800H
	LD	BC,800H
	LDIR
;
	RET


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	PRINT TEXT ON THE PRINTER COMMAND 15
; EXERCISES THE I/O CAPABILITY
;	ENTRY-	A= PORT #
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
PRINT:	OUT	(HXAD15),A	;SET PORT TO DATA
	SET	7,A		;MAP TO HOST
	LD	C,A
;
;   OUTPUT NEW LINE
;
	CALL	CRLF
;
;   OUTPUT A LINE
;
	LD	E,'0'	;START WITH '0'
	LD	B,80	;DO 1 LINE
PRINT1:	CALL	PRT
	INC	E
	DJNZ	PRINT1
;
;   OUTPUT A NEW LINE
;
CRLF:	LD	E,0DH
	CALL	PRT
	LD	E,0AH
	JP	PRT


;----------------------------------------------------------------------------
;
;	RETURN FIRMWARE VERSION COMMAND 17
;	EXIT -	HDATA= VERSION # (HEX)
;
;----------------------------------------------------------------------------
RETVERS:
	LD	A,VERSN		;LOAD DATA REGISTER WITH VERSION
	OUT	(HDATA),A
;
	RET


;****************************************************************************
;
;	PRINT A CHARACTER TO HOST PORT
;	ENTRY-	C= PORT #
;		E= CHARACTER TO OUTPUT
;
;****************************************************************************
PRT:	IN	A,(C)	;IF BUSY THEN WAIT
	AND	1
	JR	NZ,PRT
;
;   OUTPUT STROBE* ON BIT 7
;
	LD	A,E	;OUTPUT CHARACTER WITH STROBE HIGH
	SET	7,A
	OUT	(C),A
;
	RES	7,A
	OUT	(C),A
;
	SET	7,A
	OUT	(C),A
;
	RET


	SUBTTL	SASI INTERRUPT
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	INTERRUPT WITHOUT HOST BIT SET
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
SASINT:
;
;   THIS VERSION DOESN'T SUPPORT THE INTERRUPT!
;
	LD	A,FERR04		;OUTPUT ERROR FOR NOW
	JP	FERR

	SUBTTL	IOPB EXECUTION
;----------------------------------------------------------------------------
;
;			EXECUTE IOPB COMMAND
;
;----------------------------------------------------------------------------
EXIOPB:
;
;   MOVE HOST IOPB INTO OUR LOCAL IOPB
;
	LD	HL,IOPB			;DESTINATION := LOCAL IOPB IMAGE
	LD	DE,(IOPBL)		;GET ADDRESS OF IOPB IN USER RAM
;
	LD	A,(IOPBXA)		;  SET BANK #
	LD	BC,IOPBSZ
;
	CALL	MOVFHST
;
;   ASSUME NO ERRORS
;
	LD	HL,0
	LD	(IOPB + PBSTATO),HL
	LD	(IOPB + PBST2O),HL
	LD	(IOPB + PBST4O),HL
;
;   CHECK FOR HARD DISK
;
	LD	A,(IOPB + PBDRVO)
	LD	HL,HDCMDS		;ASSUME HARD DISK COMMAND
	CP	HDNDRV
	JR	C,XTABL
;
;   NOT HARD DISK SO CHECK FOR JADE DISK
;
CHKJAD:
	LD	HL,JADCMDS		;ASSUME JADE CISK COMMAND
	SUB	JADBASD			;4..11 -> 0..7
	CP	JADNDRV
	JR	NC,XILDRV
;
	LD	(IOPB + PBDRVO),A	;CHANGE DRIVE
;
;   CHECK IF COMMAND IS ILLEGAL
;
XTABL:	LD	A,(IOPB + PBCMDO)	;CHECK IF LEGAL
	CP	MAXCMDS
	JR	NC,XILCMD
;
;   COMPUTE DRIVER ADDRESS
;
	LD	E,A
	LD	D,0
	ADD	HL,DE			;MULTIPLY CMD BY 2 FOR OFFSET
	ADD	HL,DE
	LD	A,(HL)			;GET COMMAND FROM TABLE
	INC	HL
	LD	H,(HL)
	LD	L,A
;
;   CALL THE COMMAND
;
	LD	DE,XRET		;PUT RETURN ADDRESS ON STACK
	PUSH	DE
	JP	(HL)			;EXECUTE COMMAND
;
XRET:
;
;   MOVE LOCAL IOPB TO HOST IOPB AREA FOR STATUS RETURN
;
	LD	HL,IOPB		;SOURCE := LOCAL IOPB IMAGE
	LD	DE,(IOPBL)	;GET ADDRESS OF IOPB IN USER RAM
	LD	A,(IOPBXA)	;  SET BANK #
;
	LD	BC,IOPBSZ
;
	CALL	MOV2HST
;
;   RETURN ERROR CODE IN STATUS REGISTER FOR COMPATABILITY
;
	LD	A,(IOPB + PBSTATO)
	OR	A,A
	JP	Z,IOPBCDN
;
	LD	A,1 SHL HSERRB
;
IOPBCDN:
	OUT	(HSTAT),A
;
;   SET DISK SELECT TIMEOUT
;
	LD	HL,-1		;MAX TIME
	LD	(TIMOUT),HL
;
;   TELL HOST WE'RE DONE
;
	OUT	(HINTC),A
	RET
;
;
;   ILLEGAL DRIVE ERROR
;
XILDRV:	LD	A,SELERR
	JR	SETSTAT
;
;
;   ILLEGAL COMMAND ERROR
;
XILCMD:	LD	A,CMDERR
SETSTAT:
	LD	(IOPB + PBSTATO),A
	JR	XRET


;############################################################################
;
;	IOPB COMMANDS
;
;############################################################################
JADCMDS:
	DW	JADLOG		;0: LOG ON DISK
	DW	JADREAD		;1: READ SECTOR
	DW	JADWRT		;2: WRITE SECTOR
	DW	JADFORM		;3: FORMAT TRACK
	DW	JADRDAD		;4: READ ADDRESS
	DW	JADEXEC		;5: EIA OUTPUT
	DW	JADEXEC		;6: EIA STATUS
	DW	JADEXEC		;7: IDLE
	DW	JADEXEC		;8: RETURN FIRMWARE VERSION
	DW	JADEXEC		;9: SET DISK FLAGS
	DW	JADEXEC		;10: LOAD HEAD & IDLE
	DW	JADEXEC		;11: SEEK TRACK
	DW	JADEXEC		;12: SET DRIVE PARAMETERS
	DW	JADEXEC		;13: RETURN DRIVE STATUS
	DW	JADEXEC		;14: SET EIA BAUD RATES
	DW	JADEXEC		;15: CLEAR
;
HDCMDS:
	DW	HDLOG		;0: LOG ON DISK (SELECT DISK)
	DW	HDREAD		;1: READ DEBLOCKED SECTOR
	DW	HDWRT		;2: WRITE DEBLOCKED SECTOR
	DW	HDFORM		;3: FORMAT TRACK
	DW	HDCERR		;4: RESERVED
	DW	HDCERR		;5: RESERVED
	DW	HDCERR		;6: RESERVED
	DW	HDCERR		;7: RESERVED
	DW	HDCERR		;8: RETURN FIRMWARE VERSION
	DW	HDCERR		;9: RESERVED
	DW	HDCERR		;10: RESERVED
	DW	HDSEEK		;11: SEEK TRACK (NORMALLY IMPLIED)
	DW	HDCERR		;12: RESERVED
	DW	HDCERR		;13: RETURN DRIVE STATUS
	DW	HDCERR		;14: RESERVED
	DW	HDCERR		;15: CLEAR
;
MAXCMDS	EQU	($ - HDCMDS) / 2

	SUBTTL	JADE IOPB COMMANDS
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	JADE CONTROLLER LOGON COMMAND IS SAME AS READ
;	EXIT -	(IOPB + PBSTATO)= 0 OR ERROR CODE
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
JADLOG:


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	JADE CONTROLLER READ SECTOR COMMAND
;	EXIT -	(IOPB + PBSTATO)= 0 OR ERROR CODE
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
JADREAD:
;
;   EXECUTE THE READ COMMAND
;
	HSTOUT	DDPORT,DDMB0	;SWITCH DD INTO MEMORY
	CALL	FDSKEX
;
;   XFER THE JADE CONTROLLER DATA TO LOCAL BUFFER
;
	HSTOUT	DDPORT,DDMB1	;DATA IN BANK 1
	LD	HL,(FDADDR)	;GET FDC ADDRESS
	LD	DE,JADSECB
	EX	DE,HL
	LD	BC,128		;FETCH SECTOR DATA
	XOR	A
	CALL	MOVFHST
;
;   REMOVE THE JADE CONTROLLER WINDOW
;
	HSTOUT	DDPORT,DDOUT
;
;   XFER THE SECTOR DATA FROM THE LOCAL BUFFER TO THE HOST MEMORY
;
	LD	HL,JADSECB	;NOW WRITE TO HOST
	JP	HDHSTW


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	JADE CONTROLLER WRITE SECTOR COMMAND
;	EXIT -	(IOPB + PBSTATO)= 0 OR ERROR CODE
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
JADWRT:
;
;   XFER DATA FROM HOST TO LOCAL BUFFER
;
	LD	HL,JADSECB	;GET DATA TO BUFFER
	CALL	HDHSTR
;
;   XFER LOCAL BUFFER TO JADE CONTROLLER
;
	HSTOUT	DDPORT,DDMB1	;GET FDC WINDOW
	LD	HL,(FDADDR)
	EX	DE,HL
	LD	HL,JADSECB
	LD	BC,128
	XOR	A
	CALL	MOV2HST
;
;   EXECUTE THE COMMAND
;
	CALL	FDSKEX		;EXECUTE WRITE SECTOR CMD
;
;   REMOVE THE JADE WINDOW
;
	HSTOUT	DDPORT,DDOUT	;REMOVE WINDOW
;
	RET


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	JADE CONTROLLER FORMAT COMMAND	(NOT IMPLEMENTED)
;	EXIT -	(IOPB + PBSTATO)= 0 OR ERROR CODE
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
JADFORM:


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	JADE CONTROLLER READ ADDRESS COMMAND (NOT IMPLEMENTED)
;	EXIT -	(IOPB + PBSTATO)= 0 OR ERROR CODE
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
JADRDAD:

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	JADE CONTROLLER ILLEGAL COMMAND(S) (NOT IMPLEMENTED)
;	EXIT -	(IOPB + PBSTATO)= 0 OR ERROR CODE
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
JADEXEC:
	LD	A,CMDERR	;UNSUPPORTED FOR NOW!


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	SET IOPB STATUS BYTE FUNCTION
;	ENTRY-	A= STATUS BYTE
;	EXIT -	NZ= ERROR
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
IOPBERR:
	LD	(IOPB + PBSTATO),A
	OR	A,A
	RET

	SUBTTL	JADE FDC SUBR
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	EXECUTE THE COMMAND BLOCK FUNCTION
;	EXIT -	NZ= ERROR
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
FDSKEX:
;
;   CHANGE LOGICAL SECTOR {0..N-1} TO PHYSICAL {1..N}
;
	LD	A,(IOPB + PBSECO)
	INC	A
	LD	(IOPB + PBSECO),A
;
;   MOVE IOPB INTO JADE CONTROLLER
;
	LD	DE,DDCBO	;OFFSET OF IOPB IN MEMORY BANK 0
	LD	HL,(FDADDR)	;BASE ADDRESS OF JADE MEMORY BANKS
	ADD	HL,DE
	EX	DE,HL
	LD	HL,IOPB
	LD	BC,PBDMAXO + 1	;COUNT, INCLUSIVE
	XOR	A
	CALL	MOV2HST
;
;   ISSUE COMMAND TO JADE CONTROLLER
;
	HSTOUT	DDPORT,DDEXC		;ISSUE COMMAND
;
;   SET UP FOR RETURN
;
	LD	BC,IOPBSZ - PBSTATO	;SET UP TO MOVE STATUS DOWN
;
;   WAIT FOR JADE CONTROLLER TO FINISH
;
FDSKWT:	HSTIN	DDPORT			;WAIT UNTIL DONE
	AND	DDSHLT
	JR	NZ,FDSKWT
;
;   DONE, GET WINDOW
;
	HSTOUT	DDPORT,DDMB0		;GET WINDOW
;
;   FETCH COMMAND RESULT STATUS
;
	XOR	A
	CALL	MOVFHST
;
;   CHECK FOR ERRORS
;
	LD	A,(IOPB + PBSTATO)		;IF NO ERROR THEN RETURN 0, NC
	OR	A
	RET


	SUBTTL	HARD DISK IOPB COMMANDS
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	UNSUPPORTED COMMAND
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HDCERR:	LD	A,CMDERR
	JP	IOPBERR


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	DRIVE SELECT/LOG-ON COMMAND
;	EXIT -	(IOPB + PBSTATO)= 0 OR ERROR CODE
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HDLOG:
;
;   SELECT THE CONTROLLER
;
	CALL	HDSELCT
	RET	NZ
;
;   READ THE ID SECTOR
;
	LD	IY,IDRCDB		;READ THE ID SECTOR
	CALL	GETLUN
	CALL	HDRDBUF
	RET	NZ
;
;   CHECK FOR LEGAL ID SECTOR
;
	LD	DE,IDTXT	;TXT PTR
	LD	HL,HDSECB	;TEXT IN SECTOR BUFFER
	LD	B,IDSZE		;SIZE
;
HDCKID:	LD	A,(DE)		;COMPARE
	CP	(HL)
	JR	NZ,HDNTID	;IF NOT SAME THEN EXIT
;
	INC	HL		;NEXT CHAR
	INC	DE
	DJNZ	HDCKID		;DO UNTIL DONE
;
;   ID CHECKS, RETURN VALID ID FLAG
;
	LD	A,-2
	JR	HDLOG2
;
;   NO ID, USE DEFAULT
;
HDNTID:
	LD	HL,DEFDSEC		;PASS BACK DEFAULT DESCRIPTOR SECTOR
	LD	DE,HDSECB
	LD	BC,128
	LDIR
;
	LD	A,-2			;DEFAULT IS EXTENDED TYPE
;
;   RETURN THE DESCRIPTOR SECTOR FLAG TO HOST
;
HDLOG2:	LD	(IOPB + PBST2O),A	;STORE THE DESCRIPTOR SECTOR TYPE
;
;   WRITE THE HOST BUFFER
;
	LD	HL,HDSECB		;WRITE ID SECTOR TO HOST
	CALL	HDHSTW
;
;   FLUSH BUFFER OF DESCRIPTOR SECTOR
;
	JP	CLRBUFR


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	READ DEBLOCKED SECTOR COMMAND
;	EXIT -	(IOPB + PBSTATO)= 0 OR ERROR CODE
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HDREAD:
;
;   SELECT DRIVE
;
	CALL	HDSELCT		;IMPLIED SELECT
	RET	NZ
;
;   SET UP AND READ THE SECTOR
;
	LD	IY,LAXCDB	;USE XFER CDB
	CALL	GETLUN
	CALL	GETLAD
	CALL	HDRDBUF
	RET	NZ
;
;   SELECT THE BUFFER HALF
;
	SELCTBUF
;
;   WRITE THE SECTOR BUFFER TO THE HOST MEMORY
;
	JP	HDHSTW


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	WRITE SECTOR COMMAND
;	EXIT -	(IOPB + PBSTATO)= 0 OR ERROR CODE
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HDWRT:
;
;   SELECT THE DRIVE
;
	CALL	HDSELCT		;IMPLIED SELECT
	RET	NZ
;
;   PREREAD THE SECTOR BUFFER, IF APPLICABLE
;
	LD	IY,LAXCDB	;USE XFER CDB
	CALL	GETLUN
	CALL	GETLAD
;
	CALL	HDRDBUF		;REFRESH BUFFER WITH SECTOR DATA
	RET	NZ
;
;   SELECT THE BUFFER HALF
;
	SELCTBUF
;
;   XFER THE DATA FROM THE HOST MEMORY
;
	CALL	HDHSTR		;READ HOST BUFFER
;
;   WRITE THE SECTOR BUFFER
;
	JP	HDWRBUF		;WRITE TO DISK


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	FORMAT TRACK COMMAND
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HDFORM:
;
;   SELECT THE DRIVE
;
	CALL	HDSELCT		;IMPLIED SELECT
	RET	NZ
;
;   SET UP THE CDB
;
	LD	IY,LAXCDB	;ELSE USE XFER CDB
	LD	(IY + CMD),SCFMTT
;
	LD	A,(IOPB + PBSECO)	;SECTOR BYTE HAS INTERLEAVE FACTOR
	AND	00011111B	;MASK OFF HEAD BITS
	LD	(IY+ILV),A
;
;   FORCE SECTOR TO 0 FOR CLEANLINESS
;
	XOR	A
	LD	(IOPB + PBSECO),A
;
;   SET UP CDB FROM IOPB
;
	CALL	GETLUN		;GET DRIVE
	CALL	GETLAD		;GET LOGICAL ADDRESS
;
;   EXECUTE
;
	CALL	XCDB6
;
;   RESTORE ILV BYTE OF CDB FOR SUBSEQUENT OPS
;
	LD	(IY+ILV),0	;RESTORE ILV BYTE TO 0
	RET	NZ		;ERR?
;
;   RETURN RESULTS
;
	JP	GETRES		;FINISH UP


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	RECAL COMMAND
;	EXIT -	(IOPB + PBSTATO)= 0 OR ERROR CODE
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HDRECAL:
;
;   SELECT DRIVE
;
	CALL	HDSELCT
	RET	NZ
;
;   USE PRIMITIVE
;
	JP	RECALC


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	SEEK COMMAND
;	EXIT -	(IOPB + PBSTATO)= 0 OR ERROR CODE
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HDSEEK:
;
;   SELECT DRIVE
;
	CALL	HDSELCT		;IMPLIED SELECT
	RET	NZ
;
;   SET UP CDB
;
	LD	IY,LAXCDB	;USE XFER CDB
	LD	(IY+CMD),SCSEEK	;SEEK COMMAND
	CALL	GETLUN
	CALL	GETLAD		;GET USER'S BLOCK
;
;   EXECUTE THE SEEK
;
	CALL	XCDB6		;SEND CDB
	RET	NZ
;
;   RETURN THE RESULTS
;
	JP	GETRES		;GET ANY ERRORS

	SUBTTL	HARD DISK SUBROUTINES
;****************************************************************************
;
;	CLEAR CONTROLLER SUBR
;
;****************************************************************************
INIT:
;
;   INIT VARIABLES
;
	LD	A,-1
	LD	(CURDRV),A	;CURRENT DRIVE = NONE
;
;   INIT COMMAND DESCRIPTOR BLOCKS (CDB)
;
	LD	HL,NULCDB	;ZERO CDBS
	LD	B,CDBINIT
INITRAM:
	LD	(HL),0
	INC	HL
	DJNZ	INITRAM
;
;   RESET THE HARD DISK CONTROLLER
;
	LD	A,1 SHL SRESET	;RESET CONTROLLER
	OUT	SASICMD,A
;
	EX	(SP),HL		;GIVE A LITTLE EXTRA TIME
	EX	(SP),HL
;
	LD	A,1 SHL SERRCLR	;RELEASE RESET
	OUT	SASICMD,A
;
;   CLEAR THE SECTOR BUFFER
;
	CALL	CLRBUFR		;START WITH FRESH BUFFER READ
;
;   SET UP THE JADE CONTROLLER POINTERS
;
	HSTIN	DDPORT		;FETCH FDC ADDRESS
	AND	DDSASW
	RLCA
	OR	HIGH DDBASE
	LD	H,A
	LD	L,0
	LD	(FDADDR),HL
;
;   ALL DONE
;
	RET


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	SELECT DRIVE FUNCTION
;	EXIT -	NZ= ERROR
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HDSELCT:
;
;   IF CURRENT DRIVE == REQUESTED DRIVE THEN RETURN
;
	LD	A,(IOPB + PBDRVO) ;IF REQUESTED DRIVE = CURRENT DRIVE THEN
	LD	HL,CURDRV
	SUB	A,(HL)
	RET	Z		;   RETURN
;
;   TEST DRIVE READY
;
	LD	IY,NULCDB	;USE NUL CDB
	LD	(IY+CMD),SCRDY	;TEST READY COMMAND
;
	CALL	GETLUN		;REQUEST LUN FROM USER
	CALL	XCDB6		;EXECUTE CDB
	RET	NZ		;NOT READY, EXIT
;
;   GET RESULTS
;
	CALL	GETRES		;GET RESULT BYTE
	RET			;CAN'T EVEN GET RESULT STATUS..HARD ERROR


;****************************************************************************
;
;	READ HD SECTOR INTO BUFFER SUBR
;	ENTRY-	IY= CDB PTR
;		CDB= SET UP
;	EXIT -	NZ= ERROR
;
;****************************************************************************
HDRDBUF:
;
;   IF BUFFER DATA VALID THEN SKIP PREREAD
;
	CALL	QBUFR
	RET	Z
;
;   SET UP RETRY COUNT
;
	LD	C,4		;ASSUME RETRIES
;
	LD	HL,IOPB + PBFLGO
	LD	A,(HL)		;FETCH FLAGS
	BIT	PBRTRY,A
	JR	Z,HDRTRY1
;
	LD	C,0		;IF NO RETRIES ALLOWED THEN COUNT = 0
;
HDRTRY1:
	LD	A,C
	LD	(RETRYS),A
;
;   SEND RETRY DISABLE FLAG TO CONTROLLER
;
	LD	A,(HL)		;CHECK FOR CONTROLLER RETRY DISABLE
	AND	80H
	LD	(IY + RTY),A
;
;   EXECUTE THE READ COMMAND
;
HDRDRTY:
	LD	(IY+CMD),SCREAD	;READ COMMAND
	LD	(IY+NBK),1	;ALLWAYS USE 1 BLOCK (SECTOR)
;
	CALL	XCDB6		;SEND CDB
	RET	NZ		;IF ERROR HERE THEN HARD ERROR!
;
;   SET UP FOR DATA XFER
;
	LD	BC,[HDBUFSZ SHL 8] + SASIDATA	;SET COUNT, PORT
	LD	HL,HDSECB	;XFER PTR
;
;   WAIT FOR DATA REQUEST
;
HDRDLP:
	CALL	GETSTAT		;IF NOT READY THEN WAIT
	BIT	SREQ,A
	JR	Z,HDRDLP
;
	AND	SSXMSK		;   IF DATA READY THEN GET IT
	CP	SSNDDAT
	JP	Z,HDRD2
;
	CP	SSNDST		;   ELSE IF NOT READY FOR STATUS THEN ERR
	JR	NZ,HDRWFER
;
;   OPERATION DONE, GET RESULTS
;
HDRDDN:	CALL	GETRES
;
;   BUFFER CONTAINS GOOD DATA, SET BUFFER PTRS
;
	PUSH	AF
	CALL	Z,MAKSAME	;MAKE BUFFER PTRS REFLECT DISK DATA
	POP	AF
	RET	Z
;
;   ELSE CHECK RETRIES
;
	LD	A,(RETRYS)
	SUB	A,1
	LD	(RETRYS),A
	JP	NC,HDRDRTY
;
;   ERROR OCCURRED, CLEAR BUFFER PTRS TO FORCE SUBSEQUENT READ
;
	CALL	CLRBUFR		;BUFFER CONTAMINATED
;
;   RETURN ERROR STATUS
;
	OR	A,A		;CLRBUFR RETURNS -1
	RET
;
;
;   DATA REQUEST TRUE, XFER THE DATA
;
HDRD2:	INI			;*PTR++ = SASI DATA; CNT--
	JP	NZ,HDRDLP
;
;   XFER OVERFLOW (CONTROLLER REQUESTED MORE DATA THAN 1 SECTOR'S WORTH)
;   DETERMINE WHAT CONTROLLER WANTS & RE-SYNC SASI BUS
;
HDRDOV:	CALL	GETSTAT		;IF READY THEN INPUT DATA
	BIT	SREQ,A
	JR	Z,HDRDOV
;
	AND	SSXMSK
	CP	SSNDST		;IF READY FOR STATUS THEN GET IT
	JP	Z,HDRDDN
;
;   IGNORE THE EXCESS DATA
;
HDWASTE:
	CALL	HDXWST		;OVERFLOW, WASTE DATA
	CALL	GETRES		;FINISH UP
;
;   ASSUME DATA BUFFER CONTAMINATED, CLEAR IT!
;
HDRWFER:
	CALL	CLRBUFR		;BUFFER CONTAMINATED
;
;   RETURN UNKNOWN FIRMWARE ERROR
;
	LD	A,FERR08	;   UNKNOWN CONDITION, USE HANDSHAKE
	JP	IOPBERR


;****************************************************************************
;
;	WRITE HD SECTOR FROM BUFFER SUBR
;	ENTRY-	IY= CDB PTR
;		CDB= SET UP
;	EXIT -	NZ= ERROR
;
;****************************************************************************
HDWRBUF:
;
;   SET UP CDB
;
	LD	(IY+CMD),SCWRIT	;WRITE COMMAND
;
	LD	(IY+NBK),1	;ALLWAYS USE 1 BLOCK (SECTOR)
;
;   EXECUTE THE COMMAND 1ST
;
	CALL	XCDB6		;SEND CDB
	RET	NZ
;
;   SET UP FOR DATA XFER
;
	LD	BC,[HDBUFSZ SHL 8] + SASIDATA	;SET COUNT, PORT
	LD	HL,HDSECB
;
;   WAIT FOR DATA REQUEST
;
HDWRLP:	CALL	GETSTAT		;IF READY THEN
	BIT	SREQ,A
	JR	Z,HDWRLP
;
;   IF DATA REQUEST THEN GO XFER IT
;
	AND	SSXMSK		;   IF DATA READY THEN PUT IT
	CP	SGTDAT
	JP	Z,HDWR2
;
;   IF STATUS MODE THEN GET IT
;
	CP	SSNDST		;   ELSE IF READY FOR STATUS THEN GET IT
	JP	NZ,HDRWFER	;   ELSE UNKNOWN CONDITION!
;
	JP	GETRES
;
;
;   DATA REQUEST, XFER DATA
;
HDWR2:	OUTI			;SASI DATA = *PTR++; CNT--
	JP	NZ,HDWRLP
;
;   DATA XFER COUNT EXHAUSTED, BETTER BE REQUESTING STATUS NOW
;
HDWROV:	CALL	GETSTAT		;OVERFLOW, WASTE DATA
	BIT	SREQ,A
	JR	Z,HDWROV
;
	AND	SSXMSK
	CP	SSNDST
	JP	NZ,HDWASTE	;IF NOT STATUS THEN WASTE DATA
;
;   STATUS IS BEING REQUESTED, GO GET IT
;
	JP	GETRES


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	QUERY BUFFER THE SAME FUNCTION
;	EXIT -	ZF= SAME
;		NZ= NOT SAME
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
QBUFR:
;
;   IF NOT SAME DRIVE THEN RETURN NZ
;
	LD	A,(IOPB + PBDRVO)	;CHECK DRIVE 1ST
	LD	HL,BUFDRV
	CP	(HL)
	RET	NZ
;
;   IF SECTOR NOT SAME THEN RETURN NZ
;
	LD	DE,(IOPB + PBSECO)	;NOW CHECK SECTOR
;
	RES	0,E		;CLEAR BLOCKING BIT
;
	LD	HL,(BUFSEC)
	SBC	HL,DE
	RET	NZ
;
;   IF TRACK NOT = THEN RETURN NZ
;
	LD	DE,(IOPB + PBTRKO)	;LAST, CHECK TRACK
	LD	HL,(BUFTRK)
	SBC	HL,DE
	RET


;****************************************************************************
;
;	CLEAR BUFFER SUBR
;	EXIT -	A= -1
;
;****************************************************************************
CLRBUFR:
;
;   STORING -1 INTO DRIVE FORCES A READ
;
	LD	A,-1
	LD	(BUFDRV),A
	RET


;****************************************************************************
;
;	MAKE BUFFER PTRS = PB PTRS
;
;****************************************************************************
MAKSAME:
;
;   STORE IOPB PTRS INTO BUFFER PTRS
;
	LD	A,(IOPB + PBDRVO)
	LD	(BUFDRV),A
	LD	HL,(IOPB + PBTRKO)
	LD	(BUFTRK),HL
	LD	HL,(IOPB + PBSECO)
	RES	0,L		;CLEAR BLOCKING BIT 1ST
	LD	(BUFSEC),HL
	RET


;****************************************************************************
;
;	READ DATA FROM HOST IOPB SUBR
;   MOVES 128 BYTES FROM (PBDMA) TO (HL)
;	ENTRY-	HL= DESTINATION PTR
;	EXIT -	BC, DE, HL= ?
;
;****************************************************************************
HDHSTR:	LD	DE,(IOPB + PBDMAO)	;GET DESTINATION PTR
	LD	A,(IOPB + PBDMAXO)	;SET BANK REGISTER
	LD	BC,128		;MOVE 128 BYTES


;****************************************************************************
;
;	BLOCK MOVE FROM HOST SUBR
;	ENTRY-	HL= LOCAL PTR (DST)
;		DE= HOST PTR (SRC)
;		BC= BYTE COUNT
;		A= BANK ADDRESS (SRC)
;	EXIT -	HL= DE + BYTE COUNT
;		DE= HL + BYTE COUNT
;		A, BC= ?
;
;****************************************************************************
MOVFHST:
;
;   SET EXTENDED ADDRESS REGISTER
;
	LD	(MOVX),A	;SAVE EXTENDED ADDRESS FOR BUMPING
	OUT	(HXADDR),A
;
;   PASS DIRECTION TO MOVER
;
	XOR	A		;TRANSFER FROM S100
	EX	AF,AF'
	JP	MOVIT


;****************************************************************************
;
;	WRITE DATA TO HOST IOPB SUBR
;   MOVE 128 BYTES OF DATA FROM (HL) TO (PBDMA)
;	ENTRY-	HL= SOURCE PTR
;
;****************************************************************************
HDHSTW:	LD	DE,(IOPB + PBDMAO)	;GET DESTINATION PTR
	LD	A,(IOPB + PBDMAXO)	;SET BANK REGISTER
	LD	BC,128		;MOVE 128 BYTES
	

;****************************************************************************
;
;	BLOCK MOVE TO HOST SUBR
;	ENTRY-	HL= LOCAL PTR (SRC)
;		DE= HOST PTR (DST)
;		BC= BYTE COUNT
;		A= BANK ADDRESS (DST)
;	EXIT -	DE= DE + BYTE COUNT
;		HL= HL + BYTE COUNT
;		A, BC= ?
;
;****************************************************************************
MOV2HST:
;
;   SET UP EXTENDED ADDRESS REGISTER
;
	LD	(MOVX),A	;SAVE EXTENDED ADDRESS VALUE FOR BUMPING
	OUT	(HXADDR),A
;
;   PASS DIRECTION TO MOVER
;
	LD	A,1		;TRANSFER TO S100
	OR	A
	EX	AF,AF'


;****************************************************************************
;
;	MOVE SUBR CHECKS FOR A MOVE CROSSING ANY 32K BOUNDARY
; AND SELECTING A FAST BLOCK MOVE IF NOT, AND A SLOWER BLOCK MOVE
; WHICH CHECKS AFTER EACH BYTE FOR AN OVERFLOW CONDITION IF TRUE.
;	ENTRY-	HL= LOCAL MEMORY PTR
;		DE= S100 MEMORY PTR
;		BC= BYTE COUNT TO TRANSFER
;		AF'= 0: XFER FROM S100 MEMORY TO LOCAL MEMORY
;		     1: XFER FROM LOCAL MEMORY TO S100 MEMORY
;
;	EXIT -	AF, AF'= ?
;		BC= 0
;		HL= HL + BC
;		DE= DE + BC
;
;****************************************************************************
MOVIT:
;
;   INSURE DIRECTION FLAGS ARE SET
;
	EX	AF,AF'		;SET FLAGS
	OR	A
	EX	AF,AF'
;
;   SET UP BIT 15 REGISTER
;
	LD	A,D		;SET BIT 15
	OUT	(HXAD15),A
;
;   CHECK FOR LONG MOVE
;
	DEC	BC		;IF > 32K MOVE THEN DO LONG WAY
	LD	A,B
	CP	32768 / 256
	JR	NC,DOLONG
;
	LD	A,E		;IF 64K CROSS THEN DO LONG WAY
	ADD	C
	LD	A,D
	ADC	B
	JR	C,DOLONG
;
	XOR	D		;IF 32K CROSS THEN DO LONG WAY
	JP	M,DOLONG
;
;   SET UP FOR BLOCK MOVE INSTRUCTION
;
	INC	BC		;RESTORE COUNT
;
	SET	7,D		;INSURE S100 MAP
;
;   SET DIRECTION
;
	EX	AF,AF'		;IF FROM S100 THEN
	JP	NZ,MOV1
;
	EX	DE,HL		;  SWAP
;
;   DO FAST MOVE
;
MOV1:	LDIR
;
;   RESTORE PTRS
;
	JP	NZ,MOV6
;
	EX	DE,HL		;  SWAP BACK
;
;   RETURN NO ERRORS
;
MOV6:	EX	AF,AF'
	XOR	A
	RET
;
;
;   LONG TRANSFER PART TESTS EACH BYTE FOR THRESHOLDS
;
DOLONG:
;
;   SET UP
;
	INC	BC		;RESTORE COUNT
;
	LD	A,D		;SET UP CURRENT BIT 15
	LD	I,A
;
NO64KX:	SET	7,D		;INSURE S100
;
;   SET DIRECTION
;
MOV4:	EX	AF,AF'		;IF HL= S100 THEN
	JP	NZ,MOV2
;
	EX	DE,HL
;
;   MOVE 1 BYTE
;
MOV2:	LDI
;
;   RESTORE PTRS
;
	JP	NZ,MOV3
;
	EX	DE,HL
;
;   IF COUNT EXHAUSTED THEN EXIT
;
MOV3:	JP	PO,MOV6		;IF DONE THEN RETURN
;
;   IF NO ROLLOVER THEN DO NEXT
;
	EX	AF,AF'
	BIT	7,D		;IF NOT ROLLOVER THEN REPEAT
	JP	NZ,MOV4
;
;   ELSE TOGGLE HOST BIT 15
;
	LD	A,I		;TOGGLE BIT 15
	CPL
	LD	I,A
	OUT	(HXAD15),A
;
;   IF BIT 15 TOGGLED TO 0 THEN BUMP EXTENDED ADDRESS
;
	BIT	7,A
	JP	NZ,NO64KX
;
	LD	A,(MOVX)
	INC	A
	LD	(MOVX),A
	OUT	(HXADDR),A
	JP	NO64KX


;****************************************************************************
;
;	WASTE OVERFLOW DATA SUBR
;
;****************************************************************************
HDXWST:
;
;   WAIT UNTIL DATA REQUEST
;
	CALL	GETSTAT		;IF READY THEN INPUT DATA
	BIT	SREQ,A
	JR	Z,HDXWST
;
;   IF READY FOR STATUS THEN RETURN FOR STATUS
;
	AND	SSXMSK
	CP	SSNDST		;IF READY FOR STATUS THEN GET IT
	RET	Z
;
;   XFER DATA & IGNORE
;
	LD	A,0E5H		;OUTPUT WILL ALSO DO FOR INPUT
	OUT	SASIDATA,A
	JR	HDXWST


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	RECALIBRATE FUNCTION
;	EXIT -	NZ= ERROR
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
RECALC:
;
;   EXECUTE THE COMMAND
;
	LD	IY,NULCDB
	LD	(IY+CMD),SCREC		;RECAL COMMAND
	CALL	GETLUN
;
	CALL	XCDB6
;
;   RETURN THE RESULTS
;
	JP	GETRES		;FINISH UP


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	GET STATUS FUNCTION
;	EXIT-	A= STATUS WORD
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
GETSTAT:
	IN	A,SASIST	;GET STATUS WORD
	AND	SSTMSK		;REMOVE UNUSED BITS
	XOR	SSTINV		;INVERT SOME
	RET


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	TRANSMIT CDB FUNCTION
;	ENTRY-	IY= CDB TO XMIT PTR
;	EXIT -	NZ= ERROR
;		BC= ?
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
XCDB6:
;
;	ISSUE CONTROLLER SELECT PER SHUGART MANUAL
;
	LD	A,[1 SHL HDCONT]	;SELECT DB0
	OUT	SASIDATA,A
;
	LD	A,[1 SHL SSELECT] OR [1 SHL SERRCLR]	;OUTPUT STROBE
	OUT	SASICMD,A
;
;   INIT TIMEOUT COUNT
;
	LD	BC,0
;
;   WAIT FOR BUSY
;
BSYWT2:	CALL	GETSTAT		;WAIT FOR BUSY
	BIT	SBUSY,A
	JR	NZ,BSYOK2
;
	DEC	BC		;CHECK FOR TIMEOUT
	LD	A,C
	OR	B
	JR	NZ,BSYWT2
;
;   TIMED OUT, RETURN TIMEOUT ERROR
;
	LD	A,FERR07	;HANDSHAKE TIMEOUT ERR
	JP	IOPBERR
;
;
;   CONTROLLER WENT BUSY, CLEAR SELECT STROBE
;
BSYOK2:	LD	A,1 SHL SERRCLR		;REMOVE SELECT STROBE
	OUT	SASICMD,A
;
;   CHECK FOR COMMAND MODE
;
XCDB2:	CALL	GETSTAT
	BIT	SREQ,A		; WAIT FOR REQUEST
	JR	Z,XCDB2
;
	BIT	SCD,A		;IF NOT COMMAND THEN ???
	JR	NZ,XOK
;
;   NOT COMMAND MODE, RETURN CONTROLLER SYNC ERROR
;
XCDBER:	LD	A,FERR08	;CONTROLLER SYNC ERROR
	JP	IOPBERR
;
;
;   READY FOR COMMAND, SET UP FOR CDB XFER
;
XOK:	LD	BC,[6 SHL 8] + SASIDATA		;BYTE COUNT IN B
;
;   CHECK DIRECTION
;
	BIT	SIO,A		;IF DIRECTION NOT OUT THEN ERR
	JR	NZ,XCDBER
;
;   SET XFER PTR

	PUSH	IY
	POP	HL
;
;   XFER CDB DATA
;
XCDB3:	PUTDATA			;GET CDB DATA
	JR	NZ,XCDB3
;
;   DONE WITH CDB, CONTROLLER SHOULD BE WAITING FOR DATA XFER OR RESULT
;
	XOR	A		;RETURN NO ERRORS
	RET


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	GET CONTROLLER RESULTS FUNCTION
;	EXIT -	NZ= HARD ERROR
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
GETRES:
;
;   SET UP TO RETURN RESULT IN IOPB
;
	LD	HL,RSTAT	;INSURE DESTINATION CORRECT
	LD	C,SASIDATA
	GETDATA			;GET RESULT STATUS BYTE
;
;   CHECK FOR HARDWARE PARITY ERROR
;
	BIT	SPERR,A
	JR	NZ,HDPERR
;
;   IF NO ERROR THEN RETURN ZF
;
	LD	A,(RSTAT)
	AND	00000011B
	RET	Z
;
;   CHECK FOR CONTROLLER PARITY ERROR
;
	BIT	1,A		;IF CONTROLLER PARITY ERROR THEN EXIT
	JR	Z,HDPERR
;
;   ISSUE REQUEST SENSE COMMAND
;
	LD	(IY+CMD),SCSNSE
	CALL	XCDB6
	RET	NZ		;HARD ERROR
;
;   READ 4 BYTES OF STATUS INTO IOPB
;
GETR1:	LD	HL,IOPB + PBSTATO	;READ SENSE STATUS BYTES
	LD	BC,[4 SHL 8] + SASIDATA
;
GETR2:	GETDATA
	JR	NZ,GETR2
;
;   READ STATUS OF SENSE COMMAND
;
GETR3:	CALL	GETSTAT		;FINISH OUT COMMAND
	BIT	SREQ,A
	JR	Z,GETR3
;
;   IF NO ERROR IN SENSE COMMAND THEN RETURN ERROR
;
	IN	A,(C)		;GET RESULT BYTE OF COMMAND
	AND	00000011B	;IF ERROR THEN HARD ERROR
;
	LD	A,FERR09
	JP	NZ,IOPBERR
;
	OR	A,A		;ERROR ANYWAY
	RET
;
;
;   PARITY ERROR ENCOUNTERED
;
HDPERR:
;
;   CLEAR THE PARITY ERROR LATCH
;
	XOR	A		;CLEAR ERROR
	OUT	(SASICMD),A
	LD	A,1 SHL SERRCLR
	OUT	(SASICMD),A
;
;   RETURN PARITY ERROR CODE
;
	LD	A,FERR11	;RETURN PARITY ERROR
	JP	IOPBERR


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	GET LUN FROM USER FUNCTION
;	ENTRY-	IY= CDB PTR
;	EXIT -	BC, DE, AF= ?
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
GETLUN:
;
;   FETCH & CONDITION THE DRIVE #
;
	LD	A,(IOPB + PBDRVO)	;FETCH DRIVE #
	AND	00000011B
;
;   PUT DRIVE # INTO PROPER CDB FIELD
;
	RRCA
	RRCA
	RRCA
;
;   STORE INTO ALL CDBS
;
	LD	(NULCDB + LUN), A
	LD	(LAXCDB + LUN), A
	LD	(IDRCDB + LUN), A
	RET


;****************************************************************************
;
;	GET LOGICAL ADDR FROM IOPB SUBR
;	ENTRY-	IY= CDB PTR
;
;****************************************************************************
GETLAD:
;
;   XFER COUNT = SECTOR SIZE
;
	LD	HL,256		;SECTOR SIZE
	LD	(BYTCNT),HL
;
;   CALCULATE LOGICAL ADDRESS FROM SECTOR & TRACK
;
	LD	A,(IOPB + PBSECO)	;FETCH SECTOR
	LD	E,A
;
	LD	A,(IOPB + PBTRKO)	;PICK UP TRACK LSB & PUT INTO LA0 BIT 7
	SRL	A			;  SECTOR BIT 0 IS WASTED
	RR	E
	LD	(IY+LA0),E		;PHEW! LA0 DONE
;
	LD	(IY+LA1),A		;LA1 HAPPENS TO BE IN A
	RET


;****************************************************************************
;
;	POWER UP TESTS PERFORM THE FOLLOWING:
;	1. TEST HOST DMA ACCESS:
;		A. READ LOCATION 0F800H FOR 0C3H.
;		B. NON-DESTRUCTIVELY TEST LOCATION 100H
;		C. TEST 32K BOUNDARY (A15).
;	2. FIND OWN PORT # IN HOST SPACE.
;	3. TEST PORT REGISTERS:
;		A. READ/WRITE TEST DATA & STATUS PORTS
;		B. TEST COMMAND PORT WITH INTERRUPTS DISABLED
;		C. TEST INTERRUPT WITH ILLEGAL COMMAND & TEST STATUS
;	4. TEST SASI:
;		A. TEST SASI INTERRUPT & RESULTANT ERROR.
;		B. TEST SASI PARITY BY DESLECTING & OUTPUTTING ODD/EVEN DATA
;		C. TEST REQUEST BY SELECTING CONTROLLER & SENSING REQUEST ETC.
;		D. TEST DRIVE READY ON DRIVE 0
;
;****************************************************************************
PUTEST:
;
;   CLEAR THE EXTENDED ADDRESS PORT TO TALK TO BANK 0 FIRST
;
	XOR	A,A
	OUT	(HXADDR),A
;
;   TEST HOST LOCATION 0F800H FOR 0C3H
;
	LD	A,-1
	OUT	(HXAD15),A
	LD	A,(0F800H)
	SUB	A,0C3H
	JR	Z,TST2
;
;   ERROR!
;
	LD	(IOPBL),A
	LD	A,-1
	JP	FERR
;
;   NON-DESTRUCTIVE TEST HOST LOCATION 100H
;
TST2:
	OUT	(HXAD15),A		;A HAS 0 FROM PREVIOUS TEST
;
	LD	HL,S1MEM + 100H
	LD	A,(HL)
	LD	C,A
	CPL
	LD	(HL),A
	LD	B,(HL)
	CP	B
	CPL
	LD	(HL),A
	JR	Z,TST3
;
	LD	(IOPBL),BC	;RETURN FAILURE DATA
	LD	A,-2
	JP	FERR
;
;   32K BOUNDARY TEST
;
TST3:	;NOT IMPLEMENTED
;
;   FIND OWN PORT NUMBER IN HOST MEMORY
;
TST4:
	LD	A,55H			;START WITH DATA IMAGE
	OUT	(HDATA),A
;
	XOR	A,A			;START WITH BANK 0
	OUT	(HXAD15),A
	LD	I,A
;
TST4B:	LD	C,[0 OR 80H]		;PORT #
;
TST4A:	IN	A,(C)			;SEARCH FOR 1ST PATTERN
	CP	A,55H
	JR	NZ,NXTPRT
;
;   POSSIBLE PORT FOUND
;
	LD	A,0AAH			;CHECK OTHER DATA PATTERN
	OUT	(HDATA),A
	IN	A,(C)
	CP	A,0AAH
;
;   RESTORE DATA PATTERN BEFORE RETURNING
;
	LD	A,55H
	OUT	(HDATA),A
	JR	NZ,NXTPRT
;
;   PORT FOUND, SAVE PORT #
;
	DEC	C		;SEARCHED DATA PORT IS BASE + 1, COMPENSATE
	LD	A,C
	AND	7FH
	LD	B,A
	LD	A,I			;MERGE IN HOST BIT 7
	AND	80H
	OR	A,B
	LD	(HPORT),A
	JR	TST5
;
NXTPRT:	INC	C			;IF ++PORT == 0 THEN DONE THIS HALF
	JR	NZ,TST4A
;
	LD	A,I			;NOW DO 80H..FFH
	CPL
	LD	I,A
	OUT	(HXAD15),A
	BIT	7,A			;IF TOGGLED FROM 1 TO 0 THEN DONE
	JR	NZ,TST4B
;
	LD	A,-4			;NOT FOUND SO ERROR
	JP	FERR
;
;   TEST HOST STATUS/COMMAND PORT ACCESS (DATA PORT ALREADY TESTED)
;
TST5:	LD	A,55H
	OUT	(HSTAT),A
	IN	A,(C)		;C ALREADY HAS STATUS/COMMAND PORT #
	CP	A,55H
	JR	NZ,TST5A
;
	LD	A,0AAH
	OUT	(HSTAT),A
	IN	A,(C)
	CP	A,0AAH OR 1	;BUSY BIT IS SET
	JR	Z,TST6
;
TST5A:	LD	A,-5
	JP	FERR
;
;   TEST COMMAND PORT
;
TST6:	DI			;NO INTERRUPTS
	LD	A,55H
	OUT	(C),A
	IN	A,(HCMD)
	CP	A,55H
	JR	NZ,TST6A
;
	LD	A,2AH		;NOTE: AAH WOULD RESET THE PROCESSOR
	OUT	(C),A
	IN	A,(HCMD)
	CP	A,2AH
	JR	Z,TST7
;
TST6A	LD	A,-6
	JP	FERR
;
;   TEST HOST INTERRUPT WITH ILLEGAL COMMAND
;
TST7:
	LD	A,3FH		;USE AN UNSUPPORTED COMMAND
	OUT	(C),A
;
	PUSH	BC
	EI			;ALLOW INTERRUPT
	NOP			;NEXT INSTRUCTION GETS EXECUTED
	NOP			;THIS INSTRUCTION SHOULD GET INTERRUPTED 
;
	DI			;RESTORE BUSY STATUS
	OUT	(HINTS),A
;
	POP	BC		;FETCH STATUS
	IN	A,(C)
	AND	A,0FEH		;MASK OFF BUSY BIT
	CP	A,HFERR
	JR	NZ,TST7A
;
	INC	C		;TEST COMMAND ERROR
	IN	A,(C)
	CP	A,FERR03
	JR	Z,TST8
;
TST7A:	LD	A,-7
	JP	FERR
;
;   TEST SASI PARITY ERROR DETECTION
;
TST8:
	XOR	A,A		;DESELECT CONTROLLER
	OUT	(SASIDATA),A
	LD	A,1 SHL SSELECT
	OUT	(SASICMD),A
;
	LD	A,1 SHL SERRCLR	;ENABLE PARITY DETECTION
	OUT	(SASICMD),A
;
	IN	A,(SASIST)	;TEST PARITY STROBE GATE
	BIT	SPERR,A
	JR	NZ,TST8A	;IF PARITY ERROR NOW THEN NOT INHIBITED
;
	IN	A,(SASIDATA)	;CLOCK THE PARITY DATA
	IN	A,(SASIST)	;WITH DATA == 0 THEN S/B PARITY ERROR
	BIT	SPERR,A
	JR	Z,TST8A
;
	XOR	A,A		;DISABLE PARITY DETECTION TO STOP GLITCHES
	OUT	(SASICMD),A
;
	INC	A		;FORCE AN EVEN PARITY BIT GENERATION
	OUT	(SASIDATA),A
	LD	A,1 SHL SERRCLR	;RE-ENABLE PARITY DETECTION
	OUT	(SASICMD),A
;
	IN	A,(SASIST)	;RE-CHECK THE GATE
	BIT	SPERR,A
	JR	NZ,TST8A	;IF PARITY ERROR NOW THEN ERROR
;
	IN	A,(SASIDATA)	;CLOCK PARITY CHECK
	IN	A,(SASIST)	;CHECK BIT
	BIT	SPERR,A
	JR	Z,TST9		;DATA == 1 THEN NO PARITY ERROR
;
TST8A:	LD	A,-8
	JP	FERR
;
;   SASI DATA REQUEST INTERRUPT TEST
;
TST9:
;
;   SASI REQUEST BIT TEST
;
TST10:
;
;   SASI COMMUNICATION TEST
;
TST11:	CALL	INIT		;INIT CDB, IOPB
	LD	IY,TESTCDB
	LD	(IY + CMD),SCRDY	;DO A TEST DRIVE READY COMMAND
	CALL	XCDB6
	JR	NZ,TST11A
;
	CALL	GETRES			;FETCH COMMAND RESULTS
	JR	NZ,TST11A
;
	LD	A,(IOPB + PBSTATO)	;TEST FOR ERROR
	OR	A
	JR	Z,TST12
;
TST11A:	CALL	DESELECT
	LD	A,-11		;PASS ERROR TO HOST
	JP	FERR
;
;   END OF TESTS
;
TST12:
;
;   FALL INTO DESELECT
;


;****************************************************************************
;
;	DESELECT SASI BUS SUBROUTINE
;	EXIT -	A= ?
;
;****************************************************************************
DESELECT:
	XOR	A,A		;DESELECT
	OUT	(SASIDATA),A
	LD	A,[1 SHL SSELECT] OR [1 SHL SERRCLR]
	OUT	(SASICMD),A
;
	LD	A,1 SHL SERRCLR	;LEAVE PARITY ERROR DETECTION ENABLED
	OUT	(SASICMD),A
	RET


;****************************************************************************
;
;	SET ADDRESS PTRS FROM IOPB_PTRS FUNCTION
;	EXIT -	HL= IOPB PTR (BIT 15 SET FOR HOST ACCESS)
;		A, BANK ADDRESS REGISTER= IOPB BANK ADDRESS (IOPBXA)
;		I, HOST BIT 15 REGISTER= IOPB_PTR HOST BIT 15 IN BIT 7
;
;****************************************************************************
SETPTRS:
	LD	HL,(IOPBL)	;FETCH IOPB BASE ADDRESS
	LD	A,(IOPBXA)
	OUT	(HXADDR),A	;SET THE BANK ADDRESS
	LD	(MOVX),A
;
	LD	A,H		;SELECT HOST BIT 15
	OUT	(HXAD15),A
	LD	I,A		;SAVE IN INTERRUPT REGISTER
	SET	7,H		;SET LOCAL BIT 15
	RET


;****************************************************************************
;
;	BUMP HL FUNCTION CARRIES THROUGH TO HOST BIT 15 & BANK ADDRESS
;	ENTRY-	HL= HOST ADDRESS
;		I= HOST BIT 15 IN BIT 7
;		(MOVX)= BANK ADDRESS IMAGE
;	EXIT -	HL= HL + 1 (BIT 15 SET)
;		I= HOST BIT 15, INCLUDING ANY CARRY
;		(MOVX), BANK ADDRESS= UPDATED IF HOST BIT 15 CARRIED
;		A= ?
;
;****************************************************************************
BUMPHL:	INC	HL		;PTR++
	BIT	7,H		;IF NO BIT 15 CARRY THEN RETURN
	RET	NZ
;
	SET	7,H		;SET LOCAL BIT 15
	LD	A,I		;COMPLEMENT HOST BIT 15
	CPL
	OUT	(HXAD15),A
	LD	I,A
	BIT	7,A		;IF NO HOST BIT 15 CARRY INTO BANK THEN RETURN
	RET	NZ
;
	LD	A,(MOVX)	;BUMP BANK ADDRESS
	INC	A
	LD	(MOVX),A
	OUT	(HXADDR),A
	RET

	SUBTTL	CONSTANTS
;############################################################################
;
;	DEFAULT DISK DESCRIPTOR SECTOR FOR LOGON
;
;############################################################################
DEFDSEC:
	DB	0,0,0		;POSSIBLE JUMP VECTOR
IDTXT:	DB	'Disk Descriptor Sector'
IDSZE	EQU	$ - IDTXT
;
	REPT	DEFDSEC + 20H - $
	LIST	OFF
	DB	0
	LIST	ON
	ENDM
	DW	128		;SPT
	DB	5		;BSH
	DB	31		;BLM
	DB	1		;EXM
	DW	1015		;DSM
	DW	1152 / 2	;DRM
	DB	0FFH		;AL0
	DB	80H		;AL1
	DW	0		;CKS
	DW	2		;OFF
;
	REPT	DEFDSEC + 30H - $
	LIST	OFF
	DB	0
	LIST	ON
	ENDM
	DB	0		;STAGGER (NOT USED)
	DB	[1 SHL DFDBLB] OR [1 SHL DFHARDB] OR [1 SHL DFTSDB]
;				256 B/S, HARD DISK, 2 SIDED
	DB	64,64,64	;PHYSICAL SPT (0,1,DATA)
;
	REPT	DEFDSEC + 128 - $
	LIST	OFF
	DB	0
	LIST	ON
	ENDM
	DB	0
	IF	$ >= (LOCROM + ROMSIZE)
;   PROTECTION MESSAGE
	CONMSG	**** ERROR! CODE TOO LARGE FOR DECLARED PROM SIZE! ****
	ENDIF

	SUBTTL	RAM AREA
	ORG	LOCRAM
;############################################################################
;
;	VARIABLES
;
;############################################################################
IOPBL	DS	1		;LOW ADDRESS OF IOPB TO EXECUTE
IOPBH	DS	1		;HIGH ADDRESS OF IOPB
IOPBXA	DS	1		;BANK ADDRESS OF IOPB
;
CURDRV	DS	1	;CURRENT DRIVE SELECTED
BYTCNT	DS	2	;SECTOR SIZE
RETRYS	DS	1	;RETRY COUNT
MOVX	DS	1	;HOST BANK ADDRESS SAVE FOR BLOCK MOVE SUBRS
FDADDR	DS	2	;FDC ADDRESS PTR
TIMOUT	DS	2	;UNSELECT SASI DELAY
HPORT	DS	1	;HOST'S BASE PORT # FOR DATA REGISTER


;############################################################################
;
;	I/O PARAMETER BLOCK SAVE AREA
;
;############################################################################
IOPB	DS	IOPBSZ
;
PBRTRY	EQU	PBNRT		;RETRY DISABLE BIT


;############################################################################
;
;	HARD DISK SECTOR BUFFER
;
;############################################################################
HDBUFSZ	EQU	256
HDSECB	DS	HDBUFSZ
;
RSTAT	DS	1	;COMMAND STATUS RETURNED
;				BIT 1: ERROR (ISSUE SENSE COMMAND)
;				BIT 5..7: LUN
BUFDRV	DS	1	;BUFFER CONTENTS DRIVE BYTE
BUFSEC	DS	2	;BUFFER CONTENTS SECTOR WORD
BUFTRK	DS	2	;BUFFER CONTENTS TRACK WORD


;############################################################################
;
;	JADE SECTOR BUFFER
;
;############################################################################
JADSECB	DS	256


;############################################################################
;
;	DISK CONTROLLER COMMAND DESCRIPTOR BLOCKS (CDB)
;
;############################################################################
NULCDB:	DS	6		;NO TRANSFER CDB
LAXCDB:	DS	6		;MAIN XFER CDB
IDRCDB	DS	6		;ID SECTOR READ CDB
TESTCDB	DS	6		;TEST CDB
CDBINIT	EQU	$ - NULCDB
;
;	CDB OFFSETS
;
	STRUCT	0
CMD	DS	1	;COMMAND
LUN	DS	1	;LOGICAL UNIT NUMBER IN BITS 5..7
LA2	EQU	LUN	;LOGICAL ADDRESS 2 IN BITS 0..4
LA1	DS	1	;LOGICAL ADDRESS 1
LA0	DS	1	;LOGICAL ADDRESS 0
ILV	DS	1	;FORMAT COMMAND INTERLEAVE FACTOR
NBK	EQU	ILV	;XFER COMMANDS BLOCK (SECTOR) COUNT
RTY	DS	1	;RETRY FLAG 0: RETRY 3 TIMES, 80H: NO RETRYS
LUND	EQU	RTY	;COPY COMMAND DEST. LUN IN BITS 5..7
LA2D	EQU	RTY	;COPY COMMAND DEST. LOGICAL ADDR 2 IN BITS 0..4
LA1D	DS	1	;COPY COMMAND DEST. LOGICAL ADDR 1
LA0D	DS	1	;COPY COMMAND DEST. LOGICAL ADDR 0
CDBSPR	DS	1	;COPY COMMAND SPARE
RTYD	DS	1	;COPY COMMAND RETRY FLAG
CDBSIZ	DS	0
	ENDM


;############################################################################
;
;	STACK AREA
;
;############################################################################
	IF	$ > (LOCRAM + RAMSIZE - 32)
	CONMSG	**** ERROR! DATA TOO LARGE FOR DECLARED RAM SIZE! ****
	ENDIF
	DS	32
STACK	EQU	LOCRAM + RAMSIZE

	END
