.SBTTL INTRODUCTION .TITLE BD ;16. CHANNEL HANDLER FOR MBD .IDENT 'V001D' ; ; 16. CHANNEL MICROPROGRAMMABLE BRANCH DRIVER (MBD) HANDLER FOR RSX11D ; ; THIS HANDLER IS AN RSX11D PRIVILEGED TASK WHICH CAN SUPPORT ; SIMULTANEOUS OPERATION OF UP TO 16. MBD CHANNELS DISTRIBUTED AMONG ; ANY NUMBER OF MBD'S. EACH MBD CAN HAVE 1 TO 8. CHANNELS DEFINED AT ; SYSGEN TIME BY PUD ENTRIES. EACH CHANNEL IN EACH MBD IS ASSOCIATED ; WITH A UNIQUE UNIT NUMBER (0 TO 15.) FOR DEVICE NAME "BD". ; IN DEQUEUING REQUESTS FOR THE 16. UNITS, NO. 15. IS THE ; HIGHEST PRIORITY AND NO. 0 THE LOWEST. ALL 16. UNITS (16. PUD ; ENTRIES) NEED NOT BE PRESENT IN A PARTICULAR RSX SYSTEM; ; ANY UNITS WHICH ARE NOT NEEDED MAY SIMPLY BE OMITTED AT SYSGEN ; TIME. ; ; THE PUD ENTRY FOR A PARTICULAR UNIT MUST CONTAIN THE FOLLOWING ; INFORMATION: ; ; DEVICE NAME U.DN "BD" ; UNIT NO. U.UN 0 TO 15. (BYTE) ; CHARACTERISTICS 1 U.C1 UC.SQD=40 (OCTAL)-SEQUENTIAL DEVICE ; CHARACTERISTICS 2 U.C2 0 ; CHARACTERISTICS 3 U.C3 MBD CHANNEL NO.: 0-7 ; CHARACTERISTICS 4 U.C4 MBD MEMORY SIZE:256.,512.,1K,2K,3K,OR 4K ; INTERRUPT VECTOR U.TV INTERRUPT VECTOR ADDR. FOR GIVEN CHANNEL ; INTERRUPT PSW U.IP INTERRUPT PRIORITY = 5 (BITS 7-5) ; DEVICE ADDRESS U.DA MBD CSR ADDRESS IN EXTERNAL PAGE ; ; NOTE IN ASSIGNING CHANNEL NUMBERS THAT CHANNEL 7 HAS THE ; HIGHEST PRIORITY AND 0 HAS THE LOWEST IN ANY PARTICULAR MBD. ; ; THE FOLLOWING QIO FUNCTIONS ARE SUPPORTED: ; ; KILL I/O (12) CANCELS ALL REQUESTS FOR A GIVEN TASK ON A ; GIVEN UNIT ; I/O RUNDOWN (22) LIKE KILL I/O, FOR EXECUTIVE REQUEST ; UNLOAD HANDLER(42) WAITS FOR ALL OPERATIONS TO COMPLETE, THEN ; HANDLER EXITS ; WRITE (400) LOADS MBD MEMORY ; READ (1000) ACTIVATES AN MBD CHANNEL ; ATTACH (1400) ATTACHES THE MBD UNIT TO THE CALLER ; DETACH (2000) DETACHES THE MBD UNIT FROM CALLER ; ; IF A CHANNEL HAS ALREADY BEEN STARTED BY A "READ" REQUEST AND ; A "KILL I/O" OR "I/O RUNDOWN" IS REQUESTED FOR THE SAME TASK ; AND UNIT, THE MBD CHANNEL IS INITIALIZED WITH THE PDX EQUAL TO ; 177777; THE MBD PROGRAM SHOULD RESPOND BY TURNING OFF LAM SOURCES ; FOR THE CHANNEL AND EXITING VIA EX4. ; ; A "WRITE" REQUEST REQUIRES TWO PARAMETERS: ; 1.)BUFFER START ADDRESS (USER VIRTUAL) ; 2.)BUFFER SIZE (BYTES) ; ; THE FIRST WORD OF THE BUFFER SHOULD BE AN MBD START ADDRESS FOR ; THE LOAD. ; THE SECOND WORD OF THE BUFFER SHOULD BE THE NUMBER OF WORDS TO ; LOAD (BUFFER SIZE MINUS 2 WORDS). ; THE THIRD TO LAST WORDS OF THE BUFFER SHOULD BE INSTRUCTIONS TO ; BE LOADED INTO THE MBD. ; THE BUFFER MAY BE AT ANY PHYSICAL ADDRESS BUT CANNOT EXCEED ; 8132. BYTES IN LENGTH. ; ; ON A WRITE (MBD LOAD) OPERATION, THE HANDLER CHECKS THAT THE SECOND ; WORD OF THE BUFFER (NO. OF WORDS TO LOAD) CORRESPONDS WITH ; THE BUFFER LENGTH; IF IT DOES NOT, AN IE.BAD ERROR IS RETURNED. ; IF THERE ARE ANY ACTIVE CHANNELS ON THE MBD WHICH IS TO BE ; LOADED, AN IE.WLK ERROR IS RETURNED. IN EITHER CASE, LOADING IS ; NOT PERFORMED. THE HANDLER ALSO VERIFIES THE DATA LOADED BY ; READING IT BACK AFTER LOADING; IF A DISCREPANCY IS FOUND, ; AN IE.BBE ERROR IS RETURNED AND THE SECOND WORD OF THE I/O STATUS ; BLOCK CONTAINS THE NUMBER OF BYTES SUCCESSFULLY PROCESSED, FROM ; WHICH THE FAILING MBD ADDRESS CAN BE CALCULATED. ; ; A "READ" REQUEST REQUIRES TWO PARAMETERS: ; 1.) BUFFER START ADDRESS (USER VIRTUAL) ; 2.) BUFFER SIZE (BYTES) ; ; THE CONTENTS OF THE BUFFER AND THE DIRECTION OF TRANSFER ARE A ; FUNCTION ONLY OF THE MBD PROGRAM FOR THE CHANNEL. THE MAXIMUM ; BUFFER SIZE IS 32,765. WORDS. ; ; IN ORDER TO PASS CONTROL DATA TO AND FROM THE MBD CHANNEL ON ; INITIALIZATION AND COMPLETION, THE TWO WORDS BEFORE THE USER- ; SPECIFIED BUFFER ARE USED. THE USER MUST THEREFORE INSURE ; THAT THESE WORDS ARE (1) WITHIN HIS VIRTUAL ADDRESS SPACE; ; (2) NOT MODIFIED, EXAMINED, EXECUTED, OR OTHERWISE USED WHILE ; THE MBD CHANNEL IS OPERATING (FROM QIO TIME TO I/O COMPLETION). ; TO PROVIDE PSEUDO-TRANSPARENCY, THE CONTENTS OF THESE TWO ; WORDS ARE SAVED INSIDE THE DRIVER BEFORE STARTING THE MBD, ; AND RESTORED AFTER THE CHANNEL INTERRUPT OCCURS. ; HOWEVER, IF AN ERROR OCCURS WHILE RESTORING THE TWO WORDS, ; THE I/O STATUS BLOCK ERROR CODE IE.OVR WILL BE RETURNED AND ; THE USER ON SEEING THIS CODE SHOULD EXPECT THAT THE TWO ; WORDS PRECEDING HIS BUFFER WERE CLOBBERED. ; ; SINCE THE MBD'S MEMORY ADDRESS (MAR) REGISTER CONTAINS A 16-BIT WORD ; ADDRESS, IT CAN REPRESENT ANY OF 64K WORDS. FURTHERMORE, A CHOICE CAN ; BE MADE VIA THE RST17 AND SET17 CONTROL INSTRUCTIONS AS TO WHETHER ; IT WILL OPERATE ON AN UPPER OR LOWER MEMORY BANK OF THAT SIZE (UNIBUS ; A17 ADDRESS BIT ON OR OFF). HOWEVER, THE CHOICE APPLIES TO ALL ; CHANNELS EXECUTING ON THAT MBD AND MUST BE FIXED BEFORE ANY CHANNELS ; ARE STARTED. HENCE THE HANDLER CHECKS THAT THE EXTENDED ADDRESS BIT ; A17 FOR THE USER BUFFER MATCHES THE CURRENT SETTING OF THE MBD. IF ; IT DOES NOT, THE HANDLER VERIFIES THAT NO CHANNELS ARE ACTIVE ON THAT ; MBD AND SETS OR RESETS A17 AS NEEDED USING SINGLE INSTRUCTION MODE ; BEFORE STARTING THE CHANNEL. IF OTHER CHANNELS ARE ACTIVE, HOWEVER, ; A FATAL ERROR (IE.RSU) IS RETURNED TO THE I/O STATUS BLOCK AND THE ; CHANNEL IS NOT STARTED (THE USER MAY TRY AGAIN LATER). IN ANY CASE, ; THE USER'S BUFFER (INCLUDING THE TWO HEADER WORDS IN FRONT) MUST ; ALWAYS BE ENTIRELY WITHIN EITHER THE UPPER OR LOWER 64K MEMORY BANK; ; BUFFERS CROSSING THE BOUNDARY ARE NOT ALLOWED (SORRY ABOUT THAT). ; ; SINCE OLDER MBD MODELS COULD NOT ADDRESS BEYOND 32K ON THE UNIBUS, AN ; ASSEMBLY OPTION IS PROVIDED (BY DEFINING SYMBOL "NOXMEM") TO REJECT ; ALL BUFFERS WHICH ARE NOT IN THE BOTTOM 32K OF PHYSICAL MEMORY. ; ; BEFORE INITIALIZING THE CHANNEL FOR A READ FUNCTION, THE HANDLER ; PUTS THE PHYSICAL WORD ADDRESS OF THE BUFFER HEADER (I.E., 2 WORDS ; LESS THAN THE BUFFER ADDRESS SUPPLIED IN THE QIO) INTO THE ; PDX. AFTER SAVING THE TWO BUFFER HEADER WORDS, IT PUTS THE ; WORD COUNT (I.E., HALF THE BYTE COUNT SUPPLIED IN THE QIO, ; NOT INCLUDING THE 2 HEADER WORDS) INTO THE FIRST HEADER WORD, ; AND A STATUS CODE OF IE.ONP IN THE SECOND HEADER WORD. ; THE MBD PROGRAM SHOULD BEGIN BY PUTTING THE PDR VALUE INTO ; THE MAR (A WORD ADDRESS), DOING A DMA READ OPERATION AT THE MAR ; ADDRESS TO READ THE WORD COUNT, ADDING 2 TO THE MAR, AND SAVING ; THE WORD COUNT. AT THE END OF THE CHANNEL'S OPERATION, ; IT SHOULD WRITE OUT (VIA DMA) A COMPLETION CODE INTO THE SECOND ; HEADER WORD (IS.SUC = 1 FOR A SUCCESSFUL TRANSFER, OTHER VALUES TO ; INDICATE PROBLEMS, E.G., NO Q OR X RESPONSE FROM A MODULE). IF THE ; COMPLETION CODE IS NEGATIVE (FATAL ERROR), AN ERROR INFORMATION ; WORD SHOULD BE WRITTEN INTO THE FIRST HEADER WORD; BUT IF POSITIVE, ; THE ACTUAL WORD COUNT FOR THE OPERATION SHOULD BE WRITTEN INTO THE ; FIRST WORD. THE CHANNEL MUST THEN INTERRUPT THE COMPUTER VIA AN ; "INT" INSTRUCTION. THE HANDLER THEN PUTS TWICE THE RETURNED WORD ; COUNT FROM THE FIRST HEADER WORD (I.E., A BYTE COUNT) INTO THE SECOND ; WORD OF THE I/O STATUS BLOCK IF THE COMPLETION CODE IS POSITIVE, OR ; JUST THE CONTENTS OF THE FIRST HEADER WORD (ERROR INFORMATION) ; UNCHANGED IF THE COMPLETION CODE IS NEGATIVE; AND PUTS THE LOW 8 BITS ; OF THE COMPLETION CODE INTO THE FIRST WORD OF THE I/O STATUS BLOCK. ; THE ORIGINAL CONTENTS OF THE BUFFER HEADER WORDS IS THEN RESTORED. ; NOTE THAT IF THE MBD PROGRAM FAILS TO OVERWRITE THE COMPLETION CODE ; IN THE SECOND HEADER WORD, THE "IE.ONP" ERROR CODE ORIGINALLY STORED ; BY THE HANDLER WILL BE RETURNED TO THE I/O STATUS BLOCK, ; INDICATING THAT THE MBD IS NOT LOADED. ; ; THE MBD CODE BEGINNING IN LOCATION 1 SHOULD READ THE CHANNEL ; NUMBER (CCL SOURCE), CHECK THE PDX VALUE (177777 IMPLIES CHANNEL KILL, ; OTHER VALUES IMPLY CHANNEL START), AND BRANCH TO ONE OF 16. POSSIBLE ; ADDRESSES BASED ON A DISPATCH TABLE. THAT IS, EACH CHANNEL PROGRAM ; SHOULD HAVE A PRIMARY ENTRY POINT, WHICH CLEARS MODULES, ENABLES LAM ; SOURCES IF APPROPRIATE, WAITS FOR A LAM (VIA EX2), READS ; OUT DATA, DISABLES LAM SOURCES, INTERRUPTS THE PDP11, AND ; EXECUTES EX4; AND AN ABORT ENTRY POINT, WHICH DISABLES LAMS ; AND EXECUTES AN EX4. ; ; WHEN INITIATING A CHANNEL, THE HANDLER WAITS UP TO 12 MILLISECONDS ; FOR THE READY BIT IN THE CSR TO COME ON; IF IT REMAINS OFF FOR ; THIS PERIOD, THE HANDLER ASSUMES THE MBD IS IN AN INFINITE ; LOOP AND THEREFORE EXECUTES A RESET MBD FUNCTION, KILLING ALL ; ACTIVE CHANNELS ON THAT MBD. IT RETURNS AN I/O STATUS BLOCK ERROR ; CODE IE.FHE FOR ALL CHANNELS ABORTED, THEN RETRIES THE CHANNEL ; INITIALIZE. A ROUTINE WHICH ISSUES AN MBD READ AND OBTAINS AN ; IE.FHE ERROR SHOULD THEREFORE ASSUME THE OPERATION WAS TERMINATED ; FOR REASONS BEYOND ITS CONTROL, AND RE-ISSUE THE QIO. SINCE THE ; TERMINATION MAY HAVE OCCURRED IN THE MIDDLE OF A DATA READOUT, ; WITH SOME MODULES READ AND OTHERS NOT, THE MBD CHANNEL CODE ; SHOULD IF POSSIBLE BEGIN BY CLEARING MODULES BEFORE ENABLING AND ; WAITING FOR A LAM. ; ; THE HANDLER WILL RE-TRY CHANNEL INITIATION IN THE ABOVE FASHION A ; MAXIMUM OF 5 TIMES; IF THE MBD READY BIT IS STILL NOT ON, AN ERROR ; CODE OF IE.DNR WILL BE RETURNED. ; ; THE FOLLOWING COMPLETION CODES ARE RETURNED BY THE HANDLER: ; ; IE.BAD -01 INCORRECT WORD COUNT IN MBD LOAD IMAGE ; IE.IFC -02 INVALID FUNCTION CODE ; IE.DNR -03 CHANNEL INITIALIZE FAILED IN 5 ATTEMPTS ; (READY BIT OFF) ; IE.ONP -05 MBD PROGRAM DID NOT REWRITE COMPLETION CODE ; BEFORE INTERRUPTING (MBD PROGRAM NOT LOADED) ; IE.SPC -06 IMPROPER USER BUFFER ADDRESS OR LENGTH ; IE.DNA -07 DETACH FAILED--DEVICE NOT ATTACHED ; IE.DAA -08 ATTACH FAILED--DEVICE ALREADY ATTACHED ; IE.WLK -12 MBD CANNOT BE LOADED--ACTIVE CHANNELS ; IE.DAO -13 MBD LOAD IMAGE LONGER THAN MBD MEMORY SIZE ; IE.ABO -15 MBD CHANNEL ABORTED BY KILL I/O OR I/O RUNDOWN ; IE.PRI -16 PRIVILEGE VIOLATION ; IE.RSU -17 ACTIVE CHANNELS USING OTHER 64K MEMORY BANK ; IE.OVR -18 ERROR RESTORING BUFFER HEADER WORDS ON A READ ; IE.BYT -19 ODD BYTE COUNT OR VIRTUAL BUFFER ADDRESS ; IE.CON -22 CONNECT TO INTERRUPT FAILED ; IE.BBE -56 MBD MEMORY LOCATION READ BACK WRONG AFTER LOAD ; IE.FHE -59 CHANNEL TERMINATED BY MBD RESET ; IE.OFL -65 POWER FAILED; OPERATION TERMINATED; ; MBD MUST BE RELOADED ; IS.SUC +01 SUCCESSFUL COMPLETION ; OTHERS DEFINED BY MBD PROGRAM ; ; TASK ATTRIBUTES: /-AB /-CP /DS /-FP /-FX /HD /-MU /-PI /PR /-TA /-TR ; ; TASKNAME: BD.... ; PARTITION: GEN ; POOL LIMIT: 40 ; PRIORITY: 248 ; STACK: 50 ; UIC: [1,1] ; UNITS: 0 ; .SBTTL SYMBOL DEFINITIONS ; ; MACRO CALLS: ; RSXMAC: .MCALL DIR$,EXIT$S,ASTX$S,SPRA$,WTLO$ ; ; DEFINITIONS: ; PS = 177776 ;PDP11 PROCESSOR STATUS WORD PR7 = 340 ;PRIORITY 7 MASK ; N.RNA = 2 ;OFFSET FROM UIT ENTRY TO NORMAL RNA EF.NIR = 1 ;NORMAL REQUEST EVENT FLAG MASK EF.XIR = 2 ;EXPRESS REQUEST EVENT FLAG MASK EF.INT = 4 ;INTERRUPT (I/O DONE) EVENT FLAG MASK WRT = 1 ;TRANSFER DIRECTION FOR WRITE ; PDESC = 77402 ;PAGE DESCRIPTOR FOR ACCESS TO USER BUF ASROFF = 60000 ;ASR3 VIRTUAL ADDRESS OFFSET ; MIN = 6 ;MINIMUM WRITE BUFFER LENGTH MAX = 2*<4096.-32.> ;MAXIMUM WRITE BUFFER LENGTH WRTHDL = 2 ;WRITE BUFFER HEADER LENGTH (WORDS) RDHDL = 2 ;READ BUFFER HEADER LENGTH (WORDS) ; BDNAM = "BD ;HANDLER NAME RETRY = 5 ;CHANNEL INITIALIZE MAX RETRIES TIMOUT = 1000. ;MBD READY WAIT LOOP TIME ; PDX = 2 ;OFFSET OF PDX FROM CSR MSK = 4 ;OFFSET OF MSK FROM CSR (MBD REGISTERS) IR = 6 ;OFFSET OF IR FROM CSR ; INIT = 3 ;CODE FOR RESET MBD AND SET SINGLE CYCLE MODE A17 = 40 ;EXTENDED MEMORY BIT IN CSR CGO = 104 ;CODE FOR CHAN INIT AND INTERRUPT ENABLE CHBITS = 3400 ;CHANNEL NUMBER BITS IN CSR KILL = 177777 ;PDX CODE FOR KILL CHANNEL ; ST = 130000 ;MBD STORE INSTRUCTION LD = 140000 ;MBD LOAD INSTRUCTION EX4 = 3400 ;MBD EX4 INSTRUCTION (CHANNEL HALT) INT = 5400 ;MBD INT INSTRUCTION (PDP11 INTERRUPT) SET17 = 5000 ;MBD SET17 INSTRUCTION (SET A17 BIT) RST17 = 6000 ;MBD RST17 INSTRUCTION (RESET A17 BIT) ; ; .PSECT MBDRW .SBTTL INITIALIZATION CODE, EXIT CODE, AND IDLE CODE ; BDSTRT: MOV #BDUIT,R0 ;SET ADDR OF UIT MOV #BDNAM,R2 ;SET HANDLER NAME MOV #UF.RH,R3 ;HANDLER RESIDENT FLAG JSR PC,@#..DSUT ;DECLARE HANDLER RESIDENT BCS EXIT ;GO AWAY IF IT FAILS DIR$ #PFDPB ;SET UP POWER FAIL AST BCS NONRES ;EXIT IF IT FAILS JSR PC,BDINIT ;INITIALIZE MBD MOV PC,SP ;INCREASE STACK SIZE ; IDLE: TST EXITFL ;HANDLER WANT TO EXIT? BEQ SLEEP ;NO MOV #UNIT1,R2 ;ADDR FIRST UNIT IN UIT MOV #NUNITS,R1 ;NO. OF UIT ENTRIES 1$: TST (R2) ;IS PUD ADDR 0? BEQ 2$ ;YES, UNIT DOESN'T EXIST TST N.RNA(R2) ;IS THERE A NORMAL REQUEST ACTIVE? BNE SLEEP ;YES, CAN'T EXIT 2$: ADD #UITSZ,R2 ;GO TO NEXT UNIT IN UIT SOB R1,1$ ;LOOP OVER ALL UNITS MOV #UNIT1,R2 ;FIRST UIT ENTRY MOV #NUNITS,R1 ;NO. OF UNITS 3$: MOV (R2),R5 ;PUD ADDRESS BEQ 4$ ;UNIT NONEXISTENT MOV #INIT,@U.DA(R5) ;INITIALIZE MBD, CLEAR RUN MODE JSR PC,GTUNIT ;SET R3=UNIT NO, R4=UNIT MASK BIT R4,CONINT ;INTERRUPT CONNECTED THIS UNIT? BEQ 4$ ;NO MOV U.TV(R5),R0 ;INTERRUPT VECTOR JSR PC,@#..DINT ;DISCONNECT FROM INTERRUPT 4$: ADD #UITSZ,R2 ;NEXT UNIT SOB R1,3$ ;DO ALL OF THEM NONRES: MOV #BDUIT,R0 ;GET UIT ADDR JSR PC,@#..DNRC ;DECLARE NONRESIDENT EXIT: EXIT$S ;AND BECOME NON-RESIDENT ; SLEEP: DIR$ #WFDPB ;WAIT FOR NORMAL RQ, EXPRESS RQ, OR ;MBD INTERRUPT ; .SBTTL I/O COMPLETION, REQUEST DQ-ING, AND DISPATCH ; CHECK: MOV #BDUIT,R0 ;GET UIT ADDRESS MOV @#.CRTSK,R1 ;HANDLER ATL ADDRESS MOV @#PS,-(SP) ;SAVE PRIORITY BIS #PR7,@#PS ;INHIBIT INTERRUPTS MOV A.EF(R1),R5 ;GET HANDLER EVENT FLAGS BIC #EF.INT,A.EF(R1);CLEAR INTERRUPT FLAG MOV INTCHN,R4 ;PATTERN OF INTERRUPTING CHANNELS CLR INTCHN ;RESET IT MOV (SP)+,@#PS ;RE-ENABLE INTERRUPTS BIT #EF.INT,R5 ;MBD INTERRUPT? BEQ CHECKQ ;NO MOV R0,-(SP) ;YES, DO COMPLETION PROCESSING... MOV R5,-(SP) ;AFTER SAVE OF UIT AND FLAGS MOV #NUNITS,R3 ;NO. OF UNITS MOV #UNIT1,R2 ;FIRST UIT ENTRY 1$: MOV (R2),R5 ;PUD ADDR OR 0 BEQ 10$ ;0--UNIT DOESN'T EXIST MOV N.RNA(R2),R1 ;NORMAL REQUEST NODE ADDR BEQ 10$ ;NO REQUEST IN PROGRESS TST REINIT ;POWER FAIL? BNE 2$ ;YES MOVB U.UN(R5),-(SP) ;UNIT NO. BIC #177760,@SP ;LIMIT TO 0-15 RANGE MOV #1,R0 ;CONSTRUCT... ASH (SP)+,R0 ;...PROPER MASK BIT R0,R4 ;THIS CHANNEL INTERRUPT? BEQ 10$ ;NO! 2$: MOV R4,-(SP) ;SAVE INTERRUPTING CHANNELS, MOV R3,-(SP) ;COUNTER, MOV R2,-(SP) ;AND UIT POINTER JSR PC,SETHDR ;SET R2 = HEADER ADDR, R3 = LENGTH TST REINIT ;POWER FAIL? BEQ 3$ ;NO MOV #IE.OFL,R3 ;SET ERROR CODE BR 4$ 3$: MOV #ERRBLK,R4 ;ADDR OF ERROR STATUS BLOCK JSR PC,@#..BLXI ;READ BUFFER HDR INTO ERRBLK BCC 5$ ;WORKED! MOV #IE.OVR,R3 4$: CLR R4 ;0 BYTES TRANSFERRED BR 9$ ;LOSE! 5$: MOV R5,R4 ;GET PUD ADDR JSR PC,GETHDR ;GET ADDR OF SAVED BUFFER HEADER JSR PC,@#..BLXO ;WRITE SAVED WORDS BACK INTO BUFFER BCC 6$ ;SUCCESS! MOV #IE.OVR,R3 ;ELSE SET ERROR CODE BR 7$ 6$: MOV ERRBLK+2,R3 ;SET STATUS FROM MBD OPERATION BLT 8$ ;IF MINUS (FATAL), ERRBLK IS ERROR INFO 7$: ASL ERRBLK ;ELSE IS WORD COUNT: MAKE BYTE COUNT 8$: MOV ERRBLK,R4 ;GET # BYTES TRANSFERRED OR ERROR INFO 9$: JSR PC,IOCOMP ;DO I/O COMPLETION MOV (SP)+,R2 ;RESTORE WHAT WE SAVED MOV (SP)+,R3 MOV (SP)+,R4 CLR N.RNA(R2) ;CLEAR NORMAL RNA TO ALLOW DQ-ING 10$: ADD #UITSZ,R2 ;NEXT UIT ENTRY SOB R3,1$ ;DO ALL CLR REINIT ;RESET POWER FAIL FLAG MOV (SP)+,R5 ;RESTORE EVENT FLAGS MOV (SP)+,R0 ;RESTORE UIT ADDR ; CHECKQ: BIT #EF.XIR,R5 ;ANY EXPRESS Q REQUESTS? BEQ 1$ ;NO JSR PC,@#..DQRE ;DQ EXPRESS REQUESTS BCC 2$ ;GOT ONE! 1$: BIT #EF.NIR,R5 ;ANY NORMAL Q-REQUESTS? BEQ IDLEJ ;NO JSR PC,@#..DQRN ;DQ NORMAL REQUEST BCS IDLEJ ;NONE TO DO. (SO HOW'D WE GET HERE??) 2$: MOVB R.FC+1(R1),R3 ;GET FUNCT CODE CMP R3,#NFUNS ;SEE IF TOO BIG FOR TABLE BHIS UNRFNJ ;YES, ILLEGAL JSR PC,@#..VACC ;VERIFY THAT IT'S OK BCS NOPRVJ ;NO, DON'T HAVE NEEDED PRIVILEGES JMP @#..DISP ;YES, DISPATCH USING FUNCT. TBL ; IDLEJ: JMP IDLE ;GO WAIT FOR REQUESTS UNRFNJ: JMP UNRFN ;UNRECOGNIZED FUNCTION NOPRVJ: JMP NOPRIV ;NOT ENOUGH PRIVILEGES .SBTTL SPECIAL FUNCTIONS (CODE 0) ; SPECFN: MOV R.FC(R1),R3 ;GET FUNCTION CODE CMP R3,#IO.KIL ;IS IT I/O KILL? BEQ KILLRQ ;YES TST R.AT(R1) ;DOES REQUEST COME FROM EXEC? BNE UNRFNJ ;NO, CAN'T DO! CMP R3,#IO.RDN ;I/O RUNDOWN? BEQ IORNDW ;YES CMP R3,#IO.UNL ;UNLOAD HANDLER? BNE UNRFNJ ;NO, INVALID INC EXITFL ;YES, SET EXIT FLAG IOSUCJ: JMP IOSUCC ;DO I/O COMPLETION ; KILLRQ: MOV R.AT(R1),R4 ;GET ATL ADDRESS OF REQUESTOR MOV R4,R.PB(R1) ;PUT IT IN IORQ NODE PARM 1 MOV A.TD(R4),R.PB+2(R1);PUT STD ADDRESS IN PARM 2 MOV (R2),R.PB+4(R1) ;PUT PUD ADDRESS IN PARM 3 ; IORNDW: JSR PC,@#..FLSH ;FLUSH Q'S OF ALL RQ'S THIS TASK, UNIT MOV N.RNA(R2),R3 ;GET CURRENT RNA FOR THIS UNIT BEQ IOSUCJ ;THERE IS NONE; DONE! CMP R.AT(R3),R.PB(R1);DOES RQ BELONG TO THE TASK KILLED? BNE IOSUCJ ;NO, LEAVE IT ALONE CLRB R.FN(R3) ;YES: CLEAR RQ EVENT FLAG, CLR R.SB(R3) ;STATUS BLK ADDRESS, CLR R.AE(R3) ;AST ENTRY ADDRESS MOV (R2),R4 ;PUD ADDRESS MOV #KILL,R5 ;PDX VALUE TO KILL CHANNEL MOV U.DA(R4),R3 ;CSR ADDRESS OF MBD MOV U.C3(R4),R4 ;CHANNEL NO. TO BE KILLED JSR PC,CHNLGO ;INITIATE CHANNEL MOV R1,-(SP) ;SAVE SPECIAL FUNCTION RNA MOV (R2),R4 ;PUD ADDRESS MOV N.RNA(R2),R1 ;NORMAL RNA MOV R2,-(SP) ;SAVE UIT ENTRY POINTER JSR PC,SETHDR ;SET R2 = HEADER ADDR., R3 = LENGTH JSR PC,GETHDR ;GET ADDRESS OF SAVED BUFFER HEADER JSR PC,@#..BLXO ;WRITE SAVED HEADER BACK WHERE BELONGS BCC 1$ ;SUCCEEDED MOV #IE.OVR,R3 ;SET ERROR CODE BR 2$ 1$: MOV #IE.ABO,R3 ;FLAG I/O ABORTED 2$: CLR R4 ;NO BYTES TRANSFERED JSR PC,IOCOMP ;DO I/O COMPLETION MOV (SP)+,R2 ;RESTORE UIT POINTER CLR N.RNA(R2) ;ZERO NODE ADDRESS TO ALLOW DQING MOV (SP)+,R1 ;RESTORE RNA OF SPECIAL FUNCTION BR IOSUCJ ;DONE ; .SBTTL WRITE FUNCTION (LOAD MBD) ; WRITE: MOV R2,R0 ;SAVE UIT ENTRY POINTER MOV R.PB+2(R1),R3 ;NO. OF BYTES TO WRITE CMP R3,#MIN ;TOO FEW TO INCLUDE HEADER? BLT ILMRQJ ;YES CMP R3,#MAX ;TOO MANY FOR ONE ASR? BGT ILMRQJ ;YES MOV R.PB(R1),R2 ;VIRTUAL BUFFER ADDRESS MOV #WRT,R5 ;WRITE (TRANSFER DIRECTION) JSR PC,@#..VXFR ;VERIFY TRANSFER BCS ILMRQJ ;BAD BUFFER ASH #-4,R4 ;HI ORDER 2 BITS OF PHYS. ADDR. ASHC #12,R4 ;SET R4 = ASR ADDRESS, ASH #-12,R5 ;R5 = OFFSET BIC #177700,R5 ;64. BYTES MAX BIT #1,R5 ;ODD ADDRESS? BNE ODADRJ ;YES ADD #ASROFF,R5 ;MAKE ASR3 RELATIVE ADDRESS ASR R3 ;CONVERT BYTES -> WORDS BCS ODADRJ ;ODD NO. OF BYTES SUB #WRTHDL,R3 ;TWO WORD HEADER FOR LOAD IMAGE MOV #PDESC,-(SP) ;SET ASR3 PAGE DESCRIPTOR MOV R4,-(SP) ;AND SEGMENT ADDRESS JSR PC,@#..SPD3 ;SET ASR3 CMP (SP)+,(SP)+ ;DON'T NEED OLD ASR VALUE MOV R0,R2 ;RESTORE UIT ENTRY POINTER MOV (R2),R0 ;PUD ADDRESS MOV (R5)+,R4 ;MBD STARTING ADDRESS CMP R4,U.C4(R0) ;TOO BIG FOR MBD CORE SIZE? BHIS DATOVJ ;YES! MOV R4,-(SP) ADD (R5),(SP) ;ENDING MBD ADDRESS CMP (SP)+,U.C4(R0) ;TOO BIG? BHIS DATOVJ ;YES! CMP (R5)+,R3 ;NO. OF WORDS IN BUF HDR MATCH BUF SIZE? BNE BDPRMJ ;NO, DON'T LOAD MOV U.DA(R0),R0 ;CSR ADDRESS MOV R3,-(SP) ;SAVE WORD COUNT, MOV R4,-(SP) ;MBD ADDRESS, MOV R5,-(SP) ;BUFFER ADDRESS MOV #UNIT1,R5 ;FIRST UNIT IN UIT MOV #NUNITS,R4 ;NO. OF UNITS 1$: CMP R5,R2 ;IS THIS UNIT DOING LOAD? BEQ 2$ ;YES, SKIP IT MOV (R5),R3 ;GET PUD ADDRESS BEQ 2$ ;NON-EXISTANT UNIT TST N.RNA(R5) ;NORMAL RNA BEQ 2$ ;NO REQUEST IN PROGRESS CMP U.DA(R3),R0 ;REQUEST ON SAME MBD? BEQ 7$ ;YES, CAN'T DO THE LOAD 2$: ADD #UITSZ,R5 ;NEXT UIT ENTRY SOB R4,1$ ;LOOP MOV (SP),R5 ;RESTORE REGISTERS MOV 2(SP),R4 MOV 4(SP),R3 MOV #INIT,(R0) ;INITIALIZE MBD, CLEAR RUN MODE ADD #ST,R4 ;MAKE UP A STORE INSTRUCTION 3$: MOV (R5)+,PDX(R0) ;LOAD PDX WITH DATA MOV R4,IR(R0) ;EXECUTE STORE INSTRUCTION INC R4 ;NEXT MBD ADDRESS SOB R3,3$ ;LOOP UNTIL DONE MOV (SP)+,R5 ;RESTORE REGISTERS AGAIN MOV (SP)+,R4 MOV (SP),R3 ADD #LD,R4 ;MAKE UP A LOAD INSTRUCTION 4$: MOV R4,IR(R0) ;EXECUTE LOAD INSTRUCTION CMP (R5)+,PDX(R0) ;DOES DATA MATCH BUFFER? BNE 5$ ;NO! MBD MEMORY FAILED! INC R4 ;NEXT MBD ADDRESS SOB R3,4$ ;LOOP MOV (SP)+,R4 ;GET WORD COUNT MOV #IS.SUC,R3 ;SUCCESS CODE BR 6$ 5$: MOV (SP)+,R4 ;GET WORD COUNT SUB R3,R4 ;SUBTRACT WORDS NOT DONE MOV #IE.BBE,R3 ;BAD BLOCK ERROR 6$: MOV #INIT,(R0) ;RESET MBD AGAIN TO CLEAR PCR ADD #WRTHDL,R4 ;ADD BACK 2 HEADER WORDS ASL R4 ;CONVERT WORDS -> BYTES JMP IOFIN ;DO I/O COMPLETION 7$: ADD #6,SP ;CLEAN STACK MOV #IE.WLK,R3 ;MBD IS WRITE LOCKED JMP IOVER BDPRMJ: JMP BADPRM ;BAD PARAMETERS ILMRQJ: JMP ILLMRQ ;ILLEGAL MEMORY REQUEST ODADRJ: JMP ODDADR ;ODD ADDRESS ERROR DATOVJ: JMP DATOVR ;DATA OVERUN ERROR CONERJ: JMP CONERR ;CONNECT TO INTERRUPT ERROR ; .SBTTL READ FUNCTION (RUN MBD CHANNEL) ; READ: MOV (R2),R5 ;PUD ADDRESS JSR PC,GTUNIT ;SET R3 = UNIT NO., R4 = UNIT MASK BIT R4,CONINT ;THIS UNIT CONNECTED TO INTERRUPT? BNE 1$ ;YES MOV R1,-(SP) ;SAVE RNA MOV R2,-(SP) ;SAVE UIT POINTER MOV R3,-(SP) ;SAVE UNIT NUMBER MOV U.TV(R5),R0 ;INTERRUPT VECTOR ADDRESS MOV #BDINT,R1 ;INTERRUPT SERVICE ROUTINE MOVB U.IP(R5),R2 ;GET INTERRUPT PSW FROM PUD BIC #177437,R2 ;IGNORE ALL BUT PRIORITY BIS R2,R3 ;PUT UNIT NO. IN CONDITION CODES CLR R2 ;BASE ADDRESS JSR PC,@#..CINT ;CONNECT TO INTERRUPT MOV (SP)+,R3 ;RESTORE UNIT NUMBER MOV (SP)+,R2 ;RESTORE UIT POINTER MOV (SP)+,R1 ;RESTORE RNA BCS CONERJ ;CONNECT ERROR ASL R3 ;UNIT NUMBER TIMES 2 MOV @#$DSW,INTNOD(R3);SAVE INTERRUPT CODE NODE ADDRESS BIS R4,CONINT ;CONNECTED NOW 1$: MOV R2,R0 ;SAVE UIT POINTER MOV R.PB+2(R1),R3 ;BYTE COUNT MOV R.PB(R1),R2 ;VIRTUAL BUFFER ADDRESS SUB #2*RDHDL,R2 ;ALLOW FOR 2 WORD HEADER BCS ILMRQJ ;ILLEGAL ADDRESS (TOO SMALL) ADD #2*RDHDL,R3 ;ALSO FIX COUNT BCS ILLMRQ ;ILLEGAL COUNT (TOO BIG) CLR R5 ;READ (TRANSFER DIRECTION) JSR PC,@#..VXFR ;VERIFY TRANSFER BCS ILLMRQ ;BAD BUFFER ROR R3 ;CONVERT BYTES -> WORDS BCS ODADRJ ;ODD BYTE COUNT .IF DF,NOXMEM ;NO EXTENDED MEMORY CAPABILITY TST R4 ;CHECK A17 & A16 BITS (EXTENDED MEMORY) BNE ILLMRQ ;OLD-STYLE MBD CAN'T REACH ABOVE 32K! .IFF MOV R1,-(SP) ;SAVE RNA MOV R2,-(SP) ;SAVE VIRTUAL BUFFER ADDRESS MOV R3,-(SP) ;SAVE WORD COUNT MOV R5,-(SP) ;SAVE PHYSICAL BUFFER ADDRESS MOV (R0),R5 ;GET PUD ADDRESS MOV U.DA(R5),R5 ;MBD'S CSR ADDRESS MOV (R5),R1 ;READ CSR XOR R4,R1 ;COMPARE EXTENDED ADDR WITH THIS REQUEST BIT #A17,R1 ;MASK OFF ALL BUT A17 BIT BEQ 5$ ;THEY MATCH, PROCEED MOV #UNIT1,R1 ;DIFFERENT! GET FIRST UIT ENTRY MOV #NUNITS,R3 ;GET NO. OF UNITS 2$: CMP R1,R0 ;IS THIS THE UNIT BEING PROCESSED NOW? BEQ 3$ ;YES, SKIP IT MOV (R1),R2 ;NO, GET ITS PUD ADDRESS BEQ 3$ ;UNIT NONEXISTANT CMP U.DA(R2),R5 ;SAME MBD AS THAT WE'RE ABOUT TO START? BNE 3$ ;NO, SKIP IT TST N.RNA(R1) ;ANY REQUEST IN PROGRESS ON THAT MBD? BNE 7$ ;YES, CAN'T CHANGE EXTENDED MEMORY NOW 3$: ADD #UITSZ,R1 ;GO TO NEXT UNIT SOB R3,2$ ;LOOP OVER ALL MOV #INIT,(R5) ;NOTHING ACTIVE: RESET, SET SINGLE CYCLE MOV #RST17,R3 ;"RESET A17" INSTRUCTION BIT #A17,R4 ;BUT SHOULD IT BE ON? BEQ 4$ ;NO, OFF MOV #SET17,R3 ;YES, GET "SET A17" INSTRUCTION 4$: MOV R3,IR(R5) ;EXECUTE INSTRUCTION BY JAMMING INTO IR 5$: MOV (SP)+,R5 ;RESTORE PHYSICAL BUFFER ADDRESS MOV (SP)+,R3 ;RESTORE WORD COUNT MOV (SP)+,R2 ;RESTORE VIRTUAL BUFFER ADDRESS MOV (SP)+,R1 ;RESTORE RNA ASH #-5,R4 ;GET A17 INTO BIT 0, A16 INTO CARRY .ENDC ROR R5 ;16 BIT PHYSICAL WORD ADDRESS (A16-A01) BCS ODDADR ;A00 MUST BE OFF (EVEN ADDRESS)! MOV R5,R4 ;GET WORD ADDRESS ADD R3,R4 ;ADD WORD COUNT .IF DF,NOXMEM BVS ILLMRQ ;NO GOOD (MUST BE ALL IN LOW 32K) .IFF BCS ILLMRQ ;NO GOOD (MUST BE ALL ONE 64K BANK) .ENDC SUB #RDHDL,R3 ;DON'T INCLUDE HEADER IN WORD COUNT MOV R3,ERRBLK ;SET WORD COUNT FOR MBD PROGRAM MOV #IE.ONP,ERRBLK+2;AND DEFAULT STATUS MOV #2*RDHDL,R3 ;TWO WORD BUFFER HEADER MOV (R0),R4 ;PUD ADDRESS JSR PC,GETHDR ;GET ADDRESS OF PLACE TO SAVE BUFFER HDR JSR PC,@#..BLXI ;READ BUFFER HEADER INTO SAVE AREA BCS ILLMRQ ;DIDN'T WORK MOV #ERRBLK,R4 ;ADDRESS OF WORD COUNT & STATUS JSR PC,@#..BLXO ;WRITE IT INTO BUFFER HEADER BCS ILLMRQ ;FAILED! MOV R2,-(SP) ;SAVE ADDRESS & BYTE COUNT MOV R3,-(SP) MOV R0,R2 ;RESTORE UIT POINTER MOV (R2),R4 ;PUD ADDRESS MOV U.DA(R4),R3 ;ADDRESS OF CSR MOV U.C3(R4),R4 ;CHANNEL NUMBER JSR PC,CHNLGO ;START UP CHANNEL BCC 6$ ;SUCCESFUL MOV (SP)+,R3 ;RESTORE REGISTERS MOV (SP)+,R2 MOV (R0),R4 ;PUD ADDRESS JSR PC,GETHDR ;GET ADDRESS OF SAVED HEADER WORDS JSR PC,@#..BLXO ;WRITE THEM BACK INTO BUFFER HEADER BCS OVRERR ;FAILED BR NOTRDY ;MBD NOT READY 6$: CMP (SP)+,(SP)+ ;CLEAN STACK JMP CHECK ;LOOK FOR SOMETHING TO DO .IF NDF,NOXMEM 7$: ADD #10,SP ;CLEAN STACK MOV #IE.RSU,R3 ;OTHER CHANNELS ACTIVE USING OTHER BANK BR IOVER .ENDC ; .SBTTL ATTACH & DETACH, ERROR CODES, NON-INTERRUPT COMPLETION ; ATTACH: JSR PC,@#..ATUN ;ATTACH UNIT BCS ATFAIL ;FAILED BR IOSUCC ;DONE ; DETACH: JSR PC,@#..DTUN ;DETACH UNIT BCS DTFAIL ;FAILED BR IOSUCC ;DONE ; BADPRM: MOV #IE.BAD,R3 ;BAD WORD COUNT IN BUFFER BR IOVER ; UNRFN: MOV #IE.IFC,R3 ;ILLEGAL FUNCTION CODE BR IOVER ; CONERR: MOV #IE.CON,R3 ;CAN'T CONNECT TO INTERRUPT BR IOVER ; NOTRDY: MOV #IE.DNR,R3 ;DEVICE NOT READY BR IOVER ; ILLMRQ: MOV #IE.SPC,R3 ;INVALID BUFFER SPECIFICATION BR SETUIT ; DTFAIL: MOV #IE.DNA,R3 ;DEVICE NOT ATTACHED BR IOVER ; ATFAIL: MOV #IE.DAA,R3 ;DEVICE ALREADY ATTACHED BR IOVER ; DATOVR: MOV #IE.DAO,R3 ;DATA OVERRUNS MBD SIZE BR IOVER ; NOPRIV: MOV #IE.PRI,R3 ;PRIVILEDGE VIOLATION BR IOVER ; OVRERR: MOV #IE.OVR,R3 ;ERROR OVERLAYING BUFFER HEADER BR IOVER ; ODDADR: MOV #IE.BYT,R3 ;ODD BYTE COUNT OR ADDRESS SETUIT: MOV R0,R2 ;RESTORE UIT ENTRY POINTER BR IOVER ; IOSUCC: MOV #IS.SUC,R3 ;I/O FUNCTION SUCCEEDED ; IOVER: CLR R4 ;ZERO BYTES TRANSFERED IOFIN: MOV R.FC(R1),R0 ;GET FUNCTION CODE JSR PC,IOCOMP ;DO I/O COMPLETION BIC #^C,R0 ;ELIMINATE ALL BUT EXPRESS BIT ADD R0,R2 ;PROPER RNA ENTRY CLR N.RNA(R2) ;CLEAR IT TO ALLOW DQING JMP CHECK ;LOOK FOR THINGS TO DO ; .SBTTL SUBROUTINE CHNLGO -- INITIATE MBD CHANNEL ; ; ENTER WITH R2 = ADDRESS OF UIT ENTRY FOR CHANNEL TO BE STARTED ; R3 = CSR ADDRESS FOR MBD TO BE STARTED ; R4 = CHANNEL NUMBER ; R5 = PDX VALUE TO PASS TO CHANNEL ; CHNLGO: MOV R0,-(SP) ;SAVE REGISTERS MOV R1,-(SP) MOV R4,-(SP) MOV R5,-(SP) SWAB R4 ;PUT CHANNEL NO. IN BITS 8-10. BIC #^C,R4 ;MASK OFF JUNK ADD #CGO,R4 ;SET INTERRUPT ENABLE & CHANNEL INIT MOV #RETRY,R1 ;SET UP RETRY COUNTER 1$: MOV #TIMOUT,R5 ;SET UP TIME-OUT COUNTER MOVB @#PS,R0 ;SAVE PRIORITY 2$: BISB #PR7,@#PS ;DISABLE INTERRUPTS TSTB (R3) ;CHECK READY BIT IN CSR BMI 8$ ;MBD IS READY MOVB R0,@#PS ;ENABLE INTERRUPTS SOB R5,2$ ;WAIT FOR READY MOV (R3),R5 ;TIMED OUT: READ CSR MOV #INIT,(R3) ;RESET MBD .IF NDF,NOXMEM ;DO FOLLOWING IF EXTENDED MEMORY EXISTS MOV #RST17,R0 ;"RESET A17" INSTRUCTION BIT #A17,R5 ;WAS EXTENDED ADDRESS BIT ON? BEQ 3$ ;NO, OFF MOV #SET17,R0 ;ON, GET "SET A17" INSTRUCTION 3$: MOV R0,IR(R3) ;SET UP EXTENDED ADDRESSING AGAIN .ENDC MOV R4,-(SP) ;SAVE CHANNEL START VALUE, MOV R1,-(SP) ;RETRY COUNT, MOV R2,-(SP) ;AND UIT ENTRY POINTER MOV #UNIT1,R2 ;FIRST UIT ENTRY MOV #NUNITS,R5 ;NO. OF UNITS 4$: CMP R2,(SP) ;IS THIS THE UNIT BEING STARTED? BEQ 7$ ;YES, SKIP IT MOV (R2),R4 ;PUD ADDRESS BEQ 7$ ;UNIT DOESN'T EXIST CMP U.DA(R4),R3 ;SAME MBD AS THE ONE THAT GOT ZAPPED? BNE 7$ ;NO MOV N.RNA(R2),R1 ;NORMAL RNA BEQ 7$ ;NO REQUEST IN PROGRESS MOV R3,-(SP) ;SAVE CSR ADDRESS MOV R2,-(SP) ;AND UIT ENTRY POINTER JSR PC,SETHDR ;SET R2 = HEADER ADDR., R3 = LENGTH JSR PC,GETHDR ;GET ADDRESS OF SAVED BUFFER HEADER JSR PC,@#..BLXO ;WRITE SAVED WORDS INTO BUFFER HEADER BCC 5$ ;SUCCESFUL MOV #IE.OVR,R3 ;SET ERROR FLAG BR 6$ 5$: MOV #IE.FHE,R3 ;FLAG FOR CHANNEL TERMINATED 6$: CLR R4 ;ZERO BYTES READ JSR PC,IOCOMP ;DO I/O COMPLETION MOV (SP)+,R2 ;RESTORE REGISTERS MOV (SP)+,R3 CLR N.RNA(R2) ;CLEAR RNA TO ALLOW DQING 7$: ADD #UITSZ,R2 ;NEXT UNIT SOB R5,4$ ;LOOP MOV (SP)+,R2 ;RESTORE REGISTERS MOV (SP)+,R1 MOV (SP)+,R4 DEC R1 ;COUNT RETRIES BGT 1$ ;RETRY THE CHANNEL INITIATE MOV (SP)+,R5 ;MBD IS NOT READY; RESTORE R5 SEC ;SET CARRY TO FLAG ERROR BR 10$ 8$: MOV (SP)+,R5 ;GET PDX VALUE MOV R5,PDX(R3) ;PUT IT IN THE PDX CMP R5,#KILL ;IS THIS A CHANNEL ABORT? BEQ 9$ ;YES, CHANNEL WON'T TRANSFER DATA MOV (R2),R1 ;GET PUD ADDRESS MOVB U.UN(R1),R1 ;GET UNIT NUMBER ASL R1 ;CONVERT WORDS -> BYTES MOV INTNOD(R1),R1 ;GET INTERRUPT CODE NODE ADDRESS BIS I.MK(R1),@I.MD(R1);SET INTERACTION BIT IN I/O BIT MAP 9$: MOV R4,(R3) ;START CHANNEL MOVB R0,@#PS ;ENABLE INTERRUPTS CLC ;CLEAR CARRY (SUCCESS) 10$: MOV (SP)+,R4 ;RESTORE REGISTERS MOV (SP)+,R1 MOV (SP)+,R0 RTS PC ;RETURN ; .SBTTL UTILITY SUBROUTINES FOR HANDLER ; ; SUBROUTINE BDINIT. ; THIS SUBROUTINE INITIALIZES ALL MBDS AND LOADS THEIR MEMORY WITH ; "EX4" INSTRUCTIONS, EXCEPT FOR LOCATION 1, WHICH IS LOADED WITH AN ; "INT" INSTRUCTION SO THAT STARTING THE MBD BEFORE LOADING WILL CAUSE ; IMMEDIATE I/O COMPLETION. ALL REGISTERS ARE ALTERED BY THIS ROUTINE. ; BDINIT: MOV #UNIT1,R4 ;ADDRESS OF FIRST UIT ENTRY MOV #NUNITS,R3 ;NO. OF UNITS CLR R2 ;OLD CSR 1$: MOV (R4),R5 ;PUD ADDRESS BEQ 3$ ;UIT DOESN'T EXIST MOV R5,PUDPTR ;SAVE ADDRESS OF ANY PUD FOR ISR MOV U.DA(R5),R1 ;CSR ADDRESS CMP R1,R2 ;SAME MBD AS LAST UNIT? BEQ 3$ ;YES, SKIP INITIALIZATION MOV #INIT,(R1) ;INITIALIZE MBD, CLEAR RUN MODE CLR MSK(R1) ;CLEAR THE MSK MOV U.C4(R5),R0 ;GET SIZE OF MBD MEMORY 2$: MOV R0,R2 ;GET MBD ADDRESS PLUS ONE ADD #ST-1,R2 ;MAKE STORE INSTRUCTION MOV #EX4,PDX(R1) ;PUT AN EX4 INSTRUCTION IN PDX MOV R2,IR(R1) ;EXECUTE THE STORE INSTRUCTION SOB R0,2$ ;LOOP OVER ALL MBD LOCATIONS MOV #INT,PDX(R1) ;PUT AN INTERRUPT INSTRUCTION IN PDX MOV #ST+1,IR(R1) ;EXEC "ST 1" INSTRUCTION TO PUT IN LOC 1 MOV #INIT,(R1) ;RESET MBD AGAIN TO CLEAR PCR MOV R1,R2 ;SAVE OLD CSR 3$: ADD #UITSZ,R4 ;NEXT UNIT SOB R3,1$ ;LOOP RTS PC ;RETURN ; ; SUBROUTINE IOCOMP -- DO I/O COMPLETION ; ENTER WITH R1 = REQUEST NODE ADDRESS ; R3 = ERROR CODE ; R4 = NO. OF BYTES TRANSFERRED ; IOCOMP: MOV R2,-(SP) ;SAVE R2 BIC #177400,R3 ;LIMIT CODE TO 1 BYTE CLR R2 ;ADJUSTMENT TO UNITY JSR PC,@#..IODN ;DO I/O COMPLETION MOV (SP)+,R2 ;RESTORE R2 RTS PC ;RETURN ; ; ; SUBROUTINE GETHDR -- GET ADDRESS OF SAVED BUFFER HEADER ; ENTER WITH R4 = PUD ADDRESS ; RETURNS R4 = ADDRESS OF TWO SAVED BUFFER HEADER WORDS ; GETHDR: MOVB U.UN(R4),R4 ;GET UNIT NO. FROM PUD BIC #177760,R4 ;RESTRICT TO 4 BITS ASH #2,R4 ;MULTIPLY BY 4 BYTES ADD #BUFHDR,R4 ;ADD ADDRESS OF START OF SAVE AREA RTS PC ;RETURN ; ; SUBROUTINE SETHDR -- GET ADDRESS OF HEADER IN FRONT OF BUFFER ; ENTER WITH R1 = REQUEST NODE ADDRESS ; RETURNS R2 = ADDRESS OF HEADER IN BUFFER, R3 = LENGTH OF HEADER ; SETHDR: MOV R.PB(R1),R2 ;GET BUFFER ADDRESS MOV #2*RDHDL,R3 ;SET HEADER LENGTH SUB R3,R2 ;HEADER IS IN FRONT OF BUFFER RTS PC ;RETURN ; ; SUBROUTINE GTUNIT -- GET UNIT NO. & MASK FROM PUD ; ENTER WITH R5 = PUD ADDRESS ; RETURNS R3 = UNIT NUMBER, R4 = UNIT NO. MASK ; GTUNIT: MOVB U.UN(R5),R3 ;UNIT NUMBER BIC #177760,R3 ;LIMIT TO PROPER RANGE MOV #1,R4 ASH R3,R4 ;CONSTRUCT MASK RTS PC ;RETURN ; .SBTTL INTERRUPT SERVICE ROUTINE AND POWER-UP AST ; BDINT: JSR R1,(PC) ;SAVE R1 (DON'T DISTURB CONDITION CODES) MOV @#PS,R1 ;GET CONDITION CODES BIC #177760,R1 ;REMOVE REST OF JUNK MOV R0,-(SP) ;SAVE R0 MOV #1,R0 ASH R1,R0 ;SET UP MASK WORD BIS R0,INTCHN ;SET PROPER CHANNEL INTERRUPTED BIT MOV PUDPTR,R0 ;GET PUD ADDRESS (ANY WILL DO...) MOV #EF.INT,R1 ;INTERRUPT EVENT FLAG JSR PC,@#..STEF ;SET EVENT FLAG MOV (SP)+,R0 ;RESTORE REGISTERS MOV (SP)+,R1 JMP @#..INTX ;EXIT INTERRUPT SERVICE ; PWRUP: MOV R0,-(SP) ;SAVE REGISTERS MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV R4,-(SP) MOV R5,-(SP) JSR PC,BDINIT ;INITIALIZE MBDS INC REINIT ;SET RE-INITIALIZED FLAG MOV #EF.INT,R1 ;INTERRUPT EVENT FLAG MOV PUDPTR,R0 ;A PUD ADDRESS JSR PC,@#..STEF ;SET EVENT FLAG MOV (SP)+,R5 ;RESTORE REGISTERS MOV (SP)+,R4 MOV (SP)+,R3 MOV (SP)+,R2 MOV (SP)+,R1 MOV (SP)+,R0 ASTX$S ;EXIT AST ; .SBTTL UNIT ID TABLE (UIT) AND FUNCTION DISPATCH TABLE (FDT) ; ; BDUIT: .WORD BDFDT ;POINTER TO FUNCTION DISPATCH TABLE .BYTE NUNITS,0 ;NO. OF UNITS .WORD 0,0,0 ;RESERVED UNIT1: .WORD 17,0,0 ;FIRST UIT ENTRY UITSZ = .-UNIT1 ;UIT ENTRY LENGTH .IRP UNIT,<16,15,14,13,12,11,10,7,6,5,4,3,2,1,0> .WORD UNIT,0,0 ;OTHER UIT ENTRIES .ENDR NUNITS = <.-UNIT1>/UITSZ ;NUMBER OF UNITS ; .MACRO FD L,H,ADDR ;FDT TABLE ENTRIES .BYTE L,H .WORD ADDR .ENDM ; BDFDT = .-4 ;NO SEND/RCV; OVERLAY LAST 2 UIT WORDS FUN0: FD 000,000,SPECFN ;SPECIAL FUNCTIONS (0) FUNSZ = .-FUN0 ;FDT ENTRY LENGTH FD 010,162,WRITE ;WRITE LOGICAL (1) FD 010,161,READ ;READ LOGICAL (2) FD 020,160,ATTACH ;ATTACH (3) FD 020,160,DETACH ;DETACH (4) FD 010,000,UNRFN ;CONTROL (5) FD 140,160,UNRFN ;(6) FD 140,160,UNRFN ;(7) FD 140,160,UNRFN ;(10) FD 140,160,UNRFN ;FIND FILE (11) FD 140,160,UNRFN ;(12) FD 140,160,UNRFN ;REMOVE FILE (13) FD 140,160,UNRFN ;ENTER FILE (14) FD 140,161,IOSUCC ;ACCESS FOR READ (15) FD 140,163,IOSUCC ;ACCESS FOR WRITE (16) FD 140,167,IOSUCC ;ACCESS FOR EXTEND (17) FD 100,160,IOSUCC ;DEACCESS (20) FD 100,161,READ ;READ VIRTUAL (21) FD 100,162,WRITE ;WRITE VIRTUAL (22) NFUNS = <.-FUN0>/FUNSZ ;NUMBER OF FUNCTIONS ; PFDPB: SPRA$ PWRUP ;POWER FAIL AST DPB WFDPB: WTLO$ 0,EF.NIR!EF.XIR!EF.INT;WAIT FOR MULTIPLE FLAGS DPB ; CONINT: .WORD 0 ;CHANNELS CONNECTED TO INTERRUPTS INTCHN: .WORD 0 ;INTERRUPTING CHANNELS PUDPTR: .WORD 0 ;ANY PUD ADDRESS EXITFL: .WORD 0 ;HANDLER WILL EXIT REINIT: .WORD 0 ;POWER FAIL -- REINITIALIZE MBD ERRBLK: .WORD 0,0 ;TEMPORARY STORAGE INTNOD: .BLKW NUNITS ;PLACE TO SAVE INTERRUPT NODE ADDRESSES BUFHDR: .BLKW 2*NUNITS ;SPACE TO SAVE BUFFER HEADER WORD PAIRS ; .END BDSTRT ;