.TITLE VM V04.00 KT11 DISK DRIVER .IDENT /V04.00/ .ENABL LC ; RT-11 KT11 DISK DRIVER ; ; COPYRIGHT (c) 1979 BY ; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. ; ; 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 WHICH IS NOT SUPPLIED BY DIGITAL. .SBTTL General comments ; "Faster than a speeding bullet..." ; -Clark Kent ;+ ; VM.SYS is a handler to access extended memory on PDP 11's with the ; KT11 memory management unit as a disk device. ; ; Author: ; RB 01-May-75 ; With random assistance from A(C and HJ ; ; Edits: ; CG 15-Aug-79 V04 format and bootstrap ;- .SBTTL Macros and Definitions .MCALL .DRDEF .DRDEF VM,377,FILST$,0,177572,250 ; Memory management registers MMSR0 = 177572 ;STATUS REG 0 MMSR1 = 177574 ;STATUS REG 1 MMSR2 = 177576 ;STATUS REG 2 MMSR3 = 172516 ;STATUS REG 3 UISDR0 = 177600 ;USER I DESC REG 0 UISDR7 = 177616 ;USER I DESC REG 7 UISAR0 = 177640 ;USER I ADDR REG 0 UISAR7 = 177656 ;USER I ADDR REG 7 KISDR0 = 172300 ;KERNEL I DESC REG 0 KISDR7 = 172316 ;KERNEL I DESC REG 7 KISAR0 = 172340 ;KERNEL I ADDR REG 0 KISAR7 = 172356 ;KERNEL I ADDR REG 7 ; Miscellaneous definitions V.TRP4 = 4 ;Trap to 4 vector PS = 177776 ;PROCESSOR STATUS WORD UMODE = 140000 ;CURRENT MODE = USER (IN PS) ADRS22 = 000020 ;22-BIT ADDRESSING MODE FOR 11/70 PUMODE = 030000 ;PREVIOUS MODE = USER MODE (IN PS) .SBTTL Installation code ;+ ;- .ASECT . = 200 .ENABL LSB VMINST: BR 1$ ;Non-system device enters here MOV (PC)+,R0 ;System device installation enters here MFPI @R1 ; MOV R0,91$ ; MOV R0,31$ ; 1$: CLR R0 ;Set lowest memory block & flag for trap to 4 MOV #8.,R1 ;R1 = # of memory management registers MOV #KISAR0,R3 ;R3 -> kernel I descriptor register 0 2$: MOV #77406,KISDR0-KISAR0(R3) ;Set up descriptor register BCS 41$ ;Oops, no KT-11 MOV R0,(R3)+ ;Set up base address ADD #200,R0 ;Bump base by 4k words SOB R1,2$ ;Set up all 8 registers MOV #177600,-(R3) ;Kernel APR7 maps to I/O page MOV #77406,@#UISDR0 ;Set user 0-4K map BIS #PUMODE,@#PS ;Set previous mode = user BIS #1,@#MMSR0 ;Enable memory management MOV #UISAR0,R3 ;R3 -> user 0-4k APR MOV #1600,@R3 ;Map over 28k-32k MOV #7740,R0 ;R0 = max APR value VMIPAT: BR 3$ ;NOMODE22 ;Don't check for 11/70 NOP ;NOMODE22 NOP ;NOMODE22 ; BIS #ADRS22,@#MMSR3 ;MODE22 ;Set 22-bit mode for 11/70 TST @#MMSR3 ;Is it an 11/70? BEQ 3$ ;Branch if not. Limit ok MOVB R0,R0 ;Else set R0 = 177740 3$: CLR R1 ;Set up address of 0 91$: CLR -(SP) ;Push a 0 to put in memory CLC ;C=0 in case system device MTPI (R1)+ ;Clear first word of 1K block BCS 4$ ;Trap, no K here CMP R0,@R3 ;No trap, that K is there. Did we reach max? BEQ 4$ ;Branch if at max BR 31$ ; . = 540 31$: CLR -(SP) ;Push a word to clear CLC ;C=0 in case system device MTPI (R1)+ ;Clear a word out there BCS 4$ ;Trapped (inside a K??), stop here CMP R1,#4000 ;Done one K? BLO 31$ ;Loop until cleared ADD #40,@R3 ;Else bump by 1k words and try again BR 3$ ; 4$: BIS #PUMODE,@#PS ;Set user previous mode again MOV @R3,R0 ;Get memory size BIC #7,R0 ;Round down to a block multiple SUB #1600,R0 ;Adjust for first 28K in use BLOS 41$ ;Return error if nothing there ;CLC ;C=0 from above (BLOS => BLO = BCS) ROR R0 ; in 256. word ASR R0 ; blocks ASR R0 ; MOV R0,54 ;Save the device size 42$: TST (PC)+ ;Skip next instruction, C=0 41$: SEC ;C=1 for installation error CLR @#MMSR0 ;Turn off KT-11 RETURN ;Return to bootstrap or KMON .DSABL LSB .SBTTL SET Options .ENABL LSB . = 0 .DRSET MODE22,NO.22-1$,SETMOD,NO SETMOD: MOV #BIT.22-1$,R3 ;Entry point for MODE22 ADD PC,R3 ;Entry point for NOMODE22 ;R3 pic -> mod list 1$: TST @R3 ;Anything left to fix? BEQ 3$ ;Branch if not MOV PC,R0 ;Get PIC address of location to fix 2$: ADD (R3)+,R0 ;R0 = address to modify MOV (R3)+,(R0)+ ;Modify MOV (R3)+,(R0)+ ; three MOV (R3)+,(R0)+ ; locations BR 1$ ;Try for more 3$: CLC ;We're done RETURN BIT.22: .WORD VMIPAT-2$ ;Location to fix MOV #ADRS22,@#MMSR3 ;See if status register 3 is there .WORD VMHPAT-2$ ;Location to fix MOV #ADRS22,@#MMSR3 ;See if status register 3 is there .WORD VMHPT1-2$ ;Location to fix MOV #ADRS22,@#MMSR3 ;See if status register 3 is there .WORD 0 ;Stopper NO.22: .WORD VMIPAT-2$ ;Location to fix BR .+16 ;No SR3. Skip check NOP ;Filler NOP .WORD VMHPAT-2$ ;Location to fix NOP ;Don't check SR3 NOP ; since the user told us that NOP ; it doesn't exist .WORD VMHPT1-2$ ;Location to fix NOP ;Don't check SR3 NOP ; since the user told us that NOP ; it doesn't exist .WORD 0 ;Stopper .DSABL LSB .IIF GT <. - 540>, .ERROR . - 540 ;SET code too big! .SBTTL Driver entry .DRBEG VM .ENABL LSB MOV VMCQE,R3 ;R3 -> QUEUE ELEMENT MOV (R3)+,R2 ;R2 = BLOCK NUMBER ASL R2 ASL R2 ASL R2 ;R2 = VM MEMORY BLOCK # ADD #1600,R2 ; + 28K WORDS CLR R4 ;R4 = MEMORY BLK # MOV #UISAR0,R1 ;R1 -> USER I ADDRESS REGS MOV #8.,R0 ;8 REGS TO LOAD 1$: MOV #77406,UISDR0-UISAR0(R1) ;LOAD USER DESC REG MOV #77406,KISDR0-UISAR0(R1) ;LOAD KERNEL DESC REG MOV R4,KISAR0-UISAR0(R1) ;LOAD KERNEL I ADDR REG MOV R4,(R1)+ ;AND USER I ADDR REG ADD #200,R4 ;BUMP ADDR BY 4K SOB R0,1$ ;AND LOOP TO SET UP ALL 8 MOV R2,-(R1) ;MAP VM BLK OVER USER I/O PAGE MOV #37406,@#UISDR7 ;WITH A LENGTH OF 2K WORDS MOV #177600,@#KISAR7 ;MAP I/O PAGE TO KERNEL MOV #160000,R5 ;R5 -> BASE OF I/O PAGE VMHPAT: NOP ;NOMODE22 ;Filler NOP ;NOMODE22 NOP ;NOMODE22 ; BIS #ADRS22,@#MMSR3 ;MODE22 ;SET 22-BIT MODE FOR 11/70 BIS #UMODE,@#PS ;GO INTO USER MODE BIS #1,@#MMSR0 ;ENABLE MANAGEMENT TST (R3)+ ;SKIP UNIT NUMBER IN Q ELEMENT MOV (R3)+,R0 ;R0 = BUFFER ADDRESS MOV @R3,R4 ;R4 = WORD COUNT BMI VMWRT ;IF NEGATIVE, WRITE REQUEST BEQ VMTRAP ;IF SEEK THEN DONE IMMEDIATELY INC R4 ;FOLD WORD COUNT TO SPEED TRANSFER ASR R4 BCC 2$ VMREAD: MOV (R5)+,(R0)+ ;COPY TO USER BUFFER 2$: MOV (R5)+,(R0)+ SOB R4,VMREAD ;LOOP UNTIL TRANSFER COMPLETE BR VMTRAP ;THEN GO TO COMMON EXIT VMWRT: NEG R4 ;MAKE WORD COUNT POSITIVE INC R4 ;FOLD WORD COUNT TO SPEED TRANSFER ASR R4 BCC 4$ 3$: MOV (R0)+,(R5)+ ;MOVE A WORD FROM USER BUFFER 4$: MOV (R0)+,(R5)+ SOB R4,3$ ;LOOP UNTIL TRANSFER COMPLETE MOVB @R3,R4 ;CHECK IF ZERO-FILL REQ'D BEQ VMTRAP ;NOPE - MULTIPLE OF A BLOCK 5$: CLR (R5)+ ;ELSE CLEAR A WORD DECB R4 ;UNTIL REACH A BLOCK BOUNDARY BNE 5$ VMTRAP: CLR @#MMSR0 ;TRY TO TURN OFF MANAGEMENT MOV PC,R4 ;POINT TO Q ELEMENT AGAIN ADD #VMCQE-.,R4 MOV @#54,R0 ;GET BASE OF RMON JMP @270(R0) ;AND DISPATCH ELEMENT ; ABORT ENTRY BR VMTRAP ;ABORT BY DISABLING MANAGEMENT ; INTERRUPT SERVICE VMINT: MOV #160000,R5 ;RESET TO POINT TO BASE OF I/O PAGE ADD #100,@#UISAR7 ;AND REMAP TO NEXT 2K CHUNK MOV @#MMSR2,R1 ;R1 = VIRTUAL PC OF ERROR CMP @R1,(PC)+ ;CHECK FOR R0 MODIFICATION MOV (R0)+,(R5)+ ; ON THIS INSTRUCTION ONLY! BNE 6$ ;NOT THIS ONE, SO SKIP CORRECTION TST -(R0) ;ELSE UPDATE 6$: BIC R5,@#MMSR0 ;CLEAR SEGMENT LENGTH FAULT MOV PC,R2 ;GET ADDR OF EXIT CODE ADD #VMTRAP-.,R2 ; IN R2 CMP R1,R2 ;TRYING TO EXIT? BNE 7$ ;NOPE BIC R5,2(SP) ;ELSE RETURN TO KERNEL MODE 7$: MOV R1,@SP ;RESTART INSTRUCTION RTI ;AND EXIT .DSABL LSB .SBTTL Bootstrap read routine .DRBOT VM,BOOT1,READ . = VMBOOT + 240 BOOT1: JMP @#BOOT-VMBOOT . = VMBOOT + 250 .WORD VMINT1-VMBOOT ;VM interrupt entry .WORD 340 ; and priority ;+ ; Enters with: ; R0 = Block # ; R1 = Word count ; R2 = Buffer address ; ; JSR PC,READ ; ; All registers modified ;- .ENABL LSB READ: ASL R0 ASL R0 ASL R0 ;R0 = VM MEMORY BLOCK # ADD #1600,R0 ; + 28K WORDS CLR R4 ;R4 = MEMORY BLK # MOV #UISAR0,R3 ;R3 -> USER I ADDRESS REGS MOV #8.,R5 ;8 REGS TO LOAD 3$: MOV #77406,UISDR0-UISAR0(R3) ;LOAD USER DESC REG MOV #77406,KISDR0-UISAR0(R3) ;LOAD KERNEL DESC REG MOV R4,KISAR0-UISAR0(R3) ;LOAD KERNEL I ADDR REG MOV R4,(R3)+ ;AND USER I ADDR REG ADD #200,R4 ;BUMP ADDR BY 4K SOB R5,3$ ;AND LOOP TO SET UP ALL 8 MOV R0,-(R3) ;MAP VM BLK OVER USER I/O PAGE MOV #37406,@#UISDR7 ;WITH A LENGTH OF 2K WORDS MOV #177600,@#KISAR7 ;MAP I/O PAGE TO KERNEL MOV #160000,R5 ;R5 -> BASE OF I/O PAGE VMHPT1: NOP ;NOMODE22 NOP ;NOMODE22 NOP ;NOMODE22 ; BIS #ADRS22,@#MMSR3 ;MODE22 ;SET 22-BIT MODE FOR 11/70 ..V.. = +-1000 .IIF GT ..V.. - 1000, .ERROR ..V..-1000 ;Something too big in boot!! BIS #UMODE,@#PS ;GO INTO USER MODE BIS #1,@#MMSR0 ;ENABLE MANAGEMENT INC R1 ;FOLD WORD COUNT TO SPEED TRANSFER ASR R1 BCC 5$ 4$: MOV (R5)+,(R2)+ ;COPY TO USER BUFFER 5$: MOV (R5)+,(R2)+ SOB R1,4$ ;LOOP UNTIL TRANSFER COMPLETE VMTRP1: CLR @#MMSR0 ;TRY TO TURN OFF MANAGEMENT CLC ;No error to report RETURN VMINT1: MOV #160000,R5 ;RESET TO POINT TO BASE OF I/O PAGE ADD #100,@#UISAR7 ;AND REMAP TO NEXT 2K CHUNK MOV @#MMSR2,R3 ;R3 = VIRTUAL PC OF ERROR BIC R5,@#MMSR0 ;CLEAR SEGMENT LENGTH FAULT MOV PC,R0 ;GET ADDR OF EXIT CODE ADD #VMTRP1-.,R0 ; IN R0 CMP R3,R0 ;TRYING TO EXIT? BNE 6$ ;NOPE BIC R5,2(SP) ;ELSE RETURN TO KERNEL MODE 6$: MOV R3,@SP ;RESTART INSTRUCTION RTI ;AND EXIT BOOT: MOV #10000,SP ;Set up the stack pointer MOV #2,R0 ;Read the rest of the boot (start at block 2) MOV #<4*400>,R1 ;Every block but the one we are in (4 blocks) MOV #1000,R2 ; into location 1000 JSR PC,READ ;Go read it in MOV #READ-VMBOOT,@#B$READ ;Store -> bootstrap read routine MOV #B$DNAM,@#B$DEVN ;Store the RAD50 device name CLR @#B$DEVU ;Set up the unit number (always 0) JMP @#B$BOOT ;Start the secondary boot .DSABL LSB .DREND VM .END