Google
 

Trailing-Edge - PDP-10 Archives - BB-BT99U-BB_1990 - 10,7/feload/feload.p11
There are 5 other files named feload.p11 in the archive. Click here to see a list.
	.TITLE	FELOAD -- BOOT PROGRAM TO FIND & LOAD RSX20F V1(5) 30-Jan-89

;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1989.  ALL RIGHTS RESERVED.
;
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY  OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF THE  SOFTWARE  IS  HEREBY
;TRANSFERRED.
;
;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT  NOTICE
;AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.
;
;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY  OF  ITS
;SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.

;Original program supplied by Jeff Guenther, ADP Network Services,
;Ann Arbor, Michigan.

;Edit history
;
;Edit	Description
;----	-----------
;1	Modify sense of leftmost Switch-register bit
;	test so that '1' means load KLDCP and '0' means
;	load RSX-20F.  Add title, copyright statement.
;	28-Jan-88/JJF
;
;2	Change "Loading CORIMG.SYS" to "Loading RSX-20F".  Also change
;	all text messages to make them more meaningful; add prefix 
;	question-mark before all error messages to fit into TOPS standards.
;	05-Feb-88/JJF
;
;3	Extend table of .STDTB values to include the one for version
;	16-00 of RSX-20F.
;	10-Feb-88 /JJF
;
;4	Fix bug where the messages were too long and the code wouldn't
;	assemble because it was too big to fit in blocks 4 to 7.
;	12-May-88 /JJF
;
;5	Extend .STDTB table to include value for RSX-20F version 16-01.
;	30-Jan-89 /JJF
;
;[End of edit history]

;;	FELOAD is a small program used to load the "front end" program.
;;	Taking cues from the pdp11 switch register and the operator
;;	console teletype, it decides which front end system (ie: rsx20f
;;	or kldcp) to run, searches the appropriate front end directory
;;	and loads the correct boot for the system and starts it by
;;	branching to location 0.

	.ENABL	ABS,LC
	.ENABL	LC		;REALLY LOWER CASE


;;	If FELOAD is started at it's "starting address", rather than 0
;;	then it will load rsx20f unconditionally.  This is to support
;;	booting from KLDCP into RSX20F via the .P 20F or >. RSX commands.

;	First, the BM873YJ rom reads our block 0 code into physical core
;	block 0.  Then we read in blocks 4-7 into physical locations 4000-7777.
;	We always use 10000-10777 as impure data storage.
;	Then if we are booting rsx20f we move ourselves to 130000 and above.


NEWADR=	130000	;RELOCATION IF WE NEED TO LOAD 20F
KLDIR=	12000	;BUILD KLDCP DIRECTORY HERE UPWARDS
.SBTTL	UNIVERSALS -- F11HOM - Format of the FILES-11 home block, offsets as seen from 11

.MACRO	BSYM	.name,.value	;;MACRO TO DEFINE SYMBOLS
	W.'.name'=.offset	;;define name as current offset
	.offset=.offset+'.value'.;;redefine offset for next symbol
.ENDM	BSYM

.MACRO	F11HOM	;;ALL OFFSETS BELOW ARE GIVEN IN DECIMAL
	.offset=0	;;	START OFF AT 0
	BSYM	IBSZ,2	;;	OFFSET TO INDEX-BIT-MAP SIZE
			;;	# OF BLOCKS IN THE "SAT" PORTION ONLY
			;;	SO THE FILE INDEXF.SYS IS ALWAYS LARGER
			;;	SINCE IT INCLUDES THE FILE HEADERS ("RIB"S)
			;;	AS WELL AS THE SAT.
	BSYM	IBLB,4	;;	DISK ADDRESS (LBN) OF THE INDEX-BIT-MAP
	BSYM	FMAX,2	;;	# OF FILES ALLOWED
	BSYM	SBCL,2	;;	STORAGE-BIT-MAP CLUSTER SIZE
	BSYM	DVTY,2	;;	DISK-DEVICE TYPE
	BSYM	VLEV,2	;;	STRUCTURE LEVEL
	BSYM	VNAM,12	;;	12 ASCII CHARACTERS "VOLUME NAME"
	BSYM	RES1,4	;;	"RESERVED"
	BSYM	VOWN,2	;;	VOLUME OWNERS
	BSYM	VPRO,2	;;	VOLUME PROTECTION
	BSYM	VCHA,2	;;	VOLUME CHARACTERISTICS
	BSYM	DFPR,2	;;	DEFAULT PROTECTION
	BSYM	RES2,6	;;	"RESERVED"
	BSYM	WISZ,1	;;	DEFAULT NUMBER OF RETRIEVAL POINTERS IN A WINDOW
	BSYM	FIEX,1	;;	DEFAULT NUMBER OF BLOCKS TO EXTEND FILES
	BSYM	LRUC,1	;;	NUMBER OF ENTRIES IN DIRECTORY LRU
	BSYM	AVAL,11	;;	"AVAILABLE SPACE"
	BSYM	CHK1,2	;;	CHECKSUM OF WORDS 0-28.
	BSYM	VDAT,14	;;	CREATION DATE AND TIME
	BSYM	VHL,100	;;	VOLUME-HEADER LABEL
	BSYM	SYSI,82	;;	SYSTEM-SPECIFIC INFORMATION
	BSYM	RVOL,254;;	RELATIVE VOLUME TABLE
	BSYM	CHK2,2	;;	CHECKSUM OF HOME BLOCK WORDS 0 THRU 255
.ENDM	F11HOM
	F11HOM
.SBTTL UNIVERSALS -- T10HOM - Format of TOPS10 home block, as seen from 11 side

.MACRO	WSYM	.NAME,.VALUE
	'.NAME'='.VALUE'.
.ENDM	WSYM

.MACRO	T10HOM
;	This stuff defines the "PDP11 WORD NUMBER" of each thing
WSYM	HOMNA0,0	;;OFFSET CONTAINING SIXBIT .HOM. (TRUNCATED TO 16 BITS)
	SIXHOM=105755	;;TOPS10 SIXBIT "HOM" TRUNCATED TO 16 BITS
WSYM	HOMNA1,1	;;2ND HALF OF SIXBIT .HOM. (ALWAYS 0)

;;	HERE ARE THE KLDCP POINTERS
WSYM	HOMKV1,98	;;CONTAINS .RAD50 /KL / IF KLDCP VERSION 1
WSYM	HOMKV2,106	;;CONTAINS .RAD50 /KLA/ IF KLDCP VERSION 2
WSYM	HOMKV3,107	;;CONTAINS .RAD50 /D10/ IF KLDCP VERSION 2
WSYM	HOMKCY,108	;;CONTAINS CYLINDER OF KLADFE.SYS
WSYM	HOMKTS,109	;;CONTAINS TRACK/SECTOR OF KLADFE.SYS
WSYM	HOMKLN,110	;;CONTAINS LENGTH OF KLADFE.SYS

;;	HERE ARE THE FILES11 POINTERS
WSYM	HOMFEV,98	;;CONTAINS 100000 IF FILES11 VALID
	VALID=100000	;;BIT ON IF FILES11 VALID
WSYM	HOMFE0,99	;;CONTAINS LBN OF FILES11 FILE SYSTEM
WSYM	HOMFLN,101	;;LENGTH OF CONTIGUOUS FILES11 FILE SYSTEM
.ENDM	T10HOM

	T10HOM		;;FORCE DEFAULT DEFINITIONS

.SBTTL UNIVERSALS -- F11HED - format of FILES-11 file header block, as seen from 11

.MACRO	BSYM	.name,.value
	W.'.name'=.offset
	.offset=.offset+'.value'.
.ENDM	BSYM

.MACRO	F11HED
	.offset=0
	BSYM	IDOF,1	;;	OFFSET INTO THE ID AREA
	BSYM	MPOF,1	;;	OFFSET INTO THE MAP AREA (FROM THE ID AREA)
	BSYM	FNUM,2	;;	FILE NUMBER
	BSYM	FSEQ,2	;;	FILE SEQUENCE
	BSYM	FLEV,2	;;	STRUCTURE LEVEL AND SYSTEM NUMBER
	BSYM	PROG,1	;;	MEMBER NUMBER
	BSYM	PROJ,1	;;	GROUP NUMBER
	BSYM	FPRO,2	;;	FILE-PROTECTION CODE
	BSYM	UCHA,1	;;	USER CONTROLLER FILE CHARACTERISTICS
