	TITLE	'XIOS200, Copyright 1979, ALTOS COMPUTER SYSTEMS'
;-----------------------------------------------------------------------
;
;
;	ALTOS COMPUTER SYSTEMS
;	2338A WALSH AVENUE
;	SANTA CLARA, CALIFORNIA 95050
;
;	(408) 244-5766
;
;
;	Copyright 1979, ALTOS COMPUTER SYSTEMS
;
;	This program is a copyright program product of 
;	ALTOS COMPUTER SYSTEMS and is distributed to the
;	owners of ALTOS SUN SERIES 8000 computers for
;	use on those systems only. Any other use of this
;	software constitutes a breach of the copyright
;	license to the purchaser.
;
;	VERSION NUMBER: 1.00
;	VERSION DATE:   DECEMBER 31, 1979
;	.	Add support for CP/M version 2.0
;	.	Add support for Hard disk drives
;	.	Add support for disk MODE selection
;	.	Provide compatability MODE for 1.4 operation
;	.	Remove CTC/1791 counter reset
;
;-----------------------------------------------------------------------

;-----------------------------------------------------------------------
;
;	Mode	0	IBM single density
;		1	ALTOS double density Version 2.0
;		2	ALTOS double density Version 1.4
;		3	ALTOS hard disk Version 2.0 (8 MEG AT 000)
;		4	ALTOS HARD DISK VERSION 2.0 (8 MEG AT 512)
;		5	ALTOS HARD DISK VERSION 2.0 (8 MEG AT 1024)
;		6	ALTOS HARD DISK VERSION 2.0 (4 MEG AT 512)
;
;-----------------------------------------------------------------------

;-----------------------------------------------------------------------
;
;	ASSEMBLER CONTROL STATEMENTS
;
;-----------------------------------------------------------------------

	MACLIB	DISKDEF
	MACLIB	Z80S

TRUE	EQU	0FFFFH		;VALUE FOR TRUE
FALSE	EQU	NOT TRUE	;VALUE FOR FALSE

;-----------------------------------------------------------------------
;
;	THE FOLLOWING EQUATES ARE USER MODIFIABLE BASED ON THE
;	PARTICULAR USER SYSTEM AND OPTIONS SELECTED.
;
;-----------------------------------------------------------------------

DMA	EQU	TRUE		;DMA HARDWARE SUPPORT ??
HARDSK	EQU	TRUE		;HARD DISK SUPPORT

;-----------------------------------------------------------------------
;
;	THE FOLLOWING CONSTANTS APPLY TO THE DEBLOCKING OF
;	SECTORS LARGER THAN 128 FOR THE ALTOS DOUBLE DENSITY
;	AND THE ALTOS HARD DISK.
;
;-----------------------------------------------------------------------

BLKSIZ	EQU	16384		;CP/M ALLOCATION SIZE
HSTSIZ	EQU	1024		;HOST DISK SECTOR SIZE
HSTSPT	EQU	16		;HOST DISK SECTORS PER TRACK
HSTBLK	EQU	HSTSIZ/128	;CP/M SECTORS PER HOST BUFFER
CPMSPT	EQU	HSTBLK * HSTSPT ;CP/M SECTORS PER TRACK
SECMSK	EQU	HSTBLK - 1	;SECTOR MASK
SECSHF	EQU	3		;LOG2(HHSTBLK)

	PAGE
;-----------------------------------------------------------------------
;
;	THE FOLLOWING EQUATES APPLY TO THE RELOCATABILITY
;	OF THE CBIOS AND SHOULD NOT BE USER ALTERED.
;
;-----------------------------------------------------------------------

RELOC	EQU	TRUE		;RELOCATABLE VERSION ??

;-----------------------------------------------------------------------

	IF	HARDSK
MAXDSK	EQU	12		;MAXIMUM NUMBER OF LOGICAL DRIVES
	ELSE
MAXDSK	EQU	4		;MAXIMUM NUMBER OF LOGICAL DRIVES
	ENDIF

	IF	RELOC
	ORG	0000H
	ELSE
	ORG	0C000H
	ENDIF

BASE	EQU	$

;-----------------------------------------------------------------------

WRALL	EQU	0		;WRITE TO ALLOCATED
WRDIR	EQU	1		;WRITE TO DIRECTORY
WRUAL	EQU	2		;WRITE TO UNALLOCATED


NMBCNS	EQU	4	; NUMBER OF CONSOLES

POLL	EQU	131	; XDOS POLL FUNCTION
FLAGWT	EQU	132	; XDOS FLAG WAIT FUNCTION
FLAGST	EQU	133	; XDOS FLAG SET FUNCTION

PLLPT	EQU	0	; POLL PRINTER
PLCO0	EQU	PLLPT+1	; POLL CONSOLE OUT #0 (CRT:)
PLCO1	EQU	PLCO0+1	; POLL CONSOLE OUT #1 (CRT:)
PLCO2	EQU	PLCO1+1	; POLL CONSOLE OUT #2 (CRT:)
PLCO3	EQU	PLCO2+1	; POLL CONSOLE OUT #3 (CRT:)
PLCI0	EQU	PLCO3+1	; POLL CONSOLE IN #0 (CRT:)
PLCI1	EQU	PLCI0+1	; POLL CONSOLE IN #1 (CRT:)
PLCI2	EQU	PLCI1+1	; POLL CONSOLE IN #2 (CRT:)
PLCI3	EQU	PLCI2+1	; POLL CONSOLE IN #3 (CRT:)

MEMPORT	EQU	009H	; MEMORY SELECT PORT
MEMSK	EQU	002H	; MEMORY SELECT MASK


	PAGE
;-----------------------------------------------------------------------
;
;	JUMP VECTORS FOR ENTRIES TO CBIOS ROUTINES
;
;-----------------------------------------------------------------------

;	EXTERNAL JUMP TABLE (BELOW XIOS BASE)


PDISP	EQU	$-3
XDOS	EQU	PDISP-3

	JMP	COLDSTART	;COLD START
WBOTE:
	JMP	WARMSTART	;WARM START
	JMP	CONST		;CONSOLE STATUS
	JMP	CONIN		;CONSOLE CHARACTER IN
	JMP	CONOUT		;CONSOLE CHARACTER OUT
	JMP	LIST		;LIST CHARACTER OUT
	JMP	RTNEMPTY	;PUNCH NOT IMPLEMENTED
	JMP	RTNEMPTY	;READER NOT IMPLEMENTED
	JMP	HOMEIT		;MOVE HEAD TO HOME
	JMP	SELDSK		;SELECT DISK
	JMP	SETTRK		;SET TRACK NUMBER
	JMP	SETSEC		;SET SECTOR NUMBER
	JMP	SETDMA		;SET DMA ADDRESS
	JMP	READ		;READ DISK
	JMP	WRITE		;WRITE DISK
	JMP	POLLPT		;LIST STATUS
	JMP	SECTRAN		;SECTOR TRANSLATE

;	EXTENDED I/O SYSTEM JUMP VECTOR

	JMP	SELMEMORY	; SELECT MEMORY
	JMP	POLLDEVICE	; POLL DEVICE
	JMP	STARTCLOCK	; START CLOCK
	JMP	STOPCLOCK	; STOP CLOCK
	JMP	EXITREGION	; EXIT REGION
	JMP	MAXCONSOLE	; MAXIMUM CONSOLE NUMBER
	JMP	SYSTEMINIT	; SYSTEM INITIALIZATION
	NOP			; NO JMP HERE
	NOP			; FOR MP/M DELAY
	NOP			;



	JMP	SETMOD		;ROUTINE TO SET DISK MODE
	JMP	RETMOD		;ROUTINE TO RETURN CURRENT MODE

COLDSTART:
WARMSTART:
	MVI	C,0		; SEE SYSTEM INIT
				; COLD & WARM START INCLUDED ONLY
				; FOR COMPATIBILITY WITH CP/M
	JMP	XDOS		; SYSTEM RESET, TERMINATE PROCESS

RTNEMPTY:
	XRA	A		; NOT USED
	RET			;

LAST:
	ORG	(((LAST-BASE)+0A2H) AND 0FF00H) +05EH

INTERUPT:
	DW	FLOPPY$INT		;FLOPPY DISK INTERRUPT
	DW	NULL$INT		;
	DW	NULL$INT		;
	DW	NULL$INT		;
	DW	INT1HND			;CTC INTERRUPT
	DW	NULL$INT		;
	DW	HARD$INT		;HARD DISK INTERRUPT
	DW	NULL$INT		;
	DW	NULL$INT		;

NULL$INT:
	EI
	RETI

	PAGE



;-----------------------------------------------------------------------
;
;	WORK AND CONTROL AREAS FOR CBIOS SERVICES
;
;-----------------------------------------------------------------------

TRK0:	DB	0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH
SEL0:	DB	004H,008H,010H,020H,010H,010H,010H,020H,020H,020H,010H,020H
MODE:	DB	000H,000H,000H,000H,003H,004H,005H,003H,004H,005H,006H,006H
TCNT:	DB	000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
PCNT:	DB	000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H    

DISKNO:	DB	000H				;CURRENT DRIVE NUMBER
TRAKNO:	DB	000H				;CURRENT TRACK NUMBER
HEADNO:	DB	000H				;CURRENT HEAD NUMBER
DMAADR:	DW	000H				;CURRENT DMA ADDRESS
SECTNO:	DB	000H				;CURRENT SECTOR NUMBER
DPEPTR:	DW	000H				;CURRENT DPE ADDRESS
DBLKAD:	DW	000H				;CURRENT EXTENSION ADDRESS
MPARMS:	DW	000H				;MISC. PARAMETERS
HTK1:	DB	10H				;HARD DISK  # 1  TRACK
HTK2:	DB	20H				;HARD DISK  # 2  TRACK
;
;	PARAMETER FLAGS
;
;	0100H = DOUBLE HEADED DRIVES
;	0200H = CENTRONICS PRINTER FOR LIST DEVICE
;	0400H = FOUR DRIVE SYSTEM  [ A B C D ]
;-----------------------------------------------------------------------
;
;-----------------------------------------------------------------------
;
;	NOTE:
;	NO CHANGES ARE TO BE MADE TO THE ABSOLUTE LOCATIONS OF
;	ANY FIELDS PRIOR TO THIS POINT. EXTERNAL PROGRAMS ARE
;	DEPENDENT UPON THE LOCATION OF THE PRECEEDING DATA.
;
;-----------------------------------------------------------------------

NMIRTN:	DB	0EDH,0A2H,0EDH,045H		;FAKE INI AND RETN INST

DMAS1:	DB	0C3H,07DH			;FIRST PART OF DMA SETUP
DMASA:	DW	000H				;ADDRESS FOR I/O
DMALEN:	DW	1025-1				;LENGTH FOR I/O

DMAS2H:	DB	054H,0CEH,068H,0CEH,0A5H,020H	;HARD DISK SETUP

DMAS2F:	DB	014H,028H,085H,007H		;FLOPPY DISK SETUP

DMAS3:	DB	08AH,0CFH,001H,0CFH		;LAST PART OF DMA SETUP
DMAS3F:	DB	001H				;001=READ, 005=WRITE
	DB	0CFH,087H			;SETUP DMA, ENABLE

	PAGE
;-----------------------------------------------------------------------
;
;	CONTROL BLOCKS FOR DISK DRIVER
;
;-----------------------------------------------------------------------

DPBASE	EQU	$		;START OF DISK PARAMETER BLOCKS

