.MCALL .MODULE .MODULE DUPBOT,VERSION=35,COMMENT=,IDENT=NO ; Copyright (c) 1998 by Mentec, Inc., Nashua, NH. ; All rights reserved ; ; This software is furnished under a license for use only on a ; single computer system and may be copied only 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 except for use on such ; system and to one who agrees to these license terms. Title ; to and ownership of the software shall at all times remain ; in Mentec, Inc. ; ; The information in this document is subject to change without ; notice and should not be construed as a commitment by Digital ; Equipment Corporation, or Mentec, Inc. ; ; Digital and Mentec assume no responsibility for the use or ; reliability of its software on equipment which is not supplied ; by Digital or Mentec, and listed in the Software Product ; Description. ; ; Edit Who Date Description of modification ; ---- --- ---- --------------------------- ; 001 WLD 07-MAY-1991 Fix SAVMMU, CLRMMU, and RESMMU ; to work on the FALCON processor. ; 002 WLD 30-JUL-1991 Fix possible system hang in BOOTIT ; after RESET instruction. Technique ; is to null out LQE and CQE of target ; boot device if it's in memory. ; The architecturally correct solution ; would be to abort any system or ; foreground tasks, and then do the ; RESET/READ. ;-- ; Edit History: ; ; 001 28-Jan-80 10:57 Guldenschuh, Chuck cpg [240,148] ; Correct "Volume not RT-11 format" problem ; (001) ; 002 18-Feb-80 17:43 Metsch, James (29602) [240,122] ; Fix no boot on volume problem ; (002) ; 003 29-Apr-80 10:52 Fingerhut, David [240,134] ; Missing colon on BOOT DX causes system crash ; (003) ; 004 10-Nov-81 03:58 PM David Fingerhut [40,134] ; Changes for RTEM ; (004) ; 031 4-May-89 Stevens, George [240,150] ; Fixed BOOT/FOR DW: ; (031) ; 033 24-Aug-89 Stevens, George [240,150] ; Added code to check for pre-V5.3 device handler ; ; 034 06-Nov-1990 JFW ; Bracket error messages in ;+/;ERROR/.../;- .SBTTL Edit History ; CG14 New handler suffix code DUPBOT EL33 DUP V04.00 .ENABL LC,GBL .SBTTL Symbolic definitions .IIF NDF MDUP, MDUP = 0 ;Default to no MDUP .IIF NDF M$UPD, M$UPD = 0 ;Default to no MDUP Update .IIF NDF SDC, SDC = 0 ;Default to no SDCOPY B$BOOT = 1000 ;Start of boot when secondary boot is in core B$DEVN = 4716-1000 ;Offset to secondary boot handler filename B$DEVU = 4722-1000 ;Offset to secondary boot unit number B$FNAM = 4724-1000 ;Offset to secondary boot monitor filename B$READ = 4730-1000 ;Offset to secondary boot -> primary read SYOP = 4776-1000 ;Offset to SYSGEN options word in boot HND.OP = 60 ;Offset to handler options word H.DCSR = 174 ;Offset to handler display CSR H.ICSR = 176 ;Offset to handler install CSR H1.VEC = 1000 SUFFIX = 412 ;Offset to monitor suffix RAD50 word GETVEC = 436 ;Offset to $GTVEC, $GTCSR, $GTSLT address tbl SYG.XM = 2 ;Bit indicating XM in handler options word V.TR4 = 4 ;Non-existent memory trap vector V.TRAP = 34 ;TRAP vector SR0 = 177572 ;MMU Status Register 0 LKS = 177546 ;Line clock status register .SBTTL PSECT definitions PSECT IMPURE ;Impure data psect PSECT IMPURO ;001 PSECT BOOT ;Code psect PSECT PATCH ;Patch psect .BLKW 32. .MCALL .MTPS, .GVAL, .EXIT .MCALL .CSTAT .ASSUME PR7 = 340 ;Priority 7 PSECT IMPURO ;***** CRITICAL ORDERING ***** MON.OP: .WORD 0 ;Monitor sysgen option word BOTPTR: .WORD 0 ;-> primary bootstrap in handler BOTSIZ: .WORD 0 ;Size of primary boot in bytes BOTRED: .WORD 0 ;-> primary bootstrap read routine ;***** END CRITICAL ORDERING ***** PSECT IMPURE .IF EQ MDUP SWAP: .RAD50 \SYSSWAP SYS\ ;Name of the swap file BOTDEV: .RAD50 /SY / ; Handler always resides on SY:. .WORD 0 ; Handler name plus suffix. .WORD 0 ; Always blank (zero). .RAD50 /SYS/ ; Handler extension is "SYS". BTLKBK: .WORD 0,0,0,0 ;For non file-structured lookup to boot device BTCSBK: .BLKW 6 ;For CSTAT on boot device INBLK: .BLKW 1 ;Current handler block in memory ; Used to get PRO slot id .NLIST BEX MISSIN: .ASCII \Missing \ FILNAM: .ASCII \dev:filnam.typ\<200> JOTCMD: .ASCIZ \RUN SY:JOAT /E/Y\ JOTSIZ =.-JOTCMD .LIST BEX .EVEN .ENDC ;EQ MDUP .SBTTL PIC boot mover ;+ ; The following piece of code (PIC) gets relocated to just below the resident ; monitor. It copies the boot code down to location 0, and then jumps to the ; (R3). It also sets up the date and time for RT-11 systems. ; ; PRIMOS = size of the primary boot ; PRIMO -> primary boot ; SECNDS = size of secondary boot ; SECOND -> secondary boot ; R0 = booted device unit number ; R3 = start address of code ;- PIC:: MOV #5000,R5 ;R5 -> hi-order boot time word MOV (PC)+,(R5)+ ;Store hi-order time BHTIM: .WORD 0 MOV (PC)+,(R5)+ ;Store lo-order time BLTIM: .WORD 0 MOV (PC)+,(R5)+ ;Store date BDATE: .WORD 0 MOV (PC)+,R1 ;Get size of primary boot PRIMOS: .WORD 256. ;Normally 1 block MOV (PC)+,R2 ;R2 -> primary boot PRIMO: .WORD 0 CLR R5 ;R5 -> start location for primary boot 1$: MOV (R2)+,(R5)+ ;Move a word down SOB R1,1$ ;Loop until done MOV (PC)+,R1 ;R1 = size of secondary boot SECNDS: .WORD 256.*4 ;Normally 4 blocks BEQ GOBOOT ;Branch if no secondary boot MOV (PC)+,R2 ;R2 -> secondary boot SECOND: .WORD 0 MOV #1000,R5 ;R5 -> start location for secondary boot 1$: MOV (R2)+,(R5)+ ;Move a word down SOB R1,1$ ;Loop until done GOBOOT: .IF EQ MDUP MOV (PC)+,R1 BOTCSR: .WORD 0 ; Boot time device CSR. .ENDC ;EQ MDUP JMP @R3 ;Go boot PICEND: PICSIZ = PICEND - PIC .SBTTL BOOT - Boot a device ;+ ; BOOT ; This routine is called to boot a device or file. ; ; Both ICHAN and OCHAN opened non-file-structrured on the device. ; INFILE+2,+4 = RAD50 filename of the file to boot, or 0 ; FL.FOR set in $MFLAG if device being booted is foreign (non-RT-11) ; ; CALL BOOT ;- ORIGIN BOOT .ENABL LSB .IF EQ MDUP REBOOT:: BIS #FL.YES,$MFLAG ;Force /Y BIS #FLG.FL,$ISFLG ;There will be a filename MOV @#S$RMON,R0 ;R0 -> base of RMON ADD #S.MNAM,R0 ;R0 -> currently running monitor filename MOV #INFILE+2,R1 ;R1 -> place to store it MOV (R0)+,(R1)+ ;Store first word MOV @R0,@R1 ; and second word of filename MOV R5,R0 ;Get -> buffer space BR 1$ ;Go boot .IFTF ;EQ MDUP BOOT:: .IFT ;EQ MDUP .GTCOR #<512.*6> ;Get the memory we need BCC 1$ ;Branch if we got it ;+ ;ERROR .ERR #ERAREA,#FE.NOM,LEVEL=FATAL,RETURN=NO ; <-F-Insufficient memory> ;- 1$: MOV R0,IBFBEG ;Save the start address .IFF ;EQ MDUP MOV IBFBEG,R0 ;R0 -> buffer space .IFTF ;EQ MDUP MOV R0,$DIRBF ;Save it here, too .IFT ;EQ MDUP CALL FGCHEK ;Check for foreground loaded BEQ 2$ ;No FG or "Y" JMP 15$ ;FG and not "Y" 2$: CMP @#$RTEID,#RTE$ID ;Running under RTEM? BNE 101$ ;No - continue MOV #510,R1 ;Get start of chain area MOV #JOTCMD,R2 ;Get start of RAD50 device name and cmd MOV #JOTSIZ,(R1)+ ;Stuff size 102$: MOVB (R2)+,(R1)+ ;Move the data into the chain area BNE 102$ ;Loop BIS #40!4000,@#44 ;Set special chain exit CLR R0 ;Do a HARD exit .EXIT 101$: WAIT #WAITIN,#INFILE ;Wait for the device to be mounted BIT #FL.FOR,$MFLAG ;/FOREIGN? ; BEQ 6$ ;Branch if not BNE 3$ ;Branch if so JMP 6$ .IFTF ;EQ MDUP 3$: .IFT ;If DUP MOV (R2),BTLKBK ;Set the device name .LOOKU #IOAREA,#2,#BTLKBK ;Open it non file-structured BCS 146$ ;In case of error... .CSTAT #IOAREA,#2,#BTCSBK ;Get some status on the device MOV BTCSBK+12,BOTDEV+2 ;Store the physical device name .PURGE #2 ;We're done with the channel for now CMP #7,BTCSBK+10 ; Is the unit number greater than 7? BHIS 140$ ; Branch if not ;+ ; Get pointer to $PNAM2 and offset to $PNAME ;- MOV R3,-(SP) ; Save non-volitale registers MOV R4,-(SP) MOV R5,-(SP) MOV @#S$RMON,R5 ; R5 -> RMON MOV S.PNAM(R5),R4 ; R4 = offset from RMON to $PNAME. ADD R5,R4 ; R4 -> $PNAME MOV R4,R3 ; R3 -> $PNAME ; Calculate $SLOT*4 by searching for -1 at end of $ENTRY table 141$: CMP (R3)+,#-1 ; Search for end of $ENTRY table. BNE 141$ ; Keep going TST -(R3) ; R3 -> end of $ENTRY table SUB R4,R3 ; R3 = bytes in combined tables ; R3 now contains the value $SLOT*4; the size of 2 tables MOV R3,R0 ; Save $SLOT*4 value ASL R3 ; Calculate offset from $PNAME ADD R0,R3 ; to $PNAM2 $SLOT*4 * 3 TST (R3)+ ; + 2 for -1 at end of $ENTRY table ADD R3,R4 ; R4 -> $PNAM2 ;+ ; Find device name in $PNAM2 - must be there since unit # greater than 7 ;- 142$: CMP BOTDEV+2,(R4)+ ; Is this the entry? BNE 142$ ; Branch if not, loop till found ;+ ; Get 2 letter device name from corresponding entry in $PNAME ;- SUB R3,R4 ; R4 -> entry in $PNAME + 2 MOV -(R4),BOTDEV+2 ; Get 2 letter device name MOV (SP)+,R5 ; Restore non-volitale registers MOV (SP)+,R4 MOV (SP)+,R3 140$: MOV @#S$RMON,R1 ;R1 -> $RMON ADD SUFFIX(R1),BOTDEV+2 ;Merge the handler suffix .LOOKU #IOAREA,#2,#BOTDEV,#0 ;Do a lookup for the handler file 146$: BCS 4$ ;Again, in case of error MOV IBFBEG,R2 ;R2 -> Where to place the info .READW #IOAREA,#2,R2,#256.,#0 ; we read from block 0 of the handler BCS 4$ ;In case of read failure MOV H.ICSR(R2),BOTCSR ;Get the CSR BNE 145$ ;Got CSR CMP #^RHAN,(R2) ;Is this a pre-V5.3 handler? BNE 147$ ;Branch if so MOV H.DCSR(R2),BOTCSR ;Try for display CSR BNE 145$ ;Got CSR 147$: MOV S.CNF2(R1),R0 ;Get configuration word 2 BIC #^C,R0 ;Determine if running on a CTI CMP R0,#C2.PRO ;Is this a CTI bus machine BNE 145$ ;No CLR INBLK ;Currently have block 0 ADD #H1.VEC,R2 ;Address to be read in R2 CALL ADJPTR ;Get data to be read from handler file BCS 4$ ;In case of read failure ASL (R2) ;Make word offset and test for minus BCC 145$ ;Branch if it was positive ADD (R2)+,R2 ;Point to CALL ADJPTR ;Get data if not in memory BCS 4$ ;In case of read failure TST (R2)+ ;Is this a PRO vector? BPL 145$ ;Branch if not CALL ADJPTR ;Get data if not in memory BCS 4$ ;In case of read failure MOV (R2),-(SP) ;PHEW! Put slot id on stack MOV GETVEC(R1),R0 ;Point to address of $GTVEC TST (R0)+ ;Point to address of $GTCSR CALL @R0 ;Get device CSR MOV (SP)+,BOTCSR ;Put address into BOTCSR 145$: .PURGE #2 ;We're done with the channel .IFTF ;If DUP or MDUP MOV #2,R3 ;Set up boot start address CLR SECNDS ;No secondary boot to move MOV IBFBEG,PRIMO ;Set up -> primary boot READ #IOAREA,#ICHAN,IBFBEG,#256.,#0 ;Read first block of the boot BCS 4$ ;Branch if on error ; <-F-Input error dev:filename> ;+ ; Test for no boot on volume when doing /FOREIGN boot. ; ; Not used because not all formats conform to the boot standard. ; ; MOV IBFBEG,R0 ;Point to boot block just read ; ADD #3,R0 ;Point to system volume indicator byte ; CMPB #1,R0 ;Is this a System Volume ; BEQ 31$: :Branch if so ;+ ;ERROR ; MOV #NBD,R0 ;- Non-bootable device ; MOV #INFILE,R3 ;- Device being booted ; BR 10$ ;Print error message ; ;31$: ;- JMP BOOTIT ;Go boot it ;+ ;ERROR 4$: MOV #INFILE,R3 ;Set up filename 5$: MOV #FE.INE,R0 ;R0 = error code ; <-F-Input error dev:filename> .IFT ;EQ MDUP BR 10$ ;Go give error ;- 6$: MOV #OCHAN,$DIRCH ;Set up the directory channel MOV #SWAP,R3 ;R3 -> SWAP.SYS filename MOV OUTFIL,@R3 ;Give it the right device name MOV #ICHAN,R4 ;"LOOKUP" the file on the input channel CALL LOOKUP ;Do it BCC 7$ ;Branch if we found it ;+ ;ERROR CMP R0,#FE.FNF ;Was it "File not found"? BNE 10$ ;Branch if not ; <-F-Directory input error dev:> ; <-F-Invalid directory dev:> ; <-F-System error> ;- CALL CHKMIS ;See if it's ok to boot that way BEQ 7$ ;Branch if ok JMP 15$ 7$: CALL PURGE ;"PURGE" the channel BCC 9$ ;Branch if no error ;+ ;ERROR 8$: .ERR #ERAREA,#FE.SYS,LEVEL=UABORT,RETURN=NO ; <-U-System error> ;- 9$: MOV #1,R2 ;R2 = block number to read MOV #INFILE,R3 ;R3 -> input filename BIT #FLG.FL,$ISFLG ;Was one specified? BEQ 11$ ;Branch if not MOV #<^RSYS>,6(R3) ;Filetype is .SYS MOV #ICHAN,R4 ;R4 = input channel for LOOKUP CALL LOOKUP ;"LOOKUP" the monitor file ;+ ;ERROR BCC 12$ ;Branch if no error ; <-F-Directory input error dev:> ; <-F-File not found dev:filename> ; <-F-Invalid directory dev:> ; <-F-System error> ;- .IFTF ;EQ MDUP ;+ ;ERROR 10$: MOV R0,R1 ;Copy the error code .ERR #ERAREA,R1,LEVEL=FATAL,RETURN=NO,FILE=R3 ;- .IFT ;EQ MDUP 11$: READ #IOAREA,#ICHAN,IBFBEG,#256.,#0 ;Read first block of the boot BCS 5$ ;Branch on error MOV IBFBEG,R5 ;Point to boot block just read ADD #3,R5 ;Point to system volume indicator byte ;+ ;ERROR MOV #NBD,R0 ;Assume the worst TSTB (R5) ;Is this a data disk BEQ 10$ ;- Yes, no boot on volume ;- INC R2 ;Correct block number to read 12$: MOV IBFBEG,R5 ;R5 -> input buffer ADD #<512.*2>,R5 ;Skip the directory/primary boot buffer MOV #<256.*4>,R1 ;Get the number of words to read READ #IOAREA,#ICHAN,R5,R1,R2 ;Read in the secondary boot ;+ ;ERROR BCS 5$ ;Branch on error ; <-F-Input error dev:filename> CALL PURGE ;"PURGE" the channel BCS 8$ ;Branch on error ; <-F-System error> ;- 13$: MOV R1,R3 ;R3 = Number of words read ASL R3 ;Make R3 a byte count ADD R5,R3 ;R3 -> past end of buffer MOV -(R3),MON.OP ;Save monitor SYSGEN options. R3 -> to it CMP B$DEVU(R5),#<^RBOT> ;Be sure this is really a boot ;003 ; BNE 80$ ;Branch if it isnt ;003 BEQ 900$ ;Skip if it isn't - branch out of range JMP 80$ 900$: .CSTAT #IOAREA,#OCHAN,#BTCSBK ;Get device and unit number MOV BTCSBK+10,B$DEVU(R5) ;Save the unit number for the boot MOV #OUTFIL+2,R1 ;R1 -> output file spec MOV BTCSBK+12,@R1 ;Copy the device name CMP #7,BTCSBK+10 ; Is the unit number greater than 7? BHIS 130$ ; Branch if not ;+ ; Get pointer to $PNAM2 and offset to $PNAME ;- MOV R3,-(SP) ; Save non-volitale registers MOV R4,-(SP) MOV R5,-(SP) MOV @#S$RMON,R5 ; R5 -> RMON MOV S.PNAM(R5),R4 ; R4 = offset from RMON to $PNAME. ADD R5,R4 ; R4 -> $PNAME MOV R4,R3 ; R3 -> $PNAME ; Calculate $SLOT*4 by searching for -1 at end of $ENTRY table 131$: CMP (R3)+,#-1 ; Search for end of $ENTRY table. BNE 131$ ; Keep going TST -(R3) ; R3 -> end of $ENTRY table SUB R4,R3 ; R3 = bytes in combined tables ; R3 now contains the value $SLOT*4; the size of 2 tables MOV R3,R0 ; Save $SLOT*4 value ASL R3 ; Calculate offset from $PNAME ADD R0,R3 ; to $PNAM2 $SLOT*4 * 3 TST (R3)+ ; + 2 for -1 at end of $ENTRY table ADD R3,R4 ; R4 -> $PNAM2 ;+ ; Find device name in $PNAM2 - must be there since unit # greater than 7 ;- 132$: CMP @R1,(R4)+ ; Is this the entry? BNE 132$ ; Branch if not, loop till found ;+ ; Get 2 letter device name from corresponding entry in $PNAME ;- SUB R3,R4 ; R4 -> entry in $PNAME + 2 MOV -(R4),@R1 ; Get 2 letter device name MOV (SP)+,R5 ; Restore non-volitale registers MOV (SP)+,R4 MOV (SP)+,R3 130$: ADD -(R3),@R1 ;Add in handler suffix ;002 CLR 2(R1) ;Clean out any garbage ;002 BIT #FLG.FL,$ISFLG ;Was there a monitor filename? ;002 BNE 78$ ;Yes, skip the next check ;002 TST B$FNAM(R5) ;Is there a monitor filename present? ;002 BEQ 77$ ;No boot on volume - error ;002 78$: MOV #<^RSYS>,4(R1) ;Filetype is .SYS ;002 MOV #OCHAN,R4 ;R4 = output channel number MOV #OUTFIL,R3 ;R3 -> system device handler name BIT #FLG.FL,$ISFLG ;Was one specified? BNE 79$ ;YES, GO LOOK IT UP MOV B$DEVN(R5),OUTFIL+2 ; USE BOOTSTRAPPED HANDLER NAME ;+ ;ERROR 79$: CALL LOOKUP ;"Lookup" the file BCC 16$ ;Branch if no error CMP R0,#FE.FNF ;Is it "file not found"? ; BNE 10$ ;Branch if not BEQ 901$ ;Skip if so - branch out of range JMP 10$ 901$: ; <-F-Directory input error dev:> ; <-F-Invalid directory dev:> ; <-F-System error> ;- CALL CHKMIS ;See if that's ok BNE 15$ ;If no, just return ;002 JMP 3$ ;If yes, boot as if BOOT/FOR ;002 ;002 15$: RETURN ;+ ;ERROR 77$: .ERR #ERAREA,#NBO,LEVEL=FATAL,RETURN=NO ;002 ;- ;002 16$: BIT #FLG.FL,$ISFLG ;Was there an input file? BNE 17$ ;Branch if so. ;+ ;ERROR CALL PURGE ;"Purge" the channel BCC 17$ ;003 JMP 8$ ;BRANCH ON ERROR ;003 ; <-U-System error> 17$: MOV IBFBEG,R5 ;R5 -> start of our buffer space READ #IOAREA,#OCHAN,R5,#512.,#0 ;Read in handler or primary boot BCS 22$ ;Branch on error ; <-F-Input error dev:filename> ;- BIT #FLG.FL,$ISFLG ;Was a filename specified BNE 18$ ;Branch if so ; ; If no input file was specified, we just read in the primary boot (block 0) ; from the device. Therefore, we can't check the SYSGEN options. On the ; other hand, we don't have to figure out where the primary bootstrap is. ; MOV #256.,PRIMOS ;Set up size of primary for boot mover BR 24$ 18$: ADD #HND.OP,R5 ;R5 -> handler SYSGEN option word MOV #MON.OP,R3 ;R3 -> monitor SYSGEN option word CMP (R5)+,(R3)+ ;Handler and monitor options match? BEQ 20$ ;Branch if so ;+ ;ERROR .ERR #ERAREA,#CSO,LEVEL=FATAL,RETURN=NO ; <-F-Conflicting SYSGEN options> 19$: MOV #INFILE,R3 ;Set up the filename JMP 10$ ;Give the error ;002 ;- ;002 20$: MOV (R5)+,(R3)+ ;Save -> primary bootstrap BNE 21$ ;Branch if it's there ;+ ;ERROR 80$: MOV #NBF,R0 ; and the error code ;003 ; <-F-Non-bootable file dev:filename> BIT #FLG.FL,$ISFLG ;Was a file specified? BNE 19$ ;Branch if so MOV #NBD,R0 ; move in code ; <-F-Non-bootable device dev:> BR 19$ ;Go give the error ;- 21$: MOV (R5)+,(R3)+ ;Save primary boot size (bytes) MOV @R5,@R3 ;Save -> primary boot read routine MOV -(R3),R4 ;R4 = primary boot size ASR R4 ;Make it words MOV R4,PRIMOS ;Save it for the boot mover MOV -(R3),R1 ;R1 -> primary boot code in handler ASR R1 ;Make it a word offset CLR R2 ;MOVB with no sign extend BISB R1,R2 ;R2 = word offset from start of block to boot ADD R2,R4 ;Bump the number of words to read ASL R2 ;Make word offset a byte offset CLRB R1 ;High byte is block number of boot SWAB R1 ;Get block number in low byte MOV IBFBEG,R5 ;R5 -> start of input buffer MOV #OUTFIL,R3 ;R3 -> handler filename READ #IOAREA,#OCHAN,R5,R4,R1 ;Read in the boot BCC 23$ ;Branch if no error ;+ ;ERROR 22$: MOV #FE.INE,R0 ;Set up the error code ; <-F-Input error dev:filename> BR 19$ ;Set up filename and give error ;- 23$: ADD R2,R5 ;R5 -> start of primary boot 24$: MOV R5,PRIMO ;Set up the pointer for the PIC mover MOV IBFBEG,R5 ;R5 -> start of buffer space ADD #<512.*2>,R5 ;Skip past primary boot buffer MOV R5,SECOND ;Set up pointer to secondary boot BIT #FLG.FL,$ISFLG ;Input file specified? BEQ 25$ ;Branch if not MOV OUTFIL+2,B$DEVN(R5) ;Save the device name MOV INFILE+2,B$FNAM(R5) ;Save the monitor filename MOV INFILE+4,B$FNAME+2(R5) ;Both words of it MOV BOTRED,B$READ(R5) ;Save the pointer to primary read routine 25$: MOV #MON.OP,R3 ;R3 -> scratch area (now) .GTIM #IOAREA,R3 ;Get the time MOV (R3)+,BHTIM ;Save it for the boot mover MOV @R3,BLTIM ; and the low order word, also .DATE ;Get the date MOV R0,BDATE ;Save it MOV #1000,R3 ;Set up the boot start address CLR @PRIMO ;Clear first word to indicate software boot .ENDC ;EQ MDUP .DSABL LSB ;+ ; At this point, we do a hard reset to stop all I/O, and then read 1 word ; from the selected device. The reason for this is that most of the primary ; bootstraps ignore the fact that the booted unit number is in R0 and pull ; it out of the device CSR. We then go to PR7 because the 11V03's clock ; never stops. ; ; R3 = the start address of the bootstrap (0 or 1000) ;- BOOTIT: MOV #V.TRAP,R0 ;R0 -> TRAP vector MOV #1$,(R0)+ ;Store the TRAP address CLR @R0 ;PR0, kernel state TRAP 0 ;Go to kernel state 1$: CALL SAVMMU ;Save state of MMU CALL PRORST ;If on a PRO do PRO-style reset BCS 3$ ;Branch if we're on a PRO ; On return from PRORST, R0 contains value of configuration word 2 BIT #,R0 ;Running on a KXJ? BNE 3$ ;Branch if so RESET ;Stop the world, I want to start it! MOV INST+4,R0 ;Get load addr of handler. BEQ 3$ ;BR if not in memory: just continue. CLR (R0)+ ;Null LQE and CQE. CLR @R0 3$: CALL RESMMU ;Restore MMU state (RESET turns it off) READ #IOAREA,#ICHAN,#CMDBUF,#1,#0 ;Reset the controller for the ; correct unit number CALL CLRMMU ;Turn off MMU .MTPS #PR7 ;Set the processor status word to priority 7 .IF NE MDUP ; 8 unit only code for MDUP MOV INFILE,R0 ;;;R0 = physical device name of boot device CALL GTUNIT ;;;Get the boot device unit number SUB #<^R 0>,R0 ;;;Make it binary .IFF ;NE MDUP .CSTAT #IOAREA,#ICHAN,#BTCSBK ;Get boot device unit number MOV BTCSBK+10,R0 ;Save it in R0 .ENDC ;NE MDUP MOV #PICSIZ,R2 ;;;R2 = PIC code size MOV @#S$RMON,R5 ;;;R5 -> RMON base MOV R5,-(SP) ;;;Save the start location MOV #PIC,R4 ;;;R4 -> PIC relocation code ASR R2 ;;;Make R2 a word count 4$: MOV (R4)+,(R5)+ ;;;Move a word SOB R2,4$ ;;;Loop until done MOV (SP)+,R5 ;;;Restore the start location MOV #10000,SP ;;;Reset the stack pointer JMP @R5 ;;;Go relocate boot code and start it PRORST: .GVAL #IOAREA,#S.CNF2 ;Get configuration word 2 BIT #,R0 ;Running on a Professional series? CLC ;Assume we're not on PRO in case we branch BEQ 1$ ;C=0 Branch if we're not on a PRO BIT #,R0 ;C=0 Running on a KXJ? BNE 1$ ;C=0 Branch if so MOV #60,@#173202 ;Disable controller 0 interrupts MOV #60,@#173206 ;Disable controller 1 interrupts MOV #60,@#173212 ;Disable controller 2 interrupts MOV #100,@#173202 ;Disable pending controller 0 interrupts MOV #100,@#173206 ;Disable pending controller 1 interrupts MOV #100,@#173212 ;Disable pending controller 2 interrupts SEC ;Say we're on a PRO 1$: RETURN CLRMMU: CALL CATCH4 ;Ignore non-existent memory traps CLR @#SR0 ;Disable memory management NOP ; *** T11 CLR @#SR3 ;Disable UMR support NOP ; *** T11 CLR @#LKS ;Disable BDV-11 clock NOP ; *** T11 RETURN SAVMMU: CALL CATCH4 ;Ignore non-existent memory traps ;+ ; The following MOVs must use an intermediate register, because the ; source operand may not exist and can abort the instruction causing ; a trap-to-4. The abort can cause the destination operand to not ; be used. In this case, the PC might not be incremented by 2, and ; the next instruction executed would be at the in-line data location. ;- MOV @#SR0,R0 ;R0 = Current MMSR0 contents NOP ; *** T11 MOV R0,(PC)+ ;Save it in-line MMUSTA: .BLKW MOV @#SR3,R0 ;R0 = Current MMSR3 contents NOP ; *** T11 MOV R0,(PC)+ ;Save it in-line UMRSTA: .BLKW RETURN RESMMU: CALL CATCH4 ;Ignore non-existent memory traps MOV MMUSTA,@#SR0 ;Restore MMU state NOP ; *** T11 MOV UMRSTA,@#SR3 ;Restore UMR state NOP ; *** T11 RETURN CATCH4: MOV #V.TR4,R0 ;R0 -> Non-existant memory trap MOV @R0,TR4ADR ;Save trap address MOV #RTIINS,(R0)+ ;Store the vector address MOV @R0,TR4PS ;Save trap PS CLR @R0 ;PR0, kernel state CALL @(SP)+ ;Call back caller TR4ADR = .+2 MOV #.-.,@#V.TR4 ;Restore NXM Vector PC TR4PS = .+2 MOV #.-.,@#V.TR4+2 ; and PS RETURN ;Return to caller's caller RTIINS: RTI .SBTTL ADJPTR - Subroutine to adjust buffer pointer .IF EQ MDUP ;+ ; ADJPTR ; This routine reads in the required block from the handler ; ; R2 = Buffer address to be read ; (may point to data not yet available) ; ; CALL ADJPTR ; ; R2 = Buffer pointer updated to point to real data ; ; If carry set upon return, there was a read error ;- ADJPTR: MOV IBFBEG,R0 ;Get address of start of buffer ADD #511.,R0 ;Calculate last byte of buffer CMP R0,R2 ;Is it in the buffer? BHIS 10$ ;Branch if so SUB #512.,R2 ;Back the pointer off INC INBLK ;Bump the input block number .READW #IOAREA,#2,IBFBEG,#256.,INBLK ;Read next block of handler BCS 10$ ;ERROR BR ADJPTR ;Loop in case not right block (not likely) 10$: RETURN .ENDC ;EQ MDUP .SBTTL GTUNIT - Get the unit number for a channel .IF NE MDUP ;+ ; GTUNIT ; This routine returns the physical unit number of device. ; ; R0 = physical device name ; ; CALL GTUNIT ; ; R0 = unit number of the device in RAD50 ;- GTUNIT: MOV R1,-(SP) ;Save R1 MOV #50,R1 ;Get divisor CALL $DIV ;Do it MOV R1,R0 ;Copy the remainder MOV (SP)+,R1 ;Restore R1 TST R0 ;Was there a unit? BNE 1$ ;Branch if so MOV #<^R 0>,R0 ;Else make it 0 1$: RETURN .ENDC ;NE MDUP .SBTTL CHKMIS - Make sure SWAP or system handler shouldn't be missing .IF EQ MDUP ;+ ; CHKMIS ; This routine makes sure that the user knows that SWAP.SYS or the system ; handler are missing from the volume being booted. ; ; R3 -> filename to check ; ; CALL CHKMIS ; ; R0 destroyed ; Z-bit = 1 => go ahead with boot ; Z-bit = 0 => abort boot ;- CHKMIS: MOV R1,-(SP) ;Save R1 BIT #FL.YES,$MFLAG ;Should we go ahead? BNE 1$ ;Branch if so MOV #FILNAM,R1 ;Point to filename area for prompt MOV R3,R0 ;R0 -> filename CALL $FNASC ;Convert filename to ASCII MOVB #200,@R1 ;Don't print MOV (SP)+,R1 ;Restore R1 MOV #MISSIN,RUSPRM ;Set up the prompt JMP RSURE1 ;Go prompt user 1$: MOV (SP)+,R1 ;Restore R1 SEZ ;Set the Z-bit to indicate go-ahead RETURN .ENDC ;EQ MDUP .END