	title	'LOADER BIOS FOR  info-s HARDWARE AND CP/M 3.0'


;************************************************
;	LOADER BIOS FOR CPM 3.0  VERS.1.0 08/23/83
; 	DESIGNED FOR INFO-S HARDWARE
;	(C) COPYRIGHT BY G.KRAUSE 1983
;************************************************

	maclib	cpm3
	maclib	z80

;************************************************
;	BIOS EQUATES
;************************************************
;	PORT EQUATES
;************************************************
BAUD    EQU	0EDH
CONB 	EQU	0E2H
V5S	EQU	41H
V5D	EQU	40H
FDC	EQU	0H	; FLOPPY CONTROLL
FDD	EQU	1H	; FLOPPY DATA PORT
FTC	EQU	2H	; FLOPPY TERMINATE
DMA	EQU	3H	; FLOPPY DMA CONTROLLER
DRIVE	EQU	4H	; DRIVE TYPE SELECT
FBANK	EQU	5H	; FLOPPY BANK REGISTER
CBANK	EQU	0EEH	; CPU BANK REGISTER
	

;************************************************
; BIOS Jump vector.
;************************************************
	
	CSEG

?boot:	jmp INIT	; initial entry on cold start
?wboot:	jmp RETURN	; reentry on program exit, warm start

?const:	jmp RETURN	; return console input status
?conin:	jmp RETURN	; return console input character
?cono:	jmp conout	; send console output character
?list:	jmp RETURN	; send list output character
?auxo:	jmp Return	; send auxilliary output character
?auxi:	jmp RETURN	; return auxilliary input character

?home:	jmp home	; set disks to logical home
?sldsk:	jmp seldsk	; select disk drive, return disk parameter info
?sttrk:	jmp settrk	; set disk track
?stsec:	jmp setsec	; set disk sector
?stdma:	jmp setdma	; set disk I/O memory address
?read:	jmp read	; read physical block(s)
?write:	jmp RETURN	; write physical block(s)

?lists:	jmp RETURN	; return list device status
?sctrn:	jmp sectrn	; translate logical to physical sector

?conos:	jmp RETURN	; return console output status
?auxis:	jmp RETURN	; return aux input status
?auxos:	jmp RETURN	; return aux output status
?dvtbl:	jmp RETURN	; return address of device def table
?devin:	jmp RETURN	; change baud rate of device

?drtbl:	jmp getdrv	; return address of disk drive table
?mltio:	jmp RETURN	; set multiple record count for disk I/O
?flush:	jmp RETURN	; flush BIOS maintained disk caching

?mov:	jmp ?move	; block move memory to memory
?tim:	jmp RETURN	; Signal Time and Date operation
?bnksl:	jmp RETURN	; select bank for code execution and default DMA
?stbnk:	jmp RETURN	; select different bank for disk I/O DMA operations.
?xmov:	jmp RETURN	; set source and destination banks for one operation

	jmp RETURN	; reserved for future expansion
	jmp RETURN	; reserved for future expansion
	jmp RETURN	; reserved for future expansion


;************************************************
;	PARAMETER PASSED FROM BOOT MOVER
;************************************************

DEFBYTE:
	DB	00		; CONSOLE DEFINITION
	DB	00		; BOOT DRIVE DEFINITION
;***********************************************
DRVTIME:
;	STEP RATE AND HEAD LOAD 
; 	TIMING FOR DRIVES
; 	TIME FOR 5" UNITS IS DOUBLED
;************************************************
	DB	04FH		; SRT + HUT 
	DB	060H		; HLT       

;************************************************
;	Extended Disk Parameter Headers (XPDHs)
;************************************************ 
	DW	DDB2    ; default is 8" DD,DS,512 Byte
	DW	00
	DW	READ   
	DW	fd$login
	DW	00
	DB	0,1EH	 
fdsd0:	
	DW      TRANS2
	DW	00,00,00,00,00
	DW	DPB2
	DW	CSV
	DW	ALV
	DW	DIRBCB 
	DW	DATBCB 
	DW	0FFFFH
	DB	00


