	TITLE	DISK BOOTSTRAP DRIVER II
	LIST	NOCOND
;*************************************************************
;
;	DISK CONTROLLER BOOTSTRAP DRIVER
;
;	FOR M5B WITH ZMON MONITOR.
;	(ALSO WILL WORK STAND-ALONE)
;
;*************************************************************
;
; REVISION STATUS:
;
; 1.0 -	26 FEB 81, Release
; 1.1 -	Fix bug.
; 1.2 -	18 JUL 82, Move DD to high memory, clean up listing.
; 1.3 - 12 FEB 83
;	Add timout if DD not responding, add true recalibrate
;	on boot in case the head is outside track 0.
; 1.4 -	14 FEB 83
;	Make changes for rev C board.
; 1.5 -	23 MAR 83   GRH
;	Fix bug in recal routine to account for phase 1 anded with trk00
;	signal from drive. Causes recal to not work
;
; 1.6 -	3 APR 83   GRH
;	Fix bug in boot routine that assumes the controller window is
;	enabled after requesting it. Found out that if the Z-80 is
;	generating a wait signal, the bus request is never acknowledged!
;	Solution is to output the RESET bit along with the request thus
;	yanking the processor out of it's sleep.
;
; 2.0 -	18 MAR 84   GRH
;	Added hard disk boot option and boot command source disk option.
;
; 2.1 -	18 APR 85   GRH
;	Fix problem with hard disk boot from drive 1. Needs logon. Also
;	Also allow boot from 2nd platter.
;		code	logical	physical
;		42	A	DRIVE 0 HEAD 0
;		52	B	DRIVE 0 HEAD 2
;		62	C	DRIVE 1 HEAD 0
;		72	D	DRIVE 1 HEAD 2
;
VERSN	EQU	'21'
;
;*************************************************************
	SUBTTL	DECLARATIONS
;
;   COMPILE TIME VARIABLES
;
FALSE	EQU	0
TRUE	EQU	NOT FALSE

DEBUG	EQU	FALSE

REV	EQU	'C'			;BOARD REVISION LEVEL
LSTINC	EQU	FALSE			;CONDITIONAL FOR INCLUDE FILE LISTING
;*INCLUDE	MONBOARD.DEF
;*INCLUDE	JDDCONT.DEF
;*INCLUDE	JDDLOC.DEF
;*INCLUDE	ISASI.DEF
	LIST	OFF
*INCLUDE	MONBOARD.DEF
*INCLUDE	JDDCONT.DEF
*INCLUDE	JDDLOC.DEF
*INCLUDE	ISASI.DEF
	LIST	ON
;
;	MEMORY LOCATIONS:
;
	ORG	DTEMP + 1
ARGSAV	DS	1		;ARGUMENT SAVE BYTE
BIOSLN	DS	2		;BIOS LENGTH SAVE
BIOSNT	DS	2		;BIOS ENTRY
BIOSCNT	DS	1		;SECTOR COUNT
ARG2	DS	2		;LOAD ARGUMENT FOR DEBUG

LOGINBY	EQU	0004H		;CP/M CURRENT DRIVE & USER BYTE
IOPB	EQU	005CH		;USE DEFAULT FCB AS IOPB AREA
DEFBFR	EQU	0080H		;USE CPM DEFAULT BUFFER FOR BIOS SECTOR 1
PROMST:	EQU	0F800H
XOVER:	EQU	PROMST + 30H	;ROM CROSS-OVER POINT
PROMSIZ	EQU	2048		;SIZE OF THIS PROM FOR CODE CHECKING

;
;   CONSTANTS
;
BIOSSEC	EQU	13		;START SECTOR OF BIOS
HNGTMO	EQU	5			;HANGUP TIMOUT
SECSIZ	EQU	128
NMINT	EQU	66H
;
LF:	EQU	0AH
CR:	EQU	0DH