.ENDM	F11HED
	F11HED

.MACRO	F11FID	;; DEFINE ID AREA
	.offset=0	;; OFFSET FROM THE START OF THE ID AREA
	BSYM	FNAM,6	;; 6 BYTES OF RAD50, 3 CHARS PER 2 BYTES
	BSYM	FTYP,2	;; 2 BYTES OF FILE TYPE IN RAD50
	BSYM	FVER,2	;; FILE VERSION # IN BINARY
	BSYM	RVNO,2	;; REVISION # IN BINARY
	BSYM	RVDT,7	;; REVISION DATE IN ASCII ddmmmyy FORMAT
	BSYM	RVTI,6	;; REVISION TIME IN ASCII hhmmss FORMAT
	BSYM	CRDT,7	;; CREATION DATE IN ASCII ddmmmyy FORMAT
	BSYM	CRTI,6	;; CREATE TIME IN hhmmss FORMAT
	BSYM	EXDT,7	;; EXPIRE DATE IN ASCII ddmmmyy FORMAT
	.ENDM	F11FID
	F11FID		;;INCARNATE THE SYMBOLS

.MACRO	F11MAP		;; DEFINE THE MAPPING AREA TOO
	.offset=0
	BSYM	ESQN,1	;; EXTENSION SEGMENT NUMBER
	BSYM	ERVN,1	;; EXTENSION RELATIVE VOLUME NUMBER (NEVER USED)
	BSYM	EFNU,2	;; EXTENSION FILE NUMBER
	BSYM	EFSQ,2	;; EXTENSION SEQUENCE NUMBER
	BSYM	CTSZ,1	;; # OF BYTES IN A "BLOCK-COUNT FIELD" - ALWAYS 1
	BSYM	LBSZ,1	;; # BYTES IN "LOGICAL BLOCK NUMBER FIELD" - ALWAYS 3
	BSYM	USE,1	;; # RETRIEVAL POINTERS
	BSYM	MAX,1	;; MAX # RETRIEVAL SLOTS IN THIS MAP
	BSYM	RTRV,0	;; OFFSET TO RETRIEVAL POINTERS
.ENDM	F11MAP
	F11MAP		;;INCARNATE THE SYMBOLS

.SBTTL UNIVERSALS -- IOBITS - words and bits in the I/O page, seen from the 11

.MACRO	IOBITS
.SBTTL UNIVERSALS -- IOBITS - Basic CPU

V.CPU=	004	;CPU errors VECTOR
V.ILL=	010	;Illegal instruction VECTOR
V.RES=	010	;Reserved instruction VECTOR
V.BPT=	014	;BPT, breakpoint trap VECTOR
V.IOT=	020	;IOT, input/output trap VECTOR
V.PWF=	024	;Power Fail trap VECTOR
V.EMT=	030	;EMT, emulator trap VECTOR
V.TRP=	034	;TRAP instruction


PS=	177776	;Processor Status word (IE: PS)
R.SL=	177774	;Stack limit register

R.R7=	177707	;R7
R.PC=	R.R7	;Another name
R.R6=	177706	;R6
R.SP=	R.R6	;Another name

R.R5=	177705	;R5
R.R4=	177704	;R4
R.R3=	177703	;R3
R.R2=	177702	;R2
R.R1=	177701	;R1
R.R0=	177700	;R0

R.SWR=	177570	;Switch register
SWR=R.SWR	;Another name
R.DSP=	R.SWR	;Display register
.SBTTL UNIVERSALS -- IOBITS - DL11 console terminal

V.DLI=	060	;CONSOLE TERMINAL KEYBOARD VECTOR
V.DLO=	064	;CONSOLE TERMINAL PRINTER VECTOR

DL.RSR=	177560	;RECEIVER STATUS REGISTER
  DLDSCH=100000	;R/O DATASET STATUS CHANGE. REQUEST DATASET INTERRUPT.
  DLRNGI=40000	;R/O RING INDICATOR. IF RING COMES ON, SETS DLDSCH.
  DLCTS=20000	;R/O CLEAR TO SEND. IF CTS CHANGES, SETS DLDSCH
  DLCD=10000	;R/O CARRIER DETECT. IF CD CHANGES, SETS DLDSCH.
  DLRA=4000	;R/O RECEIVER ACTIVE. SET IF UART IS ASSEMBLING A CHARACTER.
  DLSRD=2000	;R/O SECONDARY RECEIVED DATA. IF SRD CHANGES, SETS DLDSCH.
  DLRD=200	;R/O RECEIVER DONE.  SET IF COMPLETE CHARACTER IS READY TO READ.
  DLRIE=100	;R/W RECEIVER INTERRUPT ENABLE.  DO INTERRUPT IF DLRD TURNS ON.
  DLDIE=40	;R/W DATASET INTERRUPT ENABLE. DO INTERRUPT IF DLDSCH TURNS ON
  DLSTD=10	;R/W SECONDARY TRANSMITTED DATA. IF SET, SIGNAL GOES ON.
  DLRTS=4	;R/W REQUEST TO SEND. IF SET, SIGNAL GOES ON.
  DLDTR=2	;R/W DATA TERMINAL READY.  IF SET, SIGNAL GOES ON.
  DLRDRE=1	;W/O READER ENABLE.  ADVANCE ASR PTR ONE FRAME IF AUTOMATIC.

DL.RBF=	177562	;RECEIVER BUFFER
  DLRERR=100000	;R/O RECEIVER ERROR.  LOGICAL OR OF (DLROVR,DLRFRM,DLRPAR)
  DLROVR=40000	;R/O RECEIVER OVERRUN.  THE OLD CHARACTER IS REPLACED WITH NEW.
  DLRFRM=20000	;R/O RECEIVER FRAMING ERROR.
  DLRPAR=10000	;R/O RECEIVER DATA PARITY ERROR.
  DLRDAT=377	;R/O RECEIVER DATA. THE CHARACTER READ.

DL.XSR=	177564	;XMITTER STATUS
  DLXRDY=200	;R/O TRANSMITTER READY. REQUESTS TRANSMITTER INTRP.
  DLXIE=100	;R/W TRANSMITTER INTERRUPT ENABLED. DO INTERRUPT IF DLXRDY SET.
  DLXMNT=4	;R/W TRANSMITTER MAINTENENCE.  CAUSES OUTPUT TO INPUT LOOP.
  DLXBRK=1	;R/W TRANSMITTER BREAK.  FORCE BREAK SIGNAL UNTIL CLEARED.

DL.XBF=	177566	;XMITTER BUFFER
  DLXDAT=377	;W/O TRANSMIT DATA. CHARACTER TO TYPE.
.SBTTL UNIVERSALS -- IOBITS - RH11/RP06 bit definitions


V.RH11=	254	;RH11 INTERRUPT VECTOR