CSV:	DS	30H

ALV:	DS	48H

DIRBCB:
	DB	0FFH
	DB	00,00,00,00,00
	DW	00,00
	DW	DIRBUF
DATBCB:
	DB	0FFH
	DB	00,00,00,00,00
	DW	00,00
	DW	DATBUF


;************************************************
;	DEFINITION OF FLAG BYTE IN DDB
;************************************************
;	X X X X    X X X X
;	I   I I	   I I I I-----	0 = 8"  /  1 = 5"
;	I   I I	   I I I------- 0 = SS  /  1 = DS
;	I   I I	   I I--------- 0 = SD  /  1 = DD
;	I   I I	   I----------- 0 = NONINV. DATA / 1 = INVERT. DATA
;       I   I I
;	I   I I---------------- 1 = 512 BYTE /SEC.     0
;	I   I------------------ 1 =   2 KBYTE/SEC.     0 = 128 BYTE/SEC.
;	I
;	I---------------------- 0 = 77 TRK. /  1 = 40 TRK
;
;************************************************
DDB0:
	DW	DDB1	; 8" SD SS  STANDART CPM
	DW	TRANS0
	DW	DPB0 
	DB	00,00	; FLAG AND SPARE BYTE
DDB1:			; 8" DD SS 512BYTE
	DW	DDB2
	DW	TRANS2
	DW	DPB1
	DB	1CH,0
DDB2:	
	DW	DDB0	; 8" DD DS 512BYTE
	DW      TRANS2
	DW	DPB2
	DB	1EH,00
DDB3:
	DW	DDB3	; 5" DD SS 48TPI
  	DW	TRANS1
	DW	DPB3
	DB	9DH,00
DDB4:		
	DW	DDB4	; 5" DD DS 48TPI
	DW	TRANS1
	DW	DPB4
	DB	9FH,00
DDB5:
	DW	DDB5	; 5" DD SS 96TPI
	DW	TRANS1
	DW	DPB5
	DB	1DH,00
DDB6:
	DW	DDB6	; 5" DD DS 96TPI
	DW	TRANS1
	DW	DPB6
	DB	1FH,00

;***********************************************  
@DTBL	dw	fdsd0
	dw	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;*********************************************** 

TRANS0	SKEW	26,6,1			; FOR STANDARD DISK

TRANS1	SKEW	10,2,1			; 5" DD 512-BYTE / SEC

TRANS2	SKEW	15,4,1			; 8" DD 512-BYTE / SEC

;************************************************

DPB0  	DPB	128,26,77,1024,64,2	; 8" 77 TRK SS SD

DPB1  	DPB	512,15,77,2048,128,2	; 8" 77 TRK SS DD

DPB2    DPB	512,15,154,2048,128,2	; 8" 77 TRK DS DD

DPB3  	DPB	512,10,40,2048,64,2	; 5" 40 TRK SS DD

DPB4  	DPB	512,10,80,2048,64,2	; 5" 40 TRK DS DD

DPB5  	DPB	512,10,77,2048,128,2	; 5" 77 TRK SS DD

DPB6  	DPB	512,10,154,2048,128,2	; 5" 77 TRK DS DD

;************************************************

DDTAB:
	DW	DDB2
	DW	DDB3
	DW	DDB4
	DW	DDB5
	DW	DDB6


;************************************************
;	DUMY FUNKTION
;************************************************
RETURN:	RET		; FUNKTION NOT IN BOOT CPM   

