DataMuseum.dk

Presents historical artifacts from the history of:

CP/M

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about CP/M

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦70829a505⟧ TextFile

    Length: 21888 (0x5580)
    Types: TextFile
    Names: »SECBOOT.ASM«

Derivation

└─⟦be0857eee⟧ Bits:30004395 CP/M-86 files - CR8 Dual floppy
    └─ ⟦this⟧ »SECBOOT.ASM« 

TextFile

 	TITLE 'CR8 - SECONDARY BOOT PROGRAM - DATE: 840117'
	PAGE 43
$*MACRO
;*****************************************************************************
;
;	WILL EXECUTE DIRECTLY IF BOOTED FROM THE SYSTEM TRACKS BY THE CR8
;	PROM BOOTLOADER. THIS IS MADE POSSIBLE BY LETTING THE PROGRAM USE
;	THE CR8 PROM I/O ROUTINES DIRECTLY AS THEY ARE PLACED IN RAM BY THE
;	BOOTLOADER.
;
;*****************************************************************************

LDADDR	EQU	0D000H		;LOAD ADDRESS FOR SYSTEM DISK SOFTWARE
BOOTLEN	EQU	01E00H		;LENGTH OF BOOT LOAD FROM SYSTEM DISK MINI
BASE	EQU	0D000H		;BASE ADDR FOR THIS MODULE


;DEFINE MEMORY BASED I/O MODULE ENTRY POINTS
;
$-PRINT
;
MODBASE EQU	0F800H		;SET JUMP TABLE STARTING ADDRESS
;
INITSER EQU	MODBASE+00	;INITIALIZE MP-SQUARE HARDWARE
;				;(NO PARAMETERS)
SETCBAUD EQU	MODBASE+03	;SET CONSOLE I/O BAUD RATE FACTOR
;				;(HL) = COUNTER TIMER PARAMETER VALUE
SETLBAUD EQU	MODBASE+06	;SET LINE PRINTER I/O BAUD RATE FACTOR
;				;(HL) = COUNTER TIMER VALUE
SETLRMSK EQU	MODBASE+09	;SET LINE PRINTER SIO RECEIVER MASK VALUE
;				;(A) = LINE PRINTER SIO MASK BYTE
SETLRVAL EQU	MODBASE+012	;SET LINE PRINTER SIO RECEIVER POLL VALUE
;				;(A) = LINE PRINTER POLL VALUE
SETLTMSK EQU	MODBASE+015	;SET LINE PRINTER SIO TRANSMITTER MASK VALUE
;				;(A) = LINE PRINTER SIO MASK BYTE
SETLTVAL EQU	MODBASE+018	;SET LINE PRINTER SIO TRANSMITTER POLL VALUE
;				;(A) = LINE PRINTER SIO POLL VALUE BYTE
CONSTAT EQU	MODBASE+021	;GET CONSOLE STATUS
;				;RETURN (A)=00 FOR NOT READY INPUT
;				;	(A)=FF FOR READY INPUT
CONIN	EQU	MODBASE+024	;GO GET CONSOLE INPUT CHARACTER
;				;(A)=INPUT CONSOLE CHARACTER
CONOUT	EQU	MODBASE+027	;PUT OUT CONSOLE CHAR
;				;(C)=CHARACTER TO OUTPUT
LPTSTAT EQU	MODBASE+030	;GET LINE PRINTER STATUS
;				;RETURN (A)=00 FOR NOT NEXT OUTPUT
;				;	(A)=FF FOR READY OUTPUT
LPTIN	EQU	MODBASE+033	;GO GET LINE PRINTER INPUT CHARACTER
;				;(A)=INPUT LPT SERIAL PORT CHARACTER
LPTOUT	EQU	MODBASE+036	;PUT OUT LINE PRINTER CHARACTER
;				;(C)=LPT SERIAL OUTPUT CHARACTER
HUNIT	EQU	MODBASE+039	;SELECT HARD DISK UNIT NUMBER
;				;(C)=UNIT NUMBER ON MSC 9205 CONTROLLER
HPLAT	EQU	MODBASE+042	;SELECT HARD DISK PLATTER (HEAD) NUMBER 
;				;(C)=HEAD SELECT NUMBER
HSURF	EQU	MODBASE+045	;SELECT HARD DISK SURFACE(HEAD 2^2) NUMBER
;				;(C)=MSB OF HEAD NUMBER
HCYL	EQU	MODBASE+048	;SELECT HARD DISK CYLINDER NUMBER
;				;(BC)=CYLINDER NUMBER
HREC	EQU	MODBASE+051	;SELECT HARD DISK RECORD NUMBER
;				;(C)=RECORD NUMBER
HCNT	EQU	MODBASE+054	;SELECT HARD DISK SECTOR COUNT
;				;(C)=RECORD COUNT
HBADDR	EQU	MODBASE+057	;SET 9205 CONTROLLER DMA ADDRESS
;				;(BC)=16 BIT DATA BUFFER ADDRESS
HREST	EQU	MODBASE+060	;RESTORE SELECTED HARD DISK UNIT
;				;(A) RETURNS ERROR CODE
HREAD	EQU	MODBASE+063	;READ SELECTED SECTOR(S)
;				;(A) RETURNS ERROR CODE
HVERF	EQU	MODBASE+066	;VERIFY SELECTED SECTOR(S)
;				;(A) RETURNS ERROR CODE
HWRIT	EQU	MODBASE+069	;WRITE SELECTED SECTOR(S)
;				;(A) RETURNS ERROR CODE
HEXEC	EQU	MODBASE+072	;EXECUTE SPECIAL COMMAND OF MSC 9205
;				;(C) ENTRY WITH MSC 9205 COMMAND
;				;(A) RETURNS ERROR CODE
HRESET	EQU	MODBASE+075	;RESET HARD DISK CONTROLLER MSC 9205
;				;NO PARAMETERS
MUNIT	EQU	MODBASE+078	;SELECT MINI FLOPPY UNIT NUMBER
;				;(C)=FLOPPY PHYSICAL UNIT NUMBER
MSURF	EQU	MODBASE+081	;SELECT MINI FLOPPY SURFACE(HEAD) NUMBER
;				;(C)=FLOPPY SIDE NUMBER
MCYL	EQU	MODBASE+084	;SELECT MINI FLOPPY CYLINDER(TRACK) NUMBER
;				;(C)=FLOPPY TRACK NUMBER
MREC	EQU	MODBASE+087	;SELECT MINI FLOPPY RECORD NUMBER
;				;(C)=FLOPPY SECTOR NUMBER
MCNT	EQU	MODBASE+090	;SELECT MINI FLOPPY PHYSICAL SECTOR COUNT
;				;(C)=MINI FLOPPY SECTOR COUNT
MSIZE	EQU	MODBASE+093	;SELECT FLOPPY SECTOR SIZE (00)=256 BYTES
;				;(C)=MINI FLOPPY TRACK NUMBER
MBADDR	EQU	MODBASE+096	;SET FLOPPY DISK DATA BUFFER ADDRESS
;				;(BC)=FLOPPY BUFFER ADDRESS
MREST	EQU	MODBASE+099	;RESTORE SELECTED MINI FLOPPY UNIT
;				;(A)=RETURNS ERROR STATUS
MVERF	EQU	MODBASE+102	;VERIFY (READ) SELECTED SECTOR
;				;(A)=RETURNS STATUS
MWRIT	EQU	MODBASE+105	;WRITE SELECTED SECTOR
;				;(A)=RETURNED STATUS
MREAD	EQU	MODBASE+108	;READ SELECTED SECTOR
;				;(A)=RETURNED STATUS
MWTRK	EQU	MODBASE+111	;WRITE SELECTED FLOPPY TRACK
;				;(A)=RETURNED STATUS
MMODE	EQU	MODBASE+114	;SET FLOPPY OPERATION MODE
;				;(C)=STANDARD MODE DEFINITION
MINST	EQU	MODBASE+117	;FETCH CURRENT INSTRUCTION CODE
;				;(A)=RETURNED INSTRUCTION PATTERN
MMOFF	EQU	MODBASE+120	;CHECK MINI FLOPPY MOTOR ON COUNT
;				;OUT TIMER
$+PRINT

	MACLIB	CR8PORTS

	MACLIB	Z80
