TITLE	'WINCHESTER BIOS FOR CPM 3'
	VER EQU  280


;	Version 1.1 has cache on, burst mode used, DMA
;	for disk reads and writes.
	
;	Version 1.0 initialized from hbw8.azm  5/9/89 
;

MACLIB	Z80
MACLIB	Z280
MACLIB	CPM3

; ###############################################


PUBLIC	BOOT
PUBLIC	WBOOT
PUBLIC	CONST
PUBLIC	CONIN
PUBLIC	CONOUT
PUBLIC	LIST
PUBLIC	AUXOUT
PUBLIC	AUXIN
PUBLIC	HOME
PUBLIC	SELDSK
PUBLIC	SETTRK
PUBLIC	SETSEC
PUBLIC	SETDMA
PUBLIC	READ
PUBLIC	WRITE
PUBLIC	LISTST
PUBLIC	SECTRAN
PUBLIC	CONOST
PUBLIC	DUMMY
PUBLIC	DRVTBL
PUBLIC	MOVE

PUBLIC @DTBL
PUBLIC ?DRTBL


;
;THE CODE BEGINS HERE:
;THIS IS THE JUMP VECTOR TABLE:
;
CSEG

BIOS:
;
	JMP	BOOT
?WBOOT:	JMP	WBOOT
	JMP	CONST
	JMP	CONIN
	JMP	CONOUT
	JMP	LIST
	JMP	AUXOUT
	JMP	AUXIN
	JMP	HOME
	JMP	SELDSK
	JMP	SETTRK
	JMP	SETSEC
	JMP	SETDMA
	JMP	READ
	JMP	WRITE
	JMP	LISTST
	JMP	SECTRAN
	JMP	CONOST
	JMP	DUMMY
	JMP	DUMMY
	JMP	DUMMY
	JMP	DUMMY
?DRTBL:	JMP	DRVTBL
	JMP	MULTIO
	JMP	FLUSH
	JMP	MOVE
	JMP	DUMMY
	JMP	DUMMY
	JMP	DUMMY
	JMP	DUMMY
	JMP	DUMMY
	JMP	DUMMY
	JMP	DUMMY
;
;
FLETTER EQU  'C'
FLOPPY EQU 	FLETTER - 'A'
;
@DTBL:
	DTBL	<WDPH0, WDPH1, FDPH, WDPH2, WDPH3, WDPH4>



FDPH:	DPH	FTRANS,FDPB

	DW	FTRANS		;FLOPPY DISK PARAMETER HEADER
	DB	0,0,0,0,0,0,0,0,0
	DB	0		;MEDIA FLAG
	DW	FDPB		;DISK PARAMETER BLOCK
	DW	0FFFEH		;CHECKSUM VECTOR
	DW	0FFFEH		;ALLOCATION VECTOR
	DW	0FFFEH		;DIR BUFFER CONTROL BLOCK (NOT ALLOCATED)
	DW	0FFFFH		;DATA BUFFER CONTROL BLOCK (NONE)
	DW	0FFFEH		;HASH TABLE (NOT ALLOCATED)
	DB	0		;HASH BANK

FTRANS:	SKEW	26,6,1		;STANDARD SSSD FLOPPY SKEW

FDPB:	DPB	128,26,77,1024,64,2	;STANDARD SSSD DISK PARAMETER BLOCK


WDPH0:	DPH	0000H, WDPB0, 0
WDPB0:	DPB	512, 16, 303+2, 2048, 640, 2, 8000H

WDPH1:	DPH	0000H, WDPB1, 0
WDPB1:	DPB	512, 16, 303+305, 2048, 640, 305, 8000H

WDPH2:	DPH	0000H, WDPB2, 0
WDPB2:	DPB	512, 16, 303+608, 2048, 640, 608, 8000H

WDPH3:	DPH	0000H, WDPB3, 0
WDPB3:	DPB	512, 16, 303+911, 2048, 640, 911, 8000H