STPOC	EQU	BCDSE + BCDR0		;STEP IN COMMAND
STPIC	EQU	STPOC + BCDAS		;STEP OUT COMMAND

	SUBTTL	MAIN PGM
	ORG	PROMST
;---------------------------------
;
;	STAND-ALONE ENTRY VECTOR
;
;---------------------------------
BOOTS:
	JP	COLD			;BOOT VECTOR


;
;	PUT VERSION # AT START OF PROM FOR VERIFICATION
;
	DB	HIGH VERSN,'.',LOW VERSN

COLD:	DI			;DISABLE ROM IMAGE
	LD	HL,0		;WAIT TO SETTLE
RESWT:	DEC	HL
	LD	A,L
	OR	H
	JR	NZ,RESWT
	OUT	(COLDRES),A

	LD	SP,DEFBFR	;SET UP COLD STACK
	LD	C,0		;SELECT OPTIONS
	JR	BEGIN
;
;	POSITION SWAP RETURN CODE TO MATCH CALLER
;
	DS	XOVER - $		;POSITION CODE

;--------------------------------------
;
;	SWAP ROMS TO RETURN TO CALLER
;
;--------------------------------------
DKRET:	LD	A,XMONROM		;SELECT MONITOR FOR RETURN
	NOP				;ALIGN NEXT INSTRUCTION
	OUT	(ROMSEL),A
;	MONITOR ROM CONTINUES EXECUTION NOW

;---------------------------------------------------------------
;
;	BOOT CALLER HAS SWAPPED ROMS & STARTS EXECUTING HERE.
;	ENTRY-	C= ARGUMENTS
;
;---------------------------------------------------------------
BEGIN:
	LD	A,C		;CHECK OPTIONS
	LD	(ARGSAV),A	; SAVE ARGS

;======================================
;
;	1ST GET THE FDC VARS
;
;======================================
	IN	A,(DDPORT)		;GET BOARD STATUS
	AND	DDSASW			;COMPUTE BOARD ADDR
	RLCA
	OR	DDBASE SHR 8
	LD	H,A	
	LD	L,0
	LD	(DADDR),HL		;STORE ADDR

	LD	A,DDSHLT		;STORE HALT FLAG FOR BIOS USE
	LD	(DMASK),A
	LD	(DTEMP),A		;SET REPEAT FLAG = NZ

;======================================
;
;	NOW VECTOR TO DISK BOOT ROUTINE
;
;======================================
	LD	A,(ARGSAV)
	AND	0F0H
	CP	40H		;IF HARD DISK THEN GO DO HARD
	JP	NC,HBOOT

	SUBTTL	JADE BOOT
;*************************************************************
;
;   The system bootstrap driver is one of two modules that
;   make up the system resident bootstrap. This module is
;   to be executed by the system processor.
;   During execution, this module performs a block move
;   of the second module (Boot Injection Module) into
;   the Double D controller memory. A successful boot
;   operation by the Double D will leave DCM in bank 0 and
;   BIOS in bank 1. The remainder of this module then moves
;   the BIOS image to the proper system address & jumps to
;   the BIOS cold start entry point.
;
;*************************************************************
;
;   INJECT BOOT MODULE INTO CONTROLLER
;   V 1.6 MOD TO RESET THE PROCESSOR TOO
;
INJECT:	LD	A,DDMB0 + DDBGN		;REQUEST DD MEMORY BANK 0
	OUT	(DDPORT),A
	LD	BC,IMSZE		;SET SIZE
	LD	DE,(DADDR)
	LD	HL,IMADR
	LDIR
;
;   RESET & START THE DISK PROCESSOR
;
	LD	A,DDBGN
	OUT	(DDPORT),A		;ISSUE CMD
	EX	(SP),HL	   		;WASTE SOME TIME FOR DD TO CATCH UP
	EX	(SP),HL