;
;MACROS

;DISPLAY TEXT STRING
;
DISPLAY	MACRO	@MSGPTR
	LXI	H,@MSGPTR   !	CALL	CRTMSG
	ENDM


;SAVE (PUSH)REGISTERS EXCEPT PSW
;
SAVER	MACRO
	PUSH	H   !	PUSH	D   !	PUSH	B
	ENDM

;RESTORE REGISTERS AS SAVED BY "SAVER" AND RETURN
;
RESTRET	MACRO
	POP	B   !	POP	D   !	POP	H   !	RET
	ENDM
;
;*****************************************************************************
;BOOTLOADER INFORMATION FOR MINI FLOPPY SYSTEM TRACKS
;
	ORG	LDADDR - 200H

	DW	LDADDR	;BOOT LOAD START ADDRESS IN RAM
	DW	BOOTLEN	;LENGTH OF BOOT LOAD FROM MINI FLOPPY

	DW	0008H	;CONSOLE_0 BAUDRATE FACTOR (DEFAULT IS 9600 BAUD)
	DW	0008H	;LINE PRINTER_0  -     -       -    -    -    -
	DB	24H,24H	;  -     -    TX MASK/READY VAL
	DB	01H,01H	;  -     -    RX   -    -    -

	DW	BASE	;START ADDRESS (TO BE USED AFTER BOOT LOAD COMPLETION):
			;I.E. START OF SYSDISK PROGRAM