;************************************************
;       BASIC INITIALIZATION 
;************************************************
INIT:
	MVI	A,0EEH		; BAUD RATE
	OUT	BAUD
	MVI	C,CONB+1	; B-PORT CONTROL
	LXI	H,IPORT1	; POINT TO PARAMETER
	MVI	B,11
	OUTIR			; LOAD DART
	DI
	IM2
	LXI	H,TERMI
	LXI	D,INTVEC+1
	RES	0,E		; MAKE EVEN ADDRESS
	MOV	A,L
	STAX	D
	INX	D
	MOV	A,H
	STAX	D
	DCX	D
	MOV	A,D
	STAI
	MOV	A,E
	STA	LIVR
	LDA	DEFBYTE+1	; BOOT DRIVE 
	SLAR	A		; *2
	MOV	C,A
	MVI	B,0
	LXI	H,DDTAB
	DAD	B
	MOV	C,M
	INX	H
	MOV	B,M
	SBCD	FDSD0-12
	XRA	A
	OUT	FBANK
	OUT	CBANK
	LXI	H,DRVTIME	; LOAD STEP RATE
	MVI	C,03		; AND HEAD LOAD TIMING
	CALL	CMDOUT
	MOV	C,M
	CALL	CMDOUT
	INX	H
	MOV	C,M
	CALL	CMDOUT
	EXX
	LDA	DEFBYTE
	MOV	B,A
	EXX
	EI
  	RET


;************************************************
;	Console Output.  Send character in <C>
;************************************************
CONOUT:	
 	LDA	DEFBYTE    	; V5 PRESENT ?
 	ANI     01		; 0=V5 1=SERIAL TERMINAL
 	JRZ	V5OUT		; YES - JUMP
CO$SPIN:
	IN      CONB+1		; READ STATUS PORT
	ANI	04H		; TEST TRANSMITTER EMPTY
	JRZ	CO$SPIN		; SPIN IF NOT
	MOV	A,C		; GET OUTPUT BYTE
	ANI	7FH		; MASK HIGH ORDER BIT
	OUT	CONB		; SEND IT
	RET

V5OUT:
	IN	V5S		; READ V5 STATUS
	ANI     01H		; TEST READY
	JRZ 	V5OUT		; LOOP IF NOT
	MOV	A,C		; GET OUTPUT BYTE
	ANI	7FH		; MASK HIGH ORDER BIT
	OUT	V5D  		; SEND IT
	RET

IPORT1:	DB	18H,01H,00H,02H,00H,03H,0C1H,04H,4CH,05H,0EAH


;************************************************
;	Utility Subroutines
;************************************************

ipchl:		; vectored CALL point
	pchl

;************************************************
?pmsg:	
; 	print message @<HL> up to a null
; 	saves <BC> & <DE>
;************************************************
	push 	b
	push 	d
pmsg$loop:
	mov 	a,m 
        ora 	a  
	jz 	pmsg$exit
	mov 	c,a  
	push 	h
	call 	?cono  
	pop 	h
	inx 	h  
	jmp 	pmsg$loop
pmsg$exit:
	pop 	d
	pop 	b
	ret

?pdec:				; print binary number 0-65535 from <HL>

	lxi 	b,table10 
	lxi 	d,-10000
next1:
	mvi 	a,'0'-1
pdecl:
	push 	h 
	inr 	a 
	dad 	d 
	jnc 	stoploop
	inx 	sp 
	inx 	sp 
	jmp 	pdecl
stoploop:
	push 	d 
	push 	b
	mov 	c,a 
	call 	?cono
	pop 	b 
	pop 	d
nextdigit:
	pop 	h
	ldax 	b 
	mov 	e,a 
	inx 	b
	ldax 	b 
	mov 	d,a 
	inx 	b
	mov 	a,e 
	ora 	d 
	jnz 	next1
	ret

table10:
	dw	-1000,-100,-10,-1,0

?pderr:
	lxi 	h,drive$msg  
	call 	?pmsg		; error header
	lda 	@adrv  
	adi 	'A'  
	mov 	c,a  
	call 	?cono		; drive code
	lxi 	h,track$msg  
	call 	?pmsg		; track header
	lhld 	@trk  
	call 	?pdec		; track number
	lxi 	h,sector$msg  
	call 	?pmsg		; sector header
	lhld 	@sect  
	call 	?pdec		; sector number
	ret