;
;   WAIT FOR TASK COMPLETION OR TIMEOUT
;
	LD	HL,HNGTMO		;SET TIMEOUT VALUES
	LD	BC,0
WAIT:	DEC	BC
	LD	A,C			;IF TIMED OUT THEN ABORT
	OR	B
	JR	NZ,WAIT2

	DEC	L
	OR	L
	SCF
	JP	Z,ABORT

WAIT2:	IN	A,(DDPORT)		;INPUT DD STATUS
	AND	DDSHLT			;IF NOT HALTED THEN WAIT
	JR	NZ,WAIT
;
;   SWITCH CONTROLLER MEMORY INTO SYSTEM BUS
;
	LD	A,DDMRQ			;REQUEST MEMORY BANK 0
	OUT	(DDPORT),A
;
;   CHECK FOR BOOT MALFUNCTION
;
	LD	IX,(DADDR)
	LD	BC,DDCBO		;ADD OFFSET TO IO BLOCK
	ADD	IX,BC
	LD	A,(IX + PBSTATO)	;ERROR CODE OFFSET
	JP	NZ,BADLD
;
;   MOVE FROM DISK MEMORY
;
	LD	E,(IX + PBST1O)		;SET ADDR PTR
	LD	D,(IX + PBST2O)		;GET START ADDR OF BIOS

;	GET BIOS SIZE

	LD	C,(IX + PBST3O)
	LD	B,(IX + PBST4O)
	PUSH	DE			;USE AS JUMP ADDR
	LD	HL,1024			;IF SIZE > 1024 THEN SAVE EXCESS
	OR	A
	PUSH	BC
	PUSH	HL
	POP	BC
	POP	HL
	SBC	HL,BC
	PUSH	HL			;SAVE ANY REMAINDER
	PUSH	AF			;SAVE FLAGS
	JR	C,LT1K			;IF CRY THEN < 1K

	LD	BC,1024
	JR	MOVE1K
;
LT1K:	ADC	HL,BC			;RESTORE COUNT
	PUSH	HL
	POP	BC
MOVE1K:
	LD	A,DDMB1			;SWITCH TO MEMORY BANK 1
	OUT	(DDPORT),A
	LD	HL,(DADDR)
	LDIR
	POP	AF
	POP	HL

NXTSEC:	JR	C,BTFINIS		;IF BIOS_SIZ <= 1024 THEN EXIT
	JR	Z,BTFINIS

	PUSH	HL			;EXCESS BYTE COUNT
	PUSH	DE			;LOAD PTR TO NEXT LOAD BYTE
	LD	A,DDMRQ			;MAKE SURE IT'S READ COMMAND
	OUT	(DDPORT),A
	LD	A,DDRDS
	LD	(IX + PBCMDO),A
	LD	A,DDEXC			;START COMMAND
	OUT	(DDPORT),A
	EX	(SP),HL			;ROTATE THUMBS
	EX	(SP),HL

	LD	HL,HNGTMO		;SET UP TIMOUT
	LD	BC,0
DKWAIT:	DEC	BC			;IF TIMOUT THEN ABORT
	LD	A,C
	OR	B
	JR	NZ,DKW2

	DEC	L
	OR	L
	SCF				;RETURN ERROR TO CALLER
	JR	Z,ABORT

DKW2:	IN	A,(DDPORT)		;IF NOT DONE THEN WAIT
	AND	DDSHLT
	JR	NZ,DKWAIT

	LD	A,DDMRQ			;IF ERROR THEN EXIT
	OUT	(DDPORT),A
	LD	A,(IX + PBSTATO)
	JR	NZ,BADLDP

	LD	A,DDMB1
	OUT	(DDPORT),A
	LD	HL,(DADDR)		;MOVE SECTOR DOWN
	POP	DE			;LAST BYTE PTR
	LD	BC,SECSIZ
	LDIR
	INC	(IX + PBSECO)		;NEXT SECTOR
	POP	HL			;COUNT = COUNT - SECSIZ
	LD	BC,SECSIZ
	OR	A
	SBC	HL,BC
	JP	NXTSEC