WDPH4:	DPH	0000H, WDPB4, 0
WDPB4:	DPB	512, 16, 303+1214, 2048, 640, 1214, 8000H



DUMMY:	RET


;
BOOT:	
	LXI	SP,TEMPSTACK

;
; TURN OFF THE CLOCK INTERRUPT
;
	DI
	XRA	A
	OUT	0F1H
	IN	0F0H
;
	MVI	A,0
	STA	BUFCNT
;
	MVI	A,98H
	OUT	87H		;INITIALIZE PARALLEL PRINTER PORT
	MVI	A,0FFH
	OUT	86H
	OUT	85H		;MAKE OUTPUT LINES HIGH
;
;	CALL	WRESET		;RESET WINCHESTER CONTOLLER
;
;
; Initialize the trap/vector table entry for interrupt line A
	
	LXI	H, 0000
	SHLD	0008H
	LXI	H, INTRES
	SHLD	000AH

; Set the interrupt/trap vector table pointer to 0000h (logical)
	LXI	H,8000H    ;800000H physical  EQU  0000H logical
	MVI	C,6
	LDCTL

	IM3

	EI		;TURN ON INTERRUPT FOR CONSOLE INPUT
;
	MVI	A,91H	;TURN ON RX INTERRUPTS
	OUT	70H
;
; Turn on the cache
	PCACHE
	LXI	H,0028H	;Turn on cache for code only with burst on upper 8mb
	MVI	C,12H
	LDCTL

; Turn off refresh
	CALL	IOPGFF
	MVI	A,60
	OUT	0E8H	;TURN OFF REFRESH
	CALL	IOPG00

	LXI	H,SIGNON
	CALL	PRMSG	;PRINT SIGN-ON

	CALL	SETJUMPS
	CALL	LOADCCP
	JMP	0100H

;
;
WBOOT:
	LXI	SP,TEMPSTACK
	CALL	SETJUMPS
	CALL	LOADCCP
	JMP	0100H

DRVTBL:
	LXI	H,@DTBL
	RET

MOVE:	XCHG
	LDIR
	XCHG
	RET

MULTIO:
	RET

FLUSH:
	XRA	A
	RET

EXTRN	@MXTPA
SETJUMPS:
	MVI	A,JMP
	STA	0
	STA	5
	LXI	H,?WBOOT
	SHLD	0001
	LHLD	@MXTPA
	SHLD	0006
	RET


;THIS LOADS THE CCP FROM A:CCP.COM

LOADCCP:
	XRA	A
	STA	CCPFCB+15
	LXI	H,0
	SHLD	FCBNR
	LXI	D,CCPFCB
	MVI	C,15
	CALL	0005	;OPEN FILE
	INR	A
	JZ	NOCCP
	LXI	D,0100H
	MVI	C,26
	CALL	0005	;SETDMA
	LXI	D,128
	MVI	C,44
	CALL	0005	;SETMULTI
	LXI	D,CCPFCB
	MVI	C,20
	CALL	0005	;READ FILE
	RET		;ASSUME READ OK

NOCCP:
	LXI	H,CCPMSG
	CALL	PRMSG
	CALL	CONIN
	JMP	LOADCCP	;LOOP; RETRYING

CCPMSG:
	DB	'CANNOT READ A:CCP.COM', 0DH, 0AH, 0

CCPFCB:
	DB	1, 'CCP     ', 'COM', 0,0,0,0
	DS	16
FCBNR:	DB	0,0,0


;
;THIS IS THE INTERRUPT RESPONSE ROUTINE FOR THE CONSOLE INPUT
;

INTRES:	PUSH	PSW	;SAVE REGISTERS
	PUSH	B
	PUSH	D
	PUSH	H
	CALL	PSHIOP
	CALL	IOPG00	;MAKE SURE WE ARE AT I/O PAGE 0
;	
	IN	72H	;SEE IF IT'S FROM UART
	ANI	81H	;CHECK INTERRUPT AND RX FULL BITS
	CPI	81H
	JNZ	?1END	;RETURN IF NOT FROM UART RECEIVER