DPE0:	DW	XLT0,0000H	;TRANSLATE TABLE AND WORK AREA
	DW	0000H,0000H	;SCRATCH AREA
	DW	DIRBUF,DPB0	;DIR BUFF, PARM BLOCK
	DW	CSV0,ALV0	;CHECK VECTOR, ALLOC VECTOR

DPE1:	DW	XLT0,0000H	;TRANSLATE TABLE AND WORK AREA
	DW	0000H,0000H	;SCRATCH AREA
	DW	DIRBUF,DPB0	;DIR BUFF, PARM BLOCK
	DW	CSV1,ALV1	;CHECK VECTOR, ALLOC VECTOR

DPE2:	DW	XLT0,0000H	;TRANSLATE TABLE AND WORK AREA
	DW	0000H,0000H	;SCRATCH AREA
	DW	DIRBUF,DPB0	;DIR BUFF, PARM BLOCK
	DW	CSV2,ALV2	;CHECK VECTOR, ALLOC VECTOR

DPE3:	DW	XLT0,0000H	;TRANSLATE TABLE AND WORK AREA
	DW	0000H,0000H	;SCRATCH AREA
	DW	DIRBUF,DPB0	;DIR BUFF, PARM BLOCK
	DW	CSV3,ALV3	;CHECK VECTOR, ALLOC VECTOR

	IF	HARDSK

DPE4:	DW	0000H,0000H	;TRANSLATE TABLE AND WORK AREA
	DW	0000H,0000H	;SCRATCH AREA
	DW	DIRBUF,DPB3	;DIR BUFF, PARM BLOCK
	DW	CSV4,ALV4	;CHECK VECTOR, ALLOC VECTOR

DPE5:	DW	0000H,0000H	;TRANSLATE TABLE AND WORK AREA
	DW	0000H,0000H	;SCRATCH AREA
	DW	DIRBUF,DPB4	;DIR BUFF, PARM BLOCK
	DW	CSV5,ALV5	;CHECK VECTOR, ALLOC VECTOR

DPE6:	DW	0000H,0000H	;TRANSLATE TABLE AND WORK AREA
	DW	0000H,0000H	;SCRATCH AREA
	DW	DIRBUF,DPB5	;DIR BUFF, PARM BLOCK
	DW	CSV6,ALV6	;CHECK VECTOR, ALLOC VECTOR

DPE7:	DW	0000H,0000H	;TRANSLATE TABLE AND WORK AREA
	DW	0000H,0000H	;SCRATCH AREA
	DW	DIRBUF,DPB3	;DIR BUFF, PARM BLOCK
	DW	CSV7,ALV7	;CHECK VECTOR, ALLOC VECTOR

DPE8:	DW	0000H,0000H	;TRANSLATE TABLE AND WORK AREA
	DW	0000H,0000H	;SCRATCH AREA
	DW	DIRBUF,DPB4	;DIR BUFF, PARM BLOCK
	DW	CSV8,ALV8	;CHECK VECTOR, ALLOC VECTOR

DPE9:	DW	0000H,0000H	;TRANSLATE TABLE AND WORK AREA
	DW	0000H,0000H	;SCRATCH AREA
	DW	DIRBUF,DPB5	;DIR BUFF, PARM BLOCK
	DW	CSV9,ALV9	;CHECK VECTOR, ALLOC VECTOR

DPEA:	DW	0000H,0000H	;TRANSLATE TABLE AND WORK AREA
	DW	0000H,0000H	;SCRATCH AREA
	DW	DIRBUF,DPB6	;DIR BUFF, PARM BLOCK
	DW	CSVA,ALVA	;CHECK VECTOR, ALLOC VECTOR

DPEB:	DW	0000H,0000H	;TRANSLATE TABLE AND WORK AREA
	DW	0000H,0000H	;SCRATCH AREA
	DW	DIRBUF,DPB6	;DIR BUFF, PARM BLOCK
	DW	CSVB,ALVB	;CHECK VECTOR, ALLOC VECTOR

	ENDIF

;-----------------------------------------------------------------------

MODL0:	DW	XLT0,000H	;MODEL DPE FOR MODE 0
	DW	000H,000H	;
	DW	DIRBUF,DPB0	;

MODL1:	DW	XLT1,0000H	;MODEL DPE FOR MODE 1
	DW	0000H,0000H	;
	DW	DIRBUF,DPB1	;

MODL2:	DW	XLT2,0000H	;MODEL DPE FOR MODE 2
	DW	0000H,0000H	;
	DW	DIRBUF,DPB2	;

;-----------------------------------------------------------------------

XLT0:	DB	1,7,13,19,25,5,11,17,23,3,9,15,21
	DB	2,8,14,20,26,6,12,18,24,4,10,16,22

XLT1:	DB	01,02,03,04,05,06,07,08,09,10,11,12,13
	DB	14,15,16,17,18,19,20,21,22,23,24,25,26
	DB	27,28,29,30,31,32,33,34,35,36,37,38,39
	DB	40,41,42,43,44,45,46,47,48,49,50,51,52

XLT2:	DB	01,02,03,04,05,06,07,08,09,10,11,12
	DB	13,14,15,16,17,18,19,20,21,22,23,24
	DB	25,26,27,28,29,30,31,32,33,34,35,36
	DB	37,38,39,40,41,42,43,44,45,46,47,48

	PAGE
;-----------------------------------------------------------------------
;
;	THESE ARE THE DISK TYPE DEFINITION BLOCKS
;	EACH OF WHICH CORRESPONDS TO A PARTICULAR MODE.
;
;-----------------------------------------------------------------------

DPB0:	EQU	$		;VERSION 2.0, IBM SINGLE DENSITY
	DW	26		;SECTORS PER TRACK
	DB	3		;BLOCK SHIFT
	DB	7		;BLOCK SHIFT MASK
	DB	0		;EXTENT MASK
	DW	242		;DISK SIZE MINUS 1
	DW	63		;DIRECTORY MAX
	DB	192		;ALLOC0
	DB	0		;ALLOC1
	DW	16		;CHECK AREA SIZE
	DW	2		;OFFSET TO START TRACK
	
DPB1:	EQU	$		;VERSION 2.0, IBM DOUBLE DENSITY
	DW	52		;SECTORS PER TRACK
	DB	4		;BLOCK SHIFT
	DB	15		;BLOCK SHIFT MASK
	DB	1		;EXTENT MASK
	DW	242		;DISK SIZE MINUS 1
	DW	127		;DIRECTORY MAX
	DB	192		;ALLOC0
	DB	0		;ALLOC1
	DW	32		;CHECK AREA SIZE
	DW	2		;OFFSET TO START TRACK
	
DPB2:	EQU	$		;VERSION 1.4 ALTOS DOUBLE DENSITY
	DW	48		;SECTORS PER TRACK
	DB	4		;BLOCK SHIFT
	DB	15		;BLOCK SHIFT MASK
	DB	0		;EXTENT MASK (1.4 COMPATABILITY)
	DW	224		;DISK SIZE MINUS 1
	DW	95		;DIRECTORY MAX
	DB	192		;ALLOC0
	DB	0		;ALLOC1
	DW	24		;CHECK AREA SIZE
	DW	2		;OFFSET TO START TRACK
	
	IF	HARDSK

DPB3:	DISKDEF	3,0,127,,16384,512,256,0,1

DPB4:	DISKDEF	4,0,127,,16384,512,256,0,513

DPB5:	DISKDEF	5,0,127,,16384,512,256,0,1025

DPB6:	DISKDEF	6,0,127,,16384,288,256,0,513

	ENDIF

	PAGE

;-----------------------------------------------------------------------
;
;	DISK ACCESS ROUTINES
;
;-----------------------------------------------------------------------

SELDSK:
	MOV	A,C		;LIMIT SELECT TO REAL OPTIONS
	CPI	MAXDSK		;
	JRNC	SELERR
	MVI	B,0
	LXI	H,SEL0
	DAD	B
	MOV	A,M
	ORA	A
	JRZ	SELERR
	MOV	A,C
	CPI	4
	JRNC	CHKHRD
	MOV	A,M
	OUT	08H
	PUSH	B
	MVI	C,1
	CALL	DELAY
	POP	B
	IN	04H
	RAL
	JRC	SELERR
	JR	SELSDT
CHKHRD:
	MOV	A,M
	OUT	20H
	PUSH	B
	MVI	C,1
	CALL	DELAY
	POP	B
	IN	24H
	RAL
	JRNZ	SELERR
SELSDT:
	LXI	H,0
	mov	a,c
	STA	NEWDSK		;SAVE FOR I/O LATER
	MOV	L,C		;COMPUTE DP HEADER ADDRESS
	DAD	H		;* 2
	DAD	H		;* 4
	DAD	H		;* 8
	DAD	H		;* 16 (DP HEADER SIZE)
	LXI	D,DPBASE	;START OF DP HEADERS
	DAD	D		;POINT TO CORRECT ONE
	SHLD	DPEPTR		;SAVE ADDRESS OF CURRENT DP BLOCK
	RET			;

SELERR:
	LXI	H,0
	RET

SETDMA:
	MOV	H,B		;TO ALLOW SAVING
	MOV     L,C		;
        SHLD    DMAADR		;
        RET			;RETURN TO CALLER

SETTRK:
	MOV	H,B		;TO ALLOW SAVE
	MOV	L,C		;
	SHLD	NEWTRK	  	;SAVE NEXT TRACK NUMBER
        RET			;RETURN TO CALLER

SETSEC:
	MOV	A,C		;FOR SAVE
	STA	NEWSEC		;
        RET			;RETURN TO CALLER

SETDEN:
	LXI	D,SEL0		;START OF SELECT/DENSITY MASKS
	LHLD	NEWDSK		;NEXT DRIVE ADDRESS
	MVI	H,000H		;ENSURE ZERO FOR SINGLE BYTE QUANTITY
	DAD	D		;POINT TO CORRECT MASK
	MOV	A,C		;ISOLATE DENSITY BIT
	ANI	00000001B	;
	MOV	C,A		;SAVE FOR NOW
	MOV	A,M		;LOAD SELECT DENSITY MASK
	ANI	11111110B	;RESET CURRENT DENSITY SETTING
	ORA	C		;SET NEW VALUE
	MOV	M,A		;RESTORE MASK IN TABLE
	RET			;RETURN TO CALLER

READ:
	CALL	RETMOD		;WHAT TYPE OF I/O ??
	CPI	003H		;
	JC	READSOFT	;FLOPPY DISK DRIVE....
	JMP	READHARD	;HARD DISK I/O

WRITE:
	CALL	RETMOD		;WHAT TYPE OF I/O ??
	CPI	003H		;
	JC	WRITESOFT	;FLOPPY DISK
	JMP	WRITEHARD	;HARD DISK I/O

	PAGE
;-----------------------------------------------------------------------
;
;	ROUTINES TO SET AND RETURN THE CURRENT DRIVE MODE
;
;-----------------------------------------------------------------------

SETMOD:
	LHLD	NEWDSK		;NEXT DRIVE FOR I/O
	MVI	H,000H		;
	MOV	A,L		;CHECK MODE SET VALIDITY
	CPI	004H		;ONLY VALID FOR FLOPPY DISK DRIVES
	RNC			;INVALID DRIVE FOR MODE SET, RETURN
	LXI	D,MODE		;START OF MODE BYTES
	DAD	D		;
	MOV	M,C		;SAVE NEW MODE BYTE
	PUSH	H		;SAVE MODE BYTE ADDRESS
	MOV	A,C		;SETUP FOR DENSITY CHANGE
	ORA	A		;
	MVI	C,000H		;ASSUME SINGLE DENSITY MODE....
	JRZ	SETSEL		;VERIFY ASSUMPTION
	MVI	C,001H		;SET FOR DOUBLE DENSITY MODE....
