;DRIVE TEST
;	ORIGINAL 3_15_82 NORM TILLSBARY (SP?)
;	FIRST REVISION 10_MAY_82 ZALABAK

;********************************************************************
;BEGIN DATA DEFINITIONS
;********************************************************************

;CONDITIONAL ASSEMBLY EQUATES

ON	EQU	0FFFFH	;DEFINE ON
OFF	EQU	NOT ON	;AND OFF
STOP	EQU	OFF	;CONDITION `ON` YIELDS RST 7 ON ERROR

	IF STOP		;EXAMINES CONDITION
TRAP	EQU	0FFH	;RESTART 7 OP CODE
	ENDIF
	IF NOT STOP	;OTHERWISE
TRAP	EQU	0	;NOP CODE
	ENDIF

;--------------------------------------------------------------------
;CONTROLLER COMMAND SET

RDSEC	EQU	20H	;READ A SECTOR
WRSEC	EQU	21H	;WRITE A SECTOR
SNSTA	EQU	22H	;SENSE DRIVE STATUS
SETMA	EQU	23H	;SET DMA ADDRESS
CONHLT	EQU	25H	;HALT CONTROLLER
BRNCH	EQU	26H	;BRANCH IN CHANNEL
SETCHN	EQU	27H	;SET CHANNEL ADDRESS
STRTRY	EQU	28H	;SET ERROR RETRY COUNT
RDTRK	EQU	29H	;READ A TRACK
WRTRK	EQU	2AH	;WRITE A TRACK
STTKSZ	EQU	2DH	;SET TRACK SIZE
STLGCL	EQU	2EH	;SET LOGICAL DRIVE
STTIME	EQU	2FH	;HEAD UNLOAD/DRIVE DESELECT TIMEOUT

;--------------------------------------------------------------------
;BIT MASKS

GOOD	EQU	40H		;NORMAL COMMAND COMPLETION
FIVER	EQU	04H		;FIVE INCH DRIVE FLAG
WRTPRO	EQU	40H		;WRITE PROTECT FLAG
DBLSID	EQU	04H		;DOUBLE SIDED DRIVE & MEDIA FLAG
SD2BIT	EQU	80H		;SIDE TWO BIT
INDEX	EQU	10H		;DELTA INDEX STATUS BIT
WPRTCT	EQU	40H		;WRITE PROTECTED STATUS BIT
PROERR	EQU	90H		;WRITE-PROTECTED ERROR CODE
DREADY	EQU	80H		;DRIVE READY STATUS BIT
NOTRDY	EQU	82H		;DRIVE NOT READY

;--------------------------------------------------------------------
;DEFINE DATA AREAS AND SIZES

TBLSZ	EQU	26		;TRACK TABLE SIZE
EIGHTK	EQU	2000H		;DISK BUFFER SIZE
MAPSIZ	EQU	152		;BADMAP 76 X 2 SIDES

;--------------------------------------------------------------------
;CPM DEFINITIONS AND ENTRY POINTS

CONIN	EQU	1		;CHARACTER IN CONSOLE
COUT	EQU	2		;CHARACTER OUT CONSOLE
WRSTRN	EQU	9H		;BDOS WRITE STRING
CONSTA	EQU	0BH		;GET CONSOLE STATUS
WBOOT	EQU	0		;WARM BOOT ADDRESS
BDOS	EQU	5		;BDOS ENTRY ADDRESS

;--------------------------------------------------------------------
;MISC DEFINITIONS

LF	EQU	0AH		;LINE FEED
CR	EQU	0DH		;CARRIAGE RETURN
ESC	EQU	1BH		;ESCAPE CHARACTER
RETRIES	EQU	05H		;DISK RETRIES BEFORE VERIFY ERROR
CHANNL	EQU	50H		;START CHANNEL ADDRESS
VECTOR	EQU	CHANNL+1	;BRANCH ADDRESS
STARTR	EQU	0EFH		;PORT ADDRESS TO START THE CONTROLLER

;********************************************************************
;START OF MAIN LINE
;********************************************************************

START:	ORG	100H
	LXI	SP,STACK
	LXI	D,ONMS		;START-UP MESSAGE
	MVI	C,WRSTRN	;CPM_FUNCTION:=WRITE_STRING
	CALL	BDOS
	LXI	H,DRVLOG	;LOAD LOG ADDRESS
	SHLD	LOGPNT		;INITIALIZE POINTER
	MVI	A,BRNCH		;BRANCH COMMAND
	STA	CHANNL		;CONTROLLER STARTS HERE
	LXI	H,SETDMA	;SET DMA ADDRESS COMMAND
	SHLD	VECTOR		;GUIDE CONTROLLER
	SUB	A		;ZERO A
	STA	VECTOR+2	;EXTENDED ADDRESS BYTE
	STA	HLTED		;ZERO HALT RESULT BYTE
	OUT	STARTR		;START CONTROLLER
	CALL	WAIT1		;WAIT FOR IT TO FINISH
	LXI	H,RETRYS	;ADDRESS OF SET TRIES CMND
	SHLD	VECTOR		;TO GUIDE CONTROLLER
	SUB	A		;ZERO A
	STA	HLTED		;CLEAR HALT RESULT BYTE
	OUT	STARTR		;START CONTROLLER
	CALL	WAIT1		;WAIT FOR IT TO FINISH
	CALL	DRVCKS		;LOOK FOR DRIVES
	CALL	TEST		;TESTEM
	JMP	START		;RUN TEST AGAIN

;====================================================================
;CHECK FOR ACTIVE DRIVES
;====================================================================

DRVCKS:	MVI	C,8		;MAXIMUM NUMBER OF DRIVES
	LXI	H,SNSTAT	;GET ADDRESS OF SENSE COMMAND
	SHLD	VECTOR		;STORE IT IN VECTOR
DRVLP:	MVI	A,8		;# OF POSSIBLE DRIVES
	SUB	C		;TO FIND CURRENT DRIVE
	MOV	B,A		;SAVE DRIVE # IN B
	PUSH	B		;SAVE COUNT
	STA	SNSDRV		;TELL SENSE COMMAND
	SUB	A		;ZERO A
	STA	SNSRLT		;CLEAR RESULT BYTE OF SENSE COMMAND
	STA	HLTED		;CLEAR HALT COMMAND RESULT BYTE
	OUT	STARTR		;START CONTROLLER
	CALL	WAIT1		;WAIT FOR IT TO FINISH
	LDA	SNSRLT		;SENSE COMMAND RESULT STATUS
	CALL	LOGIN		;RECORD RESULTS IN TABLE
	POP	B		;RECOVER COUNT
	DCR	C		;DRIVE COUNT-DOWN
	JNZ	DRVLP		;NEXT DRIVE
	RET			;ELSE RETURN

;--------------------------------------------------------------------
;LOG ON ACTIVE DRIVES
;	1) THIS ROUTINE IS ONLY USED BY THE CHECK FOR ACTIVE DRIVES
;	   ROUTINE (DRVCKS).

LOGIN:	CPI	GOOD		;ZERO MEANS ACTIVE DRIVE
	JZ	CKIT		;TO FIND OUT ABOUT IT
	CPI	NOTRDY		;APPROPRIATE RESULT
	CNZ	LOGERR		;REPORT TO TERMINAL