;
	IN	73H	;GET CHARACTER
	ANI	7FH	;CLEAR BIT SEVEN 
;
	MOV	B,A	;SAVE CHAR
	LDA	BUFCNT
	CPI	BUFMAX
	JNZ	?1A	;IF BUFFER IS FULL, BEEP AND DUMP CHAR
	MVI	C,07
	CALL	CONOUT
	JMP	?1END
;
?1A:	INR	A
	STA	BUFCNT	;INCREMENT BUFFER COUNT
;
	LXI	H,CONBUF-1
	ADD	L
	MOV	L,A
	JNC	?1C
	INR	H	;ADD ACCUM TO HL TO GET ADDRESS OF 
			;TOP OF BUFFER
?1C:	MOV	M,B	;BUT CHAR IN BUFFER
;
?1END:	
	CALL	POPIOP
	POP	H
	POP	D
	POP	B
	POP	PSW	;RESTORE REGISTERS
	INX	SP
	INX	SP	; Pop off "reason code"
	RETIL		; Return from interrupt long
			; (restores previous interrupt enable state) 
;
;
CONST:

	LDA	BUFCNT
	ANA	A	;SEE IF BUFFER COUNT IS ZERO
	RZ		;RETURN WITH ACC = 0 IF SO
	MVI	A,0FFH
	RET		;ELSE 0FFH MEANS SOMETHING IN BUFFER
;
;
CONIN:	CALL	CONST
	ORA	A
	JZ	CONIN	;WAIT FOR A CHARACTER TO ARRIVE
;
	LXI	H,CONBUF
	LXI	D,BUFHED
	LXI	B,BUFMAX  ;SET UP TO SHIFT BUFFER DOWN
	DI		;ENTER CRITICAL SECTION
;
	LDIR		;SHIFT BUFFER
	LXI	H,BUFCNT
	DCR	M	;DECREMENT BUFFER COUNT
	LDA	BUFHED	;GET CHARACTER
;
	EI		;LEAVE CRITICAL SECTION
	RET
;
;
BUFMAX	EQU	32		;LENGTH OF BUFFER
;
BUFCNT:	DB	0	;# OF CHARS IN BUFFER
BUFHED:	DB	0	;PLACE TO SHIFT BUFFER HEAD
CONBUF:	DS	BUFMAX	;INPUT BUFFER



;
CONOST:
	IN	70H
	ANI	02H
	RZ
	MVI	A,0FFH
	RET
;
CONOUT:	IN	70H
	ANI	02H
	JZ	CONOUT
	MOV	A,C
	OUT	71H
; THIS ADDS TWO PAD CHARS AFTER LF'S
	CPI	0AH
	RNZ
	MVI	C,00H	;NULL
	CALL	CONOUT	;RECURSIVE
	CALL	CONOUT
	RET
;
;
LIST:
	RET
;
LISTST:
	RET
AUXOUT:
;	RET
AUXIN:
	RET
;
;
;
;THIS IS USED IN SEVERAL PLACES. IT GIVES
; ( .5 * HL ) MILLISECONDS OF DELAY.
;
DELAY:	MVI	B,154
DELAY1:	DJNZ	DELAY1	;.5 MS DELAY
	DCX	H
	MOV	A,H
	ORA	L
	JNZ	DELAY	;LOOP HL TIMES
	RET
;
;
;
HOME:	LXI	H,0
	SHLD	SEKTRK
	RET
;
;
SELDSK:	
	MOV	A,C
	STA	SEKDSK
	MVI	B,0	;BC HAS DRIVE NUMBER
	LXI	H,@DTBL
	DAD	B
	DAD	B	;INDEX TO POINTER IN DRIVE TABLE FOR DISK
	MOV	A,M
	INX	H
	MOV	H,M
	MOV	L,A
	RET

;
;
SETTRK:	SBCD	SEKTRK
	RET
;
;
SETSEC:	MOV	A,C
	STA	SEKSEC
	RET