SETSEL:	CALL	SETDEN		;SET DENSITY BASED ON LOW BIT
	POP	H		;RESTORE
	MOV	L,M		;PICKUP MODE AGAIN
	MVI	H,000H		;FOR SINGLE BYTE PRECISION
	MOV	A,L		;SAVE MODE IN ACCUMULATOR FOR LATER
	DAD	H		;* 2
	DAD	H		;* 4
	PUSH	H		;SAVE * 4
	DAD	H		;* 8
	POP	D		;REGAIN * 4
	DAD	D		;* 12
	LXI	D,MODL0		;FIRST MODEL DPE
	DAD	D		;POINT TO THIS ONE
	XCHG			;SETUP TEMPORARILY AS DESTINATION
	LHLD	DPEPTR		;ADDRESS OF CURRENTLY SELECTED DPE
	XCHG			;SETUP TO ALTER
	LXI	B,12		;LENGTH FOR MOVE
	LDIR			;DO MOVE
	RET			;RETURN TO CALLER

RETMOD:
	LXI	D,MODE		;START OF MODE BYTES
	LHLD	NEWDSK		;NEXT DRIVE FOR I/O
	MVI	H,000H		;RESET FOR SINGLE BYTE QUANTITY
	DAD	D		;POINT TO IT....
	MOV	A,M		;LOAD IT FOR CALLER
	RET			;RETURN, WITH CURRENT MODE SETTING

	PAGE
;-----------------------------------------------------------------------
;
;	THIS IS THE HOME DEVICE ROUTINE
;
;-----------------------------------------------------------------------

HOMEIT:	LDA	NEWDSK		; CHECK FOR FIRST HOME
	CPI	4		;  CHECK FOR FLOPPY
	JC	HOME		;  DO NOT BYPASS FLOPPY HOME
	MOV	C,A		;
	MVI	B,0		; POINT TO PRESENT TRACK STORED
	LXI	H,TRK0		;
	DAD	B		;
	MOV	A,M		; CHECK IF INITIALIZED
	CPI	0FFH		;
	MVI	A,0		;
	RNZ			; YES  -  RETURN WITH NO ERROR
	MOV	M,A		;
HOME:
	LDA	NEWDSK		;GET VALUE OF DRIVE FOR HOME
	CPI	004H		;IS IT A HARD DISK ??
	JNC	HOMEHARD	;YES, PROCESS....

HOMESOFT:
	CALL	DSKSEL		;SELECT CORRECT DRIVE (IN ACCUMULATOR)
	CALL	POINT		;POINT TO TRACK REGISTER SAVE AREA
	MVI	M,000H		;RESET TO TRACK ZERO
	CALL	DBL$UPDATE	;
	MVI	A,00AH		;HOME COMMAND....
	OUT	004H		;DO IT....
HOME1:	CALL	WAIT0		;WAIT UNTIL I/O COMPLETE
	LDA	STATUS		;PICKUP STATUS BYTE
	ANI	10011000B	;CHECK STATUS
	RZ			;RETURN WITH GOOD ESULT
	MVI	A,001H		;SET ERROR ON HOME
	RET			;AND RETURN....

HOMEHARD:
	IF	HARDSK
	CALL	DSKSEL		;SELECT CORRECT DRIVE (IN ACCUMULATOR)
	CALL	POINT		;POINT TO SAVE AREA
	MVI	M,000H		;SET TO TRACK ZERO
	XCHG			;POINT TO SELECT WORD
	MOV	A,M		;LOAD SELECT MASK
	ANI	11110000B	;RESET HEAD MASK
	MOV	M,A		;SAVE
	OUT	020H		;WRITE HEAD/SELECT MASK
	MVI	A,020H		;HOME COMMAND
	OUT	023H		;DO IT....
HOME2:	CALL	WAIT0		;WAIT UNTIL I/O COMPLETE
	MVI	C,20		;DELAY FOR 20 MILLISECONDS
	CALL	DELAY		;
	XRA	A		;SET NEW TRACK REGISTER TO ZERO
	OUT	022H		;FOR CONTROLLER
;	LXI	H,MHM		;***DEBUG***
;	CALL	MSPRT		;***DEBUG***
	LDA	STATUS		;PICKUP STATUS BYTE
	ANI	01011101B	;CHECK STATUS
	RZ			;
	MVI	A,001H		;SET ERROR ON HOME
	ENDIF
	RET			;AND RETURN

	PAGE
;-----------------------------------------------------------------------
;
;	THESE ARE THE HARD DISK UNBLOCK/REBLOCK AND READ AND WRITE
;	ROUTINES CALLED BY THE BDOS SOFTWARE.
;
;-----------------------------------------------------------------------

READHARD:
	IF	HARDSK
	XRA	A		;RESET UNALLOCATED COUNT
	STA	UNACNT		;
	MVI	A,001H		;READ THE SELECTED CP/M SECTOR
	STA	READOP		;
	STA	RSFLAG		;MUST READ DATA
	MVI	A,WRUAL		;
	STA	WRTYPE		;TREAT AS UNALLOCATED
	JMP	RWOPER		;TO PERFORM THE READ
	ENDIF

WRITEHARD:
	IF	HARDSK
	XRA	A		;WRITE THE SELECTED CP/M SECTOR
	STA	READOP		;NOT A READ OPERATION
	MOV	A,C		;WRITE TYPE IS PASSED IN REG C
	STA	WRTYPE		;
	CPI	WRUAL		;IS IT WRITE UNALLOCATED ??
	JRNZ	CHKUNA		;CHECK FOR UNALLOCATED

;
;	WRITE TO UNALLOCATED, SET PARAMETERS
;

	MVI	A,BLKSIZ/128	;NEXT UNALLOC RECS
	STA	UNACNT		;
	LDA	NEWDSK		;DISK FOR I/O
	STA	UNADSK		;UNADSK = NEWDSK
	LHLD	NEWTRK		;
	SHLD	UNATRK		;UNATRK = NEWTRK
	LDA	NEWSEC		;
	STA	UNASEC		;UNASEC = NEWSEC

;
;	CHECK FOR WRITE TO UNALLOCATED SECTOR
;

CHKUNA:
	LDA	UNACNT		;ANY UNALLOCATED REMAIN ??
	ORA	A		;
	JZ	ALLOC		;SKIP IS NOT

;
;	MORE UNALLOCATED RECORDS REMAIN
;

	DCR	A		;UNACNT = UNACNT - 1
	STA	UNACNT		;
	LDA	NEWDSK		;SAME DISK ??
	LXI	H,UNADSK	;
	CMP	M		;NEWDSK = UNADSK ??
	JNZ	ALLOC		;SKIP IF NOT

;
;	DISKS ARE THE SAME
;

	LXI	H,UNATRK	;
	CALL	NEWTRKCMP	;NEWTRK = UNATRK ??
	JNZ	ALLOC		;SKIP IF NOT

;
;	TRACKS ARE THE SAME
;

	LDA	NEWSEC		;SAME SECTOR ??
	LXI	H,UNASEC	;
	CMP	M		;NEWSEC = UNASEC ??
	JRNZ	ALLOC		;SKIP IF NOT

;
;	MATCH, MOVE TO NEXT SECTOR FOR FUTURE REFERENCE
;

	INR	M		;UNASEC = UNASEC + 1
	MOV	A,M		;END OF TRACK ??
	CPI	CPMSPT		;COUNT CP/M SECTORS
	JRC	NOOVF		;SKIP IF NO OVERFLOW

;
;	OVERFLOW TO NEXT TRACK
;

	MVI	M,000H		;UNASEC = 0
	LHLD	UNATRK		;
	INX	H		;
	SHLD	UNATRK		;UNATRK = UNATRK + 1
 
;
;	MATCH FOUND, MARK AS UNNECESSARY READ
;

NOOVF:
	XRA	A		;ZERO TO ACCUMULATOR
	STA	RSFLAG		;RSFLAG = 0
	JR	RWOPER		;TO PERFORM THE WRITE

;
;	NOT AN UNALLOCATED RECORD, REQUIRES PRE-READ
;

ALLOC:
	XRA	A		;ZERO TO ACCUMULATOR
	STA	UNACNT		;UNACNT = 0
	INR	A		;ONE TO ACCUMULATOR
	STA	RSFLAG		;RSFLAG = 1

;-----------------------------------------------------------------------
;
;	THE FOLLOWING CODE IS COMMON TO BOTH READ AND WRITE
;
;-----------------------------------------------------------------------

RWOPER:
	XRA	A		;ZERO TO ACCUMULATOR
	STA	ERFLAG		;NO ERRORS YET....
	LDA	NEWSEC		;COMPUTE HOST SECTOR
	REPT	SECSHF		;COMPUTE HOST SECTOR
	ORA	A		;CARRY = 0
	RAR			;SHIFT RIGHT
	ENDM
	STA	NEWHST		;HOST SECTOR TO SEEK

;
;	ACTIVE HOST SECTOR ??
;

	LXI	H,HSTACT	;HOST ACTIVE FLAG
	MOV	A,M		;
	MVI	M,001H		;ALWAYS BECOMES 1
	ORA	A		;WAS IT ALREADY ??
	JZ	FILLHST		;FILL HOST IF NOT

;
;	HOST BUFFER ACTIVE, SAME AS SEEK BUFFER
;

	LDA	NEWDSK		;
	LXI	H,HSTDSK	;SAME DISK ??
	CMP	M		;NEWDSK = HSTDSK ??
	JNZ	NOMATCH		;

;
;	SAME DISK, SAME TRACK ??
;

	LXI	H,HSTTRK	;
	CALL	NEWTRKCMP	;NEWTRK = HSTTRK ??
	JRNZ	NOMATCH		;

;
;	SAME DISK, SAME TRACK, SAME BUFFER ??
;

	LDA	NEWHST		;
	LXI	H,HSTSEC	;NEWHST = HSTSEC ??
	CMP	M		;
	JZ	MATCH		;SKIP IF MATCH

;
;	PROPER DISK, BUT NOT CORRECT SECTOR
;

NOMATCH:
	LDA	HSTWRT		;HOST WRITTEN ??
	ORA	A		;
	CNZ	WRITEHST	;CLEAR HOST BUFFER

;
;	MAY HAVE TO FILL HOST BUFFER
;

FILLHST:
	LDA	NEWDSK		;
	STA	HSTDSK		;
	LHLD	NEWTRK		;
	SHLD	HSTTRK		;
	LDA	NEWHST		;
	STA	HSTSEC		;
	LDA	RSFLAG		;NEED TO READ ??
	ORA	A		;
	CNZ	READHST		;YES, IF 1
	XRA	A		;ZERO TO ACCUMULATOR
	STA	HSTWRT		;NO PENDING WRITE

MATCH:
	LDA	NEWSEC		;MASK BUFFER NUMBER
	ANI	SECMSK		;LEAST SIGNIF BITS
	MOV	L,A		;READY TO SHIFT
	MVI	H,000H		;DOUBLE COUNT
	REPT	7
	DAD	H		;
	ENDM

