.TITLE VEDRV - VE: DRIVER .SBTTL VEDRV - TITLE PAGE .IDENT /V01.3X/;GCE 8/15/83 ; ; ************************************************************************ ; * ; THIS PROGRAM IS PROVIDED ON AN "AS IS" BASIS ONLY. DIGITAL EQUIPMENT * ; COMPUTER USER'S SOCIETY, DIGITAL EQUIPMENT CORPORATION, MONSANTO, AND * ; THE AUTHOR DISCLAIM ALL WARRANTIES ON THE PROGRAM, INCLUDING WITHOUT * ; LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABLITY AND FITNESS. * ; * ; FULL PERMISSION AND CONSENT IS HEREBY GIVEN TO DECUS AND TO THE DECUS * ; SPECIAL INTEREST GROUPS TO REPRODUCE, DISTRIBUTE, AND PUBLISH AND * ; PERMIT OTHERS TO REPRODUCE IN WHOLE OR IN PART, IN ANY FORM AND * ; WITHOUT RESTRICTION, THIS PROGRAM AND ANY INFORMATION RELATING THERETO * ; * ; ************************************************************************ ; ; VE: (VIRTUAL DISK) DEVICE DRIVER. ; ; VERSION: V01.00 ; ; AUTHOR: R.W. STAMERJOHN MAPC 15-MAR-79 ; ; MODIFICATION HISTORY: ; ; R.S. MEARNS, INFORMATICS INC. 30-MAR-81 ; MODIFIED TO RUN UNDER RSX-11/M+ V1.0 ; ALL CHANGES ASSOCIATED WITH 11M+ ARE DENOTED BY ; CONDITIONAL ASSEMBLY BASED ON THE SYMBOL 'R$$MPL'. ; ; R.S. MEARNS 30-MAR-81 ; ADDED VE: UNIT OFFLINE TEST. THIS IS NECESSARY IN ORDER ; TO PREVENT A SYSTEM CRASH WHEN A VE: UNIT (VE1: IN THIS ; EXAMPLE) IN ACCESSED UNDER CIRCUMSTANCES SIMILAR TO THE ; FOLLOWING SCENARIO: 1) VE0: IS ASSIGNED (W/ AVE) AND ; MOUNTED, THEN 2) VE1: IS ASSIGNED ON VE0: AND MOUNTED, ; AND FINALLY 3) VE0: IS DISMOUNTED AND DEASSIGNED (W/DVE). ; ; G. EVERHART, MOD FOR ASSIGNING MULTIPLE DISKS TO A SINGLE ; VIRTUAL DISK. THIS WILL OPERATE BY HAVING A NONPHYSICAL ; "BAD BLOCK" AT THE PHYSICAL BOUNDARIES TO ENSURE THAT ; NO QIO$ WILL CROSS A DISK BOUNDARY (IF BAD IS RUN...). ; ; G. EVERHART 19-JUL-82 - ADD CONDITIONAL SECURITY CHECKING ; CODE TO ALLOW ACCESS TO A VE: UNIT ONLY IF THE TI: UCB ; ADDRESS IS AS STORED IN THE UCB. IF THIS IS 0 IN UCB, ; ALLOW ACCESS ALWAYS. (LIKEWISE IF NO TCB). ; .SBTTL VEDRV - DECLARATIONS ; ; MACRO LIBRARY CALLS: ; .MCALL PKTDF$ ;DEFINE PACKET SYMBOLICS PKTDF$ .MCALL SCBDF$ ;DEFINE SCB SYMBOLICS SCBDF$ .MCALL UCBDF$ ;DEFINE UCB SYMBOLICS UCBDF$ .MCALL TCBDF$ TCBDF$ .IF DF,R$$MPL .MCALL DDT$ ;DEFINE DRIVER DISPATCH TABLE .ENDC ; ; GLOBAL DECLARATIONS: ; .GLOBL $VETBL ;DRIVER DISPATCH TABLE ; ; GLOBAL REFERENCES: ; .GLOBL $BLKCK ;BLOCK CHECK I/O FUNCTION .GLOBL $DRQRQ ;QUEUE I/O REQUEST .GLOBL $GTPKT ;GET I/O PACKET ROUTINE .GLOBL $IOALT ;FINISH I/O PACKET .GLOBL IE.IFC ;ILLEGAL FUNCTION CODE .GLOBL IE.WLK ;DEVICE WRITE LOCKED .GLOBL IE.OFL ;DEVICE OFFLINE .GLOBL IO.RLB ;READ LOGICAL BLOCK .SBTTL VEDRV - LOCAL DATA ; ; LOCAL DATA: ; ; DEVICE DISPATCH TABLE ; .WORD VEXIT,VEXIT ;FOR NEW V4.1/V2.1 OFFSETS... ;DON'T KNOW IF THESE ARE NEEDED BUT MAY BE FATAL IF THEY ARE AND ;WE DON'T HAVE 'EM. SINCE THEY ARE AHEAD OF DRIVER DISPATCH TBL, ; THESE OFFSETS SHOULDN'T HURT TO BE THERE... .IF NDF,R$$MPL ;FOR RSX11M ------------------------- $VETBL:: ;REF. LABEL .WORD VEINI ;DEVICE INITIATOR .WORD VECAN ;CANCEL I/O .WORD VEOUT ;DEVICE TIMEOUT .WORD VEPWF ;POWER RECOVERY .IFF ;FOR RSX11M+ ------------------------ DDT$ VE,0,NONE,,,NEW .ENDC ;----------------------------------- .SBTTL VEDRV * DRIVER CODE ; ; THIS DRIVER MEARLY RELOCATES THE LOGICAL BLOCK TO THE REAL LOGICAL ; BLOCK WITHIN THE DISK. THE MCR TASK AVE IS USED TO SETUP THE UCB ; FOR THIS OPERATION. ; .IF DF,M$VE$$ VVUCB: .WORD 0 ;UCB ADDRESS FOUND .ENDC VEINI: CALL $GTPKT ;GET PACKET BCC 7222$ JMP VEXIT ; IF CS - NO PACKET 7222$: ; ; BLOCK CHECK FOR VIRTUAL DISK. ; CALL $BLKCK ;BLOCK CHECK PARAMETERS ; ; PARAMETERS OK, CHECK IF ACCESS ALLOWED. ; ; UCB ADDRESS IN R5 ; I/O PKT IN R1 (REALLY I.PRM+12) .IF DF,O$WNRS TST U.TIU(R5) ;IS THIS UNIT TO BE PROTECTED? BEQ 7320$ ;IF NOT, DO NO FURTHER CHECKS MOV R0,-(SP) MOV I.TCB(R3),R0 ;GET REQUESTOR'S TCB ADDRESS BEQ 7322$ ;IF ZERO LET IT BY... BIT #T3.CLI!T3.ACP!T3.PRV!T3.NET,T.ST3(R0) ;IF IT'S AN ACP LET IT BY TOO BNE 7322$ ;THE ABOVE ALLOWS CLIS, NETWORK TASKS, OR ACPS TO HAVE ACCESS. TST T.UCB(R0) ;IS THERE A TI: FOR THIS TASK? BEQ 7322$ ;IF NOT, BEST LET IT BY. CMP T.UCB(R0),U.TIU(R5) ;NOW THE $64000 QUESTION... IS ; ;THIS TASK AT THE TERMINAL WE ARE ; ;RESTRICTING ACCESS TO? IF NOT, FAIL. BEQ 7322$ MOV (SP)+,R0 ;RESTORE STACK AND R0 FIRST THOUGH. JMP 2015$ 7322$: MOV (SP)+,R0 7320$: .ENDC BITB #US.OFL,U.ST2(R5) ;IS UNIT OFFLINE? ;RSM BNE 2015$ ; IF NE - YES, ERROR ;RSM MOV U.NXT(R5),R0 ;GET EXTENSION BLOCK ADDRESS BEQ 2015$ ;IF ZERO, BETTER FAIL THE QIO. CMPB #IO.RLB/400,I.FCN+1(R3) ;CHECK FOR LEGAL FUNCTION BLO 2000$ ; IF LO - BAD FUNCTION BEQ 1000$ ;SKIP WRITE CHECK BIT #XF.RON,X.FLG(R0) ;IS WRITE ACCESS ALLOWED? BNE 2010$ ; IF NE - NO, ERROR .IF NDF,M$VE$$ 1000$: ADD X.OFF+2(R0),(R1) ;ADD IN LOW OFFSET ADC -(R1) ; IN DOUBLE PRECISION ADD X.OFF+0(R0),(R1) ;ADD IN HIGH OFFSET .IFF ;MULTIPLE VIRTUAL DISKS 1000$: ;CHECK WHICH PHYSICAL DISK WE ARE IN VIA RANGE TESTS MOV R5,-(SP) MOV R4,-(SP) ;NEED SOME REGISTERS MOV R3,-(SP) ;FIRST HAVE TO FIND OUT WHAT DEVICE WE ARE DEALING WITH... MOV (R1),R5 ;GET LOW BLOCK NUMBER MOV -2(R1),R4 ;AND HIGH ONE ;SUBTRACT OFF SIZES TILL DONE DOWN TO 0. NOTE THAT EVERY NEW VE ADDED HAS ;1 EXTRA BAD BLOCK TACKED ONTO ITS END... MOV R0,-(SP) TST (R0)+ ;PASS FLAG WORD 1003$: SUB 6(R0),R5 ;COUNT DOWN BY LOW BLK # SBC R4 SUB 4(R0),R4 ;SUBTRACT HIGH PARTS SECOND ;IF (R4,R5) = 0 THEN THIS BLK IS A BAD ONE BECAUSE IT'S A BOUNDARY BLK MOV R4,-(SP) BIS R5,(SP) TST (SP)+ ;SEE IF BOTH ARE 0 BEQ 1007$ ;IF SO DECLARE ERROR. ;IF R4 < 0 THEN WE WENT TOO FAR AND PREVIOUS BLK IS THE DEVICE WE WANT TST R4 ;CHECK...WAS LAST THE ONE WE WANTED? BLT 1009$ ;IF SO THEN GO GRAB NUMBERS 1006$: ADD #10.,R0 ;ELSE BUMP DESCRIPTOR POINTERS SUB #1,R5 ;COUNT DOWN BY EXTRA BLK SBC R4 ;TO 32 BITS BR 1003$ ;AND KEEP LOOKING 1009$: MOV 10(R0),VVUCB ;SAVE NEXT UCB BEQ 1007$ ;WHICH BETTER NOT BE 0. ADD 6(R0),R5 ;ADD THE LAST BLK COUNT BACK IN ADC R4 ADD 4(R0),R4 ;AGAIN DOUBLE PRECISION ;CHECK THAT THE BLOCK NUMBER IS NOT TOO CLOSE TO THE SIZE. ;REASONABLE SIZE FILES SHOULDN'T NEED ;TO HAVE CHECKS AT THEIR BEGINNINGS... MOV <4-12>(R1),R3 ;GET BYTES TO TRANSFER ; DEC R3 ASH #-9.,R3 ;CONVERT TO BLOCKS BIC #177600,R3 ;ZERO SIGN EXTENSION IF ANY ;SEE IF (BLK # + NO. BLKS TO XFER) IS GREATER THAN THE LENGTH OF ; THE CURRENT FILE BY SUBTRACTING BLK # OF QIO START FROM FILE SIZE ; AND SUBTRACTING BLKS TO XFER. IF NEGATIVE TOTAL, THEN XFER GOES PAST ; THE FILE BOUNDARY AND IT BETTER FAIL. NEEDED SINCE BAD DOES MULTI ; BLOCK QIO'S. MOV 4(R0),-(SP) ;PUSH H.O. FILE SIZE MOV 6(R0),-(SP) ;AND L.O. FILE SIZE OF LAST SUB R3,(SP) ;SUBTRACT OFF BLKS TO DO FIRST SBC 2(SP) ;(ALWAYS TO 32 BITS) SUB R5,(SP)+ ;THEN SUBTRACT BLK NO. WE HAVE HERE SBC (SP) ;THEN SUBTRACT CARRY OFF HIGH ORDER SUB R4,(SP)+ ;FINALLY SUBTRACT AND TEST RESULT BLT 1007$ ;IF LT, THEN IT CROSSES AND SHOULD FAIL ;NOW (R4,R5) IS BLK # IN FILE WE WANT... MAKE IT BLK # ON DISK BY ;ADDING OFFSET AND SAVE IN IORQ NODE ADD 2(R0),R5 ;LOW OFFSET ADC R4 ADD (R0),R4 ;HIGH OFFSET ADD IN NOW MOV R5,(R1) ;STORE LOW OFFSET MOV R4,-(R1) ;AND HIGH ONE MOV (SP)+,R0 MOV (SP)+,R3 MOV (SP)+,R4 MOV (SP)+,R5 BR 1008$ 1007$: MOV (SP)+,R0 MOV (SP)+,R3 MOV (SP)+,R4 MOV (SP)+,R5 BR 2017$ ;GO DECLARE FATAL HW ERR 1008$: .ENDC ; ; MARK THIS DRIVER NOT BUSY AND QUEUE PACKET TO NEXT DEVICE. ; BICB #US.BSY,U.STS(R5) ;CLEAR UCB BUSY CLRB S.STS(R4) ;CLEAR SCB BUSY MOV R3,R1 ;COPY PACKET ADDRESS .IF NDF,M$VE$$ MOV X.UCB(R0),R5 ;GET NEXT UCB .IFF ;GET CORRECT UCB FOR THIS PHYSICAL DISK MOV VVUCB,R5 ;GET THE UCB NEXT SAVED ABOVE .ENDC CLR I.LNK(R1) ;CLEAR LINK WORD MOV R5,I.UCB(R1) ;SET NEW UCB CALLR $DRQRQ ;QUEUE TO REAL DRIVER ; ; RETURN ERRORS TO USER. ; 2000$: MOV #IE.IFC&377,R0 ;SET ERROR CODE BR 2020$ ; CONTINUE 2010$: MOV #IE.WLK&377,R0 ;SET ERROR CODE BR 2020$ ; CONTINUE ;RSM 2015$: MOV #IE.OFL&377,R0 ;SET ERROR CODE ;RSM BR 2020$ .IF DF,M$VE$$ ;HARDWARE ERROR TO MAKE UP OUR PSEUDO BAD BLOCKS RETURNS... 2017$: MOV #IE.BBE&377,R0 ;SET FAKE HARDWARE ERROR ;GCE ;NOTE USE THE IE.BBE ("BAD BLOCK") RETURN TO FOOL THE BAD UTILITY. ; BR 2020$ ;(FOR SYMMETRY) .ENDC 2020$:; BICB #US.BSY,U.STS(R5) ;CLEAR UCB BUSY ; CLRB S.STS(R4) ;CLEAR SCB BUSY ; CLR R1 ;CLEAR 2ND I/O STATUS WORD CALL $IOALT RETURN ;RETURN PACKET TO USER, THEN EXIT ; CALLR $IOFIN ;RETURN PACKET TO USER ; ; POWER FAIL SETS UCB OFFLINE. ALL OTHER DRIVER ENTRIES ARE NO-OP'S. ; VEPWF: BISB #US.OFL,U.ST2(R5) ;MARK DRIVE OFFLINE VECAN: ;NO-OP VEOUT: ;NO-OP VEKRB: ;CNTROLLER STAT CHNG (NO-OP, NO-CTLR!) VEUCB: ;UNIT STATUS CHANGE (NO-OP) VEXIT: RETURN ;RETURN TO CALLER .END