;----------------------------
;
;   TRANSFER CONTROL TO OS
;  OS ENTRY IS ON STACK
;
;----------------------------
BTFINIS:
	LD	A,DDOUT			;REMOVE DD FROM MEMORY MAP
	OUT	(DDPORT),A
	RET

;----------------------------
;
;   ERROR HAS BEEN DETECTED
;
;----------------------------
BADLDP:	POP	DE			;BALANCE STACK
	POP	HL
	POP	HL
BADLD:
	RLCA				;IF DISK NOT READY THEN RETURN NC
	CCF
;
;	TIMOUT ENTRY (EXIT?) POINT
;
ABORT:	LD	A,DDOUT		      ;REMOVE DD FROM MEMORY MAP BEFORE RETURN
	OUT	(DDPORT),A
	JP	DKRET

	SUBTTL	BOOTSTRAP INJECTION MODULE
;*********************************************************
;
;   The bootstrap injection module is downloaded into the
; Double D memory by the previous system bootstrap driver.
; The module then reads in the disk controller module (DCM)
; from track 0.
; The origin of this program is fixed, as it is assembled to
; execute inside the Double D. 
; NOTE: Step timing and motor turn-on delays are defined in 
; this module. Patching may be required.
;
;*********************************************************
;
;	THIS PART IS DESIGNED TO EXECUTE FROM LOCATION 0 OF THE
;  DISK CONTROLLER. ALL ABSOLUTE ADDRESSES MUST BE BIASED WITH
;  NAME - IMADR.
;
;************************************************************
;
;   SET STACK, START DRIVE MOTOR & SET INVERT SWITCH (C)
;
IMADR	EQU	$
	LD	SP,BANK1

	IN	A,XPMTX			;TURN ON MOTOR

	LD	C,0			;ASSUME 1793
	IN	A,(BLSTS)		;GET STATUS
	AND	BSUS0			;TEST USER SWITCH 0
	JR	NZ,SELECT		;GOTO SELECT DRIVE

	LD	C,0FFH			;1791-01 INVERTS DATA BUS

;
;   CLEAR 179X INTERRUPT & SELECT DRIVE 0
;
SELECT:	
	CALL	STATUS - IMADR		;179X FORCED CLEAR
	LD	A,BCDSE + BCDR0 + BCDAS	;DRIVE 0 ENABLED & DIRECTION IN
	OUT	(BLCTL),A		;OUTPUT CONTROLS
;
;	RC: CHECK DRIVE READY
;
	CALL	STATUS - IMADR
	LD	(8000H + DDCBO + PBSTATO),A		;PASS BACK TO SYSTEM
	AND	DMDNR
	XOR	A
	JP	NZ,ERHLT - IMADR	;IF NOT READY THEN HALT
;
;	PERFORM RECAL BY STEPPING IN UNTIL NOT 0 OR MAX TIMES THEN SEEKING
;  TRACK 0. MODIFIED TO REQUIRE 2 CONSECUTIVE STEPS WITH NO TRACK 0.
;
	LD	L,NBTRK			;MAX # STEPS = # TRACKS

RECAL:	DEC	L			;IF MAX STEPS THEN ABORT
	JP	Z,ERHOM - IMADR

	CALL	STEPIN - IMADR		;STEP IN 1

	CALL	STATUS - IMADR		;IF ON TRK 0 THEN STEP IN UNTIL NOT 0
	AND	DMTK0
	JR	NZ,RECAL

	DEC	L
	JP	Z,ERHOM - IMADR

	CALL	STEPIN - IMADR		;STEP IN AGAIN

	CALL	STATUS - IMADR		;IF 2ND STEP TRK 0 THEN NOT FOUND TRK 1
	AND	DMTK0
	JR	NZ,RECAL