RP.CS1=	176700	;;CONTROL AND STATUS REGISTER 1
  RPSC=100000	;;R/O SPECIAL CONDITION. LOGICAL OR OF "RPTRE","RPATTN","RPMCPE"
  RPTRE=40000	;;R/O TRANSFER ERROR.  LOR OF DLT,WCE,UPE,NED,NEM,PGE,
		;;MXF, MDPE, OR A DRIVE ERROR DURING DATA XFER.
  RPCPE=20000	;;R/O CONTROL BUS PARITY ERROR (DURING REMOTE REGISTER READ)
  RPDVA=4000	;;R/O DRIVE AVAILABLE. 1=NOT BUSY ON OTHER PORT.
  RPPSEL=2000	;;R/W PORT SELECT. 1=DO DATA TRANSFER VIA UNIBUS B.
  RPAD17=1000	;;R/W UNIBUS ADDRESS BIT 17.
  RPAD16=400	;;R/W UNIBUS ADDRESS BIT 16.
  RPRDY=200	;;R/O READY. 1=DATA TRANSFER IN PROGRESS. 0=DONE.
  RPIE=100	;;R/W INTERRUPT ENABLE. DO INTERUPT IF RPRDY OR RPATTN GET SET.
  RPFUNC=77	;;R/W FUNCTION AND GO BITS.
    RPOPNP=0	;  NO OPERATION
    RPOPUL=2	;  UNLOAD/STANDBY
    RPOPRC=6	;  RECALIBRATE
    RPOPDC=10	;  DRIVE CLEAR
    RPOPRP=12	;  RELEASE PORT
    RPOPSR=30	;  SEARCH COMMAND
    RPOPWC=50	;  WRITE CHECK DATA
    RPOPWH=52	;  WRITE CHECK HEADER & DATA
    RPOPWD=60	;  WRITE DATA
    RPOPWF=62	;  WRITE FORMAT (HEADER & DATA)
    RPOPRD=70	;  READ DATA
    RPOPRF=72	;  READ FORMAT (HEADER & DATA)
    RPOPSK=4	;  SEEK
    RPOPOF=14	;  OFFSET
    RPOPCL=16	;  (RETURN TO) CENTERLINE
    RPOPPA=22	;  PACK ACKNOWLEDGE
    RPOPRI=20	;  READ-IN PRESET
      RPGO=1	;;R/W GO. REQUEST DRIVE TO DO FUNCTION. CLEARED WHEN DONE.

RP.WC=	176702	;;R/W WORD COUNT REGISTER. 2s COMPLEMENT WORD COUNT FOR XFER.

RP.BA=	176704	;;R/W UNIBUS ADDRESS REGISTER. LOW 15 BITS OF XFER ADDRESS.

RP.DA=	176706	;;DESIRED SECTOR/TRACK ADDRESS REGISTER
  RPTRKA=017400	;;R/W TRACK ADDRESS - HIGH BYTE OF WORD IS TRACK ADDRESS
  RPSCTA=37	;;R/W SECTOR ADDRESS - LOW BYTE OF WORD IS SECTOR ADDRESS

RP.CS2=	176710	;;CONTROL AND STATUS 2 REGISTER
  RPDLT=100000	;;R/O DATA LATE. CAUSES RPTRE TO GET SET.
  RPWCE=40000	;;R/O WRITE CHECK ERROR. MISMATCH DURING WRITE. SETS RPTRE.

RP.DS=	176712	;;DRIVE STATUS REGISTER
  RPATA=100000	;;R/O ATTENTION.
  RPERR=40000	;;R/O SET IF RP.ER1,RP.ER2,RP.ER3 GET SET. ONLY RPOPDC CAN CLR.