;*****************************************************************************
;	S T A R T   A D D R E S S
;
	ORG	BASE

ENTRY	EQU	$

	JMP	START
;-----------------------------------------------------------------------------
	PAGE
;*****************************************************************************
; CHARACTER EQUATES
;
ETX	EQU	003H
TAB	EQU	009H
EOF	EQU	01AH
SPC	EQU	020H

CTRLC	EQU	ETX


; FCB EQUATES
;
FCBEXT	EQU	12		;FCB EXTENT OFFSET
FCBS2	EQU	14		; -  S2 BYTE
FCBCR	EQU	32		; -  CURRENT RECORD
FCBLEN	EQU	36		; -  LENGTH

; MISC. EQUATES
;
RESTART	EQU	0		;
;
CNFLOC	EQU	0A000H		;START ADDR. OF CONFIG TABLE
TMPLOC	EQU	00100H		;START ADDR. OF TEMPORARY FILE
SCILOC	EQU	02000H		;REAL START ADDR. OF SCIFILE
TABOFF	EQU	040H		;BLOCK OFFSET IN CONFIG TABLE
PG8088	EQU	CNFLOC+TABOFF	;ADDR. OF 8088 BLOCK
PGZ80	EQU	CNFLOC+(TABOFF*02H);ADDR. OF Z80 BLOCK
FIADOF	EQU	030H		;OFFSET TO FILE ADDR.
SMADOF	EQU	032H		;OFFSET TO SEMAPHORE ADDR.
SEMZ80	EQU	PGZ80+SMADOF	;ADDR OF Z80 SEMAPHORE ADDR
;
BIOSENT	EQU	0E600H		; 
BIOSBO	EQU	BIOSENT+01H	;ADDR OF BIOS JUMP TABLE( JMP BOOT )
BIOSWB	EQU	BIOSENT+04H	; "   "   "    "     "  ( JMP WBOOT )
BIOSCB	EQU	BIOSENT+33H	; "   "   "    "     "  ( JMP CBCPMIN )

;CONSOLE INPUT ROUTINE (RETURNS CHARACTER IN A REGISTER)
;(ALL OTHER REGISTERS UNCHANGED)
;
CI:	SAVER
	CALL	CONIN
	RESTRET

;CONSOLE OUTPUT ROUTINE (OUTPUT CHARACTER FROM C REG)
;DESTROYS: PSW   (ALL OTHER REGISTERS UNCHANGED)
;
CO:	SAVER
	CALL	CONOUT
	RESTRET

;CONSOLE TERMINAL STATUS ROUTINE
; RETURNS A=00 IF NO CHARACTER PRESENT
; RETURNS A=FF IF    CHARACTER PRESENT
;(ALL OTHER REGISTERS UNCHANGED)
;
CSTS:	SAVER
	CALL	CONSTAT
	RESTRET

	PAGE
;*****************************************************************************
;ROUTINE TO DISPLAY A MESSAGE ON THE CRT. REGISTERS (HL) POINT TO THE
;MESSAGE. END OF MESSAGE IS INDICATED BY 0 (ZERO VALUE, I.E. 'NULL' CHAR).
;DESTR: PSW, HL
;
CRTMSG:	PUSH	B
CRTMS1:	MOV	A,M	;REPEAT
	ANA	A	;  IF CHAR=0
	JRZ	CRTMSX	;  THEN EXIT
	MOV	C,A	;  ELSE
	CALL	CO	;    WRITE CHAR
	INX	H	;    POINT TO NEXT
	JR	CRTMS1	;END
CRTMSX:	POP	B
	RET

;*****************************************************************************
;ROUTINE TO PRINT A CR/LF FOLLOWED BY A FULL LINE OF THE CHAR IN (A)
;DESTROYS: PSW
;
WRLINE:	PUSH	B
	CALL	CRLF
	MVI	B,80		;SET NUMBER OF CHARS
	CALL	MULTCH
	POP	B
	RET

;*****************************************************************************
;ROUTINE TO PRINT A CHARACTER A SPECIFIED NUMBER OF TIMES
; (A)=CHAR, (B)=COUNT
;DESTROYS: PSW, BC
;
MULTCH:	MOV	C,A	;GET CHAR
MULTC1:	CALL	CO
	DJNZ	MULTC1
	RET

;*****************************************************************************
;SEND CR/LF TO CONSOLE
;DESTROYS: NOTHING
;
CRLFLF:	CALL	CRLF

CRLF:	PUSH	PSW
	PUSH	B
	MVI	C,CR
	CALL	CO
	MVI	C,LF
	CALL	CO
	POP	B
	POP	PSW
	RET

;*****************************************************************************
;CLEAR SCREEN (ASSUMING 'ESC Æ2J' WILL DO THE JOB)
;DESTROYS: PSW
;
CLRSCR:	PUSH	H
	DISPLAY	CSMSG
	POP	H
	RET