;************************************************
;	Disk I/O interface routines
;************************************************ 

;************************************************
;       GETDRV
;	Return address of drive table
;************************************************
getdrv:
	lxi 	h,@dtbl  
	ret


;************************************************
;       SELDSK
;	Select Disk Drive.  
;	Invoke login procedure for drive
;	if this is first select.  Return
;	address of disk parameter header
;	in <HL>
;************************************************
seldsk:
	XRA 	A
	STA 	@ADRV			; save drive select code
	STA	@RDRV
	LXI	H,FDSD0
	MOV	A,E  
	ANI	1 
        jnz 	not$first$select	; examine login bit
	push 	h  
	xchg				; put pointer in stack & <DE>
	CALL	FD$LOGIN
	pop 	h			; recover DPH pointer
not$first$select:
	ret

;************************************************
;	HOME
;	Home selected drive.  Treated as SETTRK(0).
;************************************************
home:
	lxi 	b,0		; same as set track zero

;************************************************
;       SETTRK
;	Set Track. Saves track address from <BC> 
;	in @TRK for further operations.
;************************************************
settrk:
	mov 	l,c  
	mov 	h,b
	shld 	@trk
	ret

;************************************************
;       SETSEC
;	Set Sector.  Saves sector number from <BC>
;		in @sect for further operations.
;************************************************
setsec:
	mov 	l,c  
	mov 	h,b
	shld 	@sect
	ret

;************************************************
;       SETDMA
;	Set Disk Memory Address.  Saves DMA address
;	from <BC> in @DMA and sets @DBNK to @CBNK
;	so that further disk operations take place
;	in current bank.
;************************************************
setdma:
	mov 	l,c  
	mov 	h,b
	shld 	@dma
	RET

;************************************************
;       SECTRN
;	Sector Translate.  Indexes skew table in <DE>
;	with sector in <BC>.  Returns physical sector
;	in <HL>.  If no skew table (<DE>=0) then
;	returns physical=logical.
;************************************************
sectrn:
	mov 	l,c  
	mov 	h,b
	mov 	a,d  
	ora 	e  
	rz
	xchg  
	dad 	b  
	mov 	l,m  
	mvi 	h,0
	ret



;************************************************
FD$LOGIN:
; This entry is called when a logical drive is about to
; be logged into for the purpose of density determination.
; It may adjust the parameters contained in the disk
; parameter header pointed at by <DE>
;************************************************
	MVI	A,-1		; SET FLAG FOR 1ST ENTRY
	CALL	CHGDRV		; DEFINE DPB IN DPH
LOG02:
	PUSH	D
	POP	H
	SHLD	SAVE
	LXI	H,0002
	SHLD	@TRK		; SET TRK 2
	DCX	H
	SHLD	@SECT		; SET SEC 1
	LXI	H,BUFF
	SHLD	@DMA		; READ IN BUFFER
	DCX	D
	PUSH  	D
	XTIX			; EX (SP),IX
	CALL	TRK0		; RECALIBRATE DISK
	CALL	SET0		; ADJUST DISK
	CALL	RDDATA		; READ DIRECTORY
	CALL	RESULT		; GET RESULT
	LXI	H,RESTAB	; ANALYSE RESULT
	MOV	A,M		; STATUS BYTE
	ANI	0C0H		; MASK BITS        
 	JRNZ	LOG01		; TRY ANOTHER DDB
	LDX	A,0		; LOAD MASK BYTE
	BIT	0,A		; TEST FOR 5"
	JRNZ	FOUND		; 5" - JUMP
	ANI	0BFH		; TEST FOR 8" SD FORMAT
	JRZ	FOUND		; 8" SD - JUMP
 	LDA	DRVST		; DRIVE STATUS
 	ANI	08		; TWO SIDET ?
	SRAR	A
	SRAR	A
	MOV	B,A
	LDX	A,0
	ANI	02
	XRA	B
	JRZ	FOUND
