.TITLE VADRV .SBTTL SYMBOLS, MACROS AND GLOBAL LOCATIONS .MCALL PKTDF$,CLKDF$,TCBDF$,UCBDF$,QIOSY$ PKTDF$ CLKDF$ TCBDF$ UCBDF$ QIOSY$ TINTPT=2 ; SECONDS BETWEEN CLOCK INTERRUPTS C.UCB=C.AR5+2 I.P1=I.PRM I.P2=I.PRM+2 I.P3=I.PRM+4 I.P4=I.PRM+6 I.P5=I.PRM+10 I.P6=I.PRM+12 OK=0 ERR=-3 CREATED=1 ACCESSED=2 BUF$OVF=-1 TIM$OUT=-2 NORMAL=0 INTERRUPT=1 .MACRO JEQ DEST,?LAB BNE LAB JMP DEST LAB: .ENDM JEQ .PSECT .PROG.,RW,I,LCL,REL,CON $VATBL:: .WORD VAINI .WORD $INTXT .WORD $INTXT .WORD VAPWF ; ; GLOBAL VARIABLES REFERENCED BY C ROUTINES ; AETHER:: .WORD 0 BUF$LIST:: .WORD BUF0 MSG$LIST:: .WORD HDR0 NAM$LIST:: .WORD LTL0 AET$NAME:: .WORD NAMBUF PASSWORD:: .WORD PASBUF PCB:: .WORD 0 NML$AST:: .WORD 0 INT$AST:: .WORD 0 AST$PARM:: .WORD 0 IF$ACCESS:: .WORD 0 TYPE:: .WORD 0 DESCRIPT:: .WORD 0 BUF$PTR:: .WORD 0 BUF$SIZE:: .WORD 0 LIFE$TIM:: .WORD 0 STATUS:: .WORD 0 ; ; BUFFERS TO HOLD AETHER NAME AND PASSWORD PASSED BY USER ; NAMBUF: .BLKB 16. PASBUF: .BLKB 16. ; ; ; THIS ROUTINE IS CALLED BY THE EXECUTIVE WHENEVER AN IO REQUEST IS MADE ; TO THE VA DRIVER. THE REQUEST IS COMPLETED IMMEDIATELY. ; ; VAINI: MOV KISAR6,-(SP) ; SAVE CURRENT APR6 MAPPING MOV #ERR,STATUS ; ASSUME ERROR CLR DESCRIPT ; INITIALIZE DESCRIPTOR MOV R1,R3 ; IRP ADDRESS NEEDED IN R3 FOR $IOFIN MOV I.TCB(R3),PCB ; STORE PCB ADDRESS MOVB I.FCN+1(R3),R0 ; FUNCTION CODE CMPB R0,#IO.WLB/256. ; SEND TO AETHER? JEQ DO$SEND ; YES CMPB R0,#IO.WVB/256. ; SEND TO AETHER? JEQ DO$SEND ; YES CMPB R0,#IO.RLB/256. ; RECEIVE NEXT MESSAGE? JEQ DO$RECEIVE ; YES CMPB R0,#IO.RVB/256. ; RECEIVE NEXT MESSAGE? JEQ DO$RECEIVE ; YES CMPB R0,#IO.CRE/256. ; CREATE AN AETHER? JEQ DO$CREATE ; YES CMPB R0,#IO.ACW/256. ; ACCESS AN EXISTING AETHER? JEQ DO$ACCESS ; YES CMPB R0,#IO.DAC/256. ; DEACCESS FROM AETHER? JEQ DO$DEACCESS ; YES CMPB R0,#IO.CLN/256. ; CLEAN UP AFTER EXITING TASK? JEQ DO$CLEAN ; YES CMPB R0,#IO.STP/256. ; STOP TIMER FOR DRIVER UNLOAD? JEQ DO$STOP ; YES VAFIN: MOV STATUS,R0 ; RETURN STATUS MOV DESCRIPT,R1 ; SECOND WORD IN DESCRIPT MOV (SP)+,KISAR6 ; RESTORE APR6 MAPPING CALLR $IOFIN ; FINISH UP .PAGE .SBTTL DO$ACCESS - ACCESS AN AETHER DO$ACCESS: JSR PC,DO$COMMON ; PERFORM COMMON STUFF BCS 10$ ; C SET => ERROR JSR PC,AET$ACCESS ; ACCESS AETHER TST R0 ; SUCCESSFUL? BEQ 10$ ; NO MOV #2,@I.LN2(R3) ; "FILE" OPEN ON LUN 10$: JMP VAFIN .PAGE .SBTTL DO$CLEAN - CLEAN UP AFTER EXITING PROCESS DO$CLEAN: JSR PC,AET$CLEANUP ; CLEANUP AFTER EXITING PROCESS CLR @I.LN2(R3) ; "FILE" NO LONGER OPEN JMP VAFIN .PAGE .SBTTL DO$CREATE - CREATE AN AETHER DO$CREATE: JSR PC,DO$COMMON ; PERFORM COMMON STUFF BCS 10$ ; C SET => ERROR MOV I.P6(R3),IF$ACCESS ; COPY ACCESS IF CREATED SWITCH JSR PC,AET$CREATE ; CREATE THE AETHER TST R0 ; SUCCESSFUL? BEQ 10$ ; NO MOV #2,@I.LN2(R3) ; "FILE" OPEN ON LUN 10$: JMP VAFIN .PAGE .SBTTL DO$DEACCESS - DEACCESS FROM AN AETHER DO$DEACCESS: MOV I.P1(R3),DESCRIPT ; COPY DESCRIPTOR INTO GLOBAL LOC JSR PC,AET$DEACCESS ; DEACCESS FROM AETHER JMP VAFIN .PAGE .SBTTL DO$OSEND - SEND MESSAGE TO AETHER OWNER DO$OSEND: MOV I.P1(R3),R0 ; VIRTUAL ADDRESS OF NAME MOV AET$NAME,R4 ; DESTINATION ADDRESS JSR PC,ACKCPY ; ADDRESS CHECK AND COPY BCS 10$ ; C SET => ERROR JSR PC,SETBUF ; SET UP BUFFER BCS 10$ ; C SET => ERROR JSR PC,AET$OSEND ; SEND TO OWNER 10$: JMP VAFIN .PAGE .SBTTL DO$RECEIVE - RECEIVE MESSAGE FROM AETHER DO$RECEIVE: MOV #IO.RLB/256.,R0 ; CONVERT RVB TO RLB MOV I.P1(R3),DESCRIPT ; USER-SUPPLIED DESCRIPTOR JSR PC,SETBUF ; SET UP BUFFER BCS 10$ ; C SET => ERROR JSR PC,AET$RECEIVE ; GET NEXT MESSAGE 10$: JMP VAFIN .PAGE .SBTTL DO$SEND - SEND MESSAGE TO AETHER DO$SEND: MOV #NORMAL,TYPE ; ASSUME NORMAL MESSAGE MOVB I.FCN(R3),R1 ; SUB-FUNCTION VALUE BEQ 10$ ; IF 0, REGULAR SEND CMPB R1,#1 ; SEND TO OWNER? JEQ DO$OSEND ; YES 10$: MOV I.P1(R3),DESCRIPT ; USER-SUPPLIED DESCRIPTOR TST R1 ; REGULAR SEND? BEQ 20$ ; YES MOV #INTERRUPT,TYPE ; TYPE OF MESSAGE JSR PC,AET$ISEND ; SEND INTERRUPT BR 100$ 20$: JSR PC,SETBUF ; SET UP USER BUFFER BCS 100$ ; C SET => ERROR MOV I.P4(R3),LIFE$TIM ; COPY USER-SUPPLIED LIFE$TIME JSR PC,AET$SEND ; SEND MESSAGE 100$: JMP VAFIN .PAGE .SBTTL DO$STOP - STOP PERPETUAL TIMER DO$STOP: MOV #IE.PRI&377,STATUS ; ASSUME ERROR MOV I.TCB(R3),R0 ; TCB ADDRESS MOV T.UCB(R0),R0 ; TI: UCB ADDRESS BIT #U2.PRV,U.CW2(R0) ; IS TERMINAL PRIVELEGED? BEQ 10$ ; NO MOV U.CLQB(R5),R0 ; CLOCK QUEUE BLOCK BEQ 10$ ; IF 0, TIMER NOT ACTIVE MOV R3,-(SP) ; SAVE R3 MOV R5,-(SP) ; SAVE R5 MOV #C.SYST,R4 ; CLOCK QUEUE REQUEST TYPE MOV R0,R5 ; ID IS BLOCK ADDRESS JSR PC,$CLRSM ; REMOVE ENTRY FROM QUEUE MOV (SP)+,R5 ; RESTORE UCB ADDRESS MOV #C.LGTH,R1 ; LENGTH OF BLOCK TO RETURN MOV U.CLQB(R5),R0 ; ADDRESS OF BLOCK JSR PC,$DEACB ; RETURN BLOCK TO DSR CLR U.CLQB(R5) ; TIMER INACTIVE MOV (SP)+,R3 ; RESTORE R3 MOV #IS.SUC&377,STATUS ; SUCCESSFUL 10$: JMP VAFIN .PAGE .SBTTL DO$COMMON - PERFORM COMMON STUFF FOR CREATE AND ACCESS ;+ ; THIS ROUTINE COPIES THE AETHER NAME, PASSWORD, AND INTERRUPT ; ADDRESSES INTO GLOBAL LOCATIONS ; ; IF ANY ERRORS, RETURNS C BIT SET, OTHERWISE CLEAR ; ; R3, R5 REMAIN THE SAME ACROSS THE CALL ;- DO$COMMON: MOV I.P1(R3),R0 ; VIRTUAL ADDRESS OF NAME MOV AET$NAME,R4 ; ADDRESS OF NAME BUFFER JSR PC,ACKCPY ; ADDRESS CHECK AND COPY BCS 10$ ; C SET => ERROR MOV I.P2(R3),R0 ; VIRTUAL ADDRESS OF PASSWORD MOV PASSWORD,R4 ; ADDRESS OF PASSWORD BUFFER JSR PC,ACKCPY ; ADDRESS CHECK AND COPY BCS 10$ ; C SET => ERROR MOV I.P3(R3),NML$AST ; COPY NORMAL AST ADDRESS MOV I.P4(R3),INT$AST ; COPY INTERRUPT AST ADDRESS MOV I.P5(R3),AST$PARM ; COPY REAL AST ADDRESS CLC ; CLEAR C BIT FOR SUCCESS 10$: RETURN .PAGE .SBTTL ACKCPY - ADDRESS CHECK AND COPY SMALL BUFFER ; ; INPUTS ; R0 VIRTUAL ADDRESS OF BUFFER ; R4 DESTINATION TO COPY TO ; OUTPUTS ; BUFFER WILL BE ADDRESS CHECKED AND COPIED ; R0,R3,R5 UNCHANGED ; R1,R2,R4 MANGLED ; C BIT SET IF ERROR ; C BIT CLEAR IF OK ; ACKCPY: MOV #16.,R1 ; SIZE OF BUFFER JSR PC,$ACHKB ; ADDRESS CHECK ON BYTE BOUNDARIES BCS 30$ ; C SET => ERROR JSR PC,$RELOC ; RELOCATE RELATIVE TO APR6 MOV R1,KISAR6 ; LOAD APR6 MOV #7.,R1 ; MAX BYTES TO MOVE 10$: MOVB (R2)+,(R4)+ ; COPY THE CHARACTER BEQ 20$ ; IF NULL, DONE SOB R1,10$ ; TRY AGAIN 20$: CLRB (R4) ; MAKE SURE OF NULL FOR STRCMP'S CLC ; CLEAR C BIT FOR SUCCESS 30$: RETURN .PAGE .SBTTL SETBUF - SET UP USER BUFFER SETBUF: MOV I.P3(R3),R1 ; SIZE OF BUFFER BLT 20$ ; IF < 0, ERROR CMPB R0,#IO.RLB/256. ; READ FUNCTION BEQ 10$ ; YES, ANY LENGTH IS OK CMP R1,U.CW4(R5) ; WRITE TOO LARGE? BGT 20$ ; YES 10$: MOV R1,BUF$SIZE ; STORE IN GLOBAL VARIABLE MOV I.P2(R3),R0 ; VIRTUAL ADDRESS OF BUFFER JSR PC,$ACHKB ; CHECK BUFFER ADDRESSES BCS 20$ ; C SET => ERROR JSR PC,$RELOC ; RELOCATE BUFFER MOV R1,KISAR6 ; LOAD APR6 MOV R2,BUF$PTR ; APR6 VIRTUAL ADDRESS CLC ; C CLEAR => SUCCESS RTS PC 20$: SEC ; C SET => ERROR RTS PC .PAGE .SBTTL VAPWF - POWERFAIL ENTRY POINT ;+ ; THIS ROUTINE IS CALLED WHEN THE SYSTEM IS BOOTED, UPON RESTORATION ; OF POWER, AND WHEN THE DRIVER IS LOADED, SINCE THE UC.PWF BIT ; IS SET IN THE U.CTL FIELD OF THE UCB ; ; THIS ROUTINE ALLOCATES A CLOCK QUEUE CONTROL BLOCK FROM POOL ; IT THEN FILLS IT IN AND QUEUES IT ; THE INTERRUPT SERVICE ROUTINE PROPAGATES THIS INTERRUPT. ; ; THIS ROUTINE ALSO PLACES A PSEUDO-VCB ADDRESS IN U.VCB FOR ; RUNDOWN IN DREIF ; ; IF THE CLOCK BLOCK CANNOT BE ALLOCATED FROM POOL, THE DRIVER INDICATES ; THAT THE DEVICE IS OFFLINE BY SETTING THE BIT IN THE U.ST2 FIELD ; OF THE UCB AND HAVING TKTN ISSUE A DEVICE NOT READY MESSAGE ON ; THE CONSOLE. ; ; INPUTS: ; R3 CONTROLLER INDEX ; R4 SCB ADDRESS ; R5 UCB ADDRESS ; ; OUTPUTS: ; 1. THE DELTA TIME FOR EACH CLOCK INTERRUPT IS CALCULATED AND ; STORED IN THE UCB ; 2. THE ADDRESS OF THE ALLOCATED CLOCK BLOCK IS STORED IN THE UCB ; 3. A CLOCK INTERRUPT IS QUEUED FOR THE DRIVER ; ;- .ENABL LSB VAPWF: JSR R0,$$CSAV ; SAVE REGISTERS MOV R5,(SP) ; SAVE FRAME POINTER MOV 6(R5),R5 ; UCB ADDRESS IN R5 TST U.CLQB(R5) ; SEE IF TIMER ALREADY ACTIVE BNE 20$ ; IF != 0, YES MOV R5,R0 ; BUILD "VCB" ADDRESS ADD #U.PVCB,R0 ; NOW HAVE "VCB" ADDRESS MOV R0,U.VCB(R5) ; STORE IT AWAY IN UCB MOV #TINTPT,R0 ; SECONDS BETWEEN CLOCK INTERRUPTS MOV $TKPS,R1 ; CLOCK TICKS/SECOND JSR PC,$MUL ; DOUBLE WORD DELTA TIME IN R0,R1 MOV R0,U.TIM1(R5) ; SAVE IN UCB MOV R1,U.TIM2(R5) MOV #C.LGTH,R1 ; SIZE OF CLOCK QUEUE CORE BLOCK JSR PC,$ALOCB ; ALLOCATE FROM POOL BCS CLKERR ; C SET => ALLOCATION FAILURE MOV R0,U.CLQB(R5) ; SAVE ADDRESS OF CLOCK BLOCK MOV R5,C.UCB(R0) ; SAVE UCB ADDR IN CLOCK BLOCK MOV #DO$TIMER,C.SUB(R0) ; ADDRESS OF INTERRUPT SERVICE RTN MOV U.TIM1(R5),R1 ; DELTA TIME FOR $CLINS MOV U.TIM2(R5),R2 MOV #C.SYST,R4 ; CLOCK QUEUE REQUEST TYPE MOV R0,R5 ; CLOCK QUEUE ID IS BLOCK ADDRESS JSR PC,$CLINS ; INSERT INTO CLOCK QUEUE BR 10$ CLKERR: BISB #US.OFL,U.ST2(R5) ; SET DEVICE OFFLINE MOV #T.NDNR,R0 ; ISSUE A DEVICE NOT READY JSR PC,$DVMSG ; TO CONSOLE VIA TKTN 10$: 20$: MOV (SP),R5 ; RESTORE FRAME POINTER JMP $$CRET ; DONE .DSABL LSB .PAGE .SBTTL DO$TIMER - PERPETUAL TIMER DO$TIMER: JSR R0,$$CSAV ; SAVE REGISTERS JSR PC,AET$TIMER ; C VERSION OF TIMER MOV R5,(SP) ; SAVE FRAME POINTER MOV R4,R5 ; ID IS CLOCK BLOCK ADDRESS MOV R5,R0 ; ADDRESS OF BLOCK MOV C.UCB(R0),R4 ; ADDRESS OF UCB MOV U.TIM1(R4),R1 ; TIME IN TICKS MOV U.TIM2(R4),R2 ; ... MOV #C.SYST,R4 ; SYSTEM TYPE JSR PC,$CLINS ; INSERT INTO CLOCK QUEUE MOV (SP),R5 ; RESTORE FRAME POINTER JMP $$CRET .PAGE .SBTTL ALL$AST - ALLOCATE AST BLOCKS ALL$AST:: JSR R0,$$CSAV ; SAVE REGISTERS MOV 12(R5),R4 ; AETHER HEADER ADDRESS ADD #10,R4 ; POINT AT FIRST TRAILER 10$: MOV (R4),R4 ; NEXT TRAILER ADDRESS BEQ 100$ ; IF == 0, DONE CLR 14(R4) ; NO AST BLOCK BIT 12(R4),14(R5) ; MESSAGE FOR THIS TASK? BEQ 10$ ; NO MOV #C.LGTH,R1 ; SIZE OF BLOCK TO ALLOCATE JSR PC,$ALOCB ; ALLOCATE IT FROM POOL BCS 30$ ; C SET => FAILURE MOV R0,14(R4) ; BLOCK ADDRESS IN TRAILER MOV R1,A.CBL(R0) ; SIZE OF AST BLOCK MOV #8.*2,A.BYT(R0) ; BYTE ALLOCATION ON TASK STACK MOV 10(R4),A.AST(R0) ; REAL AST ADDRESS MOV #1,A.NPR(R0) ; NUMBER OF PARAMETERS MOV 4(R4),A.PRM(R0) ; ASSUME NORMAL AST TST TYPE ; IS THIS TRUE? BEQ 10$ ; YES MOV 6(R4),A.PRM(R0) ; INTERRUPT AST BR 10$ 30$: MOV 12(R5),R4 ; AETHER HEADER ADDRESS ADD #10,R4 ; POINT AT FIRST TRAILER 40$: MOV (R4),R4 ; NEXT TRAILER ADDRESS BEQ 90$ ; IF == 0, DONE MOV 14(R4),R0 ; ADDRESS OF AST BLOCK BEQ 40$ ; NONE MOV #C.LGTH,R1 ; SIZE OF BLOCK JSR PC,$DEACB ; RETURN BLOCK TO POOL CLR 14(R4) ; NO BLOCK ALLOCATED BR 40$ 90$: MOV #ERR,R0 ; RETURN(ERR) BR 110$ 100$: MOV #OK,R0 ; RETURN(OK) 110$: JMP $$CRET .PAGE .SBTTL QUE$AST - QUEUE SOFTWARE INTERRUPTS TO PROCESSES QUE$AST:: JSR R0,$$CSAV ; SAVE REGISTERS MOV 12(R5),R4 ; AETHER HEADER ADDRESS ADD #10,R4 ; POINT AT FIRST TRAILER 10$: MOV (R4),R4 ; NEXT TRAILER ADDRESS BEQ 20$ ; IF == 0, DONE MOV 14(R4),R1 ; AST CONTROL BLOCK ADDRESS BEQ 10$ ; NO AST FOR THIS TASK MOV 2(R4),R0 ; TCB ADDRESS JSR PC,$QASTT ; QUEUE AST TO TASK BR 10$ 20$: JMP $$CRET .PAGE .SBTTL FREE LISTS OF HEADERS, BUFFERS AND LITTLE BUFFERS BUFSIZ=32. LTLSIZ=14. HDRSIZ=12. NBUFS=60. NAETS=20. NLTLS=2*NAETS NMSGS=NBUFS/3 NHDRS=4*NAETS+NMSGS ; .MACRO TRMN8R STR,NUM STR'NUM=0 .ENDM TRMN8R .MACRO BLDNOD STR,SIZE,NUM,NXT STR'NUM: .WORD STR'NXT .BLKB SIZE .ENDM BLDNOD ; ; TRMN8R HDR,\NHDRS CTR=0 .REPT NHDRS BLDNOD HDR,HDRSIZ,\CTR,\ CTR=CTR+1 .ENDR ; ; TRMN8R LTL,\NLTLS CTR=0 .REPT NLTLS BLDNOD LTL,LTLSIZ,\CTR,\ CTR=CTR+1 .ENDR ; ; TRMN8R BUF,\NBUFS CTR=0 .REPT NBUFS BLDNOD BUF,BUFSIZ,\CTR,\ CTR=CTR+1 .ENDR ; .END