CSMSG:	DB	CR,ESC,'Æ2J',ESC,'ÆH',0		;CLEAR SCREEN

;*****************************************************************************
;ERASE CURRENT LINE AND POSITION CURSOR IN BEGINNING OF LINE
;DESTROYS: NOTHING
;
ERALIN:	PUSH	PSW
	PUSH	H
	DISPLAY	ERALMS
	POP	H
	POP	PSW
	RET

ERALMS:	DB	ESC,'ÆM',CR,0	;ERASE CURRENT LINE AND PUT CURSOR IN BEGINNING
	PAGE
;*****************************************************************************
;	X B D O S   I N T E R F A C E
;
BDOSENT	EQU	0D806H		;XBDOS ENTRY POINT IN THIS CONFIG
RESDS	EQU	13		;  -   RESET DISK SYSTEM (AND SELECT A)
SELDS	EQU	14		;  -   SELECT DISK FCT (DISK IN REG E)
OPENF	EQU	15		;  -   OPEN FILE
CLOSEF	EQU	16		;  -   CLOSE  -
DELETEF	EQU	19		;  -   DELETE -
READSEQ	EQU	20		;  -   READ SEQUENTIAL
WRITSEQ	EQU	21		;  -   WRITE    -
MAKEF	EQU	22		;  -   MAKE FILE
SDMA	EQU	26		;  -   SET DMA ADDR

;MACRO TO INVOKE XBDOS FUNCTIONS.
;
INVOKE	MACRO	@INVFCT
	MVI	C,@INVFCT   !	CALL	BDOSENT
	ENDM

;	
RESDSK:	SAVER
	INVOKE	RESDS
	JR	BDOSEX
;
SELDSK:	SAVER
	INVOKE	SELDS		;SELECT DISK IN (E) (0=A,...)
	JR	BDOSEX
;
OPEN:	SAVER
	PUSH	D
	POPIX			;IX POINTS TO FCB
	XRA	A
	STX	A, FCBEXT	;RESET 'EXT' FIELD
	STX	A, FCBCR	;  -   'CR'    -
	INVOKE	OPENF
	JR	BDOSEX
;
CLOSE:	SAVER
	INVOKE	CLOSEF
	JR	BDOSEX
;
DELETE:	SAVER
	INVOKE	DELETEF
	JR	BDOSEX
;
READ:	SAVER
	INVOKE	READSEQ
	JR	BDOSEX
;
WRITE:	SAVER
	INVOKE	WRITSEQ
	JR	BDOSEX
;
MAKE:	SAVER
	PUSH	D
	POPIX			;IX POINTS TO FCB
	XRA	A
	STX	A, FCBEXT	;RESET 'EXT' FIELD
	STX	A, FCBCR	;  -   'CR'    -
	INVOKE	MAKEF
	JR	BDOSEX
;
SETDMA:	SAVER
	INVOKE	SDMA
	JR	BDOSEX
;
BDOSEX:	RESTRET			;RESTORE REGISTERS AND RETURN FROM XBDOS FCT


;*****************************************************************************
;PROCEDURE TO GET A FILE INTO A GIVEN LOAD ADDRESS
;NOTE: THE MAX SIZE OF THE FILE TO BE LOADED IS  7F00H (A BIT LESS THAN 32K).
;ENTRY:	  HL = LOAD ADDRESS
;	  DE = PTR TO FCB
;RETURNS: HL = ADDR OF FIRST BYTE AFTER LOADED BLOCK
;	  A  = STATUS CODE  (0=OK, 1=FILE NOT FOUND, 2=LOAD ERROR)
;DESTROYS: PSW
;
MAXBFP	EQU	0D7H		;LAST LEGAL PAGE FOR LOAD
;
GETFILE:
	PUSH	B
	CALL	OPEN
	INR	A		;TEST OPEN STATUS
	JRZ	BADOPN		;BAD: GO EXIT (A=0)
	MVI	A, MAXBFP
	SUB	H		;TEST LOCATION OF LOAD
	JRC	GETBAD		;QUIT IF...
	JRZ	GETBAD		;...TOO HIGH
	CPI	80H		;IS THIS MAX AT ALL POSSIBLE
	JRC	GFADJ
	MVI	B, 0FFH		;NO: USE ABSOLUTE MAX AS 128 BYTE BLOCK COUNT 
	JR	GFRDY
GFADJ:	RLC			;YES: ADJUST FOR REAL MAX COUNT
	MOV	B,A		;USE FOR NUMBER OF READS
GFRDY:	XRA	A
	PUSH	D
	POPIX			;IX POINTS TO FCB
	STX	A, FCBEXT	;RESET 'EXT' FIELD
	STX	A, FCBCR	;  -   'CR'    -