SPEC:	LHLD	LOGPNT		;GET POINTER
	MVI	M,0		;INDICATES INACTIVE DRIVE
	INX	H		;UPDATE POINTER
	MVI	M,0		;INDICATES INACTIVE DRIVE
	INX	H		;FOR NEXT DRIVE
	SHLD	LOGPNT		;STORE POINTER
	RET
CKIT:	PUSH	B		;SAVE BC PAIR
	LXI	D,DRVMSG	;FOR OPERATOR
	MVI	C,WRSTRN	;CPM_FUNCTION:=WRITE_STRING
	CALL	BDOS
	POP	B		;RECOVER BC
	MOV	A,B		;PUT DRIVE # IN A
	CALL	BCDOUT		;SEND TO TERMINAL
	LDA	DSTAT3		;LOAD STATUS BYTE
	ANI	WRTPRO		;CK WRITE-PROTECTED BIT
	JZ	NOTPRO		;IF ITS OFF
	MVI	A,PROERR	;WRITE-PROTECTED ERROR CODE
	CALL	LOGER2		;ADVISES TERMINAL
	JMP	SPEC		;GOES ON TO NEXT DRIVE
NOTPRO:	LDA	DSTAT1		;TO FIND WHETHER 5 OR 8 INCH
	ANI	4H		;ON MEANS 5 INCH
	JZ	EIGHIN		;ELSE ITS AN 8 INCH
	LHLD	LOGPNT		;GET LOG POINTER
	MVI	M,40		;NUMBER OF TRACKS
	INX	H		;TO NEXT ENTRY (SNGL OR DBLE SIDED)
	CALL	ASKOP		;ASK OPERATOR # OF SIDES
	MVI	B,0		;ZERO B
	CPI	'1'		;SINGLE-SIDED?
	JZ	SKPDBL		;SKIP DOUBLE-SIDED ENTRY
	MVI	B,80H		;DOUBLE-SIDED BIT
SKPDBL:	LDA	DSTAT2		;SECTOR SIZE
	ADD	B		;COMBINE WITH B
	MOV	M,A		;STORE RESULT IN DRIVE LOG
	INX	H		;TO NEXT DRIVE
	SHLD	LOGPNT		;STORE THE UPDATED POINTER
	RET
EIGHIN:	LHLD	LOGPNT		;LOAD LOG POINTER
	MVI	M,77		;NUMBER OF TRACKS
	INX	H		;NEXT LOG ENTRY
	LDA	DSTAT2		;SECTOR SIZE
	CPI	0		;MAY BE WRONG IF ON TRACK 0
	CZ	RECHK		;MOVES TO TRACK 1 AND RECHECKS
	MOV	B,A		;SAVE IN B
	LDA	DSTAT3		;3 BIT TELLS SIDES
	ANI	4H		;ON MEANS DBL SIDED
	JZ	SNGL		;SINGLE SIDED
	MVI	A,80H		;DBLE SIDED BIT
SNGL:	ADD	B		;COMBINE WITH SECTOR SIZE
	MOV	M,A		;RECORD IT
	INX	H		;INCREMENT POINTER FOR NEXT DRIVE
	SHLD	LOGPNT		;SAVE IT
	RET

;--------------------------------------------------------------------
;GET THE NUMBER OF SIDES
;	1) THIS ROUTINE IS ONLY USED BY THE LOG ON ACTIVE DISKS
;	   ROUTINE (ASKOP).

ASKOP:	PUSH	H		;SAVE HL
	PUSH	B		;SAVE BC
	LXI	D,SIDESQ	;NUMBER OF SIDES QUESTION
	MVI	C,WRSTRN	;CPM_FUNCTION:=WRITE_STRING
	CALL	BDOS
	LXI	D,0		;INITIALIZE COUNTER
ASKWT:	PUSH	D		;SAVE COUNTER
	MVI	C,CONSTA	;BDOS CONSOLE STATUS CODE
	CALL	BDOS
	POP	D		;RESTORE COUNTER
	DCR	A		;A IS 1 IF DATA READY
	JZ	CKANS		;GET THE ANSWER
	DCX	D		;ELSE WAIT AWHILE
	MOV	A,E
	ORA	D
	JNZ	ASKWT
	MVI	E,'2'		;PROVIDE DEFAULT ANSWER
	MVI	C,COUT		;CONSOLE OUT
	CALL	BDOS		;SEND IT
	MVI	A,'2'		;DEFAULT IS TWO-SIDED
	JMP	EVAL		;INSERT IT FOR RETURN
CKANS:	MVI	C,CONIN		;CONSOLE-IN CODE
	CALL	BDOS		;GET ANSWER
EVAL:	POP	B		;RECOVER BC
	POP	H		;RECOVER HL
	CPI	CR		;IS IT A NULL ANSWER?
	JZ	START		;IF SO, RESTART PROGRAM
	CPI	'1'		;OR 1
	RZ			;GOOD ANSWER
	JM	ASKOP		;BAD ANSWER, ASK AGAIN
	CPI	'2'		;GOOD ANSWER
	JNZ	ASKOP		;ASK AGAIN
	MVI	A,80H		;DBLE-SIDED BIT
	RET

;--------------------------------------------------------------------
;	1) THIS ROUTINE IS ONLY USED BY THE LOG IN ACTIVE DRIVES
;	   ROUTINE (LOGIN).

RECHK:	PUSH	H		;SAVE HL
	LXI	H,RDTRAK	;SET-UP TO READ A TRACK
	SHLD	VECTOR		;TO GUIDE CONTROLLER
	MVI	A,1		;DESIRED TRACK
	STA	RDTKTK		;STORE IN COMMAND
	OUT	STARTR		;START CONTROLLER
	CALL	WAIT1		;WAIT FOR IT
	LXI	H,SNSTAT	;SENSE STATUS COMMAND
	SHLD	VECTOR		;GUIDE CONTROLLER
	OUT	STARTR		;START CONTROLLER
	CALL	WAIT1		;WAIT FOR IT
	LDA	DSTAT2		;LOAD DESIRED RESULT BYTE
	POP	H		;RESTORE HL
	RET

;====================================================================
;MAIN LINE TEST DRIVES
;====================================================================

TEST:	MVI	C,8		;NUMBER OF DRIVE POSSIBILITIES
	LXI	H,DRVLOG	;PICKUP LOG ADDRESS
NEXT:	MOV	A,M		;LOAD TRACKS
	CPI	0		;ACTIVE?
	JNZ	GO		;YES
	INX	H		;ELSE ADVANCE POINTER
	INX	H		;TO NEXT DRIVE
	DCR	C		;DECREMENT DRIVE COUNTER
	JNZ	NEXT		;LOOP TILL DONE
	RET
GO:	SHLD	LOGPNT		;SAVE POINTER
	MVI	A,8		;NUMBER OF DRIVE POSSIBILITIES
	SUB	C		;CURRENT DRIVE NUMBER
	STA	WRTKDR		;TELL COMMANDS
	STA	RDTKDR
	PUSH	H		;SAVE HL
	PUSH	B		;AND BC
	CALL	SEEKS		;DO SEEK TESTS
	CALL	RDWRTS		;DO DATA TESTS
	POP	B		;RECOVER POINTERS
	POP	H
	INX	H		;ADVANCE POINTER
	INX	H		;FOR NEXT DRIVE
	DCR	C		;DRIVE COUNT DOWN
	JNZ	NEXT		;AND LOOP
	RET			;NO MORE DRIVES

;====================================================================
;MAIN LINE SEEK TEST

SEEKS:	LXI	D,SEEKNG	;ADDRESS OF SEEK MESSAGE
	MVI	C,WRSTRN	;CPM_FUNCTION:=WRITE_STRING
	CALL	BDOS
	CALL	DRTYPE		;TELLS TRACK AND DRIVE NUMBER
	LXI	H,RDTRAK	;READ TRACK COMMAND ADDRESS
	SHLD	VECTOR		;GUIDE CONTROLLER
	MVI	A,80H		;TO ABORT COMMAND
	CALL	CLRTBL		;WRITES A TO COMMAND TABLE
	LHLD	LOGPNT		;PICKUP POINTER
	MOV	D,M		;PUT # OF TRACKS IN D
	DCR	D		;TO GET HIGHEST TRACK NUMBER
	MVI	E,0		;ZERO E
	CALL	PAT1		;SHORT-LONG-SHORT
	LHLD	LOGPNT		;PICKUP LOG POINTER
	MOV	D,M		;NUMBER OF TRACKS TO D
	DCR	D		;TO GET HIGHEST TRACK NUMBER
	CALL	PAT2		;LONG-SHORT-LONG
	MVI	D,0		;START AT 0
	CALL	PAT3		;BUTTERFLY (+2-1 OUT, THEN -2+1 BACK)
	RET

;--------------------------------------------------------------------
;SHORT-LONG-SHORT?
;	1) THE SEEK ROUTINE RETURNS THE CARRY (ERROR_FLAG) CLEAR IF
;	   THE SEEK WAS SUCCESSFUL, SET IF THERE WAS AN ERROR.

PAT1:	MOV	A,D		;D STARTS AT HIGHEST TRACK NUMBER
	CALL	SEEK		;SEEKS TO TRACK IN A
	RC			;IF (ERROR_FLAG = SET) THEN RETURN
	MOV	A,E		;E STARTS AT TRACK 0
	CALL	SEEK
	RC			;IF (ERROR_FLAG = SET) THEN RETURN
	DCR	D		;COUNT DOWN
	JM	REVERSE		;NO TRACKS LEFT
	INR	E		;COUNT UP
	CMP	M		;NUMBER OF TRACKS
	JNZ	PAT1
REVERSE:INR	D		;COUNT UP
	MOV	A,D
	CMP	M		;M HAS NUMBER OF TRACKS
	RZ
	CALL	SEEK		;ELSE SEEK
	RC			;IF (ERROR_FLAG = SET) THEN RETURN
	DCR	E
	RM			;NO TRACKS LEFT
	MOV	A,E
	CALL	SEEK
	RC			;IF (ERROR_FLAG = SET) THEN RETURN
	JMP	REVERSE

;--------------------------------------------------------------------
;LONG-SHORT-LONG?
;	1) THE SEEK ROUTINE RETURNS THE CARRY (ERROR_FLAG) CLEAR IF
;	   THE SEEK WAS SUCCESSFUL, SET IF THERE WAS AN ERROR.

PAT2:	MOV	A,D		;D STARTS AT HIGHEST TRACK NUMBER
	RAR			;DIVIDE BY 2
	MOV	D,A		;RESET D
	MOV	E,A		;SET E=D AT START
PAT2LP:	MOV	A,D		;START AT MIDDLE TRACK
	CALL	SEEK		;SEEKS TO TRACK IN A
	RC			;IF (ERROR_FLAG = SET) THEN RETURN
	DCR	E		;COUNT E DOWN, D UP
	JM	PHASE2		;REVERSE DIRECTION
	MOV	A,E		;ELSE READ IT
	CALL	SEEK
	RC			;IF (ERROR_FLAG = SET) THEN RETURN
	INR	D		;COUNT UP IN FIRST PHASE
	CMP	M		;NUMBER OF TRACKS
	JNZ	PAT2LP
PHASE2:	INR	E		;COUNT UP
	MOV	A,E
	CALL	SEEK
	RC			;IF (ERROR_FLAG = SET) THEN RETURN
	DCR	D		;COUNT DOWN
	MOV	A,D		;TO CHECK
	CMP	E		;LOOKING FOR CROSSING POINT
	RM			;FINISHED
	CALL	SEEK		;ELSE CONTINUE
	RC			;IF (ERROR_FLAG = SET) THEN RETURN
	JMP	PHASE2		;LOOP

;--------------------------------------------------------------------
;BUTTERFLY (+2-1 OUT, THEN -2+1 BACK)
;	1) THE SEEK ROUTINE RETURNS THE CARRY (ERROR_FLAG) CLEAR IF
;	   THE SEEK WAS SUCCESSFUL, SET IF THERE WAS AN ERROR.

PAT3:	MOV	A,D		;D STARTS AT 0
	CALL	SEEK		;TAKES DRIVE BACK ONE IN LOOP
	RC			;IF (ERROR_FLAG = SET) THEN RETURN
	MOV	A,D
	ADI	2		;JUMP AHEAD TWO
	CMP	M		;NUMBER OF TRACKS
	JZ	PHAZE2		;REVERSE PATTERN
	CALL	SEEK
	RC			;IF (ERROR_FLAG = SET) THEN RETURN
	INR	D		;AND BACK ONE
	JMP	PAT3		;REPEAT
PHAZE2:	DCR	A		;FOR FIRST SHOT ONLY
PHLP:	CALL	SEEK
	RC			;IF (ERROR_FLAG = SET) THEN RETURN
	MOV	A,D
	SBI	2		;IN TWO
	RM
	CALL	SEEK
	RC			;IF (ERROR_FLAG = SET) THEN RETURN
	DCR	D		;AND BACK ONE
	MOV	A,D
	JMP	PHLP

;--------------------------------------------------------------------
;SEEK TO THE TRACK IN THE ACCM.
;	1) IF THERE ARE ANY ERRORS ENCOUNTERED THEN THEY ARE REPORTED
;	   TO THE CONSOLE AND THE ERROR_FLAG (THE CARRY BIT) IS SET.
;	2) IF THERE WERE NO ERRORS THEN THE ERROR_FLAG IS RESET.

SEEK:	STA	RDTKTK		;START AT TRACK INDICATED BY A
	STA	TRACK		;KEEP RECORD
	PUSH	D		;SAVE DE
	PUSH	H		;SAVE HL
	MOV	C,A		;SAVE TRACK IN C
	LHLD	LOGPNT		;GET LOG POINTER
	INX	H		;ADVANCE LOG POINTER TO SIDES BYTE
	MOV	A,M		;LOAD BYTE
	DCX	H		;RETURN POINTER
	ANI	80H		;SEE IF DBLESIDED BIT IS ON
	JZ	ONESID		;IF NOT, FORGET IT
	LDA	RDTKSD		;ELSE LOAD SIDE BYTE
	XRI	80H		;TOGGLE IT
ONESID:	STA	RDTKSD		;REPLACE IT
	STA	SIDE		;SAVE IT
	MOV	B,A		;SAVE SIDE BYTE IN B
	PUSH	B		;SAVE BC
	SUB	A		;ZERO A
	STA	RTRSLT		;CLEAR RESULT BYTE
	OUT	STARTR		;START CONTROLLER
	CALL	WAIT1		;WAIT FOR IT TO FINISH
	POP	B		;RESTORE BC
	LDA	RTRSLT		;CHECK THE RESULTS
	CPI	GOOD		;NORMAL COMPLETION?
	POP	H		;RESTORE HL
	POP	D		;RESTORE DE
	JNZ	GRAB1		;IF ERROR = NO THEN
	STC
	CMC			;	ERROR_FLAG:=NO
	RET			;	RETURN
GRAB1:	DB	TRAP		;ELSE (CONDITIONAL RST 7)
	CALL	ERROR		;	REPORT ERROR
	STC			;	ERROR:=TRUE (CRY=SET)
 	RET			;	RETURN

;--------------------------------------------------------------------
;REPORT AN ERROR ON THE CONSOLE
;	1) THIS ROUTINE IS USED BY THE SEEK TRACK ROUTINE (SEEK).
;	2) THIS ROUTINE IS ALSO USED BY THE LOG ON ACTIVE DRIVES
;	   ROUTINE (LOGIN) WHICH ENTERS AT LOGER2.

LOGERR:	PUSH	PSW		;SAVE ERROR CODE
GRAB5:	DB	TRAP		;CONDITIONAL RST 7
	PUSH	B		;SAVE DRIVE NUMBER IN B
	LXI	D,DRVMSG	;DRIVE MESSAGE
	MVI	C,WRSTRN	;CPM_FUNCTION:=WRITE_STRING
	CALL	BDOS
	POP	B		;GET DRIVE NUMBER
	MOV	A,B		;MOVE IT
	CALL	BCDOUT		;SEND IT
	POP	PSW		;RECOVER ERROR CODE

LOGER2:	CALL	ERRFND		;LOADS DE TO ERR MSG
	INX	D		;SKIP CRS & LF
	INX	D
	INX	D
	MVI	C,WRSTRN	;CPM_FUNCTION:=WRITE_STRING
	CALL	BDOS
	RET

;====================================================================
;BEGIN READ AND WRITE TEST
;	1) WRDRV AND RDDRV RETURN CARRY CLEAR FOR NO ERROR

RDWRTS:	LXI	D,READNG	;ADDRESS OF READ/WRITE MESSAGE
	MVI	C,WRSTRN	;CPM_FUNCTION:=WRITE_STRING
	CALL	BDOS
	CALL	DRTYPE		;TRACK AND DRIVE NUMBER
	SUB	A		;ZERO A
	STA	PASS		;CLEAR PASS COUNTER
	CALL	CLRTBL		;CLEARS COMMAND TABLE
	CALL	TRKSZR		;PUTS SIZE OF TRACK AT TBYTES
	NOP
TSTDAT:	LXI	H,WRTRAK	;WRITE TRACK COMMAND ADDRESS
	SHLD	VECTOR		;TO GUIDE CONTROLLER
	CALL	WRDRV		;WRITES ALL TRACKS
	RC			;IF ERROR = TRUE THEN RETURN
	LXI	H,RDTRAK	;READ TRACK COMMAND ADDRESS
	SHLD	VECTOR		;GUIDE CONTROLLER
	CALL	RDDRV		;READS AND COMPARES ALL
	RC			;IF ERROR = TRUE THEN RETURN
	LDA	PASS		;GET PASS COUNTER
	INR	A		;INCREMENT IT
	STA	PASS		;PUT IT BACK
	CPI	4		;ONE TO MANY
	JNZ	TSTDAT		;CONTINUE DATA TEST
	RET

;--------------------------------------------------------------------
;FIGURE SIZE OF TRACK IN BYTES
;	1) THIS ROUTINE IS ONLY USED BY RDWRTS.

TRKSZR:	LHLD	LOGPNT		;PICKUP LOG POINTER
	MVI	B,0		;ZERO B
	MOV	A,M		;GET TRACKS IN A
	CPI	77		;8 INCH?
	JNZ	SKP		;DO NOT CHANGE
	MVI	B,3		;TO SKIP 5 INCH
SKP:	INX	H		;ADVANCE POINTER TO 2ND LOG ENTRY
	MOV	A,M		;LOAD SECTOR SIZE & SIDES
	ANI	7		;MASK SIZE ONLY
	ADD	B		;COVERS 5 OR 8 INCH DRIVES
	LXI	H,TKSIZ5	;INITIALIZE POINTER TO SIZES
	CALL	ADJUST		;ADJUST M BY DOUBLE A
	MOV	E,M		;LOAD LOW BYTE
	INX	H		;ADVANCE POINTER
	MOV	D,M		;LOAD HIGH BYTE
	XCHG			;PUT RESULT IN HL
	SHLD	TBYTES		;STORE RESULT
	RET

;--------------------------------------------------------------------
;WRITE ALL TRACKS ON A DRIVE
;	1) IF ANY ERRORS OCCURE THEN THE CARRY IS RETURNED SET ELSE
;	   ITS RETURNED CLEAR.

WRDRV:	LXI	D,WRTMSG	;WRITING MESSAGE
	MVI	C,WRSTRN	;CPM_FUNCTION:=WRITE_STRING
	CALL	BDOS
	LDA	PASS		;GET PASS NUMBER
	CALL	BCDOUT		;SEND IT
	CALL	CLRMAP		;CLEARS BADMAP TO ZEROS
	LXI	H,BADMAP	;ADDRESS OF MAP
	SHLD	MAPPNT		;INITIALIZES POINTER TO BADMAP
	LHLD	LOGPNT		;PICKUP LOG POINTER
	MOV	B,M		;NUMBER OF TRACKS
	SUB	A		;ZERO A
	STA	WRTKSD		;START WITH SIDE 0
	STA	SIDE		;STORE FOR ERROR MESSAGE
TRKLP:	PUSH	B		;SAVE TRACK COUNTER
	PUSH	H		;SAVE LOG POINTER
	MOV	A,M		;NUMBER OF TRACKS
	SUB	B		;TRACK COUNTER
	MOV	C,A		;SAVE TRACK IN C
	STA	WRTKTK		;CURRENT TRACK TO COMMAND
	STA	TRACK		;AND RECORD
	CALL	NEWPAT		;GET PATTERN FOR THIS TRACK
	CALL	FILBUF		;WRITES IT TO DISK BUFFER
WTTK:	SUB	A		;ZERO A
	STA	WTRSLT		;CLEAR RESULT BYTE
	OUT	STARTR		;STARTS CONTROLLER
	CALL	WAIT1		;WAIT FOR IT TO FINISH
	LDA	WRTKSD		;GET THE SIDE BYTE
	MOV	B,A		;SAVE IT IN B
	LDA	WTRSLT		;LOAD RESULT BYTE
	CPI	GOOD		;ORDINARY COMPLETION
	JZ	UPDATE		;GIVES NORMAL RETURN
GRAB2:	DB	TRAP		;CONDITIONAL RST 7
	CPI	NOTRDY		;IF DRIVE = NOT_READY THEN
	JNZ	MOD115
	POP	H		;	RESTORE STACK
	POP	B
	STC			;	ERROR = YES (CRY=SET)
	RET			;	RETURN
MOD115:	LHLD	MAPPNT		;PICKUP POINTER TO BADMAP
	MOV	M,A		;STORE ERROR CODE
	INX	H		;ADVANCE POINTER
	SHLD	MAPPNT		;STORE POINTER
	CALL	ERROR		;REPORT AND CONTINUE
	JMP	ASWAS		;NORMAL COMPLETION
UPDATE:	CALL	CKTBL		;CHECK SECTOR RESULTS TABLE
	LHLD	MAPPNT		;PICKUP POINTER TO BADMAP
	INX	H		;ADVANCE IT
	SHLD	MAPPNT		;STORE IT
ASWAS:	LHLD	LOGPNT		;GET LOG POINTER
	INX	H		;ADVANCE TO SIDE BYTE
	MOV	A,M		;LOAD IT
	ANI	80H		;CHECK SIDES BIT
	JZ	CNTDWN		;IF SINGLE-SIDED, FORGET IT
	LDA	WRTKSD		;LOAD COMMAND SIDE BYTE
	ANI	80H		;CHECK SIDE BIT
	JNZ	RESET		;ALREADY DONE
	MVI	A,80H		;SET IT
	STA	WRTKSD		;STORE IN COMMAND
	STA	SIDE		;AND STORE IT
	JMP	WTTK
RESET:	SUB	A		;RESET SIDE BIT FOR NEXT TRACK
	STA	WRTKSD		;STORE IN COMMAND
	STA	SIDE		;AND STORE IT
CNTDWN:	POP	H		;RESTORE POINTER
	POP	B		;RESTORE BC
	DCR	B		;COUNT DOWN THE TRACKS
	JNZ	TRKLP		;DO ANOTHER TRACK
	STC
	CMC			;ERROR = FALSE (CRY=CLEAR)
	RET			;PASS COMPLETE

;--------------------------------------------------------------------
;CLEAR BAD MAP
;	1) THIS ROUTINE IS ONLY USED BY THE WRITE A TRACK ROUTINE
;	   (WRDRV).

CLRMAP:	MVI	C,MAPSIZ	;SIZE OF BADMAP
	LXI	H,BADMAP	;ADDRESS OF MAP
	SUB	A		;ZERO A
MAPLP:	MOV	M,A		;PUT ZERO IN MAP
	INX	H		;ADVANCE 
	DCR	C		;COUNT-DOWN
	JNZ	MAPLP		;UNTIL DONE
	RET

;--------------------------------------------------------------------
;FILL THE DISK BUFFER
;	1) THIS ROUTINE IS ONLY USED BY THE WRITE A TRACK ROUTINE
;	   (WRDRV).

FILBUF:	PUSH	H		;SAVE HL
	LHLD	TBYTES		;TRACK SIZE
	XCHG			;PUTS SIZE IN DE
	LXI	H,DSKBUF	;POINTS M AT DISK BUFFER
BUFLP:	MOV	M,B		;STORES B IN BUFFER
	INX	H		;STEPS M
	DCX	D		;DECREMENT COUNTER
	MOV	A,E		;TO CHECK FOR ZERO
	ORA	D
	JNZ	BUFLP		;LOOP TILL DONE
	POP	H		;RESTORE HL
	RET

;--------------------------------------------------------------------
;READ ALL THE TRACKS ON A DRIVE
;	1) IF THERE ARE ANY ERRORS THEN THE CARRY IS RETURNED SET
;	   ELSE THE CARRY IS RETURNED CLEARED.

RDDRV:	LXI	D,RDNMSG	;READING MESSAGE
	MVI	C,WRSTRN	;CPM_FUNCTION:=WRITE_STRING
	CALL	BDOS
	LDA	PASS		;GET PASS
	CALL	BCDOUT		;SEND IT
	SUB	A		;ZERO A
	STA	RDTKSD		;START WITH SIDE 0
	STA	SIDE		;AND SAVE RECORD
	LXI	H,BADMAP	;INITIALIZE POINTER
	DCX	H		;TO ONE LESS
	SHLD	MAPPNT		;AND STORE IT
	LHLD	LOGPNT		;GET LOG POINTER
	MOV	B,M		;LOADS # OF TRACKS TO B
TRKLP2:	PUSH	B		;SAVE TRACK COUNTER
	PUSH	H		;SAVE LOG POINTER
	MOV	A,M		;GET NUMBER OF TRACKS
	SUB	B		;TRACK COUNTER
	MOV	C,A		;SAVE TRACK IN C
	STA	RDTKTK		;STORE IN COMMAND
	STA	TRACK		;TRACK RECORD
RD:	LHLD	MAPPNT		;PICKUP BADMAP POINTER
	INX	H		;ADVANCE IT
	SHLD	MAPPNT		;PUT IT BACK
	MOV	A,M		;LOAD IT
	ANI	0FFH		;SEE IF ITS CLEAR
	JNZ	NXTRK		;SKIP TRACK IF NOT
	SUB	A		;ZERO A
	STA	RTRSLT		;CLEAR RESULT BYTE
	OUT	STARTR		;START CONTROLLER
	CALL	WAIT1		;WAIT FOR IT TO FINISH
	LDA	RDTKSD		;GET SIDE BYTE
	MOV	B,A		;SAVE IT IN B
	LDA	RTRSLT		;GET RESULT BYTE
	CPI	GOOD		;COMPARE
	JZ	OKAY		;GIVES NORMAL RETURN
GRAB3:	DB	TRAP		;CONDITIONAL RST 7
	CPI	NOTRDY		;DRIVE GONE AWAY?
	JNZ	MOD255		;IF DRIVE = NOT_READY THEN
	POP	H		;	RESTORE STACK
	POP	B
	STC			;	ERROR = YES (CRY=SET)
	RET			;	RETURN
MOD255:	CALL	ERROR		;REPORT AND CONTINUE
OKAY:	PUSH	B		;SAVE BC
	CALL	CKTBL		;CHECK SECTOR RESULTS TABLE
	POP	B		;RESTORE BC
	CALL	NEWPAT		;GET TEST PATTERN
	CALL	VERIFY		;READ AND COMPARE DATA
NXTRK:	LHLD	LOGPNT		;GET LOG POINTER
	INX	H		;ADVANCE TO SIDE BYTE
	MOV	A,M		;LOAD IT
	ANI	80H		;CHECK SIDES BIT
	JZ	IGNOR		;IF SINGLE-SIDED, FORGET IT
	LDA	RDTKSD		;LOAD COMMAND SIDE BYTE
	ANI	80H		;CHECK SIDE BIT
	JNZ	RESET2		;ALREADY DONE
	MVI	A,80H		;SET IT
	STA	RDTKSD		;STORE IN COMMAND
	STA	SIDE		;SAVE RECORD
	JMP	RD		;DO OTHER SIDE
RESET2:	SUB	A		;RESET SIDE BIT FOR NEXT TRACK
	STA	RDTKSD		;STORE IN COMMAND
	STA	SIDE		;SAVE RECORD
IGNOR:	POP	H		;RESTORE POINTER
	POP	B		;RECOVER COUNTER
	DCR	B		;COUNT DOWN TRACKS
	JNZ	TRKLP2		;DO NEXT TRACK
	STC
	CMC			;ERROR = NO (CRY=CLEARED)
	RET			;FINISH

;--------------------------------------------------------------------
;VERIFY THAT DATA WAS CORRECTLY READ
;	1) THIS ROUTINE IS ONLY USED BY THE READ A TRACK ROUTINE
;	   (RDDRV).

VERIFY:	LXI	D,0		;ZERO DE
	PUSH	D		;SAVE DE
	LHLD	TBYTES		;LOAD TRACK SIZE
	XCHG			;MOVE TO DE
	LXI	H,DSKBUF	;SET M TO DISK BUFFER
VERLP:	MOV	A,M		;PICK UP MEMORY
	CMP	B		;WHAT IT SHOULD BE
	JZ	CNTINU		;IF CORRECT
	XTHL			;SAVE HL & GET ERROR COUNT
	INX	H		;INCREMENT ERROR COUNT
	XTHL			;RESTORE & SAVE
CNTINU:	INX	H		;INCREMENT M
	DCX	D		;DECREMENT SIZE COUNTER
	MOV	A,E		;CHECK FOR ZERO
	ORA	D
	JNZ	VERLP		;CONTINUE IF NOT
	POP	H		;GET ERROR COUNT
	MOV	A,L		;PUT L IN A
	ORA	H		;ZERO?
	RZ
	PUSH	H		;OR REPORT
	LXI	D,CRLF		;CARRIAGE RETURN & LINE FEED
	MVI	C,WRSTRN	;CPM_FUNCTION:=WRITE_STRING
	CALL	BDOS
	POP	H		;GET ERROR COUNT
	PUSH	H
	MOV	A,H
	CALL	BCDOUT		;PRINT THE HI-BYTE ERROR COUNT
	POP	H
	MOV	A,L
	CALL	BCDOUT		;PRINT THE LO-BYTE ERROR COUNT
	LXI	D,CMPERR	;COMPARE ERROR MSG
	MVI	C,WRSTRN	;CPM_FUNCTION:=WRITE_STRING
	CALL	BDOS
	LDA	RDTKTK		;GET TRACK NUMBER
	CALL	BCDOUT		;SEND IT
	LXI	D,SDMS		;SIDE MSG
	MVI	C,WRSTRN	;CPM_FUNCTION:=WRITE_STRING
	CALL	BDOS
	LDA	RDTKSD		;LOAD SIDE BIT
	ANI	SD2BIT		;GET SIDE BIT
	RLC			;PUT IT IN LOWEST BIT
	CALL	BCDOUT		;SEND IT
	RET

;--------------------------------------------------------------------
;CHECK SECTOR TABLE
;	1) THIS ROUINE IS USED BY BOTH THE READ AND THE WRITE A TRACK
;	   ROUTINES(WRTDRV,RDDRV).

CKTBL:	CALL	GETSCS		;RETURNS # OF SECTORS IN C
	MOV	B,C		;SAVE # IN B
	LXI	H,TRKTBL	;TRACK R/W RESULT TABLE
CKLP:	MOV	A,M		;LOAD M
	CPI	GOOD		;NORMAL COMPLETION
	CNZ	SECERR		;REPORT ERROR
	INX	H		;ADVANCE 
	DCR	C		;DECREMENT COUNTER
	JNZ	CKLP		;REPEAT TILL DONE
	SUB	A		;ZERO A FOR CLRTBL
	CALL	CLRTBL		;CLEAR TABLE AND RETURN
	RET

;--------------------------------------------------------------------
;RETURN NUMBER OF SECTORS ON DISK IN REGISTER C
;	1) THIS ROUTINE IS ONLY REFERENCED BY THE CHECK THE SECTOR
;	   TABLE ROUTINE (CKTBL).

GETSCS:	LHLD	LOGPNT		;GET DRIVE LOG POINTER
	MOV	A,M		;GET # OF TRACKS
	CPI	77		;IF 8 INCH
	JZ	NOT5		;SKIP 5 INCH
	MVI	C,0AH		;10 SECTORS FOR FIVE INCH
	RET
NOT5:	LDA	TRACK		;LOAD CURRENT TRACK
	CPI	0		;SEE IF ITS TRACK 0
	JNZ	NOT0		;SKIP IF ITS NOT
	MVI	C,26		;ELSE ITS 26 SECTORS
	RET
NOT0:	INX	H		;ADVANCE TO SECTOR SIZE
	MOV	A,M		;LOAD SECTOR SIZE BYTE
	ANI	7		;LOW BITS ONLY
	MOV	B,A		;SAVE IN B
	LXI	H,SCTRS		;POINT M AT TABLE
	MOV	A,L		;ADJUST M BY B
	ADD	B
	JNC	NOTOVR		;IN CASE OF CARRY
	INR	H
NOTOVR:	MOV	L,A		;M NOW ADJUSTED
	MOV	C,M		;PUT NUMBER OF SECTORS IN C
	RET

;--------------------------------------------------------------------
;REPORT SECTOR ERROR
;	1) THIS ROUTINE IS ONLY USED BY THE CHECK SECTOR TABLE
;	ROUTINE (CKTBL).

SECERR:	PUSH	H		;SAVE HL
GRAB6:	DB	TRAP		;CONDITIONAL RST 7
	PUSH	B		;AND BC
	CALL	ERRFND		;LOADS DE WITH ERR MSG
	MVI	C,WRSTRN	;CPM_FUNCTION:=WRITE_STRING
	CALL	BDOS
	LXI	D,TRKMSG	;TRACK MESSAGE
	MVI	C,WRSTRN	;CPM_FUNCTION:=WRITE_STRING
	CALL	BDOS
	LDA	TRACK		;GET TRACK NUMBER
	CALL	BCDOUT		;SEND IT
	LXI	D,SIDEMS	;SIDE MSG
	MVI	C,WRSTRN	;CPM_FUNCTION:=WRITE_STRING
	CALL	BDOS
	LDA	SIDE		;GET CURRENT SIDE
	RLC			;MOVE SIDE BIT TO DATA 0
	CALL	BCDOUT		;SEND IT
	LXI	D,SECMSG	;SECTOR MESSAGE
	MVI	C,WRSTRN	;CPM_FUNCTION:=WRITE_STRING
	CALL	BDOS
	POP	B		;RECOVER BC
	PUSH	B		;AND RE-SAVE
	MOV	A,B		;NUMBER OF SECTORS
	SUB	C		;COUNTER
	CALL	BCDOUT		;SEND IT AND RETURN
	POP	B		;RESTORE BC
	POP	H		;RESTORE HL
	RET

;--------------------------------------------------------------------
;GET A NEW TEST PATTERN

NEWPAT:	PUSH	H		;SAVE HL
	LXI	H,PATBLE	;SET M TO TEST PATTERNS
	LDA	PASS		;LOAD PASS COUNTER
	ADD	L		;ADJUST LOW BYTE OF ADDRESS
	JNC	NOCARY		;COVER OVERFLOW POSSIBILITY
	INR	H
NOCARY:	MOV	L,A		;BRINGS M TO CURRENT PATTERN
	LDA	TRACK		;GET CURRENT TRACK NUMBER
	RAR			;CHECK FOR EVEN OR ODD
	MOV	A,M		;LOAD TEST PATTERN
	JNC	EVEN		;SKIP ON ALTERNATE TRACKS
	CMA			;COMPLEMENT TEST PATTERN
EVEN:	POP	H		;RESTORE HL
	MOV	B,A		;SAVE IN B
	RET

;--------------------------------------------------------------------
;WAIT FOR CONTROLLER TO FINISH ITS OPERATION

WAIT1:	PUSH	D		;SAVE DE
	LXI	D,0A000H	;LOAD AS TIMER-COUNTER
WTLOOP:	DCX	D		;START COUNTDOWN
	MOV	A,D
	ORA	E		;CHECK IT FOR 0
	JZ	RESTRT		;REPORT TO TERMINAL & WBOOT
SKIP:	PUSH	D
	CALL	CKABRT		;CHECK FOR KEYBOARD INTERRUPT
	POP	D		;RECOVER LOCAL COUNTERS
	LDA	HLTED		;UNIVERSAL HALT RESULT
	CPI	0		;DONE YET?
	JZ	WTLOOP		;WAIT FOR IT
	ANI	GOOD		;NORMAL COMPLETION?
	JZ	RESTRT		;ABORT IF NOT
	SUB	A		;ZERO A
	STA	HLTED		;CLEAR RESULT BYTE
	POP	D		;RECOVER DE
	RET
RESTRT:	LXI	D,EIGHTN	;NO RESPONSE MESSAGE
GRAB4:	DB	TRAP		;CONDITIONAL RST 7
	MVI	C,WRSTRN	;CPM_FUNCTION:=WRITE_STRING
	CALL	BDOS
	JMP	START		;RE-START TEST

;--------------------------------------------------------------------
;ABORT OPERATION IF ESCAPE ENTERED AT CONSOLE
;	1) THIS ROUTINE IS ONLY USED BY THE WAIT FOR CONTROLLER TO
;	   FINISH ROUTINE (WAIT1).

CKABRT:	PUSH	B		;SAVE BC
	PUSH	H		;SAVE HL
	PUSH	D		;SAVE DE
	MVI	C,CONSTA	;ASKS FOR CONSOLE STATUS
	CALL	BDOS
	DCR	A		;0FFH MEANS DATA READY
	POP	D		;RECOVER DE
	POP	H		;RECOVER HL
	POP	B		;RECOVER BC
	RNZ			;NO ABORT
	MVI	C,CONIN		;GET THE CHARACTER
	CALL	BDOS
	CPI	ESC		;ESCAPE CHARACTER
	RNZ			;IGNORE ANYTHING ELSE
	RST	7		;RETURN TO DDT
	RET

;--------------------------------------------------------------------
;CLEAR SECTOR TABLE

CLRTBL:	MVI	C,TBLSZ		;SIZE OF TABLE
	LXI	H,TRKTBL	;COMMAND RESULT TABLE
TBLP:	MOV	M,A		;FILL IT WITH A
	INX	H		;INCREMENT MEMORY POINTER
	DCR	C
	JNZ	TBLP
	RET

;--------------------------------------------------------------------
;REPORT AN ERROR TO THE CONSOLE

ERROR:	PUSH	D
	PUSH	H
	PUSH	B		;SAVE REGISTER PAIRS
	CALL	ERRFND		;LOADS DE WITH ERROR MSG
	MVI	C,WRSTRN	;CPM_FUNCTION:=WRITE_STRING
	CALL	BDOS
	LXI	D,TKMSG		;TRACK MESSAGE
	MVI	C,WRSTRN	;CPM_FUNCTION:=WRITE_STRING
	CALL	BDOS
	LDA	TRACK		;GET CURRENT TRACK
	CALL	BCDOUT		;AND SEND IT
	LXI	D,SDMS		;SIDE MSG
	MVI	C,WRSTRN	;CPM_FUNCTION:=WRITE_STRING
	CALL	BDOS
	POP	B
	MOV	A,B		;GET SIDES
	RLC			;MOVE SIDE BIT TO DATA 0
	CALL	BCDOUT		;SEND IT
RESUME:	POP	H		;RECOVER REGISTER PAIRS
	POP	D
	RET

;--------------------------------------------------------------------
;GET THE BASE ADDRESS OF AN ERROR STRING

ERRFND:	ANI	1FH		;MASK OFF ERROR VALUE
	LXI	H,ERRTBL	;PICKUP ADDRESS OF MSG TABLE
	CALL	ADJUST		;ADJUST M BY TWICE A
	MOV	E,M		;LOAD LOW ADDRESS
	INX	H		;INCREMENT POINTER
	MOV	D,M		;LOAD HIGH ADDRESS
	RET

;--------------------------------------------------------------------
;DOUBLE THE ACCM. AND THEN ADD IT TO THE HL PAIR.

ADJUST:	MOV	B,A		;SAVE A IN B
	MOV	A,L		;PICKUP POINTER LOW BYTE
	ADD	B		;ADJUST TO B
	JNC	SKPNC		;IF NO OVERFLOW
	INR	H		;ADJUST H
SKPNC:	ADD	B		;FOR HIGH BYTE
	JNC	SKPNC2		;IF NO OVERFLOW
	INR	H		;ADJUST H
SKPNC2:	MOV	L,A		;PUT IN L
	RET			;POINTER IS ADJUSTED BY A

;--------------------------------------------------------------------
;PRINT THE DRIVE TYPE AND NUMBER
;	1) THIS ROUTINE IS USED BY BOTH SEEKS AND RDWRTS IN THEIR
;	   OPENING MESSAGES.

DRTYPE:	LHLD	LOGPNT		;PICK UP LOG POINTER
	MOV	A,M		;GET NUMBER OF TRACKS
	CPI	77		;SEE IF EIGHT INCH
	LXI	D,EIGHMS		;EIGHT INCH DRIVE MESSAGE
	JZ	EIGHTR		;FOR EIGHT INCH MESSAGE
	LXI	D,FIVEMS		;FIVE INCH DRIVE MESSAGE
EIGHTR:	MVI	C,WRSTRN	;CPM_FUNCTION:=WRITE_STRING
	CALL	BDOS
	LDA	RDTKDR		;GET NUMBER OF DRIVE
	CALL 	BCDOUT		;SEND TO TERMINAL
	RET

;--------------------------------------------------------------------
;PUTDC PRINTS THE ASCII DECIMAL EQUIVALENT OF THE NUMBER IN HL *
;	1) PRINT THE ACCM. AS ONE BCD DIGIT.

BCDOUT:	MOV	L,A
	MVI	H,0
PUTDC:	LXI	B,-10
PHL:	PUSH	D
	MOV	D,B
	MOV	E,B
PHLLP:	DAD	B
	INX	D
	JC	PHLLP
	XTHL
	XCHG
	MOV	A,H
	ORA	L
	CNZ	PHL
	POP	H
	MVI	A,'0'
	ADD	L
	SUB	C

PCHAR:	PUSH	H
	PUSH	B
	PUSH	D
	PUSH	PSW
	MOV	E,A
	MVI	C,2
	CALL	BDOS
	POP	PSW
	POP	D
	POP	B
	POP	H
	RET

;--------------------------------------------------------------------
;REPORT TRACK ERROR
;	1) THIS ROUTINE IS CURRENTLY UNUSED

BADTRK:	PUSH	PSW		;SAVE ERROR CODE
	CALL	ERROR		;REPORT FAULT
	LHLD	MAPPNT		;PICKUP BADMAP POINTER
	POP	PSW		;RECOVER ERROR CODE
	MOV	M,A		;STORE IT IN MAP
	INX	H		;ADVANCE POINTER
	SHLD	MAPPNT		;STORE IT
	RET

;--------------------------------------------------------------------
;BEGIN CHANNEL COMMANDS