;
;   POSITION HEAD TO TRK 0
;
HOME:	
	LD	L,NBTRK			;SET MAX TRKS

STEP:	CALL	STATUS - IMADR		;GET 179X STATUS
	AND	DMTK0			;IF TRK 0 THEN DONE
	JR	NZ,TRACK0

	DEC	L			;IF LAST TRACK THEN ERROR
	JP	Z,ERHOM - IMADR

	CALL	STEPOT - IMADR		;STEP OUT UNTIL TRK 0
	JR	STEP

;
;   LOAD HEAD ON SELECTED DRIVE
;
TRACK0:	
	LD	A,C			;GET TRK 0 VALUE
	OUT	(WDTRK),A			;SET TRACK REGISTER
	OUT	(WDDTA),A			;SEEK SAME TRACK
	LD	IY,RDSET - IMADR	;SET NMI RETURN ADDR
	LD	A,DCHDL			;OUTPUT HEAD LOAD COMMAND
	XOR	C			;INVERT DATA
	OUT	(WDCMD),A
	JR	$			;WAIT FOR INTERRUPT

;**************************************
;
;   DISK INTERRUPT VECTOR ROUTINE (NMI)
;
;**************************************
	DS	NMINT + IMADR - $	;PAD LOCATIONS TO NMI ADDR 
;
WDINT:	
	IN	A,(WDSTS)		;GET 179X STATUS
	XOR	C			;INVERT 1791
	LD	(8000H + DDCBO + PBSTATO),A		;MAKE STATUS VISIBLE
	EX	(SP),IY			;PUT RETURN ADDR ON STACK
	RETN

;
;   SET UP FOR DCM READ OPERATION
;
RDSET:
	LD	DE,TMDBR		;DELAY BEFORE READ
	CALL	TIMER - IMADR
	LD	DE,BANKL		;SET LENGTH
	LD	HL,BANK1		;SET LOAD ADDR
	LD	IY,ERRDA - IMADR	;READ ERROR TRAP
	LD	A,DCMSS			;1ST SECTOR OF DCM
	XOR	C			;INVERT
	OUT	(WDSEC),A
	LD	A,DCRMS			;SET READ MULTI-SECTOR CMD
	XOR	C
	OUT	(WDCMD),A
	EX	(SP),HL			;WAIT FOR 179X TO CATCH UP
	EX	(SP),HL
	EX	(SP),HL
	EX	(SP),HL

;
;  ACCEPT EACH BYTE & STORE IN MEMORY
;
RBYTE:	
	IN	A,(XPDSH)		;WAIT FOR DATA
	IN	A,(WDDTA)		;GET & INVERT 1791 DATA
	XOR	C
	LD	(HL),A			;STORE DATA
	INC	HL			;PTR +1
	DEC	DE			;LENGTH -1
	LD	A,D			;IF LENGTH NOT 0 THEN GET NEXT BYTE
	OR	E
	JR	NZ,RBYTE

;------------------------------------------------
;
;   TEST READ STATUS, TERMINATE OPERATION, GO DCM
;
;------------------------------------------------
RTEST:	
	IN	A,(WDSTS)		;GET READ STATUS
	XOR	C
	AND	DMRER AND NOT CSBSY	;IF ERROR THEN GO ERROR
	JR	NZ,ERRDB

	CALL	STATUS - IMADR		;ELSE STOP READ & EXEC. DCM
	JP	DCMBG

;--------------------------------------
;
;	READ ERROR HAS BEEN DETECTED
;
;--------------------------------------
ERRDA:
	LD	A,BERDA			;SET READ ERROR CODE & GO HALT
	JR	ERHLT

;----------------------------
;
;	READ ERROR TYPE B
;
;----------------------------
ERRDB:	
	LD	A,BERDB
	JR	ERHLT

;------------------------------------------------
;
;	COULD NOT FIND TRACK 0 PROPERLY ERROR
;
;------------------------------------------------
ERHOM:
	LD	A,BEHOM			;HOME ERROR CODE