GETINP:	XCHG			;(DE)=BUFFER
	CALL	SETDMA
	XCHG			;(DE)=FCB
	CALL	READ
	ORA	A
	JRNZ	ENDGET		;GOT EOF. END OF READ
	MOV	A,B		;TEMP SAVE OF COUNT
	LXI	B,128
	DAD	B		;UPDATE LOAD ADDR
	MOV	B,A
	DJNZ	GETINP		;LOOP IF FILE NOT TOO LARGE
;EXIT FROM LOOP IF LOAD NOT TERMINATED BEFORE "MAX COUNTER" COUNTED DOWN TO 0
;
GETBAD:	MVI	A, 1		;ENTER HERE FOR A TO BECOME 2
BADOPN:	INR	A		;  -     -  WITH A=0 (BECOMES 1)
	JR	GETFEX		;GO RETURN 1 0R 2
ENDGET:	XRA	A		;RETURN 0 FOR OK STATUS
GETFEX:	POP	B
	RET
;*****************************************************************************
;PROCEDURE TO TEST IF SCI BOARD IS READY.(HANDSHAKE)
;ENTRY:		HL = PTR TO SCI PAGE
;RETURNS:	 A = STATUS		ERROR/SCIOK
;
SCIREQ	EQU	06FFEH		;BOOT REQUEST BYTE ADDRESS
SCIRDY	EQU	080H		;
SCIOK	EQU	000H		;
SCIERR	EQU	0FFH		;
;
REQFLG:	DB	0H		;
ACKFLG:	DB	0H		;
;
SCITST:	PUSH	B		;
	PUSH	D		;
	PUSH	H		;SAVE REG
	IN	P$RAMCTL	;
	ORI	10H		;ENABLE BUS TIME OUT
	OUT	P$RAMCTL	;
	MOV	A,M		;GET SCI MAP REG VALUE (FROM Z80 TO SCI)
	LXI	H,REQFLG	;SOURCE
	LXI	D,SCIREQ	;DESTINATION
	LXI	B,02H		;NUMBER OF BYTES TO MOVE
	CALL	DMAMOV		;SET (SCIREQ)=0 AND (SCIACK)=0
	MVI	B,08H		;LOOP COUNT
SCIWAI:	PUSH	B		;
	MVI	A,0FFH		;
	CALL	SDLY		;TIME DELAY (A REG)*1MSEC
	POP	B		;
	POP	H		;
	PUSH	H		;
	PUSH	B		;
	MOV	A,M		;GET SCI MAP REG VALUE (FROM Z80 TO SCI)
	RLC			;
	RLC			;
	RLC			;
	RLC			;A=SCI MAP REG (FROM SCI TO Z80)
	LXI	H,SCIREQ	;SOURCE
	LXI	D,REQFLG	;DESTINATON
	LXI	B,01H		;NUMBERS OF BYTES TO MOVE
	CALL	DMAMOV		;GET (SCIREQ)
	LXI	H,REQFLG	;
	MOV	A,M		;
	CPI	SCIRDY		;
	JZ	RDTOLD		;SCI BOARD IS READY TO LOAD
	POP	B		;GET LOOP COUNT
	DJNZ	SCIWAI		;IF LOOP COUNT =0 THEN
	MVI	A,SCIERR	;
	JMP	TSTEND		;
				;
RDTOLD:	MVI	A,SCIOK		;
	POP	B		;
TSTEND:	LXI	H,REQFLG	;RESET REQFLG
	MVI	M,0H		;
	PUSH	PSW		;
	IN	P$RAM$CTL	;
	ANI	0EFH		;DISABLE BUS TIME OUT
	OUT	P$RAM$CTL	;
	POP	PSW		;
	POP	H		;RESTORE REGISTER
	POP	D		;
	POP	B		;
	RET			;
				;

	PAGE
;*****************************************************************************
;	M A I N   P R O G R A M
;
START:
	LXI	SP,PGMSTK		;INIT STACKPOINTER
	LXI	H,MHFLG			;MINIHARD FLAG (00=FLOOPY BOOT)
	MOV	M,B			;	       (FF=WINCHESTERBOOT)
	LXI	H,BTUNIT		;BOOTUNIT (00/01 IF FLOPPYBOOT)
	MOV	M,C			;	  (00/03 IF WINCHESTERBOOT)
	INR	C			;
	LXI	H,CNFFCB		;SET DRIVE NO IN CONFIG TABLE FCB
	MOV	M,C			;
	SDED	DATBF			;DATBF (POINTER TO PARAMETER SECTOR
					;				BUFFER)
					;