LOG01:
	LHLD	SAVE		; RESTORE XDPH POINTER
	PUSH	H
	POP	D
	XRA	A		; SET FLAG
	CALL	CHGDRV		; CHANGE DRIVE TYPE
	POPIX
	JR 	LOG02   	; TRY AGAIN
FOUND:
	POPIX			; RESTORE IX
	RET 

		

;************************************************ 
CHGDRV:	;CHANGE DRIVE TYPE OR FORMAT
;************************************************
	PUSH	D
	PUSH	D
	LXI	H,-0CH
	DAD	D
	MOV	E,M		; PUT DDB ADDR. IN DE
	INX	H
	MOV	D,M
	ORA	A		; TEST FLAG
	JRNZ	CHGDRV1 	; JUMP ON FIRST ENTRY
	LDAX	D		; FETCH ADDR. OF NEXT DDB
	DCX	H
	MOV	M,A
	MOV	C,A
	INX	H
	INX	D
	LDAX	D
	MOV	M,A		; STORE NEW DDB IN XDPH-12
	MOV	D,A
	MOV	E,C
CHGDRV1:
	INX	D
	INX	D		; FETCH ADDR. OF XLT
	LDAX	D
	POP	H		; RESTORE ADDR. OF XDPH
	MOV	M,A		; CHANGE XLT POINTER 
	INX	D		; IN XDPH
	LDAX	D
	INX	H
	MOV	M,A
	LXI	B,11		; ADJUST POINTER TO 
	DAD	B		; DPB IN XDPH
	INX	D		; FETCH ADDR. OF NEW DPB
	LDAX	D
	MOV	M,A		; CHANGE DPB IN XDPH
	INX	D
	INX	H 
	LDAX	D
	MOV	M,A
	POP	H		; GET XDPH POINTER
	DCX	H		; POINT TO FLAG BYTE
	INX	D
	LDAX	D		; MOVE FLAG BYTE
	MOV	M,A
	INX	H
	MOV	D,H		; COPY HL IN DE
	MOV	E,L
	RET


;************************************************
;       READ SECTOR WITH GIVEN PARAMETERS
; 	relative drive number in @rdrv (8 bits)
; 	absolute drive number in @adrv (8 bits)
; 	disk transfer address in @dma (16 bits)
; 	disk transfer bank	in @dbnk (8 bits)
; 	disk track address	in @trk (16 bits)
; 	disk sector address	in @sect (16 bits)
;
; 	transfer the appropriate data, perform retries
; 	if necessary, then return an error code in <A>
;***********************************************
READ:
	XRA	A
	STA	@RDRV
	LXI	D,FDSD0
	STA	ERRCODE+1	; SET READ FLAG
	DCX	D
	PUSH  	D
	XTIX			; EX (SP),IX
	MVI	A,10
	STA	ERRCNT
	CALL	SET0
READ004:
	LDA	ERRCNT
	ORA	A		; TEST RETRY COUNT
	JRNZ    READ008		; MAKE MORE RETRIES
	MVI	A,01		; LOAD ERROR CODE 
	JR	READ007		; JUMP TO ERROR RETURN
READ008:
	DCR	A		; UPDATE ERROR COUNT
	STA	ERRCNT		; STORE IT
	CALL	RDDATA		; READ THE DATA
	CALL	RESULT		; GET THE RESULT
	LXI	H,RESTAB	; POINT TO RESULT TABLE
	MOV	A,M		; GET STATUS BYTE
	ANI	0C0H		; 
	JRZ	READ002		; NO ERROR OCCURED
	INX	H		; POINT TO SENSE BYTE 1
	BIT	0,M		; MISS. ADDR. MARK ?
	JRZ	READ003		; NO - JUMP
	LDA	ERRCNT
	CPI	3		; ALLOW 3 RETRIES
	JRC	READ004
	MVI	A,0FFH
	JMP	READ007		; JUMP TO ERROR RETURN