;
;	SET ERROR CODE IN RAM IMAGE & HALT
;
ERHLT:	
	LD	(8000H + DDCBO + PBSTATO),A		;DISPLAY ERROR CODE
	XOR	A
	OUT	(BLSTS),A		;DESELECT DRIVE
	IN	A,(XPMTO)		;MOTOR OFF
	HALT

;*********************************
;
;   GET UPDATED 179X STATUS
;	EXIT -	A= 179X STATUS
;
;*********************************
STATUS:
	LD	A,DCSTS			;TYPE 4 - STATUS
	XOR	C
	OUT	(WDCMD),A
	EX	(SP),HL			;DELAY
	EX	(SP),HL
	EX	(SP),HL
	EX	(SP),HL
	IN	A,(WDSTS)		;GET STATUS
	XOR	C
	RET

;**********************************************
;
;   TIMER - WAIT FOR (DE * 1.0) MILLISECONDS
;
;**********************************************
TIMER:	LD	A,247			;SET LOOP CONSTANT
MSINT:	DEC	A			;INNER LOOP
	JR	NZ,MSINT

	DEC	DE			;IF VALUE -1 = 0 THEN RETURN
	LD	A,D
	OR	E
	JR	NZ,TIMER
	RET


;*********************************
;
;	STEP OUT 1 STEP SUBR
;
;*********************************
STEPOT:	LD	A,STPOC		;ISSUE STEP OUT COMMAND
STEPC:	OUT	(BLCTL),A

	IN	A,(XPSTP)		;ISSUE STEP PULSE
	LD	DE,TMSTP		;SET DELAY
	JR	TIMER


;*********************************
;
;	STEP IN 1 STEP SUBR
;
;*********************************
STEPIN:	LD	A,STPIC		;ISSUE STEP IN COMMAND
	JR	STEPC


IMSZE	EQU	$-IMADR		;THIS MUST BE LAST STATEMENT OF BIM

	SUBTTL	HARD DISK BOOT
	IF	$ >= 0FC00H
	CONMSG	WARNING!  Jade Double D code collides with DD Location!
	ENDIF
;*************************************************************
;
;	Hard disk boot function.
;	This module reads the BIOS image to the proper system
; address & jumps to the BIOS cold start entry point.
;
;*************************************************************
HBOOT:
	LD	A,1 SHL HRESET	;CLEAR CONTROLLER FIRST
	OUT	(HCMD),A
	XOR	A
	OUT	(HCMD),A

	LD	A,DDOUT		;INSURE WINDOW REMOVED
	OUT	(DDPORT),A

	LD	HL,BASIOPB	;INIT IOPB IN RAM
	LD	DE,IOPB
	LD	BC,IOPBSIZ
	LDIR

	LD	A,(ARGSAV)	;COMPUTE & SET DRIVE
	AND	070H
	RRCA
	RRCA
	RRCA
	RRCA
	SUB	A,4		;BIAS DOWN
	LD	(LOGINBY),A	;STORE DRIVE IN CP/M LOGIN BYTE FOR CBIOS

	RRA			;DRIVE = LOGICAL_DRIVE / 2
	LD	(IOPB + PBDRV),A

	RRA			;IF ODD DRIVE THEN SECTOR += 128
	AND	80H
	EXX			;SAVE SECTOR OFFSET IN C' FOR LATER USE
	LD	C,A		;   EVEN= 0, ODD= 80H (128)

	LD	A,(IOPB + PBSEC)	;IF ODD, THEN USE PLATTER 1
	OR	C
	LD	(IOPB + PBSEC),A
	EXX

CLRWT:	IN	A,(HSTATUS)	;WAIT FOR CONTROLLER READY
	CP	0FFH		;IF NOT INSTALLED THEN QUIT
	JP	Z,DKRET

	BIT	HBUSYB,A	;ELSE WAIT
	JR	NZ,CLRWT