START1:	CALL	CLRSCR			;
	MVI	A,00H			;
	STA	0004H			;CURRENT DEFAULT DRIVE NUMBER (0=A)
	LXI	H,DUMMY			;
	SHLD	BIOSBO			;CHANGE IN BIOS JUMP TABLE
	SHLD	BIOSWB			;
	MVI	A, 0C3H			;
	STA	0000H			;
	STA	0005H			;
	LXI	H, ENTRY		;
	SHLD	0001H			;PUT 'JUMP RESTART' INTO ADDR 0
	LXI	H, BDOSENT		;
	SHLD	0006H			;PUT 'JUMP BDOS ENTRY' AT ADDR 5
	CALL	RESDSK			;
	LXI	H,BTUNIT		;
	MOV	E,M			;(A=0....)
	CALL	SELDSK			;
	DISPLAY	CRASMS			;'CRAS' MESSAGE
	MVI	A,'*'
	CALL	WRLINE			;LINE OF '*'

START2:	DISPLAY	CNFMSG			;LOADING CONFIGURATION TABLE
	LXI	D,CNFFCB
	LXI	H,CNFLOC
	CALL	GETFILE
	ORA	A			;
	JNZ	ERRCNF			;LOADING ERROR
					;
LDSCI:	
	LXI	H,PGZ80			;PTR TO Z80 PAGE
LDNSCI:	LXI	D,TABOFF		;
	DAD	DE			;PTR TO SCI PAGE (MAP REG VALUE)
	MOV	A,M			;
	ORA	A			;CHECK IF SCI PAGE <> 0
	JZ	LD8088			;
	IN	P$SWITCH$2		;GET STATUS OF SWITCH 2
	ANI	02H			; IF BIT1=1 <=> SCI BOARD NOT AVAILABLE
					;    BIT1=0 <=>  "    "    IS     "
	JZ	LD0			;
	DISPLAY	NOSW			;
	JMP	LD8088			;

LD0:	PUSH	H			;SAVE SCI PAGE
	CALL	SCITST			;TEST IF SCI BOARD IS READY
	CPI	SCIOK			;
	JNZ	ERFSCI			;
	CALL	CRLF			;
	DISPLAY	MSGSCI			;LOADING SCI FILE
	POP	D			;GET PTR TO SCI PAGE
	INX	D			;
LD1:	PUSH	D			;SAVE PTR TO FCB
	LXI	H,TMPLOC		;GET DESTINATION ADDR.
	CALL	GETFILE			;MOVE SCI FILE TO TEMPORARY DESTINATION
	ORA	A			;
	JNZ	ERRSCI			;
	LXI	D,SCILOC		;
	ANA	A			;RESET CARRY
	DSBC	DE			;FIND LENGTH OF FILE
	MOV	B,H
	MOV	C,L			;LENGTH OF FILE				
	POP	H			;GET PTR TO SCI FCB
	PUSH	H			;
	DCX	H			;PTR TO SCI PAGE
	MOV	A,M			;
	LXI	D,FIADOF		;OFFSET TO FILE ADDR
	DAD	DE			;
	MOV	E,M			;
	INX	H			;
	MOV	D,M			;DE=ADDR OF SCI FILE
	LXI	H,SCILOC		;SOURCE ADDR.
	CALL	DMAMOV			;
	POP	H			;
	DCX	H			;PTR TO PRESENT SCI PAGE

	JMP	LDNSCI			;
					;
LD8088:	LXI	H,PG8088		;PTR TO 8088 MAP REG VALUE
	MOV	A,M			;
	ORA	A			;
	JZ	LDZ80			;IF MAP REG VALUE<>0 THEN DO
	CALL	CRLF			;
	DISPLAY	MSG88			;LOADING 8088 FILE
	LXI	D,PG8088		;PTR TO 8088 MAP REG VALUE
	INX	D			;PTR TO 8088 FCB
	LXI	H,TMPLOC		;
	CALL	GETFILE			;MOVE 8088 FILE TO TEMP. DESTINATION
	ORA	A			;
	JNZ	ERR88			;
	LXI	D,TMPLOC		;
	ANA	A			;
	DSBC	DE			;FIND FILE LENGTH
	PUSH	H			;SAVE FILE LENGTH
	LXI	H,PG8088		;PTR TO 8088 PAGE
	MOV	A,M			;
	LXI	D,FIADOF		;OFFSET TO FILE ADDR
	DAD	DE			;HL=PTR TO 8088 FILE ADDR
	MOV	E,M			;
	INX	H			;
	MOV	D,M			;DE=FILE ADDR
	LXI	H,TMPLOC		;SOURCE ADDR
	POP	B			;GET FILE LENGTH
	CALL	DMAMOV			;
LDZ80:	CALL	CRLF			;
	DISPLAY	MSGZ80			;LOADING Z80 FILE
	LXI	D,FIADOF		;
	LXI	H,PGZ80			;
	DAD	DE			;HL=PTR TO Z80 FILE ADDR
	MOV	E,M			;
	INX	H			;
	MOV	D,M			;
	XCHG				;HL=Z80 FILE ADDR
	LXI	D,PGZ80			;
	INX	D			;DE=PTR TO Z80 FCB
	CALL	GETFILE			;
	ORA	A			;
	JNZ	ERRZ80			;
					;