;
;
SECTRAN:
	MOV	L,C
	MOV	H,B
	MOV	A,D
	ORA	E
	RZ
	XCHG		;FLOPPY ROUTINE
	DAD	B
	MOV	L,M
	MVI	H,0
	RET
;
;
SETDMA:	SBCD	DMAADR
	RET
;
;
READ:	
	XRA	A
	STA	ERFLAG
	LDA	SEKDSK
	CPI	FLOPPY
	JZ	FREAD
	JMP	HREAD

WRITE:
	XRA	A
	STA	ERFLAG
	LDA	SEKDSK
	CPI	FLOPPY
	JZ	FWRITE
	JMP	HWRITE

;
;THESE ARE 1771 FLOPPY DISK CONTROLLER COMMANDS,
;I/O PORT ADDRESSES, AND FLAG MASKS:
;
RESTOR EQU 	08H	;6MS STEP,LOAD HEAD
SEEK EQU 	18H	;6MS STEP,LOAD HEAD
READC EQU 	88H	;NO HEAD LOAD
WRITEC EQU 	0A8H	;NO HEAD LOAD
RESET EQU 	0D0H	;RESET STATUS COMMAND
STATUS EQU 	80H
COMAND EQU 	80H
TRACK EQU 	81H
SECTOR EQU 	82H
DATA EQU 	83H
BUSY EQU 	01
RDMASK EQU 	10011111B
WRMASK EQU 	0FFH
;
;
;THIS FLOPPY READ ROUTINE CALLS FREAD2. IF THE
;READ IS UNSUCCESSFUL, THE DRIVE IS HOMED,
;AND THE READ IS RETRIED.
;
FREAD:	CALL	FREAD2
	LDA	ERFLAG
	ANA	A	;SET FLAGS
	RZ		;READ WAS OK
	CALL	FHOME
	CALL	FREAD2
	LDA	ERFLAG
	RET
;
FREAD2:	CALL	FWAIT
	LDA	SEKSEC
	OUT	SECTOR
	CALL	FTKSET
	MVI	A,11
FREAD3:	STA 	TRYNUM
	CALL	FWAIT
	LHLD	DMAADR
	MVI	C,DATA
	MVI	B,128
	MVI	D,03
	MVI	A,READC
	DI		;ENTERING CRITICAL SECTION
	OUT	COMAND
	XTHL	;SHORT DELAY
	XTHL
	XTHL
	XTHL	
	XTHL
	XTHL
	XTHL
	XTHL
?1LOOP:	IN	STATUS
	ANA	D
	DCR	A
	JZ	?1LOOP
	INI
	JNZ	?1LOOP
	EI		;LEAVING CRITICAL SECTION
	CALL	FWAIT
	IN	STATUS
	ANI	RDMASK
	JRZ	FR1END
	LDA	TRYNUM
	DCR	A
	JNZ	FREAD3
	MVI	A,1
FR1END:	STA	ERFLAG
	RET
;
;THIS IS THE FLOPPY WRITE ROUTINE. IT CALLS
;THE ACTUAL WRITING SUBROUTINE, AND IF IT
;WAS UNSUCCESSFUL, RESETS THE HEAD AND
;TRIES AGAIN.
;
FWRITE: CALL	FWR2
	LDA	ERFLAG
	ANA	A
	RZ
	CALL	FHOME
	CALL	FWR2
	LDA	ERFLAG
	RET
;
FWR2:	CALL	FWAIT
	LDA	SEKSEC
	OUT	SECTOR
	CALL    FTKSET
FWR4:	MVI	A,11
FWR3:	STA	TRYNUM
	CALL	FWAIT
	LHLD	DMAADR
	MVI	C,DATA
	MVI	B,128
	MVI	D,01
	MVI	A,WRITEC
	DI		;ENTERING CRITICAL SECTION
	OUT	COMAND
?3A:	IN	STATUS
	ANI	01
	JZ	?3A