;
;   WAIT A WHILE IN CASE G HOST ADAPTER FIDDLING WITH STATUS PORT
;
	LD	HL,0
HB1:	DEC	HL
	LD	A,H
	OR	L
	JR	NZ,HB1
;
;   AND CHECK AGAIN
;
	IN	A,(HSTATUS)
	BIT	HBUSYB,A
;
;   IF BUSY AGAIN THEN CONTINUE TO WAIT
;
	JR	NZ,CLRWT
;
;   OUTPUT THE IOPB ADDRESS TO HOST ADAPTER
;
	LD	B,03H		;3 BYTES TO XFER
	LD	HL,IOPBADR

IOPBLP:	LD	A,(HL)		;OUTPUT ADDRESS
	OUT	(HDATA),A
	INC	HL

	LD	A,(HL)
	INC	HL
	OUT	(HCMD),A

IOPBWT:	IN	A,(HSTATUS)	;WAIT FOR DONE
	BIT	HBUSYB,A
	JR	NZ,IOPBWT

	DJNZ	IOPBLP
;
;   FORCE HOST ADAPTER LOG-ON
;
	CALL	EXIOPB		;LOGON DRIVE
	SCF
	JP	NZ,DKRET

	LD	A,RDCMD		;SET IOPB TO READ
	LD	(IOPB + PBCMD),A
	
	CALL	EXIOPB		;READ THE DIRECTORY SECTOR (IOPB SET UP)
	SCF
	JP	NZ,DKRET

;======================================
;
;	LOAD THE DCM FROM THE HARD DISK
;
;======================================
	LD	A,DDMB0 + DDBGN		;OPEN WINDOW TO LOAD DCM
	OUT	(DDPORT),A

	LD	A,(DEFBFR + 9)		;FETCH 1ST DCM SECTOR FROM DIRECTORY
	EXX				;  SET UP PLATTER
	OR	C
	EXX
	LD	(IOPB + PBSEC),A

	LD	HL,(DADDR)		;SET PTR
	LD	(IOPB + PBDMA),HL

	LD	B,8			;SECTOR COUNT
	LD	DE,SECSIZ
HDRDLP1:
	CALL	EXIOPB
	SCF				;IF ERROR THEN RETURN ERROR
	JP	NZ,DKRET

	LD	HL,IOPB + PBSEC		;NEXT SECTOR
	INC	(HL)

	LD	HL,(IOPB + PBDMA)	;BUMP DMA ADDRESS
	ADD	HL,DE
	LD	(IOPB + PBDMA),HL

	DJNZ	HDRDLP1

	LD	A,DDBGN		;INITIALIZE FDC & REMOVE WINDOW FROM MAP
	OUT	(DDPORT),A

	IF	$ >= 0FC00H
	CONMSG	*** JADE DEPENDENT CODE OVERLAPS CONTROLLER MAP ***
	ENDIF