STASCI:	CALL	CRLF			;
	DISPLAY	STASEM			;LOADING START SEMAPHORES
	LXI	H,PGZ80			;
STNSCI:	IN	P$SWITCH$2		;GET STATUS OF SWITCH 2
	ANI	02H			;	IF BIT1=1 <=> SCI NOT AVAILABLE
					;	   BIT1=0 <=>  "   IS     " 
	JNZ	STA88			;
	LXI	D,TABOFF		;
	DAD	DE			;PTR TO SCI PAGE
	MOV	A,M			;
	ORA	A			;CHECK IF ANY SCI PAGE ( PAGE <> 0 )
	JZ	STA88			;
	PUSH	H			;SAVE PTR TO SCI PAGE
	CALL	SCITST			;TEST IF SCI BOARD IS READY
	CPI	SCIOK			;
	JNZ	ERSSCI			;
	LXI	B,0001H			;NUMBERS OF BYTES TO MOVE
	LXI	D,SMADOF		;OFFSET TO SEMAPHORE ADDR.
	POP	H			;GET PTR TO SCI PAGE
	PUSH	H			;
	MOV	A,M			;
	DAD	DE			;
	MOV	E,M			;
	INX	H			;
	MOV	D,M			;DE=DESTINATION ADDR.
	INX	H			;HL=SOURCE ADDR(PTR TO SEMAPHORE VALUE)
	CALL	DMAMOV			;MOVE START SEMAPHORE TO SCI 
	POP	H			;GET PTR TO SCI PAGE
	JMP	STNSCI			;
STA88:	LXI	H,PG8088		;PTR TO 8088 MAP REG VALUE
	MOV	A,M			;
	ORA A				;
	JZ	STAZ80			;
	LXI	B,0004H			;NUMBERS OF BYTE TO TRANSFER
	LXI	D,SMADOF		;OFFSET TO SEMAPHORE ADDR
	LXI	H,PG8088		;PTR TO 8088 PAGE
	MVI	A,10H			;
	DAD	DE			;PTR TO 8088 SEMAPHORE ADDR.
	MOV	E,M			;
	INX	H			;
	MOV	D,M			;DE=8088 DESTINATION ADDR.
	INX	H			;HL=SOURCE ADDR.
	CALL	DMAMOV			;MOVE PART OF START SEMAPHORE TO 8088
					;
STAZ80:	CALL	CLRSCR			;CLEAR SCREEN
	LXI	H,MHFLG			;
	MOV	B,M			;REG B = MINIHARD FLAG
	LXI	H,BTUNIT		;
	MOV	C,M			;REG C = BOOT UNIT
	LDED	DATBF			;REG DE = PTR TO PARAMETER SECTOR
	LHLD	SEMZ80			;HL=START SEMAPHORE ADDR
	PCHL				;JUMP TO START OF Z80 FILE
;
DUMMY:	RET				;DUMMY ROUTINE
;
ERRCNF:	CALL	CRLF			;CAN NOT FIND CONFIG TABLE ON
	CALL	SELECT			;DEFAULT DRIVE
	LXI	H,CNFFCB		;
	MOV	M,A			;CHANGE DRIVE NO
	JMP	START2			;
					;
ERRSCI:	CALL	SELECT			;CAN NOT FIND SCI FILE ON DEFAULT DRIVE
	POP	H			;GET PTR TO SCI FCB
	MOV	M,A			;CHANGE DRIVE NO
	XCHG				;
	JMP	LD1			;
					;
ERR88:	CALL	SELECT			;CAN NOT FIND 8088 FILE ON 
	LXI	H,PG8088		;DEFAULT DRIVE
	INX	H			;PTR TO 8088 FCB
	MOV	M,A			;CHANGE DRIVE NO
	JMP	LD8088			;
					;
ERRZ80:	CALL	SELECT			;CAN NOT FIND Z80-FILE
	LXI	H,PGZ80			;ON DEFAULT DRIVE
	INX	H			;
	MOV	M,A			;CHANGE DRIVE NO
	JMP	LDZ80			;
					;
SELECT:	DISPLAY	NOFILE			;
SELOOP:	CALL	CSTS			;TEST IF ANY INPUT FROM CONSOLE
	ORA	A			;
	JZ	SELOOP			;
	CALL	CI			;GET INPUT FROM CONSOLE 
	MOV	C,A			;
	CALL	CO			;ECCO CHAR.
	CPI	'0'			;TEST INPUT CHAR.
	JRC	ERRSEL			;	'0' =< X < '2'
	CPI	'2'			;
	JRNC	ERRSEL			;
	ANI	1			;
	INR	A			;
	RET				;
					;