?3B:	IN 	STATUS
	ANI	02
	JNZ	?2LOOP
	IN	STATUS
	ANI	01
	JZ	??ERROR
	JMP	?3B
?2LOOP:	IN	STATUS
	XRA	D
	JZ	?2LOOP
	OUTI
	JNZ	?2LOOP
	EI		;LEAVING CRITICAL SECTION
	CALL	FWAIT
	IN	STATUS
	ANI	WRMASK
	JRZ	FW2END
??ERROR: LDA	TRYNUM
	DCR	A
	JNZ	FWR3
	MVI	A,1
FW2END:	STA	ERFLAG
	RET
;
;THESE 3 SUBROUTINES ARE USED BY THE FREAD2 AND
;FWR2 ROUTINES:
;
FTKSET:	CALL	FWAIT
	LDA	SEKTRK
	OUT	DATA
	XTHL	
	XTHL
	XTHL
	XTHL
	MVI	A,SEEK
	OUT	COMAND
	XTHL	
	XTHL
	XTHL
	XTHL
	XTHL	
	XTHL
	XTHL
	XTHL
	RET
;
FWAIT:	IN	STATUS
	XTHL	
	XTHL
	XTHL
	XTHL
	ANI	10000001B
	JNZ	FWAIT
	RET
;
FHOME:	CALL	FWAIT
	MVI	A,RESTOR
	OUT	COMAND
	XTHL	
	XTHL
	XTHL
	XTHL
	RET
;
;
;THESE ARE THE DISK READ AND WRITE ROUTINES


DODMA:
	PUSH	H
	DI
	CALL	IOPGFF
	POP	H
	MOV	C,A
	MVI	B,6
?3LOOP:	OUTIW
	INR	C
	INR	B
	DCR	B
	JNZ	?3LOOP
	CALL	IOPG00
	EI
	RET


IOPGFF:	MVI	L,0FFH
	MVI	C,08
	LDCTL            
	RET

IOPG00:	MVI	L,00
	MVI	C,08
	LDCTL
	RET


; THIS PUSHES THE I/O PAGE NUMBER ONTO THE STACK
PSHIOP:
	MVI	C,08
	RDCTL		;GET I/O PAGE #
	XTHL		;EXCHANGE WITH RETURN ADDRESS ON STACK 
	PCHL		;RETURN TO RETURN ADDRESS

POPIOP:
	POP	H	;GET RETURN ADDRESS
	XTHL		;EXCHANGE WITH I/O PAGE VALUE ON STACK
	MVI	C,08
	LDCTL
	RET


; THIS PUTS INTO HL THE HI-ORDER 12 BITS OF THE PHYSICAL ADDRESS SPECIFIED
; BY DMAADR

GETPAD:
	lhld	DMAADR
	mov	a,h
	ani	0f0h
	mov	l,a
	MVI	H,80H	;ALL BUT LAST 8K IS AT 800000H PHYSICAL
	RET


RDPROG:
RDADR:	DW	0000H
	DW	0000H
	DW	WDATA
	DW	0000
RDCNT:	DW	0000
	DW	0E080H

WRPROG:
	DW	WDATA
	DW	0000
WRADR:	DW	0000H
	DW	0000H
WRCNT:	DW	0000
	DW	0808CH

;
;
;THESE ARE THE HARD DISK READ AND WRITE ROUTINES.
;THEY READ AND WRITE A 512 BYTE SECTOR TO AND
;FROM THE BUFFER.
;
;
WDATA EQU 	0D8H
WCMD EQU 	0D9H
WREAD EQU   08H
WWRITE EQU  0AH
;
HREAD:
	MVI	A,WREAD
	CALL	COMCODE
;
;SETUP DMA CONTROLLER

	; FILL IN THE DMA PROGRAM WITH THE CORRECT ADDRESS AND LENGTH
	LHLD	DMAADR
	mov	a,h
	ani	0fh
	mov	h,a
	SHLD	RDADR
	CALL	GETPAD
	SHLD	RDADR+2
	LHLD	DLEN
	SHLD	RDCNT