;======================================
;
;	LOAD THE CBIOS
;
;======================================
	LD	HL,DEFBFR		;RESTORE DMA PTR TO BUFFER
	LD	(IOPB + PBDMA),HL

	LD	A,(DEFBFR + 0BH)	;FETCH CBIOS SECTOR FROM DIRECTORY
	EXX
	OR	C
	EXX
	LD	(IOPB + PBSEC),A

	CALL	EXIOPB		;LOAD IN CBIOS SECTOR #1
	SCF			;CHECK FOR ERRORS
	JP	NZ,DKRET
	
	LD	A,(DEFBFR + 1)	;FETCH BIOS LOAD PARAMETERS
	CP	SECSIZ		;CHECK LIMITS OF OFFSET
	CCF
	JP	C,DKRET
	
	LD	HL,DEFBFR	;COMPUTE OFFSET TO CBIOS VECTORS
	LD	E,A		
	LD	D,0
	ADD	HL,DE

	DEC	HL		;FETCH BIOS LOAD ADDRESS
	LD	D,(HL)
	DEC	HL
	LD	E,(HL)

   IF	DEBUG
	LD	DE,(ARG2)	;DEBUG, LOAD IN AT ARG 2
   ENDIF

	LD	(BIOSNT),DE	;SAVE START ADDRESS

	DEC	HL		;FETCH BIOS LENGTH
	LD	B,(HL)
	DEC	HL
	LD	C,(HL)
	LD	(BIOSLN),BC	;SAVE IT

	LD	HL,DEFBFR	;MOVE THIS SECTOR TO PROPER PLACE
	LD	BC,SECSIZ
	LDIR

	LD	(IOPB + PBDMA),DE	;SET UP NEW DMA ADDRESS

	LD	IX,IOPB		;POINT TO IOPB
	INC	(IX + PBSEC)	;NEXT SECTOR

	LD	HL,(BIOSLN)	;COMPUTE # SECTORS
	LD	A,L		;IF NOT EVEN SECTOR THEN BUMP 1
	AND	127
	JR	Z,NOBUMP

	LD	DE,SECSIZ
	ADD	HL,DE

NOBUMP:	LD	A,L
	RLA			;PUT BIT 7 INTO BIT 0 OF H
	RL	H
	LD	A,H
	DEC	A		;ALREADY HAVE 1ST SECTOR
	LD	(BIOSLN),A	;PUT INTO VAR
	LD	(BIOSCNT),A

HDRDLP:
	CALL	EXIOPB
	SCF
	JP	NZ,DKRET

	INC	(IX + PBSEC)	;NEXT SECTOR

	LD	HL,(IOPB + PBDMA)	;BUMP DMA ADDRESS
	ADD	HL,DE
	LD	(IOPB + PBDMA),HL

	LD	A,(BIOSLN)	;IF NOT DONE THEN LOOP
	DEC	A
	LD	(BIOSLN),A
	JR	NZ,HDRDLP

	LD	HL,(BIOSNT)	;BIOS LOADED, GO EXECUTE IT

   IF	NOT DEBUG
	JP	(HL)

   ELSE				;IF DEBUG THEN RETURN NO ERRORS
	OR	A
	JP	DKRET

   ENDIF

;**************************************
;
;	EXECUTE IOPB SUBR
;	EXIT -	ZF= NO ERRORS
;
;**************************************
EXIOPB:
	LD	A,HEXEC		;EXECUTE IOPB
	OUT	(HCMD),A
EXIOPB1:
	IN	A,(HSTATUS)
	BIT	HBUSYB,A
	JR	NZ,EXIOPB1

	AND	(1 SHL HERRB) + (1 SHL HFERRB)	;CHECK FOR ERROR
	RET


;############################
;
;	BASE READ IOPB
;
;############################
BASIOPB:
	DB	LOGCMD		;COMMAND BYTE (LOGON 1ST)
	DB	0		;DRIVE BYTE
	DW	0		;TRACK WORD
	DW	2		;SECTOR WORD (DIRECTORY SECTOR)
	DB	0		;FLAGS BYTE
	DW	DEFBFR		;DMA ADDRESS
	DB	0		;XADDRESS
	DB	0		;ERROR FLAG
	DB	0,0,0		;ERROR STATUS
	DW	0		;SPARES

;################################################
;
;	IOPB ADDRESS STRUCTURE
;	DEF IOPBADR[2,3] :: ADDR_BYTE,COMMAND
;
;################################################
IOPBADR:
	DB	LOW IOPB	;IOPB ADDRESS
	DB	HIOPBL
	DB	HIGH IOPB
	DB	HIOPBH
	DB	0
	DB	HIOPBX


	IF	($ < PROMST) OR ($ > (PROMST + PROMSIZ))
	CONMSG	ERROR!  Code Too Large for PROM!
	ENDIF

	END