;
;	HL NOW HAS RELATIVE HOST BUFFER ADDRESS
;

	LXI	D,HSTBUF	;
	DAD	D		;HL = HOST ADDRESS
	XCHG			;NOW IN DE
	LHLD	DMAADR		;GET/PUT CP/M DATA
	XCHG			;SET FOR Z80 LDIR INSTRUCTION
	LXI	B,128		;LENGTH OF MOVE
	LDA	READOP		;WHICH WAY ??
	ORA	A		;
	JRNZ	RWMOVE		;SKIP IF READ
;
;	WRITE OPERATION, MARK AND SWITCH DIRECTION
;

	MVI	A,001H		;
	STA	HSTWRT		;HSTWRT = 1
	XCHG			;SWAP DIRECTION

;
;	MOVE SUBROUTINE
;

RWMOVE:
	LDIR			;MOVE DATA TO/FROM BUFFER
;
;	DATA HAS BEEN MOVED TO/FROM HOST BUFFER
;

	LDA	WRTYPE		;WRITE TYPE ??
	CPI	WRDIR		;TO DIRECTORY ??
	JRNZ	RWEND		;NO, JUST END UP HERE

;
;	CLEAR HOST BUFFER FOR DIRECTORY WRITE
;

	LDA	ERFLAG		;CHECK PRIOR TO DIR ACTIVITY
	ORA	A		;ERRORS ??
	JRNZ	RWEND		;SKIP IF SO....
	XRA	A		;ZERO TO ACCUMULATOR
	STA	HSTWRT		;BUFFER WRITTEN
	CALL	WRITEHST	;

RWEND:
	LDA	ERFLAG		;
	ORA	A		;IF ERRORS, RESET SO NO MATCH NEXT TIME THRU
	RZ			;NONE, JUST RETURN
	LXI	H,HSTDSK	;
	MVI	M,0FFH		;CANT POSSIBLY MATCH, MUST REDO I/O
	ENDIF
	RET			;

MVDTB:	LHLD	DMAADR		; MOVE DATA TO FLOPPY BUFFER
	LXI	D,FPYBUF	;
	LXI	B,128		; 128 BYTES
	LDIR			;
	RET			;

MVDFB:	PUSH	PSW		; MOVE DATA FROM FLOPPY BUFFER
	LDA	CMD		;
	ANI	20H		; CHECK FOR READ
	JNZ	MVDFX		;  NO - BYPAS MOVE
	LHLD	DMAADR		;
	XCHG			; DE = DESTINATION
	LXI	H,FPYBUF	;
	LXI	B,128		; 128 BYTES
	LDIR			;
MVDFX:	POP	PSW		;
	RET			;


	PAGE

;-----------------------------------------------------------------------
;
;	UTILITY SUBROUTINE FOR 16 BIT COMPARE
;
;-----------------------------------------------------------------------

	IF	HARDSK
NEWTRKCMP:
	XCHG			;HL = .UNATRK OR .HSTTRK
	LXI	H,NEWTRK	;
	LDAX	D		;LOW BYTE COMPARE
	CMP	M		;SAME ??
	RNZ			;RETURN IF NOT
	INX	D		;TO CHECK HIGH BYTE
	INX	H		;
	LDAX	D		;
	CMP	M		;SETS FLAGS
	RET			;

	PAGE
;-----------------------------------------------------------------------
;
;	WRITEHST PERFORMS THE PHYSICAL WRITE TO THE HOST DISK.
;	READHST PERFORMS THE PHYSICAL READ FROM THE HOST DISK.
;
;	HSTDSK = HOST DISK NUMBER
;	HSTTRK = HOST TRACK NUMBER
;	HSTSEC = HOST SECTOR NUMBER
;	RETURN ERROR FLAG IN ERFLAG
;
;-----------------------------------------------------------------------

WRITEHST:
	MVI	A,005H		;SETUP DMA FOR WRITE
	STA	DMAS3F		;
	MVI	A,002H		;WRITE COMMAND
	STA	CMD		;SAVE FOR LATER
	LXI	H,HSTBUF-1	;WRITE MUST WRITE CONTROL BYTE
	SHLD	DMASA		;
	JMP	HRW0		;

READHST:
	MVI	A,001H		;SETUP DMA FOR READ
	STA	DMAS3F		;
	MVI	A,004H		;READ COMMAND
	STA	CMD		;SAVE FOR LATER
	LXI	H,HSTBUF	;READ ONLY DATA BYTES
	SHLD	DMASA		;

HRW0:
	LXI	H,T$RETRIES	;SETUP TEMPORARY RETRIES COUNT
	MVI	M,003H		;

HRW1:
	LDA	HSTSEC		;HOST SECTOR NUMBER
	STA	SECTNO		;SAVE SECTOR NUMBER
	LDA	HSTDSK		;PICKUP DRIVE ID FOR SELECT
	CALL	DSKSEL		;SELECT CORRECT DRIVE FOR I/O
	CALL	POINT		;POINT TO TRACK REGISTER SAVE AREA
	XCHG			;POINT TO SELECT MASK
	MVI	A,11110000B	;TO REMOVE CURRENT HEAD SELECTION
	ANA	M		;
	MOV	M,A		;
	PUSH	H		;SAVE MASK ADDRESS
	CALL	SETHED		;COMPUTE CORRECT HEAD NUMBER
	MOV	A,L		;TRACK NUMBER AFTER HEAD CALCULATION
	STA	TRAKNO		;
	POP	H		;RESTORE MASK ADDRESS
	LDA	HEADNO		;TO OR IN NEW HEAD NUMBER
	ORA	M		;
	MOV	M,A		;SAVE NEW DRIVE/HEAD SELECTION
	ANI	07FH		; MASK OFF LARGE DRIVE FLAG
	OUT	020H		;WRITE IT TO SELECT NEW HEAD....
	MVI	C,1		;DELAY FOR 1 MILLISECOND
	CALL	DELAY		;

HRW2:
	CALL	POINT		;IS A SEEK NECESSARY ??
	LDA	TRAKNO		;CHECK
	CMP	M		;WELL ??
	JZ	HRW5		;NO SEEK NECESSARY...

HRW3:
	OUT	022H		;WRITE NEW TRACK NUMBER
	MOV	B,M		;SAVE TEMPORARILY
	MOV	M,A		;UPDATE TRACK REGISTER SAVE AREA
	MOV	A,B		;OLD TRACK NUMBER
	OUT	021H		;TO OLD TRACK REGISTER
	MVI	A,010H		;SEEK COMMAND
	OUT	023H		;DO IT....
HRW4:	CALL	WAIT0		;WAIT FOR I/O
	MVI	C,20		;DELAY AFTER SEEK FOR 20 MILLISECONDS
	CALL	DELAY		;

HRW5:
	LDA	SECTNO		;SET SECTOR
	OUT	021H		;


HRW6:
	LXI	H,DMAS1		;SETUP DMA FOR HARD DISK I/O
	LXI	B,0600H		;
	OUTIR			;
	LXI	H,DMAS2H	;
	LXI	B,0600H		;
	OUTIR			;
	LXI	H,DMAS3		;
	LXI	B,0700H		;
	OUTIR			;

	LDA	CMD		;PICKUP I/O COMMAND
	OUT	023H		;WRITE IT OUT
HRW7:	CALL	WAIT0		;WAIT FOR COMPLETION

	MVI	A,01011101B	;SETUP STATUS AND MASK
	STA	MASK		;SAVE FOR STATUS CHECK
	CALL	CHECK$STAT	;CHECK STATUS FROM I/O
	RZ			;OK ??
	JMP	HRW1		;RETRY I/O
	ENDIF

	PAGE
;-----------------------------------------------------------------------
;
;	DOUBLE SIDED TRACK REGISTER UPDATE ROUTINE
;
;-----------------------------------------------------------------------


DBL$UPDATE:
	LDA	MPARMS		;CHECK FOR DOUBLE SIDED DRIVES
	ANI	1		;  IS FLAG SET
	RZ			;   NO  - SO RETURN
	LDA	DISKNO		;CURRENT DISK DRIVE
	CPI	004H		;IS IT A FLOPPY
	RNC			;NO, RETURN WITHOUT UPDATE
	ANI	00000010B	;IS THIS DRIVE 2 0R 3 ??
	MOV	A,M		;WE WERE CALLED WITH (HL) POINTING TO TRACK
	JRZ	DBL$LOW		;IT MUST BE DRIVE ZERO OR ONE
	DCX	H		;BACKUP TO OTHER SIDE POINTER
	DCX	H		;
	JR	DBL$SAVE	;

DBL$LOW:
	INX	H		;BUMP UP TO DRIVE TWO OR THREE
	INX	H		;

DBL$SAVE:
	MOV	M,A		;UPDATE OTHER SIDE REGISTER
	RET			;


	PAGE
;-----------------------------------------------------------------------
;
;	ROUTINE TO COMPUTE HEAD NUMBER FROM TRACK NUMBER
;	TRACK NUMBER IS IN HL ON ENTRY
;
;-----------------------------------------------------------------------
	IF	HARDSK
SETHED:
	LHLD	HSTTRK		;CP/M TRACK NUMBER (0-800)
	ANI	80H		; CHECK FOR LARGE DRIVE
	MOV	A,L		;LOW ORDER
	JRZ	SETH14		;  SMALL DRIVE
	ANI	00000111B	;GET TRACK MOD 8 (HEAD NUMBER)
	MVI	C,3		;LIMIT LOOP FOR DIVIDE BY EIGHT
	JR	SETDVD		;
SETH14:	ANI	00000011B	;GET TRACK MOD 4 (HEAD NUMBER)
	MVI	C,2		;LIMIT LOOP FOR DIVIDE BY FOUR
SETDVD:	STA	HEADNO		;SAVE AS HEAD NUMBER
SHD1:	ORA	A		;ENSURE CARRY IS ZERO
	MOV	A,H		;FOR SHIFT
	RAR			;ONE BIT
	MOV	H,A		;
	MOV	A,L		;LOW ORDER
	RAR			;CARRY PARTICIPATES FROM HIGH ORDER
	MOV	L,A		;
	DCR	C		;END OF DIVIDE YET ??
	JRNZ	SHD1		;NO, CONTINUE
	RET			;RETURN TO CALLER, TRACK IN HL
	ENDIF

	PAGE
;-----------------------------------------------------------------------
;
;	DISK DRIVE SELECT ROUTINE
;		ON ENTRY, THE ACCUMULATOR CONTAINS THE DRIVE FOR SELECTION
;		RETURNS CARRY SET FOR HARD DISK SELECTED
;		RETURNS CARRY RESET FOR FLOPPY DISK SELECTED
;
;-----------------------------------------------------------------------

DSKSEL:
	CPI	004H		;IS IT HARD DISK ??
	JNC	SELHARD		;YES, GO PROCESS....

SELSOFT:
	LXI	H,DISKNO	;CURRENT DRIVE NUMBER
	CMP	M		;SAME DRIVE AS LAST TIME ??
	JRZ	SLS3		;YES, DONT BOTHER WITH UNLOAD
	MOV	M,A		;UPDATE WITH CURRENT DRIVE NUMBER

;-----------------------------------------------------------------------
;
;	WE WILL NOW FORCE THE HEAD TO UNLOAD PRIOR TO THE SWITCH
;	TO ENSURE THAT WHEN WE RETURN TO THIS DISK WE WILL
;	LOAD AND WAIT FOR THE HEAD TO SETTLE.
;
;-----------------------------------------------------------------------

SLS1:
	IN	004H		;ENSURE FLOPPY PORT NOT BUSY
	RAR			;
	JRC	SLS1		;
	IN	005H		;READ THE TRACK REGISTER
	OUT	007H		;ENSURE WE DONT MOVE THE HEAD

	MVI	A,012H		;SEEK AND UNLOAD HEAD
	OUT	004H		;DO IT....
SLS2:	CALL	WAIT0		;WAIT HERE FOR INTERRUPT

;-----------------------------------------------------------------------
;
;	WE WILL NOW LOAD THE SELECT MASK AND SELECT THE DRIVE
;	EVEN IF ITS THE SAME DRIVE BECAUSE THE DENSITY MAY
;	HAVE CHANGED.
;
;-----------------------------------------------------------------------

SLS3:
	CALL	POINT		;POINT TO TRACK SAVE AREA
	XCHG			;POINT TO SELECT MASK
	LDA	TRAKNO		;NEXT TRACK FOR I/O
	CPI	002H		;IS IT TRACK ZERO OR ONE
	MVI	A,11111111B	;ASSUME NO....
	JRNC	SLS4		;VERIFY ASSUMPTION
	MVI	A,11111110B	;FORCE SINGLE DENSITY FOR 0, & 1

SLS4:
	ANA	M		;LOAD MASK AND CORRECT IF NECESSARY
	OUT	008H		;SELECT IT
	XCHG			;RESTORE TRACK REGISTER ADDRESS
	MOV	A,M	   	;PICK UP TRACK NUMBER
	OUT	005H		;GIVE IT TO CONTROLLER
	ORA	A		;ENSURE CARRY IS RESET
	RET

;-----------------------------------------------------------------------
;
;	THIS ROUTINE SETS UP THE HARD DISK BY SELECTING THE CORRECT
;	DRIVE AND RELOADING THE HEAD AND TRACK REGISTERS IN THE
;	HARD DISK CONTROLLER READY FOR I/O LATER.
;
;-----------------------------------------------------------------------

SELHARD:
	IF	HARDSK
	LXI	H,DISKNO	;CURRENT DRIVE SELECTED
	CMP	M		;SAME ??
	RZ			;YES, NO NEW SELECT NECESSARY
	MOV	M,A		;UPDATE DISKNO

SLH1:
	CALL	POINT		;TRACK SAVE REGISTER
	XCHG			;POINT TO SELECT MASK
	MOV	A,M		;LOAD DRIVE/HEAD VALUE
	OUT	020H		;WRITE IT TO SELECT PORT
	XCHG			;REGAIN ADDRESS OF TRACK REGISTER
	MOV	A,M		;LOAD OLD TRACK NUMBER
	OUT	022H		;WRITE IT TO OLD TRACK REGISTER
	MVI	C,20		;DELAY FOR 20 MILLISECONDS AFTER SELECT
	CALL	DELAY		;
	STC			;SET CARRY TO SHOW HARD DISK
	ENDIF
	RET			;RETURN TO CALLER

	PAGE
;-----------------------------------------------------------------------
;
;	SUBROUTINE TO POINT TO CURRENT TRACK REGISTER SAVE AREA
;
;-----------------------------------------------------------------------

POINT:
	LHLD	DISKNO	   ;PICKUP CURRENT DISK
	MOV	A,L	   ;
	MVI	H,0	   ;RESET HIGH ORDER HALF
	LXI	D,TRK0	   ;LOAD TRACK POINTER
	DAD	D	   ;POINT TO CURRENT TRACK PTR
	MOV	D,H	   ; DE = TRACK
	MOV	E,L	   ;
	LXI	B,12	   ;
	DAD	B	   ; HL = SELECT
	IF	HARDSK
	CPI	4	   ;
	JRC	PNTFN	   ; FLOPPY DISK
	MVI	A,10H	   ;
	ANA	M	   ; CHECK DRIVE SELECT
	JRZ	PNTH2	   ;   MUST BE DRIVE  # 2
	LXI	D,HTK1	   ; POINT TO DRIVE 1
	JR	PNTFN	   ;
PNTH2:	LXI	D,HTK2	   ; POINT TO DRIVE 2
	ENDIF
PNTFN:	XCHG		   ; SWITCH
	RET		   ; HL = TRACK    DE = SELECT

;-----------------------------------------------------------------------
;
;	ROUTINE TO TRANSLATE SECTOR NUMBER
;
;-----------------------------------------------------------------------

SECTRAN:
	XCHG			;TABLE ADDRESS IS IN DE (NOW HL)
	MOV	A,H		;IS THERE A TABLE ADDRESS ??
	ORA	L		;
	JRZ	STRN2		;NO, JUST RETURN ENTERED QUANTITY

STRN1:
	MVI	B,000H		;ENSURE OK FOR SINGLE BYTE QUANTITY
	DAD	B		;ADD SECTOR NUMBER
	MOV	L,M		;LOAD TRANSLATED VALUE
	MVI	H,000H		;
	RET			;NEW VALUE RETURNED IN HL

STRN2:
	DAD	B		;RETURN SAME VALUE AS ENTERED
	RET			;

;-----------------------------------------------------------------------
;
;	ROUTINES TO DO FLOPPY I/O
;
;-----------------------------------------------------------------------

READSOFT:
	MVI	A,09FH		;MASK FOR READ STATUS
	STA	MASK		;
	MVI	A,001H		;SETUP DMA FOR READ
	STA	DMAS3F		;
	MVI	A,08CH		;READ COMMAND
	JR	SRW1		;

WRITESOFT:
	MVI	A,0FFH		;MASK FOR WRITE STATUS
	STA	MASK		;
	CALL	MVDTB		;
	MVI	A,005H		;SETUP DMA FOR WRITE
	STA	DMAS3F		;
	MVI	A,0ACH		;WRITE COMMAND

SRW1:
	STA	CMD		;
	LXI	H,FPYBUF	;
	SHLD	DMASA		;
	LDA	NEWDSK		;
	CALL	DSKSEL		;SELECT DRIVE FOR I/O

SRW2:
	MVI	A,003H		;SET NUMBER OF TRIALS
	STA	T$RETRIES	;SAVE FOR RETRY ROUTINE

LOAD$HEAD:
	IN	008H		;IS HEAD LOADED ??
	ANI	00000010B	;CHECK IT....
	JNZ	REMOVE$LD	;YES, ITS LOADED, DONT RELOAD....
	IN	005H		;DUMMY SEEK TO START HEAD LOADING
	OUT	007H		;KEEP IT SHORT....
	MVI	A,01AH		;START HEAD LOADING
	OUT	004H		;
LDH1:	CALL	WAIT0		;WAIT FOR I/O TO COMPLETE
	MVI	C,16		;WAIT HERE FOR 16 MS
	CALL	DELAY		;CALL WAIT ROUTINE
	CALL	POINT		;REESTABLISH TRACK REGISTER POINTER
	MVI	M,254		;ENSURE FURTHER SEEK AND DELAY....
	JR	TRKTST		;

REMOVE$LD:
	LXI	H,CMD		;POINT TO I/O COMMAND
	MVI	A,11111011B	;REMOVE HEAD LOAD BIT
	ANA	M		;DO IT....
	MOV	M,A		;SAVE IT BACK INTO CMD

TRKTST:
	CALL	POINT		;RESTORE TRACK REGISTER POINTER
	LDA	NEWTRK	   	;GET NEW TRACK NUMBER
	STA	TRAKNO		;SAVE IN COMMON PLACE
	CMP	M		;SAME AS LAST TIME ??
	JRZ	FSECSET		;YES, DONT BOTHER WITH SEEK
	MOV	M,A	   	;SAVE IT
	OUT	007H	   	;ALSO SEND IT TO CONTROLLER

	CALL	DBL$UPDATE	;DOUBLE SIDED SUPPORT

FLOPPY$SEEK:
	MVI	A,01AH		;SEEK COMMAND WITH HEAD LOAD
	OUT	004H		;DO IT....
FPS1:	CALL	WAIT0		;WAIT FOR I/O TO COMPLETE
	MVI	C,16		;SET FOR 16 MS DELAY
	CALL	DELAY		;
FSECSET:
	LDA	NEWSEC		;SET SECTOR
	STA	SECTNO		;SAVE IN COMMONN PLACE
	OUT	006H		;

	CALL	FLOPPYIO	;DO I/O
	CALL	CHECK$STAT	;CHECK STATUS OF I/O
	LDA	ERFLAG		;SETUP TO RETURN TO BDOS
	CZ	MVDFB		;
	RZ			;EITHER OK OR PERMANENT ERROR
	JMP	LOAD$HEAD	;ERROR, JUST RETRY THIS SAME I/O

	PAGE
;-----------------------------------------------------------------------
;
;	THIS IS THE ROUTINE THAT DOES THE FLOPPY DISK I/O
;
;-----------------------------------------------------------------------

FLOPPYIO:
	IF	NOT DMA
        LXI     H,066H		;MOVE DATA FROM 066H TO SAVE
        LXI     D,SAVE1		;
        LXI     B,004H		;
	LDIR			;MOVE IT

        LXI     H,NMIRTN	;SET NMI ROUTINE TO NMI ADDRESS
        LXI     D,066H		;
        LXI     B,004H		;
	LDIR			;MOVE IT

	LDA	CMD		;IS IT A WRITE ??
	ANI	20H		;
	JZ	FRD		;NO, LEAVE INI CMD IN LOW MEMORY
	LXI	H,067H		;POINT TO COMMAND AREA
	MVI	M,0A3H		;MAKE IT AN OTI CMD....
FRD	EQU	$		;LABEL
	ENDIF

	IF	DMA
	LXI	H,DMAS1		;INITIALIZE DMA
	LXI	B,0600H		;
	OUTIR			;WRITE TO DMA
	LXI	H,DMAS2F	;
	LXI	B,0400H		;
	OUTIR			;WRITE TO DMA
	LXI	H,DMAS3		;
	LXI	B,0700H		;
	OUTIR			;WRITE TO DMA
	ENDIF

	MVI	C,007H		;PORT ADDRESS FOR I/O
	LXI	H,FPYBUF	;DMA ADDRESS
	LDA	CMD		;I/O COMMAND
	OUT	004H		;WRITE TO DISK CONTROLLER
FWT1:	CALL	WAIT0		;WAIT HERE FOR I/O TO COMPLETE

	IF	NOT DMA
	LXI     H,SAVE1    	;SETUP TO REPLACE DATA
	LXI     D,066H      	;COPIED FROM NMI LOCATION
	LXI     B,004H		;
	LDIR			;MOVE IT....
	ENDIF

	RET			;RETURN, I/O COMPLETED

;-----------------------------------------------------------------------
;
;	WE WILL NOW CHECK THE STATUS OF THE I/O OPERATION
;		RETURN WITH CONDITION CODE ZERO = NO RETRY
;		RETURN WITH CONDITION CODE NON ZERO = RETRY
;
;-----------------------------------------------------------------------

CHECK$STAT:
	LXI	H,ERFLAG	;POINT TO ERROR INDICATOR
	MVI	M,000H		;ASSUME OK
	LXI	H,STATUS	;CHECK STATUS
	LDA	MASK		;MASK FOR UNWANTED BIT REMOVAL
	ANA	M		;
	MOV	M,A		;SAVE CLEANED STATUS
	RZ                 	;OK, SO RETURN

CHKS0:
	CALL	RETMOD		;
	CPI	003H		;HARD DISK ??
	LXI	H,STATUS	;
	MOV	A,M		;RELOAD STATUS BYTE
	JRNC	CHKS2		;YES, CHECK FOR DRIVE READY

CHKS1:
	CPI	080H		;IS FLOPPY DISK NOT READY ???
	JZ	BADIO		;YES, DONT BOTHER WITH RETRY OR MESSAGE
	JR	CHKS3		;GO TO BAD MESSAGE ROUTINE

CHKS2:
	CPI	000H		;IS HARD DISK NOT READY ??
	JZ	BADIO		;YES, BYPASS ERROR MESSAGE AND COUNTING
	ANI	01000000B	;IS IT WRITE FAULT ??
	JRZ	CHKS3		;NO, CONTINUE ON
	CALL	POINT		;POINT TO TRACK REGISTER
	XCHG			;POINT TO SELECT MASK
	MOV	A,M		;
	ORI	01000000B	;TURN ON WRITE FAULT CLEAR
	OUT	020H		;
	MOV	A,M		;RESET CLEAR
	OUT	020H		;
	MVI	C,20		;DELAY JUST TO BE SAFE
	CALL	DELAY		;

CHKS3:
	LDA	STATUS		;SAVE STATUS OVER HOME
	PUSH	PSW		;
	CALL	HOME		;RESET DEVICE TO HOME
	POP	PSW		;
	STA	STATUS		;SAVE FOR ERROR MESSAGE
	LXI	D,TCNT		;BUMP TEMP ERROR COUNT
	CALL	ADDERRORS	;
	LXI	H,T$RETRIES	;PICKUP RETRY COUNT
	DCR	M		;DECREMENT COUNT OF RETRIES
	RNZ			;

	LXI	D,PCNT		;BUMP PERMANENT ERROR COUNT
	CALL	ADDERRORS	;

BADIO:
	LXI	H,ERFLAG	;SET PERMANENT ERROR
	MVI	M,001H		;DO IT....
	XRA	A		;RESET TO PRECLUDE RETRIES
	RET			;RETURN TO CALLER

ADDERRORS:
	LHLD	DISKNO		;BUMP COUNT OF DISK ERRORS
	MVI	H,000H		;
	DAD	D		;POINT TO ERROR REGISTER
	INR	M		;
	RET			;

	PAGE



;-----------------------------------------------------------------------
;
;	CENTRONICS PRINTER ROUTINE (WITH SEPARATE BUSY TEST FOR SPOOLER)
;
;-----------------------------------------------------------------------

CNSTAT:
	MVI	A,001H		;TO SET STROBE HIGH
	OUT	010H		;
	IN	010H		;READ PRINTER STATUS
	ANI	020H		;REMOVE ALL BUT BUSY BIT
	MVI	A,0FFH		;ASSUME NOT BUSY
	RZ			;CHECK ASSUMPTION
	XRA	A		;SET TO SHOW STILL BUSY
	RET			;
;
;	WE WILL NOW PERFORM THE PRINT FUNCTION BUSY TEST
;
CNTBSY:
	CALL	CNSTAT		;CHECK STATUS OF PRINTER
	CPI	0FFH		;READY ??
	JRNZ	CNTBSY		;NO, WAIT HERE
	RET			;

CLIST:
	CALL	CNTBSY		;WAIT FOR PRINTER TO FREE UP
	MOV	A,C		;CHARACTER TO PRINT
	OUT	011H		;WRITE IT TO DATA PORT
	MVI	A,000H		;TO FORCE STROBE LOW
	OUT	010H		;
	MVI	A,001H		;TO FORCE STROBE HIGH
	OUT	010H		;
	RET			;

	PAGE
;-----------------------------------------------------------------------
;
;	DISK INTERRUPT ROUTINE
;
;-----------------------------------------------------------------------

FLOPPY$INT:
	SHLD	SVDHL
	LXI	H,FDINTH
	JMP	INTINIT
FDINTH:
	IN	004H	   	;GET STATUS
	STA	STATUS		;SAVE FOR I/O ROUTINE
	JMP	HDSTFLG

HARD$INT:
	SHLD	SVDHL
	LXI	H,HDINTH
	JMP	INTINIT
HDINTH:
	IN	024H		;GET STATUS
	STA	STATUS		;SAVE FOR CHECK LATER
	XRA	A		;TO RESET INTERRUPT PENDING BIT
	OUT	023H		;RESET BY RELOADING THE COMMAND REGISTER
HDSTFLG:
	MVI	C,FLAGST
	MVI	E,5
	CALL	XDOS
	JMP	INTDONE

	PAGE
;-----------------------------------------------------------------------
;
;	CONSOLE DISPLAY ROUTINES
;
;-----------------------------------------------------------------------

;
CONST:			; CONSOLE STATUS
	CALL	PTBLJMP	; COMPUTE AND JUMP TO HNDLR
	DW	PT0ST	; CONSOLE #0 STATUS ROUTINE
	DW	PT1ST	; CONSOLE #1 STATUS ROUTINE
	DW	PT2ST	; CONSOLE #2 STATUS ROUTINE
	DW	PT3ST	; CONSOLE #3 STATUS ROUTINE

CONIN:			; CONSOLE INPUT
	CALL	PTBLJMP	; COMPUTE AND JUMP TO HNDLR
	DW	PT0IN	; CONSOLE #0 INPUT
	DW	PT1IN	; CONSOLE #1 INPUT
	DW	PT2IN	; CONSOLE #2 INPUT
	DW	PT3IN	; CONSOLE #3 INPUT

CONOUT:			; CONSOLE OUTPUT
	CALL	PTBLJMP	; COMPUTE AND JUMP TO HNDLR
	DW	PT0OUT	; CONSOLE #0 OUTPUT
	DW	PT1OUT	; CONSOLE #1 OUTPUT
	DW	PT2OUT	; CONSOLE #2 OUTPUT
	DW	PT3OUT	; CONSOLE #3 OUTPUT

;
PTBLJMP:		; COMPUTE AND JUMP TO HANDLER
			; D = CONSOLE #
			; DO NOT DESTROY <D>
	MOV	A,D
	CPI	NMBCNS
	JC	TBLJMP
	POP	PSW	; THROW AWAY TABLE ADDRESS
	XRA	A
	RET
TBLJMP:			; COMPUTE AND JUMP TO HANDLER
			; A = TABLE INDEX
	ADD	A	; DOUBLE TABLE INDEX FOR ADR OFFST
	POP	H	; RETURN ADR POINTS TO JUMP TBL
	MOV	E,A
	MVI	D,0
	DAD	D	; ADD TABLE INDEX * 2 TO TBL BASE
	MOV	E,M	; GET HANDLER ADDRESS
	INX	H
	MOV	D,M
	XCHG
	PCHL		; JUMP TO COMPUTED CNS HANDLER


	PAGE

;---------------------------------------------------------------
;
;	SERIAL PORT ADDRESS EQUATES
;
;---------------------------------------------------------------

DATA0	EQU	01CH		;CONSOLE #0 DATA
STS0	EQU	DATA0+1		;CONSOLE #0 STATUS
DATA1	EQU	02CH		;CONSOLE #1 DATA
STS1	EQU	DATA1+1		;CONSOLE #1 STATUS
DATA2	EQU	02EH		;CONSOLE #2 DATA
STS2	EQU	DATA2+1		;CONSOLE #2 STATUS
DATA3	EQU	02AH		;CONSOLE #3 DATA
STS3	EQU	DATA3+1		;CONSOLE #3 STATUS
LPTPRT0	EQU	01EH		;PRINTER #0 DATA
LPTSTS0	EQU	LPTPRT0+1	;PRINTER #0 STATUS
LPTPRT1	EQU	028H		;PRINTER #1 DATA
LPTSTS1	EQU	LPTPRT1+1	;PRINTER #1 STATUS

	PAGE

;---------------------------------------------------------------
;
;	POLL CONSOLE  # 0  INPUT
;
;---------------------------------------------------------------

POLCI0:
PT0ST:				; TEST CONSOLE STATUS
	XRA	A		;  RETURN  0FFH IF READY
	OUT	STS0		;          000H IF NOT
	IN	STS0		;
	ANI	1		;  RX CHAR ?
	RZ			;   NO
	MVI	A,0FFH		;   YES  -  SET FLAG
	RET			;
;
;---------------------------------------------------------------
;
;	CONSOLE  # 0  INPUT
;
;---------------------------------------------------------------
;
PT0IN:				; RETURN CHAR IN REG A
	MVI	C,POLL		;
	MVI	E,PLCI0		; POLL CONSOLE #0 INPUT
	CALL	XDOS		;
	IN	DATA0		; READ CHARACTER
	ANI	7FH		; STRIP PARITY
	RET			;
;
;
;---------------------------------------------------------------
;
;	CONSOLE  # 0  OUTPUT
;
;---------------------------------------------------------------
;
PT0OUT:				; REG C = CHAR TO OUTPUT
	PUSH	B		;
	MVI	C,POLL		;
	MVI	E,PLCO0		;
	CALL	XDOS		; POLL CONSOLE #0 OUTPUT
	POP	B		;
	MOV	A,C		;
	OUT	DATA0		; TRANSMIT CHARACTER
	RET			;
;
;
;---------------------------------------------------------------
;
;	POLL CONSOLE  # 0  OUTPUT
;
;---------------------------------------------------------------
;
POLCO0:				; RETURN 0FFH IF READY
	MVI	A,10H		;        000H IF NOT
	OUT	STS0		; RESET INT BIT
	IN	STS0		; READ STATUS
	ANI	0CH		; MASK FOR DTR AND TXE
	CPI	0CH		; MUST HAVE BOTH
	MVI	A,0		;
	RNZ			; RETURN NOT READY
	MVI	A,0FFH		;
	RET			; RETURN READY

	PAGE

;---------------------------------------------------------------
;
;	POLL CONSOLE  # 1  INPUT
;
;---------------------------------------------------------------

POLCI1:
PT1ST:				; TEST CONSOLE STATUS
	XRA	A		;  RETURN  0FFH IF READY
	OUT	STS1		;          000H IF NOT
	IN	STS1		;
	ANI	1		;  RX CHAR ?
	RZ			;   NO
	MVI	A,0FFH		;   YES  -  SET FLAG
	RET			;
;
;---------------------------------------------------------------
;
;	CONSOLE  # 1  INPUT
;
;---------------------------------------------------------------
;
PT1IN:				; RETURN CHAR IN REG A
	MVI	C,POLL		;
	MVI	E,PLCI1		; POLL CONSOLE #1 INPUT
	CALL	XDOS		;
	IN	DATA1		; READ CHARACTER
	ANI	7FH		; STRIP PARITY
	RET			;
;
;
;---------------------------------------------------------------
;
;	CONSOLE  # 1  OUTPUT
;
;---------------------------------------------------------------
;
PT1OUT:				; REG C = CHAR TO OUTPUT
	PUSH	B		;
	MVI	C,POLL		;
	MVI	E,PLCO1		;
	CALL	XDOS		; POLL CONSOLE #1 OUTPUT
	POP	B		;
	MOV	A,C		;
	OUT	DATA1		; TRANSMIT CHARACTER
	RET			;
;
;
;---------------------------------------------------------------
;
;	POLL CONSOLE  # 1  OUTPUT
;
;---------------------------------------------------------------
;
POLCO1:				; RETURN 0FFH IF READY
	MVI	A,10H		;        000H IF NOT
	OUT	STS1		; RESET INT BIT
	IN	STS1		; READ STATUS
	ANI	0CH		; MASK FOR DTR AND TXE
	CPI	0CH		; MUST HAVE BOTH
	MVI	A,0		;
	RNZ			; RETURN NOT READY
	MVI	A,0FFH		;
	RET			; RETURN READY

	PAGE


;---------------------------------------------------------------
;
;	POLL CONSOLE  # 2  INPUT
;
;---------------------------------------------------------------

POLCI2:
PT2ST:				; TEST CONSOLE STATUS
	XRA	A		;  RETURN  0FFH IF READY
	OUT	STS2		;          000H IF NOT
	IN	STS2		;
	ANI	1		;  RX CHAR ?
	RZ			;   NO
	MVI	A,0FFH		;   YES  -  SET FLAG
	RET			;
;
;---------------------------------------------------------------
;
;	CONSOLE  # 2  INPUT
;
;---------------------------------------------------------------
;
PT2IN:				; RETURN CHAR IN REG A
	MVI	C,POLL		;
	MVI	E,PLCI2		; POLL CONSOLE #2 INPUT
	CALL	XDOS		;
	IN	DATA2		; READ CHARACTER
	ANI	7FH		; STRIP PARITY
	RET			;
;
;
;---------------------------------------------------------------
;
;	CONSOLE  # 2  OUTPUT
;
;---------------------------------------------------------------
;
PT2OUT:				; REG C = CHAR TO OUTPUT
	PUSH	B		;
	MVI	C,POLL		;
	MVI	E,PLCO2		;
	CALL	XDOS		; POLL CONSOLE #2 OUTPUT
	POP	B		;
	MOV	A,C		;
	OUT	DATA2		; TRANSMIT CHARACTER
	RET			;
;
;
;---------------------------------------------------------------
;
;	POLL CONSOLE  # 2  OUTPUT
;
;---------------------------------------------------------------
;
POLCO2:				; RETURN 0FFH IF READY
	MVI	A,10H		;        000H IF NOT
	OUT	STS2		; RESET INT BIT
	IN	STS2		; READ STATUS
	ANI	0CH		; MASK FOR DTR AND TXE
	CPI	0CH		; MUST HAVE BOTH
	MVI	A,0		;
	RNZ			; RETURN NOT READY
	MVI	A,0FFH		;
	RET			; RETURN READY

	PAGE


;---------------------------------------------------------------
;
;	POLL CONSOLE  # 3  INPUT
;
;---------------------------------------------------------------

POLCI3:
PT3ST:				; TEST CONSOLE STATUS
	XRA	A		;  RETURN  0FFH IF READY
	OUT	STS3		;          000H IF NOT
	IN	STS3		;
	ANI	1		;  RX CHAR ?
	RZ			;   NO
	MVI	A,0FFH		;   YES  -  SET FLAG
	RET			;
;
;---------------------------------------------------------------
;
;	CONSOLE  # 3  INPUT
;
;---------------------------------------------------------------
;
PT3IN:				; RETURN CHAR IN REG A
	MVI	C,POLL		;
	MVI	E,PLCI3		; POLL CONSOLE #3 INPUT
	CALL	XDOS		;
	IN	DATA3		; READ CHARACTER
	ANI	7FH		; STRIP PARITY
	RET			;
;
;
;---------------------------------------------------------------
;
;	CONSOLE  # 3  OUTPUT
;
;---------------------------------------------------------------
;
PT3OUT:				; REG C = CHAR TO OUTPUT
	PUSH	B		;
	MVI	C,POLL		;
	MVI	E,PLCO3		;
	CALL	XDOS		; POLL CONSOLE #3 OUTPUT
	POP	B		;
	MOV	A,C		;
	OUT	DATA3		; TRANSMIT CHARACTER
	RET			;
;
;
;---------------------------------------------------------------
;
;	POLL CONSOLE  # 3  OUTPUT
;
;---------------------------------------------------------------
;
POLCO3:				; RETURN 0FFH IF READY
	MVI	A,10H		;        000H IF NOT
	OUT	STS3		; RESET INT BIT
	IN	STS3		; READ STATUS
	ANI	0CH		; MASK FOR DTR AND TXE
	CPI	0CH		; MUST HAVE BOTH
	MVI	A,0		;
	RNZ			; RETURN NOT READY
	MVI	A,0FFH		;
	RET			; RETURN READY

	PAGE


;---------------------------------------------------------------
;
;	LINE PRINTER  #0  DRIVER
;
;---------------------------------------------------------------
;
LIST:				;LIST OUTPUT #0
	PUSH	B		;
	MVI	C,POLL		; POLL PRINTER STATUS
	MVI	E,PLLPT		;
	CALL	XDOS		;
	POP	B		;
	MOV	A,C		; CHARACTER TO PRINT
	OUT	LPTPRT0		;
	cpi	0ch	;** form feed test for tty 40
	rnz
	mvi	c,0	;** output a null
	call	list
	jmp	list
;
;---------------------------------------------------------------
;
;	POLL PRINTER OUTPUT
;
;---------------------------------------------------------------
;
POLLPT:				; RETURN 0FFH IF READY
	MVI	A,10H		;        000H IF NOT
	OUT	LPTSTS0		; RESET INT BIT
	IN	LPTSTS0		; READ STATUS
	ANI	0CH		; MASK FOR DTR AND TXE
	CPI	0CH		; MUST HAVE BOTH
	MVI	A,0		;
	RNZ			; RETURN NOT READY
	MVI	A,0FFH		;
	RET			; RETURN READY
;
	PAGE
;
;  MP/M 1.0   EXTENDED I/O SYSTEM
;
;

POLLDEVICE:
			; REG C = DEVICE # TO BE POLLED
			; RETURN 0FFH IF READY,
			;        000H IF NOT
	MOV	A,C
	CPI	NMBDEV
	JC	DEVOK
	MVI	A,NMBDEV; IF DEV # >= NMBDEV,
			; SET TO NMBDEV
DEVOK:
	CALL	TBLJMP	; JUMP TO DEV POLL CODE

DEVTBL:
	DW	POLLPT	; POLL PRINTER OUTPUT
	DW	POLCO0	; POLL CONSOLE #0 OUTPUT
	DW	POLCO1	; POLL CONSOLE #1 OUTPUT
	DW	POLCO2	; POLL CONSOLE #2 OUTPUT
	DW	POLCO3	; POLL CONSOLE #3 OUTPUT
	DW	POLCI0	; POLL CONSOLE #1 INPUT
	DW	POLCI1	; POLL CONSOLE #1 INPUT
	DW	POLCI2	; POLL CONSOLE #1 INPUT
	DW	POLCI3	; POLL CONSOLE #1 INPUT
NMBDEV	EQU	($-DEVTBL)/2
	DW	RTNEMPTY; BAD DEVICE HANDLER

	PAGE

; SELECT / PROTECT MEMORY


SELMEMORY:
			; REG BC = ADR OF MEM DESCRIPTOR
			; BC ->  BASE   1 BYTE,
			;        SIZE   1 BYTE,
			;        ATTRIB 1 BYTE,
			;        BANK   1 BYTE.
			;
			;    BIOS TABLE MODIFIED
	CPI	20H	;
	JZ	$
	LXI	H,3	; POINT TO BANK
	DAD	B	;
	MOV	A,M	;  GET IT
	STA	BANKNO	; SAVE BANK NUMBER
	RAL		;
	RAL		;
	RAL		;
	ANI	018H	; MASK FOR PIO
	ORI	MEMSK	;
	STA	CURMEM	; STORE CURRENT BANK MASK
	OUT	009H	; SET PIO
	RET

BANKNO:	DB	0	; LAST SELECTED MEMORY BANK NUMBER
CURMEM:	DB	0	; LAST SELECTED MEMORY BANK MASK


; START CLOCK

STARTCLOCK:
			; WILL CAUSE FLAG #1 TO BE SET
			;  AT EACH SYSTEM TIME UNIT TICK
	MVI	A,0FFH
	STA	TICKN
	RET

; STOP CLOCK

STOPCLOCK:
			; WILL STOP FLAG #1 SETTING AT
			;  SYSTEM TIME UNIT TICK
	XRA	A
	STA	TICKN
	RET

; EXIT REGION

EXITREGION:
			; EI IF NOT PREEMPTED
	LDA	PREEMP
	ORA	A
	RNZ
	EI
	RET

; MAXIMUM CONSOLE NUMBER

MAXCONSOLE:
	MVI	A,NMBCNS
	RET

;  MP/M 1.0   INTERRUPT HANDLERS

DSPTCH	EQU	142

INT1HND:
			; INTERRUPT 1 HANDLER ENTRY POINT
			;  
T20MS:
	SHLD	SVDHL
	LXI	H,TIMERINT
	JMP	INTINIT
TIMERINT:
	LDA	TICKN
	ORA	A		; TEST TICKN, INDICATES
				;  DELAYED PROCESS(ES)
	JZ	NOTICKN
	MVI	C,FLAGST
	MVI	E,1
	CALL	XDOS		; SET FLAG #1 EACH TICK
NOTICKN:
	LXI	H,CNTx
	DCR	M		; DEC TICK CNTR
	JNZ	NOT1SEC
	mvi	a,125
	dcx	h
	sub	m
	mov	m,a	;** toggle count 62 <-> 63
	inx	h
	mov	m,a	;** actual #/sec = 62.5
	MVI	C,FLAGST
	MVI	E,2
	CALL	XDOS		; SET FLAG #2 @ 1 SEC
NOT1SEC:

INTDONE:
	XRA	A
	STA	PREEMP	; CLEAR PREEMPTED FLAG
	POP	B
	POP	D
	LHLD	SVDSP
	SPHL			; RESTORE STK PTR
	POP	PSW
	LHLD	SVDRET
	PUSH	H
	LXI	H,PDISP		; MP/M DISPATCH
	PUSH	H		;  PUT ON STACK FOR RETURN
	LHLD	SVDHL

; THE FOLLOWING DISPATCH CALL WILL FORCE ROUND ROBIN
;  SCHEDULING OF PROCESSES EXECUTING AT THE SAME PRIORITY
;  EACH 1/32ND OF A SECOND.
; NOTE: INTERRUPTS ARE NOT ENABLED UNTIL THE DISPATCHER
;  RESUMES THE NEXT PROCESS.  THIS PREVENTS INTERRUPT
;  OVER-RUN OF THE STACKS WHEN STUCK OR HIGH FREQUENCY
;  INTERRUPTS ARE ENCOUNTERED.

	RETI			; DISPATCH

INTINIT:		;SAVE MACHINE STATE FOR INTRPT HNDLNG
	SHLD	ADRINTHD
	POP	H
	SHLD	SVDRET
	PUSH	PSW
	LXI	H,0
	DAD	SP
	SHLD	SVDSP		; SAVE USERS STK PTR
	LXI	SP,LSTINTSTK	; LCL STK FOR INTR HNDL
	PUSH	D
	PUSH	B

	MVI	A,0FFH
	STA	PREEMP		; SET PREEMPTED FLAG
	LHLD	ADRINTHD
	PCHL		;JUMP TO INTERRUPT HANDLER

;
; BIOS DATA SEGMENT
;
togcnt:	db	62	; toggle counter 62 <-> 63
CNTx:	DB	62	; TICK CNTR to 1 SEC
INTSTK:			; LOCAL INTRPT STK
	DW	0C7C7H,0C7C7H,0C7C7H,0C7C7H,0C7C7H
	DW	0C7C7H,0C7C7H,0C7C7H,0C7C7H,0C7C7H
	DW	0C7C7H,0C7C7H,0C7C7H,0C7C7H,0C7C7H
	DW	0C7C7H,0C7C7H,0C7C7H,0C7C7H,0C7C7H
LSTINTSTK:
ADRINTHD: DW	0	; INTERRUPT HANDLER ADDRESS
SVDHL:	DW	0	; SAVED REGS HL DURING INT HNDL
SVDSP:	DW	0	; SAVED SP DURING INT HNDL
SVDRET:	DW	0	; SAVED RETURN DURING INT HNDL
TICKN:	DB	0	; TICKING BOOLEAN,TRUE = DELAYED
PREEMP:	DB	0	; PREEMPTED BOOLEAN


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
;	THIS IS DISK WAIT ENTRY
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;

WAIT0:
	PUSH	B		; SAVE RETRY COUNT
	MVI	C,FLAGWT	; FUNCTION FLAG WAIT
	MVI	E,5		; DEVICE IS DISK
	CALL	XDOS
	POP	B		; RESTORE RETRY COUNTER IN <C>

;	READ OR WRITE IS OK, ACCUMULATOR CONTAINS ZERO


	RET

	PAGE
;-----------------------------------------------------------------------
;
;	THIS IS THE DELAY ROUTINE. IT WILL LOOP HERE FOR THE
;	NUMBER OF MILLISECONDS SPECIFIED IN REGISTER C.
;
;-----------------------------------------------------------------------

DELAY:
DEL1:	MVI	B,100		;FORCE DELAY FOR 1 MILLISECOND
DEL2:	RLC			;INSTRUCTIONS TO FILL IN TIME
	DAD	H		;
	DAD	H		;
	DCR	B		;AT ONE MILLISECOND YET ??
	JNZ	DEL2		;NO, KEEP ON LOOPING
	DCR	C		;END OF REQUESTED INTERVAL YET ??
	JNZ	DEL1		;NO, KEEP ON
	RET			;RETURN TO CALLER

	PAGE

;********************************************
;*  NOTE: THE INITIALIZATION CODE WILL BE
;*    OVERWRITTEN BY DIRBUF & FPYBUF
;********************************************

DIRBUF	EQU	$

;------------------------------------------------------------
;
;	INITIALIZE MP/M: REAL TIME CLOCK & DISKS
;
;------------------------------------------------------------

SYSTEMINIT:
	DI
	; C  = BREAKPOINT RESTART NUMBER
	; DE = BREAKPOINT RESTART HANDLER ADDRESS
	; HL = DIRECT XIOS INTERCEPT JUMP TABLE ADDRESS

	SHLD	SVDJT
	MOV	L,C
	MVI	H,0
	DAD	H
	DAD	H
	DAD	H	;HL = RESTART JUMP ADDRESS
	SHLD	SVDBPA

	MVI	A,01AH		; SELECT BANK 3
	CALL	STMVTR		; SET UP VECTORS
	MVI	A,012H		; SELECT BANK 2
	CALL	STMVTR		; SET UP VECTORS
	MVI	A,00AH		; SELECT BANK 1
	CALL	STMVTR		; SET UP VECTORS
	MVI	A,002H		; SELECT BANK 0
	CALL	STMVTR		; SET UP VECTORS

	LXI	B,003H		;SET THE MODE FOR DRIVES INITIALIZED BY "SETUP"

MODESET:
	CALL	SELDSK		;SELECT DRIVE FOR MODESET
	LXI	H,MODE		;
	DAD	B		;POINT TO CORRECT MODE BYTE
	PUSH	B		;SAVE COUNT OF DRIVES
	MOV	C,M		;
	CALL	SETMOD		;SET MODE
	POP	B		;
	DCR	C		;END OF LIST YET ??
	JP	MODESET		;SET MODE FOR ALL DRIVES
	CALL	SDCONF		;SET DISK CONFIGURATION

        LXI     B,80H
        CALL    SETDMA     	;SET DMA ADDRESS

	MVI	A,INTERUPT SHR 8 ;SETUP INTERRUPT VECTOR
	DB	0EDH,047H	;---- FAKE STAI INSTRUCTION

	MVI	A,60H		; SET VECTOR FOR CTC
	OUT	30H		; CTC CHANNEL 0
	MVI	A,0A7H		; RESET  /  LOAD TIME CONSTANT
	OUT	33H		; CHANNEL 3
	MVI	A,250		;  TIME CONSTANT
	OUT	033H		;

	IF	HARDSK
	EI
	MVI	A,080H		;ISSUE RESET AGAINST HARD DISK
	OUT	023H		;
	MVI	A,01010000B	;RESET WRITE FAULT
	OUT	020H		;DRIVE 1
	MVI	A,01100000B	;
	OUT	020H		;DRIVE 2
	MVI	A,00010000B	;SELECT DRIVE 1/ HEAD 0
	OUT	020H		;
	MVI	C,20		;WAIT FOR 20 MILLISECONDS
	CALL	DELAY		;
	CALL	WAIT0	;INTERRUPT PRODUCED BY HARD DISK RESET
	XRA	A		;ZERO ACCUMULATOR
	STA	HSTACT		;SET HOST BUFFER INACTIVE
	STA	UNACNT		;SET UNALLOCATED COUNT TO ZERO

	LXI	H,HSTBUF-1	;SETUP WRITE CONTROL BYTE FOR HARD DISK
	MVI	M,00DH		;
	ENDIF

	RET			;

STMVTR:
	OUT	MEMPORT
	MVI	A,0C3H		; SET VECTORS FOR BDOS
	STA	0		;  JMP INSTRUCTION
	LHLD	SVDJT		;
	SHLD	1
	LHLD	SVDBPA
	MOV 	M,A
	INX	H
	MOV	M,E
	INX	H
	MOV	M,D
	RET			;

SVDJT:	DS	2	; SAVED DIRECT JUMP TABLE ADDRESS
SVDBPA:	DS	2	; SAVED BREAK POINT ADDRESS

;-----------------------------------------------------------------------
;
;	DISK CONFIGURATION TABLE
;
;-----------------------------------------------------------------------

	IF	HARDSK
						;     PIN CONFIGURATION

DSCN0:	DB	00H,00H,00H,00H,00H,00H,00H,00H
	DB	10H,00H,00H,00H,00H,00H,10H,00H		;  1
	DB	90H,90H,90H,00H,00H,00H,00H,00H		;  2
	DB	00H,00H,00H,00H,00H,00H,00H,00H
	DB	10H,00H,00H,20H,00H,00H,10H,20H		;  4
	DB	00H,00H,00H,00H,00H,00H,00H,00H
	DB	90H,90H,90H,20H,00H,00H,00H,20H		;  6
	DB	90H,90H,90H,0A0H,0A0H,0A0H,0H,0H	;  7
	ENDIF
;-----------------------------------------------------------------------
;
;	SET UP DISK CONFIGURATON
;
;	[ THIS CODE EXECUTED ONLY ONCE ]
;
;-----------------------------------------------------------------------
;
SDCONF:	LXI	H,SEL0+2	;POINT TO DRIVE C:
	LDA	MPARMS		;
	ANI	05H		; TEST FOR FOUR FLOPPIES
	JMP	SDDBL		;  YES  SKIP THE ZAP
	MOV	M,A		;
	INX	H		; ZAP C: AND  D:
	MOV	M,A		;
SDDBL:
	LXI	D,SEL0+4	;POINT TO DRIVE E:
	IF	HARDSK
	MVI	A,1		; *** TEMP DEBUG
;	IN	025H		;READ CONFIGURATION PORT
	ANI	07H		;STRIP OFF HIGH PART
	RAL			;
	RAL			;
	RAL			;
	MVI	B,0		;
	MOV	C,A		;POINT TO CONFIGURATION TABLE
	LXI	H,DSCN0		;
	DAD	B		;  INDEX TO RIGHT ENTRY
	MVI	B,8		;
SDL1:	MOV	A,M		; CHANGE ALL SELECT MASKS
	STAX	D		;
SDOK:	INX	D		; NEXT
	INX	H		;  DRIVE
	DJNZ	SDL1		;
	ENDIF
	IF	NOT HARDSK
	XCHG			;
	MVI	B,8		;
	XRA	A		;
SDL2:	MOV	M,A		; ZAP ALL HARD DRIVES
	INX	H		;
	DJNZ	SDL2		;
	ENDIF			;

	RET

INITEND	EQU	$

	PAGE
;-----------------------------------------------------------------------
;
;	THE FOLLOWING AREA CONTAINS THE DISK/WORK SAVE AREAS
;	USED BY THE CBIOS IN THE NORMAL COURSE OF ACTIVITY.
;
;-----------------------------------------------------------------------

TEMPBUF	EQU	(DIRBUF-BASE)+256

	ORG TEMPBUF+((INITEND-BASE)/TEMPBUF)*((INITEND-BASE)-TEMPBUF)

BEGDAT	EQU	$			;START OF BDOS AREAS
;DIRBUF:	DS	128	;OVERLAYS SYSTEMINIT CODE
ALV0:	DS	32
CSV0:	DS	32
ALV1:	DS	32
CSV1:	DS	32
ALV2:	DS	32
CSV2:	DS	32
ALV3:	DS	32
CSV3:	DS	32
	IF	HARDSK
ALV4:	DS	64
CSV4:	DS	0
ALV5:	DS	64
CSV5:	DS	0
ALV6:	DS	64
CSV6:	DS	0
ALV7:	DS	64
CSV7:	DS	0
ALV8:	DS	64
CSV8:	DS	0
ALV9:	DS	64
CSV9:	DS	0
ALVA:	DS	36
CSVA:	DS	0
ALVB:	DS	36
CSVB:	DS	0

	DS	1			;MUST PRECEDE HSTBUF
HSTBUF:	DS	1024			;HOST BUFFER AREA
	DS	1			;MUST FOLLOW HSTBUF
	ENDIF

FPYBUF	EQU	DIRBUF+128		; FLOPPY I/O BUFFER

NEWDSK:	DS	1			;SEEK DISK NUMBER
NEWTRK:	DS	2			;SEEK TRACK NUMBER
NEWSEC:	DS	1			;SEEK SECTOR NUMBER

HSTDSK:	DS	1			;HOST DISK NUMBER
HSTTRK:	DS	2			;HOST TRACK NUMBER
HSTSEC:	DS	1			;HOST SECTOR NUMBER

NEWHST:	DS	1			;SEEK SHR SECSHF
HSTACT:	DS	1			;HOST ACTIVE FLAG
HSTWRT:	DS	1			;HOST WRITTEN FLAG

UNACNT:	DS	1			;UNALLOCATED RECORD COUNT
UNADSK:	DS	1			;LAST UNALLOCATED DISK
UNATRK:	DS	2			;LAST UNALLOCATED TRACK
UNASEC:	DS	1			;LAST UNALLOCATED SECTOR

ERFLAG:	DS	1			;ERROR REPORTING
RSFLAG:	DS	1			;READ SECTOR FLAG
READOP:	DS	1			;1 IF READ OPERATION
WRTYPE:	DS	1			;WRITE OPERATION TYPE

CMD:	DB	0			;COMMANDS FOR NEXT I/O
MASK:	DB	0			;STATUS MASKS BUFFER FOR DISK I/O
STATUS:	DB	0			;STATUS SAVE LOCATION FOR DISK I/O

SAVE1:	DB	000H,000H,000H,000H	;SAVE AREA FOR NMI ROUTINE
P$RETRIES: DB	000H			;COUNTER FOR PERMANENT ERRORS
T$RETRIES: DB	000H			;COUNTER FOR TEMPORARY ERRORS


DATSIZE	EQU	$-BEGDAT

	END