;
	;SEND PROGRAM TO DMA CONTROLLER
	MVI	A,08
	LXI	H, RDPROG
	CALL	DODMA

;
	JMP	WCHECK

;
;
HWRITE:
	MVI	A,WWRITE
	CALL	COMCODE

;SETUP DMA CONTROLLER

WIO:
	LHLD	DMAADR
	SHLD	WRADR
	CALL	GETPAD
	SHLD	WRADR+2
	LHLD	DLEN
	SHLD	WRCNT
;
	MVI	A,08
	LXI	H,WRPROG
	;SEND PROGRAM TO DMA CONTROLLER
	CALL	DODMA	
	JMP	WCHECK

;
; COMMON CODE FOR WINCHESTER READ OR WRITE
;
COMCODE:
	STA	CMDBLK+0	;STORE OPCODE
;	LDA	SEKDSK		;USE LUN 0 FOR A,B,D,E
;	CPI	5
	MVI	A,0
;	JC	?1CCA
;	ORI	20H		;USE LUN 1 FOR F AND G
?1CCA:	STA	CMDBLK+1	;SELECT LUN
	XRA	A
	STA	CMDBLK+5
	MVI	A,1		;USE 512 BYTE SECTORS FOR F AND G ON LUN 1
	STA	CMDBLK+4	;TRANSFER COUNT
	CALL	WFREE

	LHLD	SEKTRK
	DAD	H
	DAD	H
	DAD	H
	DAD	H	;MULTIPLY SEKTRK BY 16
;
	LDA	SEKSEC
	MOV	E,A
	MVI	D,0
	DAD	D	;ADD IN SECTOR TO GET BLOCK # (FOR 512 BYTE BLOCKS)
;
	MOV	A,H	;PLACE IN COMMAND BLOCK
	STA	CMDBLK+2
	MOV	A,L
	STA	CMDBLK+3
;
	CALL	SELECT	;SELECT CONTROLLER
	LXI	H,CMDBLK
	MVI	B,6
?5LOOP:	CALL	WWAIT
	MOV	A,M
	OUT	WDATA
	INX	H
	DCR	B
	JNZ	?5LOOP
;	
	CALL	WWAIT	
	IN	WCMD	;SEE IF IT REALLY WANTS DATA
	ANI	10H
	RNZ
	MVI	A,1
	STA	ERFLAG
	LXI	H,SEQMSG
	CALL	PRMSG
        CALL	WCHECK	;EAT STATUS BYTES
	POP	H	;EAT RETURN ADDRESS
	CALL	NLINE
	RET		;RETURN FROM READHST OR WRITEHST	
;
CMDBLK:	DB	0,0,0,0,1,0
;
;
; THIS SELECTS THE CONTROLLER
;
SELECT:	MVI	A,1
	OUT	WDATA
	OUT	WCMD	;ASSERT SELECT
?5A:	IN	WCMD	;WAIT FOR BSY TO BE ASSERTED
	ANI	01
	JNZ	?5A
	XRA	A
	OUT	WCMD	;DEASSERT IT
	CALL	WWAIT	;WAIT FOR REQ
	RET
;
;
; THIS DOES A REQUEST SENSE COMMAND
RDERR:
?6A:	IN	WCMD	;WAIT FOR BSY TO BE DEASSERTED
	ANI	01
	JNZ	?5B
	IN	WDATA
	JMP	?6A
?5B:
	CALL	SELECT
	LXI	H,ERRBLK
;
	LDA	SEKDSK		;USE LUN 0 FOR A,B,D,E
	CPI	5
	MVI	A,0
	JC	?1REA
	ORI	20H		;USE LUN 1 FOR F AND G
?1REA:	STA	ERRBLK+1	;SELECT LUN
;
	MVI	B,6
?7LOOP:
	CALL	WWAIT
	MOV	A,M
	OUT	WDATA
	INX	H
	DCR	B
	JNZ	?7LOOP