READ003:
	INX	H		; POINT TO SENSE BYTE 2
	BIT	4,M		; WRONG TRACK ?
	JRZ	READ004		; NO - JUMP AND DO RETRY
	CALL	RESTORE		; REPOSITION HEAD
	JR	READ004 
READ002:			; MOVE DATA IF REQUIRED
	BITX	3,0
	JRZ	READ001
	LXI	H,BUFF
	LDED	@DMA
	CALL	MOVE		; INVERTED TRANSFER
READ001:			  
	XRA	A		; SUCCESSFUL RETURN
READ007:
ERRDSPL:	
	POPIX 
	ORA	A		; TEST FOR ERRORS
	RZ			; NO ERRORS TO DISPLAY
	STA 	ERRCODE		; SAVE ERROR CODE
FULLMSG:
	CALL	?PDERR		; PRINT HEADER
RDOP:
	LXI	H,RDMSG		; OPERATIN WAS READ
SENDOP:
	CALL	?PMSG		; DISPLAY IT
	LXI	H,SENSMSG	; SENS BYTES FOLLOW
	CALL	?PMSG
	LXI	H,RESTAB	; POINT TO RESULT TABLE
	MVI	B,7		; NR. OF BYTES
SENSLP:
	PUSH	B
	CALL	ADJUST
	CALL	ADJUST
	INX	H		; POINT TO NEXT BYTE
	MVI	C,'-'		; SEND SEPARATOR
	PUSH	H
	CALL	?CONO		
	POP	H
	POP	B
	DJNZ	SENSLP
	LXI	H,CORRECT
	CALL	?PMSG
	LDA	ERRCODE		; RESTORE ERROR CODE
	RET
ADJUST:
	XRA	A
	RLD
	CPI	0AH		
	JRNC	SENSLP1		; A-F JUMP
	ORI	30H		; MAKE ASCII CODE
	JR	SENSLP2
SENSLP1:
	SUI	9		; MAKE A-F
	ORI	40H		; MAKE ASCII CODE
SENSLP2:
	MOV	C,A
	PUSH	H
	CALL	?CONO		; SEND DIGIT
	POP	H
	RET


;************************************************
;	DISK SUBROUTINES
;************************************************
SET0:
	BITX	3,0
	JRZ	SET1
	LXI	B,BUFF
	JR	SET2
SET1:
	LBCD	@DMA
SET2:
	SBCD	RBUF
	CALL	LENGTH
	DCX	B
	SBCD	RLEN
	BITX	4,0
	LXI	H,PAR512
	JRNZ	SET3
	BITX	5,0
	LXI	H,PAR2K		
	JRNZ	SET3
	LXI	H,PAR128
SET3:
	LXI	D,DSKN
	LXI	B,4
	LDIR
	XRA	A
	STA	DSKH		; HEAD 0
	LDA	@RDRV		; UNIT
	MOV	C,A
	LDA	@TRK		; TRACK
	MOV	B,A
	SBCD	DSKU
	BITX	1,0
	JRZ     SET9
	BITX	7,0
	MVI	B,40
	JRNZ	SET10
	MVI	B,77
SET10:
	SUB	B
	JRC	SET9
	MOV	B,A
	SBCD	DSKU
	MVI	A,1
	STA	DSKH
SET9:
	LDA	@SECT		; SECTOR
     	STA	DSKS	
SET4:
	LXI	H,4000H		; NOT READY COUNTER
SET5:
	PUSH	HL
	MVI	C,04H
	CALL	CMDOUT
	LDA	DSKU
	MOV	C,A
	CALL	CMDOUT
	CALL	NEXT
	STA	DRVST 
   	BIT	5,A
	POP	HL
	JRNZ	SET6 
	DCX	H
	MOV	A,H
	ORA	L
	JRNZ	SET5 
	LXI	H,DNRDY
	CALL	ERRMES
	CPI	'Y'
	JRZ	SET4
	JMP     ?WBOOT
SET6:
	BITX	0,0		; TEST FOR 8"
	JRNZ	SET8
	XRA	A		; CLOCK FOR 8"
	OUT 	DRIVE
	JR	SET7