ERRSEL:	ANI	5FH			;
	CPI	'Q'			;TEST IF CHAR = 'Q' 
	JZ	REBOOT			;
	DISPLAY	WRSEL			;ILLEGAL CHAR FROM CONSOLE
	JMP	SELECT			;
					; 
ERFSCI:					;
	CALL	CRLF			;FOR LOADING FILE
	DISPLAY	NOSCI			;SCI BOARD NOT READY
	POP	H			;GET PTR TO SCI PAGE
	JMP	LDNSCI			;
					;
ERSSCI:	POP	H			;SCI BOARD NOT READY FOR START
	JMP	STNSCI			;SEMAPHORE
					;
REBOOT:	XRA	A			;
	OUT	P$MAP3			;
	IN	P$RAMCTL		;
	ORI	M$RAMMAP		;
	OUT	P$RAMCTL		;
	JMP	0000H			;


DMAMOV:
	OUT	P$BANK$DMA	;SET MAP REGISTERS
	OUT	P$DMA$TOGGLE	;RESET BYTE POINTER FLIP-FLOP IN DMA
	DCX	B		;DMA HAS A FUNNY WAY TO COUNT BYTES
	MOV	A,C		;GET LSB OF BYTE COUNT
	OUT	P$DMA$CNT0	;OUT TO SOURCE CH.
	MOV	A,B		;GET MSB
	OUT	P$DMA$CNT0	;
	OUT	P$DMA$TOGGLE	;MAKE SURE IT IS CORRECT STATE
	MOV	A,C		;GET LSB OF BYTE COUNT
	OUT	P$DMA$CNT1	;OUT TO DESTINATION CH.
	MOV	A,B		;GET MSB
	OUT	P$DMA$CNT1	;
	OUT	P$DMA$TOGGLE	;IT'S THE SAME PROBLEM AGAIN
	MOV	A,L		;GET LSB OF SOURCE BUFFER ADDRESS
	OUT	P$DMA$ADR0	;OUT TO SOURCE CH.
	MOV	A,H		;GET MSB
	OUT	P$DMA$ADR0	;
	OUT	P$DMA$TOGGLE	;ONCE AGAIN
	MOV	A,E		;GET LSB OF DESTINATION BUFFER ADDRESS
	OUT	P$DMA$ADR1	;OUT TO DESTINATION CH.
	MOV	A,D		;GET MSB
	OUT	P$DMA$ADR1	;
	IN	P$DMA$STAT	;MIGHT BE SOME GARBAGE IN THERE
	MVI	A,04H		;VALUE TO SEND SOFTWARE DMA REQUEST TO
	OUT	P$DMA$REQ	;CHANNEL 0
DMAWAIT:
	IN	P$DMA$STAT	;GET CONTROLLER STATUS
	ANI	02H		;TEST IF FUNCTION COMPLETE
	JZ	DMAWAIT		;MUST FINISH UP SOME TIME
	RET			;

SDLY:
	MVI	L,070H
	DCR	L
	JNZ	$-1
	DCR	A
	JNZ	SDLY
	RET

	PAGE
;************************************************************************
NOFILE:	DB	CR,LF,'File not found.',CR,LF
	DB	CR,LF,'       FLOPPY DISK:      A:=0 B:=1',CR,LF
	DB	CR,LF,'Select alternate source'
	DB	CR,LF,'                     or type Q to quit  --> ',0
;
CRASMS:	DB	'CHRISTIAN ROVSING A/S  -  CR8 SECONDARY BOOT LOADER  - '
	DB	' VERS 2.2  -  DATE 840117',0
;
CNFMSG:	DB	CR,LF,'Loading configuration table.',0
;
NOSCI:	DB	'SCI board not ready.',0
;
MSGSCI:	DB	'Loading SCI-FILE.',0
;
MSG88:	DB	'Loading 8088-FILE.',0
;
MSGZ80:	DB	'Loading Z80-FILE.',0
;
STASEM:	DB	'Loading start semaphores.',0
;
WRSEL:	DB	CR,LF,'False select character.',CR,LF,0
;
NOSW:	DB	CR,LF,'Switch indicates that no SCI board is available',0
;
;************************************************************************
MHFLG:	DB	0H			;MINIHARD FLAG
BTUNIT:	DB	0H			;BOOTUNIT
DATBF:	DW	0000H			;POINTER TO PARAMETER SECTOR BUFFER
;
;FCB FOR LOADING CONFIG.SYS
;
CNFFCB:	DB	0
	DB	'CONFIG',SPC,SPC	;8 CHAR NAME
	DB	'SYS'			;3  -   TYPE
	ORG	CNFFCB+FCBLEN		;ADJUST FOR TOTAL LENGTH
;
					;
     					;PROGRAM STACK
STACK:	DS	40			;
	PGMSTK	EQU	$		;PROGRAM STACK BOTTOM
					;
					;END OF FILE
«eof»