.TITLE VVC -- Volume Valid Control Daemon .IDENT /V01/ .ENABL LC ;+ ; ; VVC -- Volume Valid Control Daemon ; ; Version: V01 ; Date: 12-Aug-85 ; System: RSX-11M-Plus V2.1 ; ; Written by: Gary L. Maxwell ; Branch of Engineering Seismology and Geology ; Office of Earthquakes, Volcanoes, and Engineering ; United States Geological Survey ; Menlo Park, California ; ; Description: ; ; This program periodically monitors the volume valid status of ; the system device. If volume valid becomes lost, this task attempts ; to reset volume valid via IO.STC QIO, and validates the volume's ; home block to guarantee that the same volume is mounted. ; ; When volume valid is determined to be lost (either software or ; hardware volume valid), this task fools the system into thinking ; that the task is VER.... This allows all QIOs to be allowed ; regardless of volume valid. When an IO.STC QIO is issued with the ; first parameter equal to the symbolic symbol VV$SET, then the ; disk drivers will attempt to access the drive and check it for ; readiness. If not ready, the software volume valid is cleared, ; and IE.DNR is returned. ; ; Assembly instructions: ; ; >MAC VVC,VVC/-SP=[1,1]EXEMC/ML,[11,10]RSXMC/PA:1,SY:[ggg,mmm]VVC ; ; Build instructions: ; ; TKB>VVC/PR/-CP,VVC/-SP=VVC ; TKB>LB:[1,1]EXELIB/LB,LB:[sysuic]RSX11M.STB/SS ; TKB>/ ; Enter options: ; TKB>TASK=VVC... ; TKB>PRI=200 ; TKB>UNITS=2 ; TKB>ASG=LB:1,CO:2 ; TKB>STACK=32 ; TKB>/ ; ; This task should be installed and run immediately after the ; system has been booted, preferably BEFORE console logging has ; been turned on. ; ; >INSTALL VVC ; >RUN VVC... 1S ! Run as a detached task ; > ; ; Proper operation of VVC is confirmed in two ways. When the system ; disk is operating normally and the system disk is quiescent, ; the RMDEMO I/O page will show one I/O issued to the system disk ; every five seconds. When the system disk is spun down, all I/O ; is stalled to the system disk until it is spun back up. VVC will ; then print a message on the console terminal. ; ;+ ;+ ; RSX Macros ;- .MCALL QIO$,QIOW$,DIR$,MRKT$S,STSE$S,EXIT$S,WSIG$S .MCALL UCBDF$,HDRDF$,DCBDF$,F11DF$ UCBDF$ ; Define UCB offsets HDRDF$ ; Define header offsets DCBDF$ ; Define DCB offsets F11DF$ ; Define Files-11 offsets .PSECT $DATA,RW,D ;+ ; Local Data ;- COQIO: QIO$ IO.WBT,2,2,,,, DSKQIO: QIOW$ IO.STC,1,1,,IOSB,,<0,VV$SET,0> DSKRLB: QIOW$ IO.RLB,1,1,,IOSB,, LBNHI = DSKRLB+Q.IOPL+6 ; High order block number LBNLO = DSKRLB+Q.IOPL+10 ; Low order block number IOSB: .BLKW 2 ; I/O status block SAVATT: .BLKW 1 ; Saved U.ATT value TKTCB: .BLKW 1 ; Our TCB address VERTK: .BLKW 1 ; Saved TCB for $VERTK ERRFLG: .BLKW 1 ; System state error flag BLOCK: .BLKW 256. ; Buffer for home block MSG1: .ASCII /VVC... -- Volume Valid reset on system device/ MSG1LN = . - MSG1 .EVEN .PSECT $CODE,RO,I $VVC:: MOV $TKTCB,TKTCB ; Save our TCB address CALL GETLB ; Get system load device BCC 10$ ; Found it IOT ; No system device...we die ; Redirect our disk LUN to the load device. UCB address is in R5. 10$: CALL $SWSTK,20$ ; Go on the system stack MOV #H.LUN,R0 ;; Get offset into LUN table (LUN 1) MOV $SAHDB,@#KISAR6 ;; Map external header (if necessary) ADD $SAHPT,R0 ;; Calculate header address MOV R5,(R0) ;; Reassign the LUN RETURN ;; Return to user state ; This marks the top of the volume valid check loop. 20$: CALL IOVV ; Try to issue volume valid call BCS 30$ ; It failed - check it out CALL SLEEP ; Go to sleep BR 20$ ; And try again ; At this point, we have trouble. There are two scenarios here. First, ; software volume valid was lost (which causes the $VOLVD routine to ; fail), or hardware volume valid was lost (IE.DNR). ; ; What we want to do is as follows: ; 1. Stall all I/O on the disk (US.SIO) and attach it. ; 2. Wait for $VERTK to exit if it is busy. ; 3. Stuff our TCB into $VERTK after saving the real TCB. ; This allows all of our QIOs to be accepted. ; 4. Keep posting IO.STC calls to the disk until it comes ; back up. ; 5. Read and validate the home block on the disk. ; 6. Clear stall I/O bit (US.SIO). ; 7. Request the driver to clear out its queue. ; 8. Replace the TCB in $VERTK and request it. ; 30$: CLR ERRFLG ; Clear system state error flag 40$: CALL $SWSTK,80$ ; Go to system state TST ERRFLG ;; Been through here before? BMI 50$ ;; If mi yes BISB #US.SIO,U.ST2(R5) ;; Set the stall I/O bit MOV U.ATT(R5),SAVATT ;; Save attached task (if any) MOV TKTCB,U.ATT(R5) ;; Attach ourselves 50$: CLR ERRFLG ;; Reset error flag MOV $VERTK,R0 ;; Get TCB of verification task BEQ 60$ ;; If eq it isn't installed BIT #TS.EXE,T.STAT(R0) ;; Is the task active? BEQ 70$ ;; If eq yes - we wait 60$: MOV R0,VERTK ;; Save the TCB address (if any) MOV TKTCB,$VERTK ;; Make us look like the verification task INC ERRFLG ;; Set the flag RETURN ;; Back to user state 70$: DEC ERRFLG ;; Indicate more work ahead CALLR $TKWSE ;; Wait for a Significant Event ; Back to user state...see how we did 80$: TST ERRFLG ; Can we proceed? BMI 40$ ; If mi no, $VERTK still busy ; Now monitor the disk until it comes back up 90$: CALL IOVV ; Try to set volume valid BCC 110$ ; It worked, we're back up 100$: CALL SLEEP ; Wait for something to happen BR 90$ ; Play it again, Sam 110$: CALL VALID ; Validate the home block BCS 100$ ; If CS then down or not same pack ; The same volume is up and running... undo what we've done CALL $SWSTK,130$ ; Go on the system stack BICB #US.SIO,U.ST2(R5) ;; Permit I/O to the disk MOV SAVATT,U.ATT(R5) ;; Restore previous attached state CLR R1 ;; No I/O packet to queue CALL $DRQRQ ;; Call driver at initiator MOV VERTK,$VERTK ;; Restore verification task TCB BEQ 120$ ;; If eq then not installed MOV $VERTK,R0 ;; Get the TCB CALL $EXRQN ;; Let it handle any pending requests 120$: RETURN ;; Back to user state 130$: DIR$ #COQIO ; Print a message of our success BR 20$ ; And back to top of loop ;+ ; SLEEP -- Routine to stop ourselves for 5 seconds ; ; Inputs: None ; Outputs: None. Program exits if system is shutting down ;- SLEEP: BIT #FE.MXT,$FMASK ; Is everyone shutting down? BEQ 5$ ; If eq no - continue EXIT$S ; Else exit out of here! 5$: MRKT$S #3,#5,#2 ; Wait - EF 3, for 5 seconds BCC 10$ ; OK WSIG$S ; Assume IE.UPN BR SLEEP ; Try again 10$: STSE$S #3 ; Wait for it RETURN ;+ ; IOVV -- Routine to issue IO.STC VV$SET QIO to the system disk ; ; Returns: Carry clear -- QIO succeeded ; Carry set -- QIO failed, disk not ready ;- IOVV: DIR$ #DSKQIO ; Issue IO.STC, volume valid BCS 10$ ; If CS then it failed TSTB IOSB ; Check I/O status BPL 10$ ; If pl OK, exit with carry clear SEC ; Set carry for return 10$: RETURN ;+ ; GETLB -- Get the UCB of the system load device ; ; Return UCB in R5, carry set if not found ;- GETLB: MOV $SYSIZ+2,R3 ; Get load device logical device number BIC #177400,R3 ; Clear high order bits to prevent trouble MOV $SYSIZ+6,R4 ; Get load device mnemonic MOV $DEVHD,R0 ; Get address of first DCB 10$: CMP R4,D.NAM(R0) ; Mnemonics the same? BEQ 30$ ; Yes 20$: MOV D.LNK(R0),R0 ; No, get address of next DCB BNE 10$ ; Try this one SEC ; Indicate no UCB RETURN ; 30$: CMPB R3,D.UNIT(R0) ; Is unit on this DCB? BLO 20$ ; No CMPB R3,D.UNIT+1(R0) ; Maybe BHI 20$ ; No CLR R2 ; Prepare to get 1st unit on DCB BISB D.UNIT(R0),R2 ; Get it MOV D.UCB(R0),R5 ; Get address of first UCB SUB R2,R3 ; Compute relative unit number BEQ 50$ ; Found it 40$: ADD D.UCBL(R0),R5 ; Point to next UCB SOB R3,40$ ; Loop until we get the right one 50$: CLC ; Indicate a UCB was found RETURN ; ;+ ; VALID -- Validate the home block of the volume in the drive ; ; Input: R5 -- UCB of device ; Output: Carry clear -- same volume in drive ; Carry set -- different volume installed in drive ; or I/O error occurred ;- VALID: MOV U.VCB(R5),R0 ; Get the VCB BEQ 50$ ; If no VCB, assume yes MOV V.HBLB(R0),LBNLO ; Low order LBN of home block MOV V.HBLB+2(R0),LBNHI ; High order LBN DIR$ #DSKRLB ; Issue read to the disk BCS 60$ ; If CS, QIO rejected TSTB IOSB ; Check I/O status BMI 60$ ; If mi - error MOV #BLOCK,R1 ; Disk read buffer MOV #H.CHK1/2-2,R2 ; Word count for first checksum MOV (R1)+,R3 ; Location to calculate checksum 10$: ADD (R1)+,R3 ; Calculate checksum SOB R2,10$ ; Loop until done CMP R3,V.HBCS(R0) ; Does it check out? BNE 60$ ; If NE - no, not the same disk MOV #BLOCK,R1 ; Get buffer address again MOV #H.CHK2/2-1,R2 ; Count for second checksum MOV (R1)+,R3 ; Start the checksum 20$: ADD (R1)+,R3 ; Calculate it SOB R2,20$ ; Loop until done CMP R3,V.HBCS+2(R0) ; Does it check out? BNE 60$ ; If ne, no MOV R0,R2 ; Copy address of VCB ADD #V.LABL,R2 ; Point to volume label MOV #BLOCK+H.VNAM,R1 ; Point to volume name in block MOV #12.,R3 ; Size of volume label 30$: MOVB (R1)+,R4 ; Get next home block char CMPB R4,#<'a> ; Is it lower case? BLO 40$ ; If LO, no CMPB R4,#<'z> ; Check again BHI 40$ ; If HI, no BICB #40,R4 ; Convert to upper case 40$: CMPB R4,(R2)+ ; Volume names match? BNE 60$ ; If NE, no SOB R3,30$ ; Yes - loop until done 50$: CLC ; Indicate success BR 70$ ; And return 60$: SEC ; Indicate failure 70$: RETURN ; And return to caller .END $VVC