SET8:
	MVI	A,1		; SET 5" DRIVE
	OUT	DRIVE
SET7:
	INR	A
	JRNZ	SET7 

;************************************************
SEEK:
;       MOVE HEAD TO TRACK GIVEN BY "DISKT"
;************************************************
     	LXI	B,030FH		; SEEK TRACK
	CALL	EXEC 
	XRA	A
	
;************************************************
SENS:
;       SEEK FINISHED ?
;************************************************
     	MVI	C,08    	; SENSE INTERRUPT
	CALL	CMDOUT 
	CALL	NEXT		; FETCH RESULT
	MOV   	B,A		; SAVE RESULT
	CPI 	080H
	CNZ     NEXT
	BIT	5,B		; SEEK FINISHED ?
	JRZ	SENS		; NO 
	RET			; YES

;************************************************
;	RESTORE HEAD
;************************************************
RESTORE:
	CALL	TRK0
	JMP  	SEEK


;************************************************
;	RECALIBRATE HEAD
;************************************************
TRK0:
	MVI	C,07H
	CALL	CMDOUT
	LDA	DSKU
	ANI	03H
	MOV	C,A
	CALL	CMDOUT
	JMP     SENS
	
;************************************************
MOVE:   ;TRANSFERS INVERTED DATA
;************************************************
	CALL	LENGTH
MOVE001:
	MOV	A,M
	CMA
	STAX	D
	INX	H
	INX	D
	DCX	B
	MOV	A,B
	ORA	C
	JRNZ	MOVE001
	RET

;************************************************
LENGTH: ;DEFINE LENGTH OF FORMAT
;************************************************
	BITX	4,0
	LXI	B,512
	RNZ
	BITX	5,0
	LXI	B,2048
	RNZ
	LXI	B,128
	RET



;************************************************
RDDATA:
;       READ PHYSICAL SECTOR FROM DISK
;       RETURNS WITH:  Z = NO ERRORS
;       AND: NZ = READ ERROR
;************************************************
	LXI	B,CRLEN*256+DMA ; C = DMA, B = CMD-LENGTH
	LXI	H,CRDT
	OUTIR			; DMA READ FROM DISK
	MVI	A,06H    	; READ
	BITX	2,0
	JRZ	RD1
	ORI	40H		; DOUBLE DENSITY
RD1:
	MOV	C,A
	MVI	B,9		; PARAMETER COUNT
    	JMP  	EXEC


;************************************************
RESULT:
;       FETCH RESULTS OF READ/WRITE OPERATION
;       AND CHECK THEM FOR R/W-ERRORS
;       RETURNS WITH: Z & A=0, IF NO ERRORS
;       AND WITH: NZ & A=? IF ANY ERROR
;************************************************

	LXI	H,RESTAB
	MVI	B,07H		; RESULT COUNT
 RES01:
	CALL	NEXT
	MOV	M,A		; STORE RESULT BYTE
	INX	H
	DJNZ	RES01 
	RET



;************************************************
ERRMES:	
;************************************************
	CALL	?PMSG		; SEND MESSAGE
	RET

;************************************************
TERMI:	
;       INTERUPT SERVICE ROUTINE
;************************************************
	OUT 	FTC		; TERMIN. UPD 765
	PUSH	PSW
	MVI	A,0C3H		; RESET DMA-LOGIC
	OUT 	DMA
	POP	PSW
	EI			
	RETI			


;************************************************
EXEC:	
;       TRANSMITS COMMAND TO FD-CONTROLLER
;************************************************
	LXI	H,DSKU
	PUSH	H
	LDA	DSKH
	ORA	A
	JRZ	EXEC2
	SETB	2,M
EXEC2:
	LXI	H,CMDTAB	; POINT TO COMMANDTABLE