RP.ER1=	176714	;;ERROR REGISTER 01
  RPDCK=100000	;;R/W DATA CHECK (IE: CORRECTABLE)
  RPUNS=40000	;;R/W UNSAVE (LOGICAL OR OF ALL UNSAFE BITS IN RPER2&RPER3)
  RPOPI=20000	;;R/W OPERATION INCOMPLETE
  RPDTE=10000	;;R/W DRIVE TIMING ERROR
  RPWLE=4000	;;R/W WRITE LOCK ERROR
  RPIAE=2000	;;R/W INVALID ADDRESS ERROR (DISK ADDRESS, NOT CORE ADDRESS)
  RPAOE=1000	;;R/W ADDRESS OVERFLOW ERROR (CYLINDER REGISTER OVERFLOWED)
  RPHCRF=400	;;R/W HEADER CRC ERROR
  RPHCE=200	;;R/W HEADER COMPARE ERROR
  RPECH=100	;;R/W ECC HARD ERROR
  RPWCF=40	;;R/W WRITE CLOCK FAIL
  RPFER=20	;;R/W FORMAT ERROR (OFFSET FMT DOESN'T MATCH DATA ON DISK)
  RPPAR=10	;;R/W PARITY ERROR
  RPRMR=4	;;R/W REGISTER MODIFICATION REFUSED
  RPILR=2	;;R/W ILLEGAL REGISTER
  RPILF=1	;;R/W ILLEGAL FUNCTION CODE

RP.OF=	176732	;;OFFSET REGISTER
  RPSCG=100000	;;R/W SIGN CHANGE (FLIPS IF HEAD IS OVER TRUE TRACK'S CENTERLINE
  RPFMT2=10000	;;R/W 1 WHEN 16BIT/WORD FORMAT, 0 WHEN 18BIT/WORD FORMAT
  RPECI=4000	;;R/W 1 TO DISABLE ECC ERROR CORRECTION
  RPHCI=2000	;;R/W 1 TO DISABLE "HEADER COMPARE"
  RPOFSD=377	;;R/W OFFSET INFORMATION

RP.DC=	176734	;;DESIRED CYLINDER
  RPCYLA=777	;;R/W CYLINDER ADDRESS.

RP.EC1=	176744	;;ECC POSITION
		;;R/O

RP.EC2=	176746	;;ECC PATTERN
		;;R/O
.ENDM	IOBITS
	IOBITS
.SBTTL UNIVERSALS -- KLDHED - Format of entry in KLDCP directory

.MACRO	WSYM	.NAME
	W.'.NAME'=.OFFSET
	.OFFSET=.OFFSET+2
.ENDM	WSYM
.OFFSET=0

.MACRO	KLDHED
WSYM	KFL0	;FIRST HALF OF KLDCP FILE NAME
WSYM	KFL1	;SECOND HALF OF KLDCP FILE NAME
WSYM	KEXT	;EXT OF KLDCP FILE NAME
WSYM	KCRE	;CREATION DATA
WSYM	KCYL	;CYLINDER OF FILE
WSYM	KTS	;TRACK/SECTOR
WSYM	KWAH	;WORDS ALLOCATED (HIGH)
WSYM	KWAL	;WORDS ALLOCATED (LOW)
WSYM	K1LA	;PDP11 LOAD ADDDRESS
WSYM	K1SA	;PDP11 START ADDRESS
WSYM	KTYP	;FILE TYPE & FILE STATUS
WSYM	KCHK	;CHECK SUM
WSYM	KRS1	;RESERVED (0)
WSYM	KRS2	;RESERVED (0)
WSYM	KCPH	;CURRENT POSITION (HIGH)
WSYM	KCPL	;CURRENT POSITION (LOW)
FDESIZ=.OFFSET	;SIZE OF AN ENTRY
.ENDM	KLDHED
	KLDHED
	.SBTTL	DEFINITIONS - "helper" macros

.MACRO	TYPE	.string	;;MACRO TO TYPE A STRING ON THE CONSOLE
	.ENABL	LC
	CALL	STYPE
	.ASCIZ	@'.string'@<15><12>
	.EVEN
.ENDM	TYPE

.MACRO	ABORT	.string	;;MACRO TO TYPE A STRING AND THEN HALT
	TYPE	<'.string'>
	HALT
.ENDM	ABORT

.MACRO	CALL	.dest
	JSR	PC,.dest
.ENDM	CALL

.MACRO	RETURN
	RTS	PC
.ENDM	RETURN
	.SBTTL	BLOCK 0 booting code
	.=0			;LOAD INTO LOCATION 0

;	THIS CODES RESIDES IN PHYSICAL DISK BLOCK 0; THE ROM LOADS IT
FELOAD:	MOV	R0,INITR0
	MOV	#INITR1,R0
	MOV	R1,(R0)+			;SAVE R1
	MOV	R2,(R0)+			;SAVE R2
	MOV	R3,(R0)+			;SAVE R3
	MOV	R4,(R0)+			;SAVE R4
	MOV	R5,(R0)+			;SAVE R5
;	MOV	SP,(R0)+			;SAVE SP
	MOV	R1,R5				;PRESERVE CSR ADDRESS IN R5
	MOV	RP.CS2-RP.CS1(R5),RPUNIT	;SAVE UNIT NUMBER

;	NOW READ IN 2ND PART OF BOOT
	MOV	#PROMPT,R0		;UNIBUS ADDRESS OF 2ND PART
	CLR	R1			;HIGH ORDER LBN=0
	MOV	#4,R2			;LOW ORDER LBN=4
	MOV	R2,R3			;REQUEST 4 BLOCK READ
	MOV	#STAK,SP		;INIT THE STACK POINTER
	CALL	REDBLK			;READ THAT BLOCK FROM RP04
	BCS	2$			;BRANCH IF CAN'T READ 2ND PART
1$:	JMP	PROMPT		;JOIN "2nD PART CODE"

2$:	ABORT	<?Can't get FELOAD part 2>
;	ROUTINE TO TYPE A CHARACTER ON THE CONSOLE TERMINAL
TYO:	MOV	R0,@#DL.XBF		;TYPE THE CHARACTER
TYO1:	TSTB	@#DL.XSR			;WAIT FOR "DONE" TO APPEAR
	BGE	TYO1			;LOOP UNTIL IT TURNS ON
	RTS	PC

;	ROUTINE TO TYPE A STRING
STYPE:	MOV	(SP)+,R1		;PICK UP ADDRESS OF STRING
STYPE1:	MOVB	(R1)+,R0		;PICK UP A BYTE
	BEQ	STYPE2			;EXIT IF WE PICK UP A ZERO
	CALL	TYO			;OTHERWISE TYPE IT
	BR	STYPE1			;LOOP TILL WE FIND THE 0
STYPE2:	INC	R1			;ADVANCE ONE BYTE
	BIC	#1,R1			;TURN OFF ODD BIT
	JMP	@R1			;RETURN TO CALLER
;	ROUTINE TO ROTATE THE 3 WORDS @R1 (R3) BITS LEFT
;	(USED TO DO ECC CORRECTION)
PROL36:	ASL	(R1)
	ROL	2(R1)
	ROL	4(R1)
	DEC	R3
	BNE	PROL36
	RETURN
;	ROUTINE TO READ RP04/RP05/RP06 DISK BLOCKS
;ENTER:
;	R0/	UNIBUS AADRESS OF 1ST WORD TO XFER
;	R1/	HIGH ORDER WORD OF LBN
;	R2/	LOW ORDER WORD OF LBN
;	R3/	# OF BLOCKS TO READ CONTIGUOUSLY, 0 MEANS 1
;	R5/	ADDRESS OF RPCS1

REDBLK:	MOV	R0,SAVUBA	;SAVE UNIBUS ADDRESS
	MOV	R3,SAVCNT	;SAVE COUNT OF BLOCKS
REDBL0:	MOV	R1,SAVHLB	;SAVE HIGH LBN
	MOV	R2,SAVLLB	;SAVE LOW LBN

;	HERE TO READ A BLOCK
	MOV	#16.,R4		;TRY UP TO 16 TIMES
REDBL1:	MOV	RPUNIT,RP.CS2-RP.CS1(R5)	;SETUP UNIT FIELD
	MOV	SAVUBA,RP.BA-RP.CS1(R5)	;SET THE UNIBUS ADDRESS
	MOV	#-400,RP.WC-RP.CS1(R5)	;SET THE WORD COUNT FOR 1 BLOCK
	CLR	R3			;START OFF WITH 0 ANSWER
1$:	INC	R3			;COUNT A SUBTRACTION
	SUB	#380.,R2		;USE A SUBTRACT LOOP ...
	SBC	R1			;...TO CALCULATE "LBN / BPC"
	BPL	1$			;...TO GET DESIRED CYLINDER ADDRESS
	DEC	R3			;FORGET THE LAST SUBTRACTION
	ADD	#380.,R2		;PUT BACK THE LAST CYLINDER'S BLOCKS
	ADC	R1			;...
; NOW R3=DESIRED CYLINDER ADDRESS
	MOV	R3,RP.DC-RP.CS1(R5)	;SPECIFY THE DESIRED CYLINDER

	CLR	R3			;CLEAR RESULT
2$:	INC	R3			;COUNT FIRST ONE
	SUB	#20.,R2
	SBC	R1			;TAKE CARE OF CARRY (IF ANY)
	BPL	2$			;LOOP UNTIL WE GO TOO FAR
	ADD	#20.,R2			;RETURN IT
	ADC	R1			;FIX FINAL CARRY
	DEC	R3			;ONE LESS THAN WE THOUGHT

	SWAB	R3			;TRACK IN LH
	BIS	R3,R2			;INSERT SECTOR
	MOV	R2,RP.DA-RP.CS1(R5)	;TELL DRIVE TRACK/SECTOR

	CLR	RP.OF-RP.CS1(R5)	;CLEAR OFFSET
	CMP	R4,#8.		;2ND 8 TRIES?
	BGT	3$			;NO
	MOV	#RPHCI,RP.OF-RP.CS1(R5)	;YES, TRY TURNING ON HEADER INHIBIT
3$:	MOV	#71,RP.CS1-RP.CS1(R5)	;TELL KONTROLLER TO DO THE READ
	CLR	R0			;CLEAR TIMEOUT COUNT
4$:	INC	R0			;COUNT UP TIMER
	BEQ	5$			;BRANCH IF XFER TIMED OUT
	BIT	#RPTRE!RPCPE!RPRDY,RP.CS1-RP.CS1(R5)	;TEST FOR DONE
	BEQ	4$			;LOOP TILL ONE COMES ON

5$:	DEC	R4			;CHECK RETRY COUNT
	BMI	GIVEUP			;GIVE UP IF NO MORE POSSIBLE
	TST	R0			;TEST TIMEOUT COUNT
	BEQ	RETRY			;IT TIMED OUT, TRY IT ALL OVER AGAIN
	BIT	#RPCPE!RPTRE,RP.CS1-RP.CS1(R5);CHECK CONTROL BUS PARITY ERROR
	BNE	RETRY			;RETRY ENTIRE OPERATION
	BIT	#RPATA!RPERR,RP.DS-RP.CS1(R5)	;CHECK DISK ERRORS
	BNE	TRYECC			;GO CONSIDER CORRECTABLE ERROR

;IF WE GET HERE, THE XFER WAS APPARENTLY ERROR-FREE
REDAOK:	MOV	SAVLLB,R2		;RESTORE LOW LBN
	MOV	SAVHLB,R1		;RESTORE HIGH LBN
	INC	R2			;ADD 1 TO LBN
	ADC	R1			;ADD POSSIBLE CARRY
	ADD	#1000,SAVUBA		;STEP TO NEXT BLOCK ADDRESS
	DEC	SAVCNT
	BGT	REDBL0			;READ ANOTHER
;	ADD TO SAVUBA WILL NEVER "OVERFLOW" 16 BIT ADDRESS
;	CLC				;CLEAR ERROR
	RETURN

;HERE TO RETRY THE XFER
RETRY:	MOV	SAVHLB,R1		;RESTORE THE LBN TO XFER
	MOV	SAVLLB,R2		;...
	BR	REDBL1			;GO DO THE OPERATION AGAIN
;WE DID OUR BEST, GIVE UP
GIVEUP:	SEC
	RETURN

;HERE IF READ FAILED, TRY AGAIN
TRYECC:	BIT	#77777,RP.ER1-RP.CS1(R5)	;CHECK FOR ANY ERROR, 'CEPT ECC DATA
	BNE	RETRY			;IF NOT ECC ERR, TRY VIA HARD RE-READ
	MOV	RP.EC1-RP.CS1(R5),R2	;GET ECC POSITION
	BEQ	RETRY			;GIVE UP IF POS=0

	CLR	ECWRD0
	CLR	ECWRD0+2
	CLR	ECWRD0+4
	CLR	ECWRD0+6
	CLR	ECWRD0+10
	CLR	ECWRD0+12

	MOV	RP.EC2-RP.CS1(R5),ECMSK0;GET ECC CORRECTION

	DEC	R2			;DIVIDE POSITION BY 18.
	CLR	R3
61$:	SUB	#18.,R2			;
	BLT	62$			;
	INC	R3			;
	BR	61$			;

62$:	ADD	#18.,R2			;DONE, R3=WORD, R2=SHIFTS
	ASL	R3			;DOUBLE WORD POSITION, 11 ADR IN BYTES
	ADD	SAVUBA,R3
	MOV	R3,ECADR0		;SETUP 1ST BAD WORD ADDRESS

	TST	(R3)+
	MOV	R3,ECADR1		;SETUP 2ND BAD WORD ADDRESS
;	MOV	#ECWRD0,R1
	MOV	(R3),ECWRD0		;SETUP 2ND BAD WORD
	MOV	(R3),ECBAD1		;SAVE 2ND BAD WORD
	CALL	PROL36			;POSITION 2ND WORD INTO UPPER 18 BITS

	MOV	@ECADR0,ECWRD0		;SETUP 1ST BAD WORD
	MOV	ECWRD0,ECBAD0		;SAVE 1ST BAD WORD

;	MOV	#ECMSK0,R1
	MOV	R2,R3
	CALL	PROL36			;POSITION ECC CORRECTION WORD

	MOV	ECMSK0,-(SP)		;CORRECT BITS 0-16
	BIC	ECWRD0,(SP)		;
	BIC	ECMSK0,ECWRD0
	BIS	(SP)+,ECWRD0

	MOV	ECMSK0+2,-(SP)		;CORRECT BITS 17-32
	BIC	ECWRD1,(SP)		;
	BIC	ECMSK0+2,ECWRD1
	BIS	(SP)+,ECWRD1

	MOV	ECMSK0+4,-1(SP)		;CORRECT BITS 33-36
	BIC	ECWRD2,(SP)
	BIC	ECMSK0+4,ECWRD2
	BIS	(SP)+,ECWRD2

;	MOV	#ECWRD0,R1
	MOV	ECWRD0,@ECADR0		;PUT 1ST CORRECT WORD BACK IN CORE

	MOV	#14.,R3
	CALL	PROL36
	MOV	ECWRD2,@ECADR1		;PUT 2ND WORD BACK IN CORE
	BR	REDAOK			;NOW GO TO NEXT BLOCK
	.SBTTL	END OF BLOCK 0 CODE

	.DEPHASE
	.=.
B0WRDS=./2		;# OF WORDS USED IN BLOCK 0 (NOT BYTES)
	.PRINT	1000-.;LOCATIONS LEFT IN BLOCK 0 BOOT
	.SBTTL	START OF BLOCK 4-7 CODE

	.=4000				;THIS GOES INTO BLOCK 4 (THRU 7)

PROMPT:	BIT	#1,INITR5		;READ "SWR" BUTTON PUSHED?
	BNE	SWRFOO			;YES, GO DO THAT

	TSTB	INITR5			;TEST THE "DISK" BIT
	BMI	DISK			;BRANCH IF DISK SET
;N.B.: HE PUSHED DTA/FLOPPY BUTTON - AND WE COULDN'T HAVE GOTTEN HERE!
	ABORT	<?FELOAD cannot boot DECtape or floppy>

SWRFOO:
DISK:	BIT	#100000,@#SWR		;IS THE HIGH ORDER BIT SET?
	BNE	GETKLD			;YES, GET KLDCP
	BR	GETRSX			;NO, GET RSX20F
	.SBTTl	BOOT IN AND START 20F FRONT END

USERSX:	MOV	#100207,INITR5
	MOV	#176700,INITR1
	MOV	#176700,R5
	MOV	#STAK,SP
GETRSX:	CALL	MOVEME			;GO TO NEW HOME
	CALL	GETHOM			;GET THE TOPS10 HOME BLOCKS
	CALL	GETH11			;GET THE FILES11 HOME BLOCK
	CALL	FND550			;GO FIND FHB FOR 5,5,0 (CORIMG.SYS)
	CALL	RED550			;GO READ IN CORIMG.SYS INTO CORE
	CALL	FNDACP			;GO FIND F11ACP.TSK
	CALL	POK20F			;GO POKE SOME MAGIC VALUES INTO
					;THE RESIDENT IMAGE OF THE 20F MONITOR
	JMP	RESACS			;RESTORE ACS AND START RSX20F
;	HERE TO LOAD AND START KLDCP FRONT END
GETKLD:	CALL	GETHOM		;GET TOPS10 HOME BLOCK(S)
	CALL	VRFKLD		;VERIFY THIS IS A KLAD PACK
	CALL	FNDDIR		;FIND THE DIRECTORY LOCATION AND SIZE
	CALL	REDDIR		;GO READ KLAD10 DIRECTORY
	CALL	FNDKLD		;GO FIND KLDCP.BIN IN THE DIRECTORY
	CALL	LODKLD		;GO LOAD KLDCP.BIN

	JMP	RESACS		;GO START KLDCP
GETHOM:	MOV	#1,R2
	CALL	GETH10
	BCS	2$
1$:	RETURN

2$:	MOV	#12,R2
	CALL	GETH10
	BCC	1$
	ABORT	<?Unable to read HOME.SYS>

;	ROUTINE TO READ A TOPS-10 HOME BLOCK

GETH10:	MOV	DBA,R0			;ADDRESS OF DISK BUFFER
	CLR	R1			;HIGH ORDER LBN OF HOME BLOCKS ALWAYS 0
	CLR	R3			;ALWAYS JUST ONE BLOCK TO READ
	CALL	REDBLK			;READ THE HOME BLOCK
	BCC	2$			;BRANCH IF NO ERRORS
1$:	SEC				;SET CARRY SO CALLER SEES ERROR
	RTS	PC			;RETURN WITH CARRY SET

;HERE IF READ OF BLOCK SUCCEEDED
2$:	CMP	#105755,DB		;MAKE SURE LH OF PDP10 WORD #0='HOM'
	BNE	1$			;GIVE ERROR RETURN IF NOT
	TST	DB+2			;MAKE SURE RH OF PDP10 WORD#0 IS ZERO
	BNE	1$			;GIVE ERROR RETURN IF NOT

	CLC				;CLEAR CARRY
	RTS	PC			;GIVE GOOD RETURN
;	ROUTINE TO READ IN THE FILES11 HOME BLOCK
;	ENTER WITH GOOD TOPS10 HOME BLOCK IN DB
GETH11:	MOV	DB+<HOMFE0*2>-2,R1	;GET "HIGH" LBN OF HOME BLOCK
	BMI	1$			;BRANCH IFF VALID BIT IS SET
	ABORT	<?VALID bit not set in TOPS-10 home block>

;	HERE IF TOPS10 HOME BLOCK SAYS WE HAVE AN RSX20F FILE AREA
;	READ IN THE FILES11 HOME BLOCK
1$:	MOVB	R1,R1			;ISOLATE LOWBYTE (OF HIGH WORD)
	MOV	DB+<HOMFE0*2>,R2	;GET LOW WORD OF HOME BLOCK LBN
	CLRB	R2			;CLEAR LOW BYTE
	ADD	#400,R2			;STEP TO MULTIPLE OF 400 SECTORS
	CLR	R3			;SETUP TO READ 0 BLOCKS (=1 BLOCK)
	MOV	DBA,R0			;SETUP TO READ INTO DISK BUFFER

	CALL	REDBLK			;READ WHAT OUGHT TO BE FILE11 HOME BLOCK
	BCC	2$			;
	ABORT	<?Unable to read FILES-11 home block>
2$:	RETURN
;	ROUTINE TO "FIND" THE FHB FOR CORIMG.SYS.
;	CORIMG.SYS IS "KNOWN" FILE 5,5,0 SO LOOKUP THE QUICK WAY.
;	ENTER WITH GOOD FILES11 HOME BLOCK IN DB
FND550:	MOV	DB+W.IBLB,R1		;GET HIGH ORDER INDEX BIT MAP LBN
	MOV	DB+W.IBLB+2,R2		;GET LOW ORDER LBN
	ADD	DB+W.IBSZ,R2		;ADD SIZE OF BIT MAP TO GET LBN OF 1,1,0
	ADC	R1			;ADD THE OVERFLOW OF THE LOW ORDER ADD
	ADD	#5-1,R2			;COMPUTE ADDRESS OF (5,5,0)
	ADC	R1			;...
	MOV	R1,SAVR1		;SAVE R1 OF FHB FOR CORIMG
	MOV	R2,SAVR2		;SAVE R2 OF FHB FOR CORIMG
	CLR	R3			;SPECIFY 0 BLOCKS (=1 BLOCK)
	MOV	DBA,R0			;READ INTO DISK BUFFER
	CALL	REDBLK			;READ WHAT OUGHT TO BE THE RIB OF
					;(5,5,0), IE: CORIMG.SYS
	BCC	3$
	ABORT	<?Can't read FHB of CORIMG.SYS to load RSX-20F>

;	HERE WHEN WE HAVE (APPARENTLY) READ IN THE FHB FOR CORIMG.SYS.
;	DO SOME (CASUAL) VERIFICATION THAT IT REALLY...
;	...IS A GOOD FHB FOR CORIMG.SYS(5,5,0).
3$:	MOV	DB+W.FNUM,R1		;GET FILE NUMBER
	MOV	DB+W.FSEQ,R2		;GET FILE SEQUENCE NUMBER
	CMP	R1,R2			;THE SAME?
	BEQ	5$			;BRANCH AHEAD IF FILSEQ=FILNUM
	ABORT	<?Sequence # of CORIMG.SYS not equal to file #>

5$:	CMP	R1,#5			;SHOULD BE FILE (5,5,0)
	BEQ	6$			;
	ABORT	<?File ID for CORIMG.SYS is not (5,5,0)>

6$:	RETURN
;	ROUTINE TO READ CORIMG.SYS INTO CORE IN THE PROPER PLACE (0-127777)
;	ENTER WITH GOOD FHB FOR CORIMG.SYS IN DB
RED550:	TYPE	<[Loading RSX-20F]>
	MOVB	DB+W.MPOF,R2		;GET OFFSET OF ID AREA
	ADD	R2,R2			;COMPUTE SIZE IN BYTES
	ADD	DBA,R2			;COMPUTE R2= ADDRESS OF MAP AREA
	MOVB	W.RTRV(R2),R1		;GET HIGH LBN BYTE
	MOV	W.RTRV+2(R2),R2		;GET LOW LBN WORD
	CLR	R0			;READ INTO LOCATION 0
	MOV	#130,R3			;READ 130 BLOCKS (IE: ALL OF CORIMG.SYS)
	CALL	REDBLK			;READ A BLOCK (IE: BLOCK 0 OF CORIMG.SYS)
	BCC	1$
	  ABORT	<Error reading CORIMG.SYS -- RSX-20F load aborted>
1$:	RETURN
;	ROUTINE TO FIND THE LOWEST FILE#'D FILE WITH NAME OF F11ACP.TSK
;	WE'LL USE THIS FILE'S LBN ADDRESS TO TELL THE INCORE RSX20F WHERE
;	IT'S PRINCIPLE ACP FOR THE BOOT DEVICE IS
;	ENTER WITH SAVR1/SAVR2 BEING THE LBN OF FHB FOR CORIMG.SYS
FHBMAX:	60.				;READ NO MORE THAN 60 FHBS
F11ACP:	.RAD50	/F11ACP   TSK/

FNDACP:	DEC	FHBMAX			;BUMP COUNT DOWN
	BMI	1$			;BRANCH IF WE'RE NEVER FOUND IT
	INC	SAVR2			;STEP TO NEXT BLOCK
	TST	SAVR2			;DID IT JUST OVERFLOW?
	BNE	2$			;NO, SKIP UPDATE
	INC	SAVR1			;
2$:	MOV	DBA,R0			;READ NEXT FHB INTO DB
	MOV	SAVR1,R1		;GET FHB LBN ADR
	MOV	SAVR2,R2		;...
	CLR	R3			;1 BLOCK ONLY
	CALL	REDBLK			;READ IN AN FHB
	BCS	FNDACP			;GO ON TO NEXT FHB IF WE CAN'T READ THIS
	MOVB	DB+W.IDOF,R2		;GET OFFSET TO ID AREA IN WORDS
	ADD	R2,R2			;COMPUTE OFFSET IN WORDS
	ADD	DBA,R2			;LOAD R2=ADDRESS OF ID AREA
	CMP	W.FNAM(R2),F11ACP	;DOES THIS LOOK AS IF IT IS F11ACP?
	BNE	FNDACP			;GO TO NEXT FHB IF FILE DOESN'T MATCH
	CMP	W.FNAM+2(R2),F11ACP+2	;...?
	BNE	FNDACP			;GO TO NEXT FHB IF FILE DOESN'T MATCH
	TST	W.FNAM+4(R2)		;...
	BNE	FNDACP			;GO TO NEXT FHB IF FILE DOESN'T MATCH
	CMP	W.FTYP(R2),F11ACP+6.	;CHECK FOR .TSK EXTENSION
	BNE	FNDACP			;GO TO NEXT FHB IF TYPE DOESN'T MATCH
	MOV	W.FVER(R2),LEVELV	;STORE THE VERSION OF THE ACP
	RETURN

1$:	SEC
	RETURN
;	ROUTINE TO POKE MAGIC VALUES INTO THE 20F CORE IMAGE
;	  TO COMPENSATE FOR THE FACT WE DIDN'T BOOT THIS VIA "SAVE"S RPBOOT.
;	ENTER WITH GOOD FHB FOR F11ACP IN DB.

;*** THE CONSTANTS DEFINED HERE NEED TO BE REDEFINED AS NEEDED
S.DL=32	;; THIS OFFSET IS START OF 2 WORD ENTRY CONTAINING DISK ADDRESS
	;; OF THE LOAD IMAGE FOR THIS TASK. OFFSET INTO STD BLOCK.
RPBOOT=7664	;; ADDRESS OF RPBOOT, TAKE FROM LISTING OF SAV TASK
RPRESU==7772	;; ADDRESS OF LINE SAYING "BOOTSTRAP COMPLETE", FROM SAV LISTING
;*** THE CONSTANTS ABOVE MAY NEED TO BE UPDATED, BUT NOTE THAT
;*** THIS IS NOT COMMON SINCE S.DL MAY NEVER CHANGE AND RPRESU-RPBOOT
;*** WILL PROBABLY REMAIN A CONSTANT EVEN IF RPRESU OR RPBOOT CHANGES
POK20F:	MOVB	DB+W.MPOF,R2		;GET OFFSET TO MAP AREA
	ADD	R2,R2			;CONVERT TO BYTE OFFSET
	ADD	DBA,R2			;ADD NEW BUFFER ADR
	MOVB	W.RTRV(R2),R1		;GET HIGH LBN BYTE OF F11ACP.TSK
	MOV	W.RTRV+2(R2),R2	;GET LOW LBN WORD OF F11ACP.TSK
	ADD	#2,R2			;ADD 2 TO GET AT SKIP TASK HEADER INFO
	ADC	R1			;...
	CALL	GETSTD		;FIND VALUE OF .STDTB BASED ON 20F VERSION
	TST	R0		;CHECK TO MAKE SURE WE GOT IT
	BEQ	1$
	ADD	#<4*2>,R0	;COMPUTE ADDRESS OF F11ACP ENTRY
	MOV	@R0,R0		;LOAD R0 WITH STD FOR F11ACP
	BEQ	1$		;BRANCH IF WE FAILED
	MOV	R1,S.DL+0(R0)	;INSERT HIGH ORDER LBN INTO STD BLOCK
	MOV	R2,S.DL+2(R0)	;INSERT LOW ORDER LBN INTO STD BLOCK

	MOV	#<RPRESU-RPBOOT>,NEWPC	;NEW PC INSIDE "RPBOOT" IN THE SAV TASK

;	Force RSX20F to believe that we used "SW/REG" rather than "DISK"
;	even if we didn't!
;[JJF %1(4) Maybe we really don't want it to believe it!]
;	BIS	#200!1,INITR5		;TURN ON "DISK=200" AND "SW=1"
	JMP	RESACS			;RESTORE ACS AND START BOOT

1$:	ABORT	<?STD address of F11ACP within CORIMG.SYS incorrect>
;	ROUTINE TO SEARCH TABLES TO FIND THE VALUE OF .STDTB
;	RETURN CURRENT 20F'S VALUE OF .STDTB IN R0

GETSTD:	MOV	#VERTAB+NEWADR,R0	;LOAD ADDRESS OF TABLE
1$:	TST	@R0			;CHECK FOR END OF TABLE
	BEQ	2$			;BRANCH IF END OF TABLE
	CMP	(R0)+,LEVELV		;COMPARE WITH 20F VERSION
	BEQ	GOTSTD			;BRANCH IF WE FIND SAME VERSION#
	BR	1$
2$:	ABORT	<?Unable to determine F11ACP.TSK file version>
GOTSTD:	MOV	VALTAB-VERTAB-2(R0),R0	;LOAD STD ADDRESS
	RETURN


;*** NOTE THAT NEWER VERSIONS OF 20F WILL NEED TO HAVE ENTRIES IN THE DTBX MACRO
;*** SIMPLY LOOK AT THE NEW RSX20F MAP FOR THE VALUE OF .STDTB.
	.MACRO	DTBX	;;LIST OF .STDTB VALUES
XP	1506,6350	;VERSION 1506
XP	1550,6372	;VERSION 1550
XP	1600,6372	;VERSION 1600
XP	1601,6372	;VERSION 1601
	.ENDM
;	MACROS TO EXPAND THE VERSION NUMBER INFO FOR 20F
.MACRO XP	a,b
.WORD	a
.ENDM
VERTAB:	DTBX
	0

.MACRO XP	a,b
.WORD	b
.ENDM
VALTAB:	DTBX
;	ROUTINE TO MOVE THE INCORE IMAGE 0-7777 TO NEWHOM-<NEWHOM+7777>

MOVEME:	MOV	#DB+NEWADR,DBA		;SETUP NEW DB ADDR
	MOV	#NEWADR,R0		;SETUP DESTINATION
	CLR	R1			;SETUP ORIGIN
	MOV	#ENDING/2,R2		;SETUP # WORDS TO MOVE
1$:	MOV	(R1)+,(R0)+		;MOVE A WORD TO NEW HOME
	SOB	R2,1$			;KEEP DOING IT

	ADD	#NEWADR,SP		;RELOCATE THE STACK
	ADD	#NEWADR,(SP)		;ADJUST RETURN ADDRESS
	RTS	PC			;RETURN TO SAME PLACE IN NEW HOME
;	ROUTINE TO VERIFY THAT THIS IS A GOOD KLAD10 PACK
;	ENTER WITH TOPS10 HOME BLOCK IN DB.
VRFKLD:	CMP	DB+<HOMKV2*2>,#043241	;CHECK FOR "KLAD10" IN RAD50
	BNE	1$		;BRANCH IF NOT THERE
	CMP	DB+<HOMKV3*2>,#016766	;CHECK 2ND HALF
	BEQ	2$		;BRANCH IF "KLAD10" THERE
1$:	ABORT	<?RAD50 "KLAD10" missing>

2$:	RTS	PC			;RETURN
;	ROUTINE TO LOCATE THE SIZE AND POSITION OF THE KLDCP DIRECTORY.
;	ENTER WITH GOOD TOPS10 HOME BLOCK IN DB.
FNDDIR:	CLR	LBNL		;CLEAR BLOCK NUMBER SUM
	CLR	LBNH		;CLEAR BLOCK NUMBER SUM HIGH ORDER
	MOV	#19.*20.,R1	;GET MULTIPLIER

3$:	ADD	DB+<HOMKCY*2>,LBNL
	ADC	LBNH		;ADD IN CARRY
	SOB	R1,3$		;LOOP

	MOV	#20.,R1		;GET MULTIPLIER
	MOVB	DB+<HOMKTS*2>+1,R4	;GET TRACK
4$:	ADD	R4,LBNL		;ADD IN A TRACK OF BLOCKS
	ADC	LBNH		;ADD IN CARRY
	SOB	R1,4$		;ACCOUNT FOR ALL TRACKS

	MOVB	DB+<HOMKTS*2>,R4	;GET SECTOR
	ADD	R4,LBNL		;ADD IN SECTOR COUNT
	ADC	LBNH		;FIX UP THE CARRY
	MOV	DB+<HOMKLN*2>,KLDLEN;REMEMBER SIZE OF DIRECTORY
	RTS	PC		;RETURN
REDDIR:	MOV	#KLDIR,R0	;SETUP ADDRESS OF DIRECTORY
	MOV	LBNH,R1		;SETUP HIGH LBN
	MOV	LBNL,R2		;SETUP LOW LBN OF DIRECTORY
	MOV	KLDLEN,R3	;RECALL SIZE OF DIRECTORY
	CALL	REDBLK		;READ IN THE DIRECTORY
	BCS	8$		;DIE IF CAN'T READ DIRECTORY
	RTS	PC		;RETURN
8$:	ABORT	<?I/O error reading KLADFE.DIR>
FNDKLD:	MOV	#KLDIR,R4	;POINT R4 AT DIRECTORY BUFFER

	CLR	R1		;CLEAR SUM (WILL BECOME COUNT OF ENTRIES)
	MOV	KLDLEN,R2	;GET MULTIPLIER
5$:	ADD	#1000/FDESIZ,R1	;COMPUTE # ENTRIES PER BLOCK
	SOB	R2,5$		;COMPUTE # OF ENTRIES


6$:	CMP	W.KFL0(R4),W.KFL0+KLDCP
	BNE	7$		;BRANCH IF NOT EQUAL IN 1ST HALF OF FILE NAME
	CMP	W.KFL1(R4),W.KFL1+KLDCP
	BNE	7$		;BRANCH IF NOT CORRECT 2ND HALF OF FILE NAME
	CMP	W.KEXT(R4),W.KEXT+KLDCP
	BEQ	FOUNDK		;BRANCH IF FILE NAMES AND EXT ALL MATCH

; HERE IF SOME PART OF FILE NAME OR EXTENSION DOES NOT MATCH
7$:	ADD	#FDESIZ,R4	;STEP TO NEXT ENTRY
	SOB	R1,6$		;LOOP FOR NEXT ENTRY
	ABORT	<?Cannot find KLDCP.BIN>

;FOUND KLDCP.BIN, CONVERT CYL/TRACK/SECTOR TO LOGICAL BLOCK NUMBER
FOUNDK:	CLR	LBNH		;CLEAR LBN HIGH
	CLR	LBNL		;CLEAR LBN LOW
	MOV	W.KCYL(R4),R0	;GET CYL#
	BEQ	2$		;SKIP IT IF ON CYLINDER 0
1$:	ADD	#380.,LBNL	;ADD IN A CYLINDER WORTH OF BLOCKS
	ADC	LBNH		;	(TAKE CARE OF CARRY, IF ANY)
	SOB	R0,1$		;...FOR EVERY CYLINDER THERE
2$:	MOVB	W.KTS+1(R4),R0	;GET TRACK # (NEVER .GT. 20, IGNORE SIGN EXTEND)
	BEQ	4$		;DON'T IF ON TRACK 0
3$:	ADD	#20.,LBNL	;ADD IN A TRACK'S WORTH OF BLOCKS
	ADC	LBNH		;	(TAKE CARE OF CARRY, IF ANY)
	SOB	R0,3$		;...FOR EVERY TRACK INVOLVED
4$:	MOVB	W.KTS(R4),R0	;GET SECTOR #
	ADD	R0,LBNL		;ADD SECTOR NUMBER AS FINAL OFFSET
	ADC	LBNH		;AND TAKE CARE OF FINAL CARRY

;CONVERT THE WORD COUNT TO A BLOCK COUNT
FIXWCK:	MOV	#8.,R0		;GET #POSITIONS TO SHIFT
1$:	ASR	W.KWAH(R4)	;SHIFT TO THE RIGHT
	ROR	W.KWAL(R4)	;THE WORD COUNT RIGHT
	SOB	R0,1$		;TO CONVERT TO A BLOCK COUNT
	TST	W.KWAH(R4)	;TEST HIGH ORDER (BLOCK) COUNT
	BEQ	2$
	ABORT	<?KLDCP.BIN is too large to load>
2$:	RTS	PC		;RETURN

KLDCP:	.RAD50	/KLDCP BIN/
LODKLD:	CLR	FCOUNT		;INITIALIZE "DVFRAM" (AND DVWORD)
	TYPE	<[Loading KLDCP.BIN]>
	MOV	W.KWAL(R4),BLKCNT
LDBIN1:	CLR	$CKS11		;INITIALIZE THE CHECKSUM
	CALL	DVFRAM		;GET A FRAME INTO R0
	DECB	R0		;CHECK FOR "BLOCK START"
	BNE	LDBIN1		;LOOP AND WAIT FOR BLOCK START CODE (IE: 1)

	CALL	DVFRAM		;READ ANOTHER FRAME (AND FORGET IT)

	CALL	DVWORD		;GET A FULL WORD, THE BYTE COUNT
	MOV	R0,LBC		;SAVE BYTE COUNT
	SUB	#6,LBC		;CHECK FOR XFER BLOCK
	BEQ	LJMP		;IF BYTE COUNT = 6, THIS IS AN XFER BLOCK
	CALL	DVWORD		;GET A FULL WORD, THE LOAD ADDRESS
	MOV	R0,R4		;SAVE LOAD ADDRESS

LDBIN2:	CALL	DVFRAM		;GET A DATA BYTE
	DEC	LBC		;DECREMENT BYTE COUNT
	BGE	LDBIN3		;BRANCH IF INSIDE DATA PART OF PACKET
	TSTB	$CKS11		;IF BYTE COUNT EXPIRES, CHECK CHECKSUM
	BEQ	LDBIN1		;START ANOTHER BLOCK IF CHECKSUM WAS OK
BADCHK:	ABORT	<?Checksum error while loading KLDCP.BIN>

LDBIN3:				;
10$:	MOVB	R0,(R4)+	;SAVE THE BYTE INTO CORE
12$:	BR	LDBIN2		;LOOP FOR MORE DATA

LJMP:	CALL	DVWORD		;GET (POSSIBEL) XFER ADDRESS
	MOV	R0,NEWPC		;REMEMBER XFER ADDRESS
	CALL	DVFRAM		;GET A FRAME
	TSTB	$CKS11		;CHECK CHECKSUM
	BNE	BADCHK
	RTS	PC		;RETURN
RESACS:	MOV	INITR0,R0	;RESTORE R0
	MOV	INITR1,R1	;RESTORE R1
	MOV	INITR2,R2	;RESTORE R2
	MOV	INITR3,R3	;RESTORE R3
	MOV	INITR4,R4	;RESTORE R4
	MOV	INITR5,R5	;RESTORE R5
	MOV	INITSP,SP	;RESTORE SP
	JMP	@NEWPC		;START AT NEWLY LOADED CODE
;	ROUTINE TO READ A FRAME
DVFRAM:	DEC	FCOUNT		;ANY FRAMES LEFT?
	BMI	DVFMOR		;NO, GO GET MORE
	MOVB	@FPOINT,R0	;YES, GET IT
	BIC	#^C377,R0	;CLEAR UPPER BYTE
	ADD	R0,$CKS11	;COMPUTE CHECKSUM
	INC	FPOINT		;UPDATE POINTER
	RETURN			;RETURN

DVWORD:	CALL	DVFRAM		;GET A FRAME
	MOV	R0,-(SP)	;SAVE THE 1ST BYTE
	CALL	DVFRAM		;GET ANOTHER FRAME
	SWAB	R0		;MAKE IT THE "HIGH" FRAME
	BIS	(SP)+,R0	;COMBINE WITH 1ST BYTE
	RETURN			;RETURN

DVFMOR:	DEC	BLKCNT		;COUNT ANOTHER BLOCK AS READ
	BMI	2$		;COMPLAIN IF PREMATURE EOF
	MOV	DBA,R0		;BUFFER ADDRESS
	MOV	LBNH,R1		;GET DISK ADDRESS
	MOV	LBNL,R2		;GET DISK ADDRESS, LOW PART
	CLR	R3		;GET 1 BLOCK ONLY
	MOV	R4,-(SP)	;SAVE R4 (BYTE POINTER)
	CALL	REDBLK		;READ ANOTHER BLOCK
	BCS	1$		;REMARK ON ERROR
	MOV	(SP)+,R4	;RESTORE BYTE POINTER
	MOV	#1000,FCOUNT	;1000 FRAMES NOW AVAILABLE
	MOV	DBA,FPOINT	;STARTING AT DB
	INC	LBNL		;START TO READ NEXT BLOCK
	ADC	LBNH		;...
	BR	DVFRAM

1$:	MOV	(SP)+,R4	;RESTORE BYTE POINTER
	ABORT	<?Input error reading KLDCP.BIN>

2$:	ABORT	<?Premature EOF while reading KLDCP.BIN>
	.SBTTL	END OF 2ND PART

DBA:	.WORD	DB
	.=.
	.PRINT	10000-.;	BYTES REMAINING IN 2ND PART OF BOOT
	.SBTTL	IMPURE NON-INITIALIZED DATA

	.=10000
	.BLKW	50
STAK:	.BLKW	1
DB:	.BLKW	400			;DISK I/O BUFFER
SAVR1:	.BLKW	1		;R1 (HIGH ORDER LBN OF CORIMG.SYS'S FHB)
SAVR2:	.BLKW	1		;R2 (LOW ORDER LBN OF CORIMG.SYS'S FHB)
BLKCNT:	.BLKW	1		;BLOCK COUNT FOR READING .BIN FILES
LBC:	.BLKW	1			;BYTE COUNT OF CURRENT .BIN PACKET
$CKS11:	.BLKw	1		;THE .BIN FILE CHECKSUM WORD
FPOINT:	.BLKW	1			;POINTER TO CURRENT FRAME
FCOUNT:	.BLKW	1			;COUNT OF FRAMES IN CURRENT DISK BUFFER

INITR0:	.BLKW	1			;THE R0 WE GOT FROM THE ROM
INITR1:	.BLKW	1			;THE R1 WE GOT FROM THE ROM
INITR2:	.BLKW	1			;THE R2 WE GOT FROM THE ROM
INITR3:	.BLKW	1			;THE R3 WE GOT FROM THE ROM
INITR4:	.BLKW	1			;THE R4 WE GOT FROM THE ROM
INITR5:	.BLKW	1			;THE R5 WE GOT FROM THE ROM
INITSP:	.BLKW	1			;THE SP WE GOT FROM THE ROM
NEWPC:	.BLKW	1		;THE R7 WE WANT TO START PROGRAM WITH
SAVUBA:	.BLKW	1			;THE UNIBUS ADDRESS
RPUNIT:	.BLKW	1			;COPY OF RPCS2 TO SAVE UNIT #
SAVHLB:	.BLKW	1			;HIGH WORD OF LBN FOR NEXT XFER
SAVLLB:	.BLKW	1			;LOW WORD OF LBN FOR NEXT XFER
SAVCNT:	.BLKW	1			;# OF BLOCKS TO XFER, 0 COUNTED AS 1
LBNH:	.BLKW	1			;LBN HIGH
LBNL:	.BLKW	1			;LBN LOW
KLDLEN:	.BLKW	1			;LENGTH OF KLDCP DIRECTORY
ECWRD0:	.BLKW	1
ECWRD1:	.BLKW	1
ECWRD2:	.BLKW	1
ECMSK0:	.BLKW	1
ECMSK1:	.BLKW	1
ECMSK2:	.BLKW	1
ECADR0:	.BLKW	1
ECADR1:	.BLKW	1
ECBAD0:	.BLKW	1
ECBAD1:	.BLKW	1
LEVELV:	.BLKW	1	;VERSION # OF 20F FROM F11ACP.TSK FILE

	.PRINT .;END OF IMPURE AREA

ENDING=.
	.END	USERSX			;GIVE USERSX FOR KLDCP