.TITLE XX.... .SBTTL SKELETON HANDLER FOR DEVELOPMENT PURPOSES .IDENT "V001" ; .LIST ME ; ; AUTHOR; F. BORGER ; DEPT OF MEDICAL PHYSICS ; MICHAEL REESE HOSPITAL ;CHICAGO ILL 60616 ; ;A BARE BONES HANDLERS WITH JUST THE CODE AND DATA AREAS COMMON TO ;ALL HANDLERS, FOR MAKING NEW HANDLERS WITHOUT TYPING ALL THIS DATA ;IN EACH TIME, OR USING AN EXISTING HANDLER AND DELETING LIKE MAD ; ; NOTE: THIS SOURCE IS PAGED WITH FF'S RATHER THAN .PAGE STATEMENTS ; TO MAKE IT EASY TO DELETE A WHOLE PAGE ;TYPICAL TASK BUILD COMMAND FILE : ; ; XX/PR/-FP/-FX/-AB/-CP,XX/-SP=XX,LB0:[1,1]EXEC.STB ; / ; LIBR=HNDLIB:RO:2 ; TASK=XX.... ; PAR=GEN ; STACK=64 ; UIC=[1,1] ; PRI=230 ; RESAPR=3 ;USED FOR IAS MULTI-VERSION HANDLERS THAT ; ;HAVE A PURE CODE AREA ; / ; ; .SBTTL DEFINITIONS ; ; ;SYSTEM EVENT FLAGS ; EVFNOR=001 ;NORMAL REQUEST EVFEXR=002 ;EXPRESS REQUEST EVFIOD=004 ;I/O TRANSFER FINISHED ; ;MISC DEFINITIONS ; PSW=177776 ;ADDR OF STAT WORD MAXFUN=30. ;MAX IO FUNCTION CODE .SBTTL GENERAL MACROS .MACRO INTOFF ;TURN OFF ALL INTERRUPTS MOV @#PSW,-(SP) ;SAVE CURRENT STATUS REGISTER BIS #340,@#PSW ;REPLACE WITH MAX HARDWARE STATUS .ENDM ; ; .MACRO INTON ;RESET INTERRUPT CAPABILITY MOV (SP)+,@#PSW ;POP STATUS TO PSW .ENDM ; ; .MACRO NORDIS A,B,C ;GENERAL NORMAL DISPATCH TABLE ENTRY .BYTE A,B ;VOLUME CHAR BYTE, CONTROL VARIABLE BYTE .WORD C ;THE ROUTINE ADDRESS TO JUMP TO .ENDM ; ; .MACRO ACPDIS A,B,C,D ;GENERAL ACP DISPATCH TABLE ENTRY ;MAKE SURE FLAG FOR SEND/REQ IS ON .BYTE A,B!200 ;VOLUME CHAR BYTE, CONTROL VARIABLE BYTE .BYTE C,D ;SUFFIX BYTE, SUB FUNCTION CODE BYTE .ENDM ; ; .MACRO ILFN ;GENERAL ILLEGAL FUNCTION MACRO NORDIS 0,0,ILLFUN .ENDM ; ; .MACRO DUMFUN ;GENERAL DUMMY FUNCTION MACRO NORDIS 0,0,DUMMY .ENDM ; ; .MACRO ERRMAC,ERROR ;GENERAL ERROR RETURN MACRO MOV #ERROR,R3 ;ERROR CODE TO R3 BR OVER ;AND JOIN COMMON EXIT SEQUENCE .ENDM ; ; .MCALL CALL .MCALL RETURN .SBTTL INITIALIZATION SECTION ; ; ;ROUTINE MUST DO THE FOLLOWING ;A DECLARE ITSELF RESIDENT ;B CONNECT INTERRUPTS (IF NECESSARY) ;C SET UP POWER UP AST ; ; INIT: MOV #UIT,R0 ;POINT R0 TO UNIT IDENTIFICATION TABLE ;BEFORE CALLING, THE UIT MUST CONTAIN ;WORD 0 THE DISPATCH TABLE ADDRESS ;WORD 1,BYTE 0 NUMBER OF UNIT ENTRIES ;EACH UNIT ENTRY MUST HAVE IN WORD 0 : ;A/ THE UNIT NUMBER FOR SINGLE UNIT HANDLERS ;B/ UNIT VALIDITY MASK FOR MULTI-UNIT HANDLERS ;WORD 1,BYTE 1 ACTUAL # OF UNITS IS RETURNED BY ..DSUT MOV #"XX,R2 ;DEVICE NAME TO R2 MOV #UF.RH,R3 ;FLAG BYTE FOR PUD FLAG WORD=RESIDENT CALL @#..DSUT ;REGISTERS SET SO CALL DECLARE ; ;FOR MULTI-USER HANDLERS USE THE ROUTINE ; CALL @#..DSMU ;ON RETURN, R1 CONTAINS ACTUAL # OF UNITS FOUND BCC 111$ ;BRANCH IF SUCCESSFUL JMP EXITDF ;EXIT DUE TO DECLARE FAILURE 111$: MOV #UNITEN,R4 ;ADDR OF UITEN TO R4 MOV (R4),R5 ;PUD POINTER TO R5 BNE DOPWR ;BRANCH IF FOUND A PUD POINTER JMP EXITCF ;EXIT IF NO PUD POINTER FOUND DOPWR: MOV #PWR,-(SP) ;POWERUP VECTOR ONTO STACK EMT 377 ;GO ENABLE IT BCC 222$ ;BRANCH IF POWER FAIL EMT SUCCESSFUL JMP EXIT ;EXIT IF IT FAILED 222$: MOV U.TV(R5),R0 ;GET TRAP VECTOR ADDRESS OF HARDWARE MOV #ISRIN,R1 ;POINTER TO ISR ROUTINE TO R1 CLR R2 ;BASE ADDRESS OF ISR =0 CLR R3 ;LOW ORDER BYTE OF STATUS WORD=0 BIS U.IP(R5),R3 ;NOW SET TO DEVICE PRIORITY CALL @#..CINT ;REGISTERS SET TO CALL ROUTINE BCC 333$ ;BR IF CONNECT WENT OK JMP EXITCF ;ELSE AN ERROR 333$: ;FOR MANY DEVICES WITH 2 INTERRUPT VECTORS, CONNECT SECOND ONE ; MOV U.TV(R5),R0 ;GET TRAP VECTOR ADDRESS OF HARDWARE ; ADD #4,R0 ;BUMP TO OUTPUT VECTOR ; MOV #ISROUT,R1 ;POINTER TO ISR ROUTINE TO R1 ; CLR R2 ;BASE ADDRESS OF ISR =0 ; CLR R3 ;LOW ORDER BYTE OF STATUSWORD=0 ; BIS U.IP(R5),R3 ;SET TO DEVICE PRIORITY ; CALL @#..CINT ;REGISTERS SET TO CALL ROUTINE ; BCC INITA ;BR IF CONNECT WENT OK ; JMP EXITCF ;ELSE AN ERROR .SBTTL RESET STACK ;FOR SIMPLE HANDLERS (WITHOUT MULTIPLE VERSIONS SHARING THE SAME ;PURE AREA, EXTRA STACK AREA CAN BE MADE AVAILABLE BY RESETTING THE ;STACK POINTER TO USE THE INIT CODE FOR STACK USAGE. ; ;THIS WILL RESULT IN SOME SAVING IN SIZE IF SIZE IS A CRITICAL FACTOR ; ;THIS WILL NOT WORK FOR MULTI-USER HANDLERS WITH SEPERATE VERSIONS ;FOR EACH UNIT THEY SERVICE ; ;IN THIS DAY AND AGE, AND WITH SYSTEM SIZE, ONE PROBABLY SHOULD NOT ;BE THIS CRUDE, BUT IF 100 BYTES OR SO IS CRUCIAL, THEN USE NEXT INSTRUCTION ; INITA: ;INTERRUPTS CONNECTED OK ; MOV PC,SP ;RESET STACK TO USE INIT CODE AREA JMP GO ; ; .SBTTL DIRECTIVE PARAMETER BLOCKS .MCALL EXIT$,SPRA$,ASTX$,WTLO$ ; ; SCRAM: ;DO SYSTEM EXIT EXIT$ ; ; PWR: ;ENABLE POWER UP ASYNC SYSTEM TRAP SPRA$ POWRUP ; ; PWREX: ;EXIT POWER UP ROUTINE ASTX$ ; ; WAITME: ;WAIT FOR NORMAL OR EXPRESS EVENT WTLO$ 0,EVFNOR!EVFEXR .SBTTL WAKE UP CODE ; ; ;COMMENT SOMETHING HAPPENED TO WAKE ME UP, SOMEBODY WANTS TO ;DO SOMETHING ; ; GO: MOV @#.CRTSK,R3 ;HEY ACTION AT LAST ;THE INT OFF/ON CODE USED TO BE STANDARD, BUT ;IF YOU'R WRITING GOOD CODE IT SHOULDN'T HAPPEN ; INTOFF ;TURN OFF ALL INTERRUPTS MOV A.EF(R3),R5 ;GET SIGNIFANT EVENT FLAGS ; BIC #177774,A.EF(R3) ;CLEAR ALL BUT NORMAL, EXP FLAGS ; INTON ;NOW CAN SAFELY TURN INTERRUPTS BACK ON ; MOV #UIT,R0 ;POINT R0 -> UIT FOR LATER DQ'S BIT #EVFEXR,R5 ;ANY EXPRESS REQUESTS ? BEQ NOEREQ ;NO SO DON'T TRY TO DEQUE ONE CALL @#..DQRE ;YES, TRY TO DEQUE EXPRESS REQUEST BCC PROREQ ;IF DEQUE SUCCEDDED PROCESS IT NOEREQ: BIT #EVFNOR,R5 ;NO EXP REQ (OR IT FAILED) ARE THERE BEQ IDLE ;ANY NORMAL REQ'S IF NOT ZZZZZZZZZZZ CALL @#..DQRN ;NORMAL REQ TRY TO DEQ IT BCC PROREQ ;DEQUE SUCCESSFUL GO PROCESS IT IDLE: ;NOTHING TO DO, OR NOTHING SUCCESSFULLY DEQUED TST EXFLAG ;PENDING EXIT REQUEST ? BEQ IDLE1 ;IF NOT SKIP NEXT SECTION TST UNITEN+2 ;CHECK IS IT A NORMAL EXIT BNE IDLE1 ;NORMAL EXIT WAIT FOR ANY I/O TO FINISH JMP EXIT ;EXPRESS REQ GO DIRECTLY TO KILL IDLE1: MOV #WAITME,-(SP) ;HO-HUM NOTHING TO DO EMT 377 ;WAKE ME WHEN THERES SOMETHING TO DO BR GO ;HEY I WOKE UP ; ; .SBTTL PROCESS I/O REQUEST ; ;SHOULD COME HERE TO PROCESS SOME REQUEST THAT ;WAS DEQUED CURRENT STATUS IS ;R0= UIT (UNIT IDENTIFICATION TABLE) ADDRESS ;R1= IO REQUEST NODE ADDRESS ;R2= UNITEN, UNIT ENTRY ADDRESS ; (IF HAVE MULTIPLE UNIT ENTRIES, ONE FOR LAST IO REQ DEQUED) ; (R2) = PUD ADDRESS FOR REQUEST ; 2(R2)= ADDRESS OF NORMAL IO REQUEST NODE DEQUED ; 4(R2)= ADDRESS OF EXPRESS IO REQUEST NODE DEQUED ;R5= ORIGINAL STATE OF EVENT FLAGS ; ;UIT+4= (BYTE) UNIT # OF LAST NORMAL REQUEST DEQUED BY ..DQRN ;UIT+5= (BYTE) UNIT # OF LAST EXPRESS REQUEST DEQUED BY ..DQRE ; PROREQ: MOVB R.FC+1(R1),R3 ;DO CURSORY CHECK OF FUNCTION CODE BLT ILLFUN ;!!!!CAN'T HAVE NEGATIVE FUNCTION CODE CMP #MAXFUN,R3 ;ALSO COULD BE OVER MAXIMUM VALUE BLE ILLFUN ;ALSO A BADDIE CALL @#..VACC ;SEE IF REQUESTING PROGRAM HAS BCS ILLPRV ;OH-OH PRIVILEDGE VIOLATION JMP @#..DISP ;PASSES THE TESTS GO DISPATCH FUNCTION .SBTTL ERROR & NORMAL RETURNS ; ILLFUN: ERRMAC IE.IFC ;ILLEGAL FUNCTION REQUESTED ; ILLBUF: CLR TRAWDC ;CLEAR SOFTWARE STATUS WORD ERRMAC IE.SPC ;ILLEGAL BUFFER ; ILLATT: ERRMAC IE.DAA ;ILLEGAL ATTACH (ALREADY ATTACHED) ; ILLDET: ERRMAC IE.DNA ;ILLEGAL DETACH (NEVER ATTACHED) ; ILLPAR: ERRMAC IE.BAD ;ILLEGAL PARAMETER ; ILLPRV: ERRMAC IE.PRI ;PRIVILEGE VIOLATION ; OVEROK: MOV #IS.SUC,R3 ;SUCCESSFUL OPERATION ;AND FALL INTO OVER CODE ; .SBTTL IODONE (OVER ) CODE ;ON ENTERING OVER CODE, MUST HAVE: ;R1 = REQUEST NODE ADDRESS ;R2 = POINTER TO UNIT ENTRY WORD CONTAINING PUD POINTER ;R3 = STATUS TO RETURN IN IO STATUS BLOCK WORD 1 ; OVER: MOV R.FC(R1),-(SP) ;SAVE FUNCTION CODE MOV R2,-(SP) ;SAVE UNIT ENTRY ADDRESS MOV R4,-(SP) CLR R2 ;CLEAR DECREMENT ;R3 ALREADY HAS STATUS CODE MOV TRAWDC,R4 ;NUMBER OF BYTES XFERRED TO R4 CLR TRAWDC ;CLEAR TRANSFER WORD COUNT CALL @#..IODN ;CALL IO DONE SUBROUTINE MOV (SP)+,R4 MOV (SP)+,R2 ;RESTORE UNIT ENTRY ADDRESS MOV (SP)+,R3 ;RESTORE FUNCTION CODE BIC #177775,R3 ;ISOLATE EXPRESS BIT ADD R3,R2 ;ADVANCE R2 IF AN EXPRESS REQ CLR 2(R2) ;CLEAR UNIT ENTRY POINTER TO LET MORE DEQUE JMP GO ;& RETURN HERE WE GO ROUND AGAIN ; ; ON EXIT WORD # 1 OF IO-STATUS BLOCK CONTAINS "ERROR" CODE ;CURRENT CODES RETURNED ARE: ; ;IE.IFC=-2 ;ILLEGAL I/O FUNCTION REQUESTED ;IE.SPC=-6 ;WORD COUNT OR POINTER BAD ;IE.DAA=-8. ;CAN'T ATTACH, ALREADY DONE ;IE.DAA=-7 ;ILLEGAL DETACH, NEVER ATTACHED ;IE.BAD=-1 ;ILLEGAL PARAMETER ;IE.PRI=-16. ;PRIVILEGE VIOLATION ;IS.SUC=1 ;SUCCESS SOMEHOW WE DID IT RIGHT ; ;WORD #2 CONTAINS # OF CHARACTERS OR BYTES TRANSFERRED) .SBTTL EXIT CODE ; EXIT: ;JUMP HERE TO EXIT AFTER ALL PENDING IO IS FINISHED ;ONE MUST BE SURE ALL INTERRUPTS ARE DISABLED ;ONE MUST DO THE FOLLOWING FOR EACH PHYSICAL UNIT ON ;A MULTIPLE UNIT HANDLER MOV UNITEN,R1 ;GET PUD POINTER IN R1 MOV U.DA(R1),R1 ;GET HARDWARE REGISTER ADDRESS BIC #100,@R1 ;IT'S A GOOD IDEA TO BE SURE INTERRUPTS ARE OFF ; BIC #100,4(R1) ;DO THIS IF 2 INTERRUPT DEVICE ; ; EXITCF: ;JUMP TO HERE IF ..CINT FAILED !!! ;FOR MULTIPLE INTERRUPT HANDLERS, MAY HAVE CONNECTED ;SOME SUCCESSFULLY, SO TRY TO DISCONNECT FROM BOTH MOV UNITEN,R0 ;GET PUD ADDRESS FROM UNIT IDENT TABLE MOV U.TV(R0),R0 ;GET TRAP VECTOR CALL @#..DINT ;DISCONNECT FROM READ INTERRUPT ;AND IF 2 INTERRUPT DEVICE ; ADD #4,R0 ;BUMP TO WRITE INTERRUPT VECTOR ; CALL @#..DINT ;AND DISCONNECT FROM WRITE INTERRUPT MOV #UIT,R0 CALL @#..DNRC ;CALL DECLARE NON RESIDENCY EXITDF: ;JUMP TO HERE IF ..DSUT FAILED !!! MOV #SCRAM,-(SP) ;GO EXIT EMT 377 ; .SBTTL SAVE & RESTORE R0 THRU R5 ; ;MOST OF THE HANDLERS EXPECTS STANDARD USAGE OF THE REGISTERS ; ;IT'S A GOOD IDEA TO SAVE REGISTERS ON ENTERING A FUNCTION, AND ;RESTORING THEM WHEN YOU'R DONE ; ; SAVREG: MOV R0,-(SP) MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV R4,-(SP) MOV R5,-(SP) ;AT THIS POINT, (SP) THRU 12(SP) HAVE SAVED ;REGISTERS, 14(SP) HAS RETURN ADDRESS MOV 14(SP),-(SP) RTS PC ;RETURN ;AFTER RETURN STACK HAS 6 REGISTERS AND ONE ;RETURN ADDRESS ON IT ; ;IF YOU CALLED SAVREG:, YOU MUST CALL RESREG BEFORE ISSUING ANY RTSPC !!! ; RESREG: ;AT THIS POINT (SP) IS RETURN ADDRESS ;2(SP) THRU 14 (SP) HAVE REGISTERS ;16(SP) HAS RETURN ADDRESS FROM SAVREG CALL MOV (SP)+,14(SP) ;OVERWRITE RETURN ADDRESS MOV (SP)+,R5 MOV (SP)+,R4 MOV (SP)+,R3 MOV (SP)+,R2 MOV (SP)+,R1 MOV (SP)+,R0 RTS PC ;RETURN TO CALLER .SBTTL ATTACH DETACH DUMMY FUNCTIONS ; ;ON ENTRY, AS A RESULT OF DISPATCHING THE FUNCTION ; ;R0 = UIT (UNIT IDENTIFICATION TABLE) ADDRESS ;R1 = IO REQUEST NODE ADDRESS ;R2 = ADDRESS OF PUD POINTER WORD IN UNITEN ;R3 = IO FUNCTION CODE ;R5 = STATE OF TASK EVENT FLAGS AT WAKE UP ; ;ITS A GOOD IDEA TO KEEP THESE AS OTHER ROUTINES USUALLY EXPECT THEM ; ; ; ATTACH: ;HERE TO ATTACH TO A UNIT CALL @#..ATUN ;CALL ATTACH SUBROUTINE BCC 11$ ;BRANCH IF OK JMP ILLATT ;ELSE REPORT ILLEGAL ATTACH 11$: JMP OVEROK ;FINISHED-- DO LEGAL EXIT ; ; DETACH: ;DETACH FROM A UNIT CALL @#..DTUN ;CALL DETACH SUB BCC 11$ ;BRANCH IF OK JMP ILLDET ;REPORT BAD DETACH 11$: JMP OVEROK ;DO LEGAL EXIT ; ; DUMMY: ;DUMMY FUNCTION FOR THINGS LIKE OPEN ON A NON-FILES DEVICE JMP OVEROK ;JUST REPORT SUCCESS ; ; .SBTTL WRITE FUNCTION ; ;ON ENTRY, AS A RESULT OF DISPATCHING THE FUNCTION ; ;R0 = UIT (UNIT IDENTIFICATION TABLE) ADDRESS ;R1 = IO REQUEST NODE ADDRESS ;R2 = ADDRESS OF PUD POINTER WORD IN UNITEN ;R3 = IO FUNCTION CODE ;R5 = STATE OF TASK EVENT FLAGS AT WAKE UP ; ;ITS A GOOD IDEA TO KEEP THESE AS OTHER ROUTINES USUALLY EXPECT THEM ; ; WRITE: CALL SAVREG ;SAVE REGISTERS MOV R.PB(R1),R2 ;BUFFER START INTO R2 MOV R.PB+2(R1),R3 ;BYTE SIZE TO R3 BNE 111$ ;BRANCH IF OK CALL RESREG ;RESTORE REGS JMP ILLBUF ;ELSE REPORT ILLEGAL BUFFER 111$: MOV @#.CRTSK,R5 ;GET ATL LISTHEAD BIC #1,A.EF(R5) ;CLEAR "NORMAL" EVENT FLAG MOV #1,R5 ;SET TO VALIDATE A WRITE CALL ..VXFR ;USE SYSTEM SUBROUTINE ;ON RETURN R4=HIGH ORDER 2 BITS OF ADDRESS (IN BITS 4,5) ; R5=LOW ORDER 16 BITS OF ADDRESS ; R4 AND R5 ARE NOW SET FOR A DMA DEVICE ; FOR OTHER OPTIONS FOR DATA HANDLING SEE THE ; "BLOCKO" (BLOCKI) AND "MAP" SUBROUTINES BCC 222$ ;BRANCH IF OK CALL RESREG ;RESTORE REGS JMP ILLPRV ;ELSE REPORT ILLEGAL PRIVILEGE 222$: ;AT THIS POINT THE USER MUST INSERT HIS ;CODE TO HANDLE THE HARDWARE ;IF ALL GOES WELL HE SHOULD EVENTUALLY ;FINISH BY A: CALL RESREG ;RESTORE REGISTERS JMP OVEROK ;ALL FUNCTIONS ARE GO .SBTTL READ FUNCTION ; ;ON ENTRY, AS A RESULT OF DISPATCHING THE FUNCTION ; ;R0 = UIT (UNIT IDENTIFICATION TABLE) ADDRESS ;R1 = IO REQUEST NODE ADDRESS ;R2 = ADDRESS OF PUD POINTER WORD IN UNITEN ;R3 = IO FUNCTION CODE ;R5 = STATE OF TASK EVENT FLAGS AT WAKE UP ; ;ITS A GOOD IDEA TO KEEP THESE AS OTHER ROUTINES USUALLY EXPECT THEM ; ; READ: CALL SAVREG ;SAVE REGISTERS MOV R.PB(R1),R2 ;BUFFER START INTO R2 MOV R.PB+2(R1),R3 ;BYTE SIZE TO R3 BNE 111$ ;BRANCH IF OK CALL RESREG ;RESTORE REGS JMP ILLBUF ;ELSE REPORT ILLEGAL BUFFER 111$: MOV @#.CRTSK,R5 ;GET ATL LISTHEAD BIC #1,A.EF(R5) ;CLEAR "NORMAL" EVENT FLAG MOV #0,R5 ;SET TO VALIDATE A READ CALL ..VXFR ;USE SYSTEM SUBROUTINE ;ON RETURN R4=HIGH ORDER 2 BITS OF ADDRESS (IN BITS 4,5) ; R5=LOW ORDER 16 BITS OF ADDRESS ; R4 AND R5 ARE NOW SET FOR A DMA DEVICE ; FOR OTHER OPTIONS FOR DATA HANDLING SEE THE ; "BLOCKO" (BLOCKI) AND "MAP" SUBROUTINES BCC 222$ ;BRANCH IF OK CALL RESREG ;RESTORE REGS JMP ILLPRV ;ELSE REPORT ILLEGAL PRIVILEGE 222$: ;AT THIS POINT THE USER MUST INSERT HIS ;CODE TO HANDLE THE HARDWARE ;IF ALL GOES WELL HE SHOULD EVENTUALLY ;FINISH BY A: CALL RESREG ;RESTORE USED REGISTERS JMP OVEROK ;ALL FUNCTIONS ARE GO .SBTTL SUBROUTINES TO DO BLOCK TRANSFERS INTO/OUTOF HANDLER ; ;THESE SUBROUTINES WILL DO A BLOCK TRANSFER OF THE DATA BUFFER ;INTO OR OUT OF THE HANDLER. THE USER SHOULD ENSURE THAT THE BUFFER ;AREA IN THE HANDLER IS OF SUFFICIENT SIZE TO HOLD THE MAXIMUM TRANSFER ;EXPECTED ; ;NOTE THAT THE MAXIMUM SIZE FOR THIS TYPE OF TRANSFER IS 4032. WORDS ; ; ;COMMON ENTRY CONDITIONS FOR BOTH ROUTINES ARE ; ;R1 = IO REQUEST NODE ADDRESS ;R4 = ADDRESS OF BUFFER IN HANDLER TO TRANSFER TO/FROM ; ;COMMON EXIT CONDITIONS ARE ; C-BIT SET TO INDICATE ERROR ; C-BIT CLEAR TO INDICATE SUCCESS ; BLOCKI: ;TRANSFER INTO BUFFER IN PROGRAM MOV R2,-(SP) MOV R3,-(SP) MOV R.PB(R1),R2 ;ADDRESS OF DATA (IN CALLER) TO R2 MOV R.PB+2(R1),R3 ;BYTE COUNT TO R3 ;BUFFER ADDRESS IN R4 AT CALLING TIME CALL ..BLXI ;VALIDATE & XFER LINE INTO MY BUFFER BCC 11$ ;BR IF OK MOV (SP)+,R3 MOV (SP)+,R2 SEC ;TO BE SURE RTS PC ;AND RETURN WITH ERROR 11$: MOV (SP)+,R3 MOV (SP)+,R2 CLC ;TO BE SURE RTS PC ; ; ; ; BLOCKO: ;TRANSFER OUT OF HANDLER TO CALLING TASK MOV R2,-(SP) MOV R3,-(SP) MOV R.PB(R1),R2 ;ADDRESS OF DATA (IN CALLER) TO R2 MOV R.PB+2(R1),R3 ;BYTE COUNT TO R3 ;BUFFER ADDRESS IN R4 AT CALLING TIME CALL ..BLXO ;VALIDATE & XFER LINE OUT OF MY BUFFER BCC 11$ ;BR IF OK MOV (SP)+,R3 MOV (SP)+,R2 SEC ;TO BE SURE RTS PC ;AND RETURN WITH ERROR 11$: MOV (SP)+,R3 MOV (SP)+,R2 CLC ;TO BE SURE .SBTTL SUBROUTINE TO MAP PAR/PDR 3 INTO CALLING TASK BUFFER ; ;THIS ROUTINE IS USED TO SWAP PAR/PDR 3 INTO THE CALLING TASKS ;BUFFER FOR SINGLE WORD/BYTE TRANSFERS, (SUCH AS A TERMINAL HANDLER ;WHO MUST PROCESS THE DATA ON A CHARACTER BY CHARACTER BASIS.) ; ;CALLING CONDITIONS ARE (AS SET UP BY ..VXFR) ; ;R4 = EXTENDED ADDRESS (IN BITS 4&5) ;R5 = LOWER 16 BIT ADDRESS ; ;RETURNS WITH PAR/PDR 3 MAPPED TO EXTERNAL BUFFER ; OLD PAR/PDR 3 SAVED FOR UNMAP SUBROUTINE ; ;AFTER THE CALL ONE WOULD ACCESS THE BUFFER IN THE FOLLOWING MANNER ; ; MOV OFFAC3,R5 ;MAP R5 TO PAR/PDR 3 ; MOV 2(R5),R4 ;GET 2ND WORD OF CALLING TASK'S BUFFER IN R4 ; . ; . ; . ; ; OFFAC3=60000 ;OFFSET TO USE PAR/PDR 3 CPDR3=077406 ;A 4K READ/WRITE PAGE DESCRIPTOR ; ; MAP: ASH #-4,R4 ;SHIFT UPPER BITS TO 1,0 ASHC #12,R4 ;OFFSET IN R5,APR ADDRESS IN R4 ASH #-12,R5 ;JUSTIFY OFFSET BIC #177700,R5 ;MASK OFF EXTRA BITS ADD #OFFAC3,R5 ;CONVERT IT TO APR3 OFFSET MOV #CPDR3,-(SP) ;NEW PAGE DESCRIPTOR ONTO STACK MOV R4,-(SP) ;NEW PAGE ADDRESS ONTO STACK CALL ..SPD3 ;CALL SWAP PAR3 AND PDR3 MOV (SP)+,OLDPAR ;SAVE OLD PAR MOV (SP)+,OLDPDR ;AND OLD PDR RTS PC ;AND RETURN ; ; ;ROUTINE TO UNMAP PAR/PDR 3 JUST TAKES SAVED OLD PAR/PDR AND ;SWAPS THEM BACK TO RESTORE ORIGINAL CONDITIONS ; ; ; UNMAP: MOV OLDPDR,-(SP) ;PUT OLD PAR ONTO STACK MOV OLDPAR,-(SP) ;AND OLD PAR CALL ..SPD3 ;SWAP THEM CMP (SP)+,(SP)+ ;RE-ALIGN STACK RTS PC ;AND RETURN .SBTTL EXPRESS FUNCTION HANDLERS ; ; ;FUNCTION 12 -------KILL REQUEST ;CLUDGES TO LOOK LIKE I/O RUNDOWN THEN ;ENTERS I/O RUNDOWN SEQUENCE ; ;FUNCTION 22 -------I/O RUNDOWN ;USES ..FLSH TO CLEAR ALL REQUESTS FROM THE CURRENT USER ; ;FUNCTION 42 -------EXIT (UNLOAD) ;VALIDATES REQUEST THEN SETS ;EXFLAG SO THAT NEXT TIME IN IDLE HANDLER ;DOES EXIT ; ; EXPFUN: MOV R.FC(R1),R3 ;GET FUNCTION CODE CMP #IO.KIL,R3 ;REQUEST FOR KILL ?? BEQ KILLRQ ;PROGRAM COMMITS HARI-KARI TST R.AT(R1) ;OTHERWISE EXEC BETTER BE ASKING FOR EXP BNE EXPILL ;NOT EXEC ---- THAT'S A NO-NO CMP #IO.RDN,R3 ;ITS THE EXEC/ I/O RUNDOWN ? BEQ IORNDQ ;YES GO DO IT CMP #IO.UNL,R3 ;IF NOT RUNDOWN BETTER BE EXIT BEQ EXITGO ;YES IT'S AN EXIT GO DO IT EXPILL: JMP ILLFUN ;FELL THROUGH UNRECON'ED FUNCTION ; ; KILLRQ: MOV R.AT(R1),R4 ;SET UP RNA POINTER MOV R4,R.PB(R1) ;STORE ATL NODE ADDRESS MOV A.TD(R4),R.PB+2(R1) ;STORE STD NODE MOV (R2),R.PB+4(R1) ;STORE PUD START ;NOW JOIN I/O RUNDOWN ; ; IORNDQ: CALL @#..FLSH ;FLUSH QUEUE OF ALL USER REQUESTS JMP OVEROK ;BRANCH TO EXIT ROUTINE ; ; EXITGO: INC EXFLAG ;SET EXIT FLAG TO INDICATE JMP OVEROK ;BRANCH TO OVER, EN ; ; .SBTTL POWER RECOVERY CODE ;ASYNCHRONOUS TRAP EXECUTED AFTER ANY POWER FAILURE OR ;AFTER ANY BOOT OF THE SYSTEM. ; ; ; POWRUP: ;INSERT POWER FAIL RESTART CODE HERE !!!!! MOV #PWREX,-(SP) ;SET UP TO DO EXIT ROUTINE EMT 377 ;AND GO DO IT .SBTTL ISR ROUTINE ; ; ;THE INTERRUPT SERVICE ROUTINES ARE INSERTED HERE ; ;PARTICULAR CARE SHOULD BE TAKEN IN ADDRESSING SINCE THESE ROUTINES ;ARE EXECUTED USING PAR/PDR SET 3 ; ;FOR MANY DEVICES, SEPERATE ENTRANCES WILL OCCUR FOR READ AND WRITE ;INTERRUPTS ; ISRIN: ;CODE TO HANDLE READ INTERRUPTS JMP @#..INTX ;EXIT ISR WHEN DONE ; ; ISROUT: ;CODE TO HANDLER WRITE INTERRUPTS JMP @#..INTX ;EXIT ISR WHEN DONE .SBTTL SYSTEM STATUS TABLES ; NOTE NOTE NOTE ; ; ANY IMPURE (READ/WRITE) DATA STORAGE SHOULD BE PLACED HERE ; IF ONE WISHES A MULTI-USER HANDLER WITH SEPERATE PURE SECTIONS ; ALL READ/WRITE DATA STORAGE SHOULD BE HERE. ; IN ADDITION, THE CODE FOR ADJUSTING THE STACK TO OVERWRITE ; THE INIT CODE SHOULD BE DELETED. ; ;THE UNIT IDENTIFICATION TABLE (UIT) CONSISTS OF A 5-WORD HEADER AREA, ;FOLLOWED BY ONE OR MORE 3 WORD UNIT ENTRIES ; ; ; ;THE FOLLOWING WORD WILL NOT CHANGE UIT: .WORD DISPCH ;POINTER TO DISPATCH TABLE ;THE LOWER BYTE OF THE NEXT WORD SHOULD BE SET ;TO THE MAXIMUM NUMBER OF UNITS SERVICED BY ;THE HANDLER (=# OF UNIT ENTRIES TO FOLLOW) ;AFTER CALLING ..DSUT OR ..DSMU THE UPPER BYTE ;WILL HAVE THE # OF UNITS ACTUALLY FOUND IN ;THE RESULTANT PUD SCAN .BYTE 1,0 ;NUMBER OF UNITS ;THE FOLLOWING WORD SHOULD INITIALLY BE 0 ;THE LOWER BYTE WILL BE FILLED WITH THE UNIT ;NUMBER OF THE LAST NORMAL REQUEST DEQUED ;THE UPPER BYTE WILL BE FILLED WITH THE UNIT ;NUMBER OF THE LAST EXPRESS REQUEST DEUED .WORD 0 ;THE FOLLOWING WORDS ARE NECESSARY BUT RESERVED .WORD 0,0 ; ; ;NOW SHOULD FOLLOW ONE OR MORE UNIT ENTRIES. THE NUMBER OF UNIT ENTRIES ;SHOULD CORRESPOND TO THE NUMBER OF UNITS SPECIFIED ABOVE ; ; ;BEFORE CALLING ..DSUT OR ..DSMU, THIS SHOULD ;CONTAIN THE UNIT NUMBER (FOR A SINGLE UNIT ;OR MULTI UNIT HANDLER) OR THE UNIT VALIDITY ;MASK (FOR A MULTI-USER HANDLER WITH SEPERATE ;VERSIONS SERVICING SEPERATE UNITS) ;AFTER CALLING ..DSUT OR ..DSMU, THIS WILL ;CONTAIN THE ADDRESS OF THE PUD FOUND BY ;THE PUD SCAN UNITEN: .WORD 0 ;THE FOLLOWING WORD WILL CONTAIN THE LAST NORMAL ;IO REQUEST NODE DEQUED BY ..DQRN .WORD 0 ;THE FOLLOWING WORD WILL CONTAIN THE LAST EXPRESS ;IO REQUEST NODE DEQUED BY ..DQRE .WORD 0 .SBTTL DISPATCH TABLE DISPCH: ; THE FIRST TWO WORDS OF THE DISPATCH TABLE ARE ONLY USED ; FOR DIRECTORY TYPE DEVICES THAT NEED AN ACP TO ASSIST THEM ; DEPENDING ON THE SUCCESS OR FAILURE OF SEND/REQUESTS TO ; THE APPROPRIATE ACP, THESE WORDS CONTAIN THE ADDRESS OF ; THE ROUTINES TO EXECUTE ; .WORD ILLFUN ;ADDRESS TO BRANCH TO IF SEND/REQ FAILS .WORD ILLFUN ;ADDRESS TO BRANCH TO IF SEND/REQ SUCCEEDS ; ; ;NOW THE FUNCTION CODE ENTRIES THEMSELVES (2-WORDS) ; FOR EACH ENTRY, THE LOWER BYTE OF THE FIRST WORD CONTAINS A ; VOLUME CHARACTERISTIC MASK V.MOU=200 ;VOLUME MUST BE MOUNTED TO PERFORM THIS FUNCTION V.F11=100 ;VOLUME MUST BE A FILES-11 VOLUME V.UNL=40 ;VOLUME MUST NOT HAVE AN UNLOAD PENDING V.ATT=20 ;VOLUME MUST PERMIT ATTACH/DETACH FUNCTIONS V.DCF=10 ;DEVICE CONTROL FNS MUST BE PERMITTED ;BITS 2-0 ARE RESERVED ; ; ; THE UPPER BYTE OF THE FIRST WORD CONTAINS A "CONTROL VARIABLE" ;THIS FUNCTION SHOULD BE ROUTED TO THE ACP TASK & CV.ACP=200 ;WORD U.DACP OF PUD CONTAINS ACP NAME CV.SUB=100 ;5 HIGH-ORDER BITS OF SUBFUNCTION CODE MUST = 0 CV.EXP=40 ;THE EXPRESS BIT (BIT 1) OF THE SUBFUNCTION CODE MUST = 0 ;BIT 20 IS RESERVED CV.DEL=10 ;USER MUST HAVE FILE DELETE PRIVELEGES CV.EXT=4 ;USER MUST HAVE FILE EXTEND PRIVELEGES CV.WRI=2 ;USER MUST HAVE FILE WRITE PRIVELEGES CV.REA=1 ;USER MUST HAVE FILE READ PRIVELEGES ; ; ;THE SECOND WORD OF THE FUNCTION ENTRY CONTAINS THE ADDRESS OF THE ;CODE TO DISPATCH TO, (IF THE HANDLER ITSELF MUST PERFORM THE FUNCTION) ; ; ;THE SECOND WORD OF THE FUNCTION ENTRY CONTAINS A SUFFIX BYTE AND A SUB- ;FUNCTION CODE BYTE, (IF A SEND/REQUEST SHOULD BE PERFORNED) ; ; THE DISPATCH TABLE ITSELF ; NORDIS 0,0,EXPFUN ;0 = EXPRESS FUNCTIONS NORDIS 0,CV.WRI,WRITE ;1 = WRITE LOGICAL NORDIS 0,CV.REA,READ ;2 = READ LOGICAL NORDIS V.ATT,CV.SUB!CV.EXP,ATTACH ;3 = ATTACH NORDIS V.ATT,CV.SUB!CV.EXP,DETACH ;4 = DETACH ILFN ;5 = CONTROL ILFN ;6 = UNDEFINED ILFN ;7 = CLOSE OUT LUN ILFN ;10 = UNDEFINED ILFN ;11 = FIND FILE ILFN ;12 = ILLEGAL ILFN ;13 = REMOVE FILE ILFN ;14 = ENTER FILE ILFN ;15 = ACCESS FOR READ ILFN ;16 = ACCESS FOR READ/WRITE ILFN ;17 = ACCESS FOR READ/WRITE/EXTEND ILFN ;20 = DEACCESS ;FOR A NON-ACP HANDLER, THE ABOVE ACCESS TYPE FUNCTIONS SHOULD BE DUMMIED ;OUT SO AS NOT TO CONFUSE TASKS LIKE ...PIP ; DUMFUN ;15 = ACCESS FOR READ ; DUMFUN ;16 = ACCESS FOR READ/WRITE ; DUMFUN ;17 = ACCESS FOR READ/WRITE/EXTEND ; DUMFUN ;20 = DEACCESS NORDIS 0,CV.REA,READ ;21 = READ VIRTUAL NORDIS 0,CV.WRI,WRITE ;22 = WRITE VIRTUAL ILFN ;23 = EXTEND ILFN ;24 = CREATE ILFN ;25 = DELETE FILE ILFN ;26 = READ ATTRIBUTES ILFN ;27 = WRITE ATTRIBUTES ;ENOUGH FUNCTIONS ALREADY !!!!!! .SBTTL GENERAL IMPURE STORAGE AREA TRAWDC: .WORD 0 ;NUMBER OF WORDS/BYTES IN IO REQUEST EXFLAG: .WORD 0 ;EXIT PENDING FLAG OLDPAR: .WORD 0 ;SAVE PAR AFTER ..SPD3 CALL OLDPDR: .WORD 0 ;SAVE PDR AFTER ..SPD3 CALL ; ;THE DATA BUFFER FOR TRANSFERS SHOULD GENERALLY BE THE LAST THING IN ;THE PROGRAM (OR THE IMPURE AREA OF A MULTI-USER HANDLER) IF HE ;ISN'T, BUFFER OVERFLOW CAN DO STRANGE THINGS TO YOUR DATA (OR CODE) ; ;IN GENERAL, MAKE SURE THE BUFFER IS BIG ENOUGH !!!! ; BUFFER: .BLKB 130. ;TYPICAL TERMINAL BUFFER .END INIT