;********************************************************
;****  THE NORTH STAR DISK OPERATING SYSTEM AS       ****
;****  DIS-ASSEMBLED BY BARRY A. WATZMAN, CDP        ****
;********************************************************
;****  THIS IS THE BOOT-STRAP ROUTINE IN PROM        ****
;********************************************************
BOARD	EQU	0E800H		;CONTROLLER BOARD ADDR
BRD	EQU	0E8H		;BOARD PAGE
DOS	EQU	2000H		;DOS ADDRESS
SYNCF	EQU	04H		;SYNC CHAR FOUND-RDY TO READ
SCTPS	EQU	0FH		;SECTOR POSITION MASK
TRAK0	EQU	01H		;TRACK ZERO MASK
MOTST	EQU	10H		;MOTOR ON TEST MASK
SETFF	EQU	BOARD+309H	;SET TRACK STEP FF
RESFF	EQU	BOARD+308H	;RESET TRACK STEP FF
ASTMS	EQU	BOARD+390H	;LOAD A STAT & START MOTR
ASTAT	EQU	BOARD+310H	;LOAD A STAT ONLY
BSTAT	EQU	BOARD+330H	;LOAD B STAT ONLY
RSFLG	EQU	BOARD+314H	;RESET SECTOR FLAG
STPIN	EQU	BOARD+31DH	;LOAD STEP DIR 'IN'
STPOU	EQU	BOARD+31CH	;LOAD STEP DIR 'OUT'
RDATA	EQU	BOARD+350H	;MASK TO READ DATA FROM DISK
;********************************************************
;**** THIS SECTION PERFORMS NECESSARY INITIALIZATION ****
;**** SO THAT THE NORMAL BLOCK READ ROUTINE AT E91EH ****
;**** MAY BE CALLED.  NOTE THAT THE MAX NO OF TRACK  ****
;**** MOVEMENTS TO GET THE HEAD TO TRACK 0 IS 58 -   ****
;**** THE AUTHOR APPARENTLY ADDED ONE FOR SAFETY BUT ****
;**** FORGOT THAT THE 58 WAS DECIMAL, NOT HEX.       ****
;********************************************************
	ORG	BOARD+100H
	LXI	SP,DOS+114H
	MVI	B,10		;READ 10 TIMES THEN GIVE UP
LE905	PUSH	B
	MVI	A,59H		;58D=MAX NO OF MOVES TO TRAK 0
	STA	DOS		;ASSUME HEAD AT WORST CASE LOC
	STA	DRSEL		;NONE OF THREE DRIVES SELECTED
	LXI	B,0001H		;B BECOMES DESIRED TRK;C=DRIVE
	MOV	A,C		;READ ONLY 1 SECTOR
	MVI	D,4		;D=BLK TO BE READ WITHIN TRACK
	MOV	E,C		;COMMAND;1 = READ
	LXI	H,DOS		;ADDRESS OF DOS TO BE LOADED
	CALL	LE91E		;MAIN PROCESSING LOOP
	JMP	CKBS		;IF OK EXIT ELSE RETRY OR DIE
;********************************************************
;**** THIS IS THE NORMAL READ ROUTINE.  THE ACC      ****
;**** HAS THE NUMBER OF SECTORS TO BE READ.  REG B   ****
;**** CONTAINS THE DESIRED TRACK, REGISTER C HAS     ****
;**** THE DESIRED DRIVE AND REGISTER D CONTAINS THE  ****
;**** DESIRED SECTOR (0-9) WITHIN THE TRACK.  THE    ****
;**** DATA WILL BE LOADED BEGINNING AT H,L. TRAK2    ****
;**** AND TRAK3 ARE INITIALIZED FROM THE DISK TO 59H ****
;**** WHEN THE 1ST BLOCK IS READ IN; THE TEST FOR    ****
;**** OLD TRK=59H IS REQD IN MULTIPLE DRIVE SYSTEMS  ****
;**** WHERE THE 2ND & 3RD DRIVES MAY BE UNINITIALIZED****
;**** FOR SOME TIME AFTER THE SYSTEM 1ST COMES UP.   ****
;********************************************************
LE91E	PUSH	PSW
	PUSH	H
	PUSH	D
	PUSH	B
	MVI	B,BRD+3		;CMNDS START AT 0EBH (C = 01H)
	CALL	MOTON		;MOTOR ON, SEL DRIVE, LOAD HEAD
	LXI	H,DOS-(BOARD+300H)-1
	DAD	B		;H = DOS + SELECTED DRIVE (1-3)
	MOV	A,M		;GET CURRENT TRACK ADDRESS
	XRI	59H		;STARTUP INIT. ALL 3 TO 59H
	PUSH	H
	CZ	LE964		;WILL POSITION HEAD TO TRK 0
	POP	H
	POP	PSW		;PUSHED AS B - DESIRED TRACK
	CALL	LE964		;POSITN HEAD TO TRK IN A
	POP	B		;PUSHED AS D - DESIRED SECTOR
;********************************************************
;**** THIS ROUTINE WAITS UNTIL WE HAVE THE DESIRED   ****
;**** SECTOR AND THEN JUMPS TO EITHER 200AH OR 2007H ****
;**** OR FALLS THRU TO READ DATA DEPENDING ON REG C  ****
;**** WHICH IS THE COMMAND (0=WRITE, 1=READ, 2=VER)  ****
;********************************************************
LE938	CALL	LE9CE		;WAIT FOR SECTOR FLAG
	LDA	BSTAT		;GET SECTOR POSITION
	ANI	SCTPS		;MASK IT
	CMP	B		;IS IT THE ONE WE WANT?
	JNZ	LE938		;NO--WAIT FOR NEXT SECTOR
	POP	H		;PUSHED AS H-DATA LOAD ADDRESS
	DCR	C		;TO SET COMMAND FOR PROPER JUMP
	JM	BOARD+0AH	;RETURN FOR WRITE ROUTINE
	JNZ	BOARD+7H	;RETURN FOR VERIFY ROUTINE
;********************************************************
;**** THIS ROUTINE WAITS UNTIL IT IS TIME TO READ    ****
;**** AND THEN JUMPS TO THE ACTUAL READ ROUTINE.  IF ****
;**** A SYNC CHARACTER HAS NOT BEEN DETECTED WITHIN  ****
;**** A SPECIFIED TIME FOLLOWING A SECTOR HOLE, THEN ****
;**** THEN ACC IS SET NON-ZERO AND A JUMP TO AN ERROR****
;**** ROUTINE IS MADE.                               ****
;********************************************************
LE94C	MVI	B,8CH		;MAX DELAY SECTOR TO SYNC CHAR
	LXI	D,RDATA		;SET UP D TO READ ACTUAL DATA
	MVI	C,0
LE953	LDA	ASTAT		;LOAD A STAT INTO ACC
	ANI	SYNCF		;SYNC CHAR FOUND-RDY TO READ
	JNZ	READ		;TO DO ACTUAL READ
	DCR	B		;WAIT SOME MORE
	JNZ	LE953		;WE HAVEN'T REACHED LIMIT YET
	MVI	A,01H		;WE'RE IN TROUBLE
	JMP	LE9AB		;JUMP TO ERROR ROUTINE
;********************************************************
;**** THIS IS THE TRACK SELECT ROUTINE.  ENTER WITH  ****
;**** DESIRED TRACK IN A AND H,L POINT TO CURRENT    ****
;**** TRACK.  IT LOADS H,L WITH A DIRECTION SETTING  ****
;**** ADDRESS AND PUTS NO OF STEPS REQD IN REG C.    ****
;********************************************************
LE964	MOV	D,A		;SAVE DESIRED TRACK
	SUB	M		;SUBTRACT PRESENT TRACK
	MOV	M,D		;STORE NEW TRACK ADDRESS
	RZ			;DONE IF OLD ADDR=NEW ADDR
	LXI	H,STPIN		;LOAD H STEP DIR 'IN'
	MOV	C,A		;DIFFERENCE IS NO OF STEPS REQD
	JP	LE97B		;GO STEP IT
	CMA			;DIFF WAS NEG--NEED TO STEP OUT
	INR	A		;INVRT THE NEG NO OF STEPS REQD
	MOV	C,A		;NO OF STEPS 'OUT' REQD IN C
	LDA	ASTAT		;ALREADY ALL THE WAY OUT?
	ANI	TRAK0		;TRACK 0 FLAG
	RNZ			;YES--CAN'T GO OUT ANY FURTHER
	LXI	H,STPOU		;LOAD H STEP DIR 'OUT'
;********************************************************
;**** THIS ROUTINE ACTUALLY DOES THE HEAD STEPPING.  ****
;********************************************************
LE97B	MOV	A,M		;SET DIR FF AS PER H REG
LE97C	LDA	SETFF		;SET TRACK STEP FF
	XTHL			;SHORT TIME DELAY
	XTHL			;MORE DELAY (MIN 10 USEC TOTAL)
	LDA	RESFF		;RESET TRACK STEP FF
	MVI	D,02H		;WAIT 2 SECTOR TIMES (40 MSEC)
	CALL	DELAY
	LDA	ASTAT		;FIND OUT WHERE WE'RE AT
	ANI	TRAK0		;TRACK ZERO?
	JZ	LE993		;JUMP IF NOT TRACK 0
	MVI	C,01H		;WERE ALL WAY OUT-SET C TO STOP
LE993	DCR	C		;NEED MORE STEPS?
	JNZ	LE97C		;YES--CONTINUE STEPPING
	RET			;NO--WERE DONE,	RETURN.
;********************************************************
;**** THIS IS THE ERROR ROUTINE FOR THE BOOTSRAP ONLY****
;********************************************************
CKBS	POP	B		;B IS CONDITION CODE
	JZ	BOARD+4H	;OK--JMP TO LOADED 1ST BLOCK
	DCR	B		;IF HARD ERROR, TRY 10 TIMES
	JNZ	LE905		;TRY AGAIN
DIE	JMP	DIE		;HARD ERROR IN BS, NO RECOVERY
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
;********************************************************
;**** THIS SETS UP B FOR HANDLING BY THE ERR ROUTINE ****
;**** POPS STACK & 0'S REG A SO CKBS WILL DET ERROR  ****
;********************************************************
LE9AB	POP	B
	ORA	A
	RET
;********************************************************
;**** THIS IS THE ACTUAL DATA READ ROUTINE.          ****
;********************************************************
READ	MOV	B,C		;MOVE 0 TO B
READ1	LDAX	D		;THIS IS THE ACTUAL DATA READ
	MOV	M,A		;STORE DATA IN MEMORY
	XRA	B		;I THINK THIS ADDS TO CKSUM
	RLC			;THIS TOO
	MOV	B,A		;MOVE PARTIAL CKSUM TO B
	INX	 H		;SET H FOR NEXT BYTE
	DCR	C		;GOING TO READ 256 BYTES & CKSUM
	JNZ	READ1		;READ MORE DATA
	LDAX	D		;READ THE CHECKSUM FROM DISK
	XRA	B		;COMPARE IT WITH CALCULATED CKSUM
	JZ	LE9C4		;IF THEY ARE SAME GO ON
	MOV	A,B		;?--CAN'T FIGURE THIS ONE OUT
	MVI	A,02H		;SET A NON-ZERO TO DETECT ERROR
	JMP	LE9AB		;JUMP TO THE ERROR HANDLER
LE9C4	POP	PSW		;GET NO OF SECTORS TO BE READ
	DCR	A		;DECREMENT IT
	RZ			;RETURN IF DONE
	PUSH	PSW		;SAVE IT
	CALL	LE9CE		;WAIT FOR SECTOR HOLE
	JMP	LE94C		;WAIT FOR SYNC & READ NXT SECTR
;********************************************************
;**** DELAY ROUTINE; DELAY IS NO OF SECTOR TIMES IN  ****
;**** THE D REGISTER.                                ****
;********************************************************
LE9CE	MVI	D,01H		;HERE TO RET WHEN SCTR FOUND
DELAY	LDA	RSFLG		;RESET SECTOR FLAG
TSTSF	LDA	ASTMS		;LOAD A STATUS REG TO ACC
	ANI	80H		;MASK SECTOR FLAG
	JZ	TSTSF		;TEST SECTOR FLAG
	DCR	D
	RZ			;IF ZERO WE'RE DONE
	JMP	DELAY		;GIVE IT MORE TIME
;********************************************************
;**** THIS ROUTINE STARTS THE MOTOR, WAITS 5 REV (50 ****
;**** SECTOR TIMES) FOR IT TO COME UP, LOADS HEAD &  ****
;**** DRIVE SELECT REG (USING CONTENTS OF C REGISTER)****
;**** STORES SELECTED DRIVE AT 2003H & DELAYS 13     ****
;**** SECTOR TIMES FOR HEAD TO SETTLE FROM LOAD.     ****
;**** IF MOTOR WAS ALREADY ON, CHECKS DRIVE CURRENTLY****
;**** SELECTED (2003H) VS DRIVE REQUESTED IN REG C   ****
;**** IF THEY ARE SAME, SKIPS HEAD LOAD SETTLE DELAY.****
;****      ON ENTRY, C=DESIRED DRIVE, B=0EBH.        ****
;********************************************************
MOTON	LDA	ASTMS		;LOAD A STAT & START MOTOR
	ANI	MOTST		;MASK MOTOR ON TEST BIT
	JNZ	CKDRV		;JUMP IF MOTOR ON
	MVI	D,32H		;5 REV TO SPEED UP
	CALL	DELAY
	JMP	LHSD		;LOAD HEAD & SELECT DRIVE
CKDRV	LDA	DRSEL		;GET DRIVE CUR SELECTED IN ACC
	CMP	C		;C HAS DRIVE WE WANT--SAME?
	RZ			;YES--HEAD IS LOADED, SKIP DELAY
LHSD	LDAX	B		;LOAD HEAD & DR SEL REG USING C
	MOV	A,C		;MOVE SELECTED DRIVE TO ACC
	STA	DRSEL		;STORE IT
	MVI	D,0DH		;SETTLE TIME FROM HEAD LOAD
	JMP	DELAY
DEFST	ORG	DOS
TRAK1	DS	1		;STORE HEAD LOC (TRACK) DRIVE #1
TRAK2	DS	1		;STORE HEAD LOC (TRACK) DRIVE #2
TRAK3	DS	1		;STORE HEAD LOC (TRACK) DRIVE #3
DRSEL	DB	1		;DRIVE CURRENTLY SELECTED
LEVL2	JMP	DOS+5AH		;ENTRY TO 2ND LEVEL BOOT
VERFY	JMP	DOS+75FH	;RE-ENTRY TO VERIFY ROUTINE
WRITE	JMP	DOS+78EH	;RE-ENTRY TO WRITE ROUTINE
	;PAGE