; READ IN 4 SENSE BYTES PLUS STATUS AND MESSAGE
	LXI	H,ERSTAT
	MVI	B,6
?1L2:
	CALL	WWAIT
	IN	WDATA
	MOV	M,A
	INX	H
	DCR	B
	JNZ	?1L2
	LDA	ERSTAT
	CPI	98H	;SEE IF CORRECTABLE ERROR
	RNZ
	LXI	H,CORMSG
	CALL	PRMSG
	XRA	A
	STA	ERFLAG	;FORGET ABOUT ERROR
	RET
;
CORMSG:	DB	'CORRECTED ', 0
;
;
ERRBLK:	DB	3,0,0,0,4,0
ERSTAT	 EQU  0FFFAH	;ERROR STAT IN LAST 6 BYTES OF MEMORY
;
; THIS READS IN THE STATUS AND MESSAGE BYTES
;
WCHECK:
?8LOOP:
	CALL	WWAIT	;WAIT UNTIL THE CONTROLLER WANTS TO SEND STATUS
	IN	WCMD
	ANI	00011000B
	JNZ	?8LOOP
;
	; TODO ;TURN OFF DMA CONTROLLER
	CALL	WWAIT
	IN	WCMD
	ANI	00011011B
	JZ	?1OK
	LXI	H,DMSG
	CALL	PRMSG
	MVI	A,1
	STA	ERFLAG
	JMP	?7B
?1OK:	IN	WDATA
	ANA	A
	JRZ	?9A
	MVI	A,1
	STA	ERFLAG
	LXI	H,STATMSG
	CALL	PRMSG
?9A:
	CALL	WWAIT
	IN	WDATA	;READ FINAL MESSAGE BYTE
;
?7B:	LDA	ERFLAG
	ANA	A
	RZ
	CALL	RDERR
	CALL	NLINE
	RET
;
SEQMSG:	DB	'DOESNT WANT DATA ', 0
STATMSG: DB	'BAD RETURN STATUS ', 0
DMSG:	DB	'DOESNT HAVE STATUS ', 0
;
; THIS WAITS FOR REQ TO BE ASSERTED:
;
WWAIT:
	IN	WCMD
	ANI	01
	JNZ	?AA	;JUMP IF NOT EVEN BUSY
	IN	WCMD
	ANI	22H   ;MASK OUT REQ AND MAKE SURE ACK FROM LAST CYCLE IS GONE
	JNZ	WWAIT
	RET
?AA:	
	LXI	H,BSYMSG
	CALL	PRMSG
	MVI	A,1
	STA	ERFLAG
	RET
;
BSYMSG:	DB	'CONTROLLER SHUT OFF ', 0
;
WRESET:
	MVI	A,2
	OUT	WCMD
	XTHL
	XTHL
	XTHL
	XTHL
	XRA	A
	OUT	WCMD
	RET
;	
WFREE:	IN	WCMD
	ANI	1FH
	CPI	1FH
	JNZ	WFREE
	RET
;
;
;
; THIS PRINTS A TEXT STRING TERMINATED BY 00H:
;
PRMSG:	MOV	A,M
	ORA	A
	RZ
	PUSH	H
	MOV	C,A
	CALL	CONOUT
	POP	H
	INX	H
	JR	PRMSG
NLINE:
	LXI	H,NLMSG
	JR	PRMSG
;
NLMSG:	DB	0DH,0AH,0
;
;
;
SIGNON: DB  'CP/M 3 BIOS FOR Z280 V1.0', 0DH, 0AH, 0
;
;
TRYNUM:	DS	1
;
SEKDSK: DS   1
SEKTRK:	DS	2	
SEKSEC:	DS	1	
;
ERFLAG:	DS	1	;DISK ERROR FLAG
DMAADR:	DS	2
DLEN:	DW	512	;FOR SINGLE-SECTOR I/O
;

; TEMPORARY STACK FOR WARM AND COLD BOOT
	DS	64
TEMPSTACK EQU     $


BIOSIZ EQU 	$ - BIOS
;
END