EXEC1:	
	CALL    CMDOUT
	INX	H		; POINT TO NEXT BYTE
	MOV	C,M
	DJNZ	EXEC1		; SEND NEXT BYTE
	POP	H
	RES	2,M
 	RET			; ALL BYTES TRANSFERRED


;************************************************
CMDOUT:
;	TRANSMIT 1 BYTE TO THE UPD765
;************************************************
	IN	FDC
	BIT	7,A
	JRZ	CMDOUT
	BIT	6,A
	JRZ	CMDOUT1
	IN	FDD
	JR	CMDOUT
CMDOUT1:
	MOV	A,C
	OUT	FDD
	RET



;************************************************
NEXT:	
;       READ NEXT RESULT-BYTE FROM FD-CONTROLLER
;       DESTROYES: AF
;************************************************
	IN	FDC
	ANI	0C0H
	CPI   	0C0H
	JRNZ	NEXT
	IN	FDD		; YES : FETCH RESULT
	RET


;************************************************
;	MOVE
;************************************************
?move:
	XCHG	
	LDIR		; use Z80 block move instruction
	XCHG
	ret

;************************************************
;	ERROR - MESSAGES 
;************************************************
DNRDY:  DB	0DH,0AH,7,'DISK DRIVE NOT READY',0DH,0AH,00
NLMSG:	DB	0DH,0AH,00

RDMSG:	DB	0DH,0AH,'READ  OPERATION  ',00
SENSMSG:
	DB	0DH,0AH,'SENSE BYTE FROM info-s FDC ',00
CORRECT:
	DB	08H,' ',0DH,0AH,00

;************************************************
;       Error message components
;************************************************
drive$msg	db	0CH,0AH,07,'BIOS Error on ',0
track$msg	db	': T-',0
sector$msg	db	', S-',0

;************************************************
;       disk communication data items
;************************************************
@adrv	ds	1		; currently selected disk drive
@rdrv	ds	1		; controller relative disk drive
@trk	ds	2		; current track number
@sect	ds	2		; current sector number
@dma	ds	2		; current DMA address


;************************************************
;	COMMAND-TABLES FOR DMA CONTROLLER
CRDT:	
;       DMA READ FROM DISK
;************************************************
	DB	83H,0C3H,79H
RBUF:	DW	00   
RLEN:	DW	128-1		; RECORD LENGHT
	DB	54H,0C8H,68H,0CCH,95H
RIO:	DB	FDD
	DB	12H
LIVR:	DB	00H
	DB	8AH,0CFH,0ABH,87H
CRDE:
CRLEN	EQU	CRDE-CRDT


;************************************************
;	PHYSICAL DISK PARAMETER
;************************************************
CMDTAB:	DB	0		; COMMAND-TABLE
DSKU:   DB	0		; PHYS. UNIT
DSKT:	DB	0  		; PHYS. TRACK 
DSKH:   DB	0		; PHYS. HEAD
DSKS:	DB	0      		; PHYS. SECTOR
DSKN:	DB	0
DSKEOT:	DB	26
DSKGPL:	DB	7
DSKDTL:	DB	128
 

;************************************************
RESTAB:
;	RESULT TABLE
;************************************************
	DB	0		; ST0
	DB	0		; ST1   
	DB	0		; ST2
	DB	0		; CYLINDER (TRACK)
	DB	0		; HEAD
	DB 	0		; RECORD (SECTOR)
	DB	0		; N (LENTGH)

;************************************************
ERRCNT:
;	RETRY COUNT
;************************************************
	DB	00
	DB	00    		; DUMMY BYTE
;************************************************
DRVST:	DB	00

ERRCODE:
	DB	00,00
SAVE:
	DW	0000
;************************************************
PAR128:	DB	0,26,7,128
PAR512:	DB	2,26,1BH,0FFH
PAR2K:	DB	4,4,99H,0FFH

BUFF:	DS	512      	; READ WRITE BUFFER 

INTVEC:
	DW	0,0,0,0,0,0,0,0
DIRBUF:	DS	512
DATBUF: DS   	512
	END

    