.TITLE FELOAD -- BOOT PROGRAM TO FIND & LOAD RSX20F V1(4) 10-Feb-88 ;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1988. 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 ; ;[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 ; 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 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 ; 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+-2,R1 ;GET "HIGH" LBN OF HOME BLOCK BMI 1$ ;BRANCH IFF VALID BIT IS SET ABORT ; 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+,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 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 ; 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 5$: CMP R1,#5 ;SHOULD BE FILE (5,5,0) BEQ 6$ ; ABORT 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 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 #,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 ; 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 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 .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- 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+,#043241 ;CHECK FOR "KLAD10" IN RAD50 BNE 1$ ;BRANCH IF NOT THERE CMP DB+,#016766 ;CHECK 2ND HALF BEQ 2$ ;BRANCH IF "KLAD10" THERE 1$: ABORT 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+,LBNL ADC LBNH ;ADD IN CARRY SOB R1,3$ ;LOOP MOV #20.,R1 ;GET MULTIPLIER MOVB DB++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+,R4 ;GET SECTOR ADD R4,LBNL ;ADD IN SECTOR COUNT ADC LBNH ;FIX UP THE CARRY MOV DB+,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 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 ;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 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 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 2$: ABORT .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