;>>>The following is retyped from a MITS printout titled HDLOADER<<<

;************************************************************
;*      THIS IS THE LOADER FOR THE HARD DIKS. IT READS      *
;*      THE OPSYS IMAGE FROM THE REMOVABLE PLATTER AND      *
;*      LOADS IT INTO MEMORY STATING AT 0.                  *
;************************************************************
	ENTRY	HDLDR
DSKCHN	EQU	160		;FIRST DISK CHANNEL
DFLTDR	EQU	0		;DEFAULT DISK DRIVE
;				;NOTE THAT THE DRIVE NUMBER
;				;MUST BE MULTIPLIED BY 4
;				;IN THIS EQUATE, SINCE THE ASSEMBLER
;				;IS STUPID
DFLTBF	EQU	0		;CONTROLLER BUFFER
OSOFF	EQU	40		;OFFSET TO OPSYS PTRS
SEEK	EQU	0		;SEEK COMMAND
WRSEC	EQU	32		;WRITE SECTOR
RDSEC	EQU	48		;READ SECTOR
WRBUF	EQU	64		;WRITE BUFFER
RDBUF	EQU	80		;READ BUFFER
STAT	EQU	96		;STATUS
;*
;**	INITIALIZE
;*
HDLDR	EQU	*
	XRA	A		;OPEN...
	OUT	DSKCHN		;...
	OUT	DSKCHN+2	;...
	OUT	DSKCHN+4	;...
	OUT	DSKCHN+6	;...DDRS
	OUT	DSKCHN+1	;SETUP...
	OUT	DSKCHN+5	;...
	CMA			;...
	OUT	DSKCHN+3	;...
	OUT	DSKCHN+7	;...DDRS
	MVI	A,44		;CLOSE...
	OUT	DSKCHN		;...
	OUT	DSKCHN+4	;...
	OUT	DSKCHN+6	;...
	MVI	A,36		;...
	OUT	DSKCHN+2	;...DDRS
;*
;**	FIND A STACK
;*
	LXI	H,0		;GET START ADDRESS
;	LXI	H,DUMSTK	;$$$$
;	JMP	ENDMEM		;$$$$
MEMLP	EQU	*
	MOV	A,M		;GET A BYTE
	MOV	B,A		;SAVE IT
	CMA			;INVERT IT
	MOV	M,A		;PUT IT BACK
	CMP	M		;WRITTEN RIGHT ?
	JNZ	ENDMEM		;NO = AT END
	MOV	M,B		;PUT BACK ORIGINAL
	INX	H		;MOVE POINTER
	JMP	MEMLP		;TRY NEXT ONE
ENDMEM	EQU	*
	SPHL			;WE HAVE A STACK
;*
;**	READ PACK DESCRIPTOR PAGE TO GET OPSYS ADDR
;*
	LXI	H,0		;DESCRIPTOR IS PAGE 0
	CALL	GETPAG		;GET IT TO CONTROLLER BUFFER
	MVI	B,OSOFF		;GET OFFSET TO OPSYS PTRS
				;(NOTE THAT THE OFFSET MUST BE >0)
OFFLP	EQU	*
	CALL	GETBYT		;SKIP BYTE
	DCR	B		;AT RIGHT PLACE?
	JNZ	OFFLP		;NO = CONTINUE
	CALL	GETBYT		;GET...
	MOV	L,A		;...
	CALL	GETBYT		;...
	MOV	H,A		;...OPSYS PAGE ADDR
	CALL	GETBYT		;GET...
	MOV	E,A		;...
	CALL	GETBYT		;...
	MOV	D,A		;...PAGE COUNT
	PUSH	D		;SAVE IT
	MVI	B,256-OSOFF-4
EATLP	EQU	*
	CALL	GETBYT
	DCR	B
	JNZ	EATLP
;*
;**	START LOADING IMAGE
;**	HL = PAGE ADDR, DE=MEM ADDR, TOP OF STACK=PAGE COUNT
;*
	LXI	D,0		;SET MEM ADDR
PAGELP	EQU	*
	CALL	GETPAG		;READ PAGE INTO BUFFER
	MVI	B,0		;SET BYTE COIUNTER
BYTELP	EQU	*
	CALL	GETBYT		;SAVE...
	STAX	D		;...NEXT BYTE
	INX	D		;MOVE MEM PTR
	DCR	B		;END OF PAGE ?
	JNZ	BYTELP		;NO = CONTINUE
	INX	H		;INCREMENT PAGE NUMBER
	XTHL			;SAVE IT, GET PAGE CNT
	DCX	H		;DEC PAGE CNT
	MOV	A,H		;AT...
	ORA	L		;...END ?
	JZ	LOADND		;YES = DONE
	XTHL			;PUT BACK CNT, GET PAGE PTR
	JMP	PAGELP		;GET NEXT PAGE
LOADND	EQU	*
	POP	H		;CLEAR STACK
	LXI	H,0		;PUT START ADDR...
	PUSH	H		;...ONTO STACK
	DAD	SP		;GET ADDR OF WHERE TO PUT...
	DCX	H		;...TURNOFF PROGRAM
	MVI	M,O311		;PUT IN RETURN
	DCX	H		;PUT IN...
	MVI	M,O375		;...DEV ADDR
	DCX	H		;PUT IN...
	MVI	M,O323		;...OUTPUT
	PCHL			;TURN IT OFF
;*
;**	GETPAG	-- GET PAGE FROM DISK
;*
GETPAG	EQU	*
	PUSH	H		;SAVE...
	PUSH	D		;..
	PUSH	B		;...REGS
	MVI	B,48		;GET SECTORS/CYL
	LXI	D,16		;
DIV1	EQU	*
	DAD	H
	MOV	A,D
	RAL
	CMP	B
	JC	DIV2
	SUB	B
	INR	L
DIV2	EQU	*
	MOV	D,A
	DCR	E
	JNZ	DIV1
;*	HL=QUOTIENT, A=REMAINDER
	MOV	B,A		;SAVE SECTOR
	CALL	DSKWT		;WAIT FOR CONTROLLER
	MOV	A,L		;SEND...
	OUT	DSKCHN+7	;...LOW ORDER PART OF CYL
	MOV	A,H		;GET HIGH ORDER PART OF TRACK
	ORI	DFLTDR+SEEK	;ADD ON DRIVE AND SEEEK COMMAND
	OUT	DSKCHN+3	;START SEEK
	CALL	DSKWT		;WAIT FOR IT
	MVI	A,21		;SELECT...
	OUT	DSKCHN+7	;...
	MVI	A,STAT+DFLTDR	;...
	OUT	DSKCHN+3	;...SEEK STATUS
	CALL	DSKIWT		;WAIT FOR IT
	IN	DSKCHN+5	;GET ERROR CODE
	ANI	16		;MASK OFF ALL BUT ERROR BIT
	ORA	A		;ERROR ?
;*
;**	CHECK FOR SEEK ERROR WOULD GO HERE
;*
	MVI	C,0		;GET HEAD
	MOV	A,B		;OUR SECTOR...
	CPI	24		;...ON HEAD 1
	JC	DOREAD		;NO = READY
	SBI	24		;ADJUST SECTOR
	MVI	C,32		;GET HEAD BITS
;*	A=SECTOR, C=HEAD*32
DOREAD	EQU	*
	ADD	C		;GET...
	MOV	B,A		;...SECTOR COMMAND
	CALL	DSKWT		;WAIT ON CONTROLLER
	MOV	A,B		;SEND...
	OUT	DSKCHN+7	;...COMMAND
	MVI	A,RDSEC+DFLTBF+DFLTDR	;GET SECTOR READ
	OUT	DSKCHN+3	;;SEND COMMAND
	CALL	DSKWT
	XRA 	A		;SEND...
	OUT	DSKCHN+7	;...READ COUNT
	MVI	A,RDBUF		;SEND...
	OUT	DSKCHN+3	;...READ BUFFER COMMAND
	CALL	DSKIWT
	POP	B		;RESTORE...
	POP	D		;...
	POP	H		;...REGS
	RET
;*
;**	GET BYTE FROM CONTROLLER BUFFER
;*
GETBYT	EQU	*
	IN	DSKCHN+5	;GET BYTE
	RET
;*
;**	WAIT FOR CONTROLLER ACK
;*
DSKWT	EQU	*
	IN	DSKCHN		;GET STATUS
	RLC			;READY ?
	JNC	DSKWT		;NO = KEEP WAITING
	IN	DSKCHN+1
	IN	DSKCHN+3
	IN	DSKCHN+5
	RET
;*
;**	WAIT FOR CONTROLLER INPUT
;*
DSKIWT	EQU	*
	IN	DSKCHN+4
	RLC
	JNC	DSKIWT
	RET
;	DS	20		;$$$$
;DUMSTK	EQU	*		;$$$$
	END	HDLDR
	