SNSTAT:	DB	SNSTA		;SENSE STATUS COMMAND
SNSDRV:	DB	0		;PHYSICAL DRIVE NUMBER
DSTAT1:	DB	0		;DSTAT 1
DSTAT2:	DB	0		;DSTAT 2
DSTAT3:	DB	0		;DSTAT 3
SNSRLT:	DB	0		;COMMAND RESULT
BRANCH:	DB	BRNCH		;BRANCH COMMAND
	DW	COMHLT
	DB	0		;EXTENDED ADDRESS
SETDMA:	DB	SETMA		;SET DMA FOR SEEKS
	DW	DSKBUF		;ALL PURPOSE BUFFER (EIGHTK-8192 BYTES)
	DB	0		;EXTENDED ADDRESS BYTE
	DB	BRNCH		;BRANCH COMMAND
	DW	COMHLT
	DB	0		;EXTENDED ADDRESS
WRTRAK:	DB	WRTRK		;WRITE TRACK COMMAND
WRTKTK:	DB	0		;
WRTKSD:	DB	0		;
WRTKDR:	DB	0		;
WRTABL:	DW	TRKTBL		;
	DB	0
WTRSLT:	DB	0
	DB	BRNCH		;BRANCH COMMAND
	DW	COMHLT
	DB	0		;EXTENDED ADDRESS
RDTRAK:	DB	RDTRK		;READ TRACK COMMAND
RDTKTK:	DB	0		;
RDTKSD:	DB	0		;
RDTKDR:	DB	0		;
RDSCTB:	DW	TRKTBL		;
	DB	0 	
RTRSLT:	DB	0
	DB	BRNCH		;BRANCH COMMAND
	DW	COMHLT
	DB	0		;EXTENDED ADDRESS
RETRYS:	DB	STRTRY		;COMMAND TO SET # OF RETRIES
	DB	RETRIES		;NUMBER OF RETRIES
	DB	BRNCH		;BRANCH COMMAND
	DW	COMHLT		;STANDARD HALT
	DB	0
COMHLT:	DB	CONHLT		;UNIVERSAL HALT COMMAND
HLTED:	DB	0		;RESULT BYTE

;--------------------------------------------------------------------
;VARIABLE STORAGE

TRKTBL:	DS	TBLSZ		;TABLE USED BY WRITE TRACK COMMAND

PATBLE:	DB	0		;TEST PATTERNS
	DB	0FFH
	DB	0AAH
	DB	55H

TKSIZ5:	DW	0		;NO EQUIVALENT ON 5 IN
	DW	2560		;5 INCH SINGLE DENSITY
	DW	5120		;5 INCH DOUBLE DENSITY
TKSIZ8:	DW	3328		;8 INCH SINGLE DENSITY
	DW	6656		;8 INCH 256 BYTE SECTORS
	DW	7680		;DITTO 512
	DW	8192		;DITTO 1024
SCTRS:	DB	26		;SINGLE DENSITY 8 INCH
	DB	26		;DOUBLE DENSITY 256 BYTE SECTORS
	DB	15		;512 BYTE SECTORS
	DB	8		;1024 BYTE SECTORS
TBYTES:	DW	0		;CURRENT TRACK SIZE
TRACK:	DB	0		;CURRENT TRACK
SIDE:	DB	0		;CURRENT SIDE
PASS:	DB	0		;CURRENT PASS

LOGPNT:	DW	DRVLOG		;POINTER TO DRVLOG
DRVLOG:	DS	16		;DRIVE LOG (TRKS, SIDES & SECTOR SIZES)

;--------------------------------------------------------------------
;MESSAGE STRINGS

SEEKNG:	DB	LF,LF,CR,CR
	DB	'TESTING SEEKS ON$'
READNG:	DB	LF,CR,CR
	DB	'TESTING READ/WRITES ON$'
TRKMSG:	DB	' TRACK $'
SIDEMS:	DB	' SIDE $'
SECMSG:	DB	' SECTOR $'
CRLF:	DB	LF,CR,CR
	DB	'$'
CMPERR:	DB	' COMPARE ERROR(S) ON TRACK $'
DRVMSG:	DB	LF,CR,CR
	DB	'PHYSICAL $'
FIVEMS:	DB	' 5 INCH PHYSICAL $'
EIGHMS:	DB	' 8 INCH PHYSICAL $'
WRPRMS:	DB	' WRITE PROTECTED$'
DBLMSG:	DB	' DOUBLE-SIDED DRIVE$'
NODRVS:	DB	LF,CR,CR
	DB	'NO DRIVES ARE READY$'
SIDESQ:	DB	': HOW MANY SIDES ON THIS DRIVE? $'
ZERO:	DB	LF,CR,CR
	DB	' IMPROPER COMMAND CODE$'
ONE:	DB	LF,CR,CR
	DB	' IMPROPER DISK DRIVE VALUE$'
TWO:	DB	LF,CR,CR
	DB	' DISK DRIVE NOT READY$'
THREE:	DB	LF,CR,CR
	DB	' IMPROPER TRACK VALUE$'
FOUR:	DB	LF,CR,CR
	DB	' UNREADABLE MEDIA$'
FIVE:	DB	LF,CR,CR
	DB	' IMPROPER SECTOR HEADER - NO SYNC BYTE(S)$'
SIX:	DB	LF,CR,CR
	DB	' CRC ERROR IN SECTOR HEADER SCAN$'
SEVEN:	DB	LF,CR,CR
	DB	' SEEK ERROR$'
EIGHT:	DB	LF,CR,CR
	DB	' COMPARE ERROR IN SECTOR HEADER SCAN$'
FOURTN:	DB	LF,CR,CR
	DB	' CRC ERROR IN DATA FIELD$'
FIFTN:	DB	LF,CR,CR
	DB	' IMPROPER SECTOR VALUE$'
SIXTN:	DB	LF,CR,CR
	DB	' MEDIA WRITE PROTECTED$'
SEVNTN:	DB	LF,CR,CR
	DB	' LOST DATA - DMA CHANNEL DID NOT RESPOND$'
EIGHTN:	DB	LF,CR,CR
	DB	' LOST COMMAND - CHANNEL DID NOT RESPOND$'
TKMSG:	DB	' TRACK $'
SDMS:	DB	' SIDE $'
SD1MS:	DB	' SIDE ONE$'
SD2MS:	DB	' SIDE TWO$'
WRTMSG:	DB	LF,CR,CR
	DB	'WRITING ALL TRACKS PASS $'
RDNMSG:	DB	LF,CR,CR
	DB	'VERIFYING ALL TRACKS WRITTEN ON PASS $'
ONMS:	DB	LF,LF,CR,CR
	DB	'TO ABORT TEST HIT "ESC".  TYPE G100 FOR RE-RUN.'
	DB	LF,LF,CR,CR,'$'

;--------------------------------------------------------------------
;MISC RESERVES

ERRTBL:	DW	ZERO,ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT
	DW	EIGHT,EIGHT,EIGHT,EIGHT,EIGHT,FOURTN
	DW	FIFTN,SIXTN,SEVNTN,EIGHTN
	DS	50
STACK	EQU	$
MAPPNT:	DW	0		;POINTER TO BADMAP
BADMAP:	DS	152		;76 TRKS TIMES 2 SIDES
DSKBUF:	DS	8192		;8K DISK BUFFER

	END
