.TITLE XMDRV - RSX-11D DMC-11 DEVICE HANDLER .IDENT /V01/ ;++ ; ; THE DMC-11 PROVIDES A DIRCET-MEMORY-ACCESS INTERFACE BETWEEN TWO PDP OR ; VAX COMPUTER SYSTEMS USING THE DDCMP LINE PROTOCOL, THUS DELIVERING ; HIGH THROUGHPUT AND RELIABILITY WHILE SIMPLIFYING PROGRAMMING. THE ; DMC-11 SUPPORTS NON-PROCESSOR REQUEST (NPR) DATA TRANSFERS OF UP TO ; 8K WORDS AT RATES UP TO 1000K BAUD. BOTH FULL- AND HALF-DUPLEX MODES ; ARE SUPPORTED. SEE THE APPROPRIATE DEC DOCUMENTATION FOR FURTHER ; DISCUSSION OF THE FUNCTION AND OPTIONS OF THE DMC-11. ; ; CHARLES M COSNER ; ; NASA - GODDARD SPACE FLIGHT CENTER ; GREENBELT ; MARYLAND 20771 ; CODE 935 ; ;-- .PAGE ; ; THE HANDLER SUPPORTS THE FOLLOWING FUNCTION CODES: ; ; STANDARD FUNCTIONS: ; IO.ATT -- ATTACH DEVICE ; IO.DET -- DETACH DEVICE ; IO.KIL -- CANCEL I/O REQUESTS ; IO.RLB -- READ LOGICAL BLOCK ; IO.WLB -- WRITE LOGICAL BLOCK ; ; SPECIAL FUNCTIONS: ; IO.FDX -- SET DEVICE TO FULL-DUPLEX MODE ; IO.HDX -- SET DEVICE TO HALF-DUPLEX MODE ; IO.INL -- INITIALIZE DEVICE AND SET DEVICE CHARACTERISTICS ; IO.TRM -- TERMINATE DEVICE ; ; THE STANDARD FUNCTION HAVE THE USUAL INTERPRETATION. NOTE THAT THE ; DEVICE MUST BE ATTACHED AND INITIALIZED BEFORE A READ OR WRITE MAY BE ; ISSUED. THE READ AND WRITE FUNCTIONS USE ONLY TWO PARAMETERS; ; THE FIRST IS THE BUFFER ADDRESS AND THE SECOND IS THE BUFFER BYTE ; LENGTH. ; ; THE FULL- AND HALF-DUPLEX MODE SETTINGS ARE MUTUALLY EXCLUSIVE. ; IF HALF-DUPLEX MODE IS DESIRED, THE FIRST PARAMETER DEFINES WHETHER ; THIS DEVICE IS THE PRIMARY OR SECONDARY STATION WITH A ZERO OR ; NON-ZERO VALUE, RESPECTIVELY, AND THE SECOND PARAMETER DEFINES WHETHER ; THIS DEVICE IS TO OPERATE IN NORMAL OR MAINTENANCE MODE WITH A ZERO ; OR NON-ZERO VALUE, RESPECTIVELY. (A DMC-11 IN MAINTENANCE MODE CANNOT ; COMMUNICATE WITH ONE IN NORMAL MODE.) ; ; THE NORMAL SEQUENCE OF USE OF A DMC-11 IS: ; ; - ATTACH THE DEVICE ; - SET THE APPROPRIATE MODE ; - INITIALIZE THE DEVICE ; - PERFORM DESIRED READ AND/OR WRITE OPERATIONS ; - TERMINATE THE DEVICE ; - DETACH THE DEVICE ; ; ON POWER FAIL RESTART, ALL ACTIVE I/O IS ABORTED AND THE DEVICE IS ; TERMINATED. ; .PAGE ; ; AS DELIVERED, THIS HANDLER WILL SUPPORT UP TO 8 DEVICES - AS DEFINED ; BY THE VALUE ASSIGNED TO THE SYMBOL "UNITS" - WITH A DEVICE NAME OF ; "XM" - AS DEFINED BY THE VALUE ASSIGNED TO THE SYMBOL "DEVICE". ; ; THE HANDLER IS ASSEMBLED WITH THE COMMAND: ; ; MAC XMDRV,XMDRV/CR/-SP=XMDRV ; ; THE HANDLER IS BUILT WITH THE COMMAND FILE: ; ; XMDRV/PR/-FP/-CP/-AB,XMDRV/-SP/SH/CR=XMDRV ; [1,1]EXEC.STB/SS ; / ; UNITS=0 ; STACK=64 ; TASK=XM.... ; PRI=248 ; UIC=[1,1] ; GBLDEF=UISAR0:177640 ; GBLDEF=UISDR0:177600 ; // ; ; THE HARDWARE STATUS OF THE DMC-11 MUST BE DEFINED AT SYSGEN TIME. ; IN PARTICULAR, WHETHER OR NOT THE DMC-11 SUPPORTS FULL-DUPLEX ; OPERATIONS IS INDICATED BY CLEARING (FULL-DUPLEX OR HALF-DUPLEX) OR ; SETTING (HALF-DUPLEX ONLY) BIT 14 IN THE SECOND PUD CHARACTERISTICS ; WORD. ; ; IN ADDITION, THE VECTOR ADDRESS, DEVICE PRIORITY AND DEVICE ADDRESS ; FIELDS IN THE PUD MUST BE SET UP AT SYSGEN TIME. ; ; OPERATIONALLY, THIS HANDLER REQUIRES TWO UNIBUS MAPPING REGISTERS FOR ; EACH INITIALIZED DEVICE PLUS ONE. THERE ARE NO PERMANENTLY ALLOCATED ; UMRS; THEY ARE ALLOCATED ON NEED. ; .PAGE .SBTTL MACROS ; ; MACROS ; .MCALL SPRA$C, WTLO$C, EXIT$S, MRKT$C, WTSE$C, ASTX$S .MCALL CALL, RETURN, CALLR .MCALL .INH, .ENB ; .MACRO PUSH ARG .IRP X, MOV X,-(SP) .ENDM .ENDM PUSH ; .MACRO POP ARG .IRP X, MOV (SP)+,X .ENDM .ENDM POP ; .MACRO DISABLE ARG PUSH PS.EXP BISB ARG,PS.EXP .ENDM DISABLE ; .MACRO ENABLE CALL ..ENB0 .ENDM ENABLE ; .MACRO .OFFSET ARG1, ARG2 .WORD ARG1+OFFSET .IIF NB, ARG2, .WORD ARG2+OFFSET .ENDM .OFFSET .PAGE .SBTTL SYMBOLS ; ; SYMBOLS ; ; ENABLE DEBUG IF DEFINED DEBUG = 1 ; ; INTERRUPT ADDRESSING OFFSET OFFSET = 60000 ; ; BIT DEFINITIONS BIT0 = 1 BIT1 = 2 BIT2 = 4 BIT3 = 10 BIT4 = 20 BIT5 = 40 BIT6 = 100 BIT7 = 200 BIT8 = 400 BIT9 = 1000 BIT10 = 2000 BIT11 = 4000 BIT12 = 10000 BIT13 = 20000 BIT14 = 40000 BIT15 = 100000 .PAGE ; ; DEVICE REGISTER OFFSETS SEL0 = 0 ; INPUT REGISTER SEL2 = 2 ; OUTPUT REGISTER SEL4 = 4 ;* DATA SEL6 = 6 ;* REGISTERS ; ; SEL0/SEL4 ASSIGNMENTS TYPE = BIT0!BIT1!BIT2 ; ; SEL0 ASSIGNMENTS TYPEI = BIT0!BIT1 ; TYPE INPUT INIO = BIT2 ; IN I/O RQI = BIT5 ; REQUEST IN IEI = BIT6 ; INTERRUPT ENABLE INPUT RDYI = BIT7 ; READY INPUT MC = BIT14 ; MASTER CLEAR RUN = BIT15 ; RUN MICROPROCESSOR ; ; INPUT TRANSACTIONS BACCI = RQI ; BUFFER ADDRESS/CHARACTER COUNT IN CNTLI = RQI!BIT0 ; CONTROL IN BASEI = RQI!BIT0!BIT1 ; BASE IN ; RELEASE = RQI!IEI ; RELEASE PORT (ON BIT CLEAR) ; XMT = BACCI ; SET TRANSMIT BUFFER RCV = BACCI!INIO ; SET RECEIVE BUFFER ; PERR = BASEI ; FORCE PROGRAM ERROR ; ; RDYI WAIT TIMEOUTS S.WAIT = 200. ; WAIT FOR RDYI SET C.WAIT = 100. ; WAIT FOR RDYI CLEAR ; ; SEL2 ASSIGNMENTS TYPEO = BIT0!BIT1 ; TYPE OUTPUT OUTIO = BIT2 ; OUT I/O IEO = BIT6 ; INTERRUPT ENABLE OUTPUT RDYO = BIT7 ; READY OUTPUT .PAGE ; ; SEL6 ASSIGNMENTS ; CNTLI MOP = BIT8 ; MAINTENANCE MODE HDX = BIT10 ; HALF DUPLEX SCNDRY = BIT11 ; HALF DUPLEX SECONDARY STATION ; ; BASEI RESUME = BIT12 ; DO NOT REINITIALIZE BASE TABLE ; ; CNTLO DATACK = BIT0 ; RETRANSMISSION THRESHOLD EXCEEDED TIMEOUT = BIT1 ; NO REMOTE RESPONSE FOR 21 SECONDS ORUN = BIT2 ; MESSAGE RECEIVED BUT NO BUFFER AVAILABLE MAINT = BIT3 ; DDCMP MAINTENANCE MESSAGE RECEIVED LOST = BIT4 ; MESSAGE RECEIVED LONGER THAN RECEIVE BUFFER DISCON = BIT6 ; MODEM DATA SET READY LEAD WENT FROM ON TO OFF START = BIT7 ; DDCMP START RECEIVED MEMORY = BIT8 ; UNIBUS TIMEOUT ON MEMORY REFERENCE BUG = BIT9 ; PROGRAM PROCEDURE ERROR PWF = BIT15 ; POWER FAIL (SET BY POWER RECOVERY AST) FATAL = TIMEOUT!MAINT!LOST!START!MEMORY!BUG!PWF ; ; PUD CHARACTERISTICS WORD 2 SYMBOLS C2.ONL = 4000 ; DEVICE ON-LINE C2.LIN = 40000 ; DEVICE SYSGENED AS HALF DUPLEX C2.HDX = 100000 ; DEVICE SET TO HALF DUPLEX ; OTHERWISE, SET TO FULL DUPLEX ; ; PUD CHARACTERISTICS WORD 3 SYMBOLS C3.MOP = MOP ; MAINTENANCE MODE C3.HDX = HDX ; HALF DUPLEX MODE C3.SCNDRY= SCNDRY ; SECONDARY STATION C3.MODE = C3.MOP!C3.HDX!C3.SCNDRY ; MODE FLAGS C3.PWF = BIT13 ; POWER FAIL FLAG C3.KIL = BIT14 ; DEVICE KILLED FLAG C3.ERR = BIT15 ; ERROR FLAG C3.CON = 0 ; CONNECT SUCCEEDED C3.FCON = -1 ; CONNECT FAILED .PAGE .SBTTL PSECTS ; ; PSECTS ; .PSECT XM, RW, I, REL, CON ; CODE .PSECT XMD, RW, D, REL, CON ; WORD ALIGNED DATA .PSECT XMDB, RW, D, REL, CON ; BYTE ALIGNED DATA .PAGE .SBTTL ENTRY .PSECT XM ;+ ; ENTRY CODE: ; 1) SETS UP ADDRESSIBILITY VIA PAR/PDR 3 ; 2) DECLARES THE HANDLER RESIDENT ; 3) CONNECTS TO DEVICES' INTERRUPT VECTORS ; 4) SETS UP FOR ERROR LOGGING ; 5) SPECIFIES POWER RECOVERY AST ; 6) GETS HANDLER ATL ENTRY AND EVENT FLAGS ADDRESSES ;- ENTRY: ; ; SET UP ADDRESSIBILITY VIA PAR/PDR 3 ; CALLING SEQUENCE: ; 2(SP) -- NEW PDR ; (SP) -- NEW PAR ; CALL ..SPD3 ; EXIT CONDITIONS: ; 2(SP) -- OLD PDR ; (SP) -- OLD PAR ; PUSH ; NEW PAR/PDR DATA CALL ..SPD3 ; SET UP ADDRESSIBILITY VIA PAR/PDR 3 CMP (SP)+,(SP)+ ; DELETE OLD PAR/PDR DATA ; ; DECLARE THE HANDLER RESIDENT ; CALLING SEQUENCE: ; R0 -- ADDRESS OF THE UNIT INFORMATION TABLE (UIT) ; R2 -- DEVICE NAME (2 ASCII CHARACTERS) ; R3 -- FLAGS BYTE FOR PUD ; CALL ..DSUT ; EXIT CONDITIONS: ; R1 -- NUMBER OF UNITS FOUND ; ERROR CONDITIONS: ; CC -- C BIT SET IF NO UNITS FOUND ; MOV #UIT,R0 ; UIT ADDRESS MOV #DEVICE,R2 ; DEVICE NAME MOV #UF.RH,R3 ; HANDLER RESIDENT FLAG CALL ..DSUT ; DECLARE HANDLER RESIDENT BCC 5$ ; NO ERROR JMP EXIT0 ; ERROR 5$: .PAGE ; ; CONNECT TO DEVICES' INTERRUPT VECTORS ; CONNECT TO DEVICE INTERRUPT VECTOR ; CALLING SEQUENCE: ; R0 -- INTERRUPT VECTOR ADDRESS ; R1 -- INTERRUPT SERVICE ROUTINE ADDRESS ; R2 -- INTERRUPT SERVICE SPACE BASE ADDRESS ; R3 -- INTERRUPT PRIORITY (BITS 5-7), ; UNIT INDEX (BITS 1-4) ; CALL ..CINT ; EXIT CONDITIONS: ; VIRTUAL 0 -- INTERRUPT CODE NODE ADDRESS ; ERROR CONDITIONS: ; CC -- C BIT SET IF CONNECT FAILES ; DISCONNECT FROM THE DEVICE INTERRUPT VECTOR ; CALLING SEQUENCE: ; R0 -- INTERRUPT VECTOR ADDRESS ; CALL ..DINT ; .PAGE PUSH UITCOUNT ; UNIT COUNT CLR R2 ; INTERRUPT SERVICE SPACE BASE ADDRESS MOV #LISTS+L.XQ+L.MK,R4 ; FIRST UNIT'S TRANSMIT I/O BIT MASK ADDRESS CLR R5 ; UNIT 0 INDEX 10$: MOV @IUITENTRY(R5),R3 ; PUD ADDRESS BEQ 50$ ; NO PUD MOV U.TV(R3),R0 ; INTERRUPT VECTOR ADDRESS MOV #XMIN,R1 ; INTERRUPT SERVICE ROUTINE ADDRESS MOV U.IP(R3),R3 ; INTERRUPT PRIORITY (BITS 5-7) BIS R5,R3 ; UNIT INDEX (BITS 1-4) CALL ..CINT ; CONNECT TO DEVICE INTERRUPT VECTOR (INPUT) BCS 20$ ; ERROR MOV $DSW,R1 ; INTERRUPT CODE NODE ADDRESS MOV I.MK(R1),-L.XQ+L.RQ(R4) ;* I/O ACTIVE MOV I.MD(R1),-L.XQ+L.RQ-L.MK+L.MD(R4) ;* BIT MASK ADD #4,R0 ; INTERRUPT VECTOR ADDRESS MOV #XMOUT,R1 ; INTERRUPT SERVICE ROUTINE ADDRESS CALL ..CINT ; CONNECT TO DEVICE INTERRUPT VECTOR (OUTPUT) BCC 30$ ; NO ERROR SUB #4,R0 ; INTERRUPT VECTOR ADDRESS CALL ..DINT ; DISCONNECT FROM DEVICE INTERRUPT VECTOR 20$: MOV #C3.FCON,R2 ; INDICATE CONNECT FAILED DECB 1(SP) ; DECREMENT UNIT COUNT BNE 40$ ; UNITS TO PROCESS TST (SP)+ ; CLEAN UP STACK JMP EXIT1 ; NO UNITS TO PROCESS 30$: MOV $DSW,R1 ; INTERRUPT CODE NODE ADDRESS MOV I.MK(R1),@R4 ;* I/O ACTIVE MOV I.MD(R1),-L.MK+L.MD(R4) ;* BIT MASK MOV #C3.CON,R2 ; INDICATE CONNECT SUCCEEDED 40$: MOV @IUITENTRY(R5),R3 ;* CONNECT MOV R2,U.C3(R3) ;* INDICATOR 50$: ADD #L.SIZE,R4 ; NEXT UNIT'S MASK ADDRESS ADD #2,R5 ; NEXT UNIT INDEX CMP R5,#UNITS*2 ; ANY MORE UNITS? BLT 10$ ; YES TST (SP)+ ; CLEAN UP STACK .PAGE ; ; SET UP FOR ERROR LOGGING ; PICK A REQUEST NODE ; CALLING SEQUENCE: ; R3 -- NUMBER OF NODES TO PICK ; CALL ..PICV ; EXIT CONDITIONS: ; R4 -- NODE ADDRESS ; ERROR CONDITIONS: ; CC -- C BIT SET ON PICK FAILURE ; MOV #<4*UNITS+7>/8.,R3 ;* PICK STATISTICS CALL ..PICV ;* NODE BCS EXIT2 ; IF ERROR, EXIT FROM HANDLER MOV R4,STATNODE ; SAVE STATISTICS NODE ADDRESS MOV #LISTS+L.XQ+L.STAT,R1 ; FIRST UNIT'S TRANSMIT STATISTICS COUNT ADDRESS MOV #UNITS,R0 ;* 60$: ;* MOV R4,@R1 ;* CLR (R4)+ ;* CLR (R4)+ ;* CLEAR AND ADDRESS MOV R4,-L.XQ+L.RQ(R1) ;* STATISTICS COUNTS CLR (R4)+ ;* CLR (R4)+ ;* ADD #L.SIZE,R1 ;* SOB R0,60$ ;* ; ; SPECIFY POWER RECOVERY AST ; SPRA$C POWERUP,XM ; SPECIFY POWER RECOVERY AST BCS EXIT3 ; IF ERROR, EXIT FROM HANDLER ; ; GET HANDLER ATL ENTRY AND EVENT FLAGS ADDRESSES ; MOV .CRTSK,ATLADR ; HANDLER ATL ENTRY ADDRESS ADD .CRTSK,EFNADD ; HANDLER EVENT FLAGS ADDRESS .PAGE .PSECT XMD ; ; ENTRY DATA ; ; DEVICE DATA DEVICE = "XM ; DEVICE NAME ; ; NUMBER OF UNITS (MAXIMUM OF 8 UNITS) UNITS = 2 ; ; UNIT INFORMATION TABLE UIT: .WORD DISPTAB UITCOUNT: .BYTE UNITS,0 .WORD 0,0,0 UITENTRY: UNIT = 0 .REPT UNITS .WORD UNIT,0,0 UNIT = UNIT+1 .ENDM ; IUITENTRY: ADDRESS = UITENTRY .REPT UNITS .OFFSET ADDRESS ADDRESS = ADDRESS+6 .ENDM ; ; STATISTICS NODE ADDRESS STATNODE:.BLKW ; ; HANDLER ATL ENTRY ADDRESS ATLADR: .BLKW ; ; HANDLER EVENT FLAGS ADDRESS EFNADD: .WORD A.EF ; (ADD ATL ADDRESS) .PAGE .SBTTL MAIN STREAM .PSECT XM ;+ ; MAIN STREAM CODE: ; 1) AWAITS A CHANGE IN STATUS ; 2) CHECKS FOR I/O DONE ; 3) CHECKS FOR AN EXPRESS REQUEST ; 4) CHECKS FOR A NORMAL REQUEST ; 5) CHECKS FOR HANDLER EXIT ;- MAINSTREAM: ; ; AWAIT A CHANGE IN STATUS ; WTLO$C 0,IOEFN!EXPEFN!NRMEFN,XM; AWAIT EVENT FLAG .INH ;;;* MOVB @EFNADD,EFNS ;;;* I/O EVENT BIC #IOEFN,@EFNADD ;;;* FLAGS .ENB ;;;* ; ; CHECK FOR I/O DONE ; CALLING SEQUENCE: ; CALL DONE ; CALL DONE ; CHECK FOR I/O DONE .PAGE ; ; CHECK FOR AN EXPRESS REQUEST ; DEQUEUE EXPRESS REQUEST ; CALLING SEQUENCE: ; R0 -- UIT ADDRESS ; CALL ..DQRE ; EXIT CONDITIONS: ; R1 -- REQUEST NODE ADDRESS ; R2 -- PUD POINTER ADDRESS ; ERROR CONDITIONS: ; CC -- C BIT SET IF NO NODE DEQUEUED ; DISPATCH THE REQUEST ; CALLING SEQUENCE: ; R0 -- UIT ADDRESS ; R1 -- REQUEST NODE ADDRESS ; R2 -- PUD POINTER ADDRESS ; CALL DISPATCH ; MOV #UIT,R0 ; UIT ADDRESS CALL ..DQRE ; DEQUEUE AN EXPRESS REQUEST BCS 10$ ; NO REQUEST TO DEQUEUE CALL DISPATCH ; DISPATCH THE REQUEST 10$: ; ; CHECK FOR A NORMAL REQUEST ; DEQUEUE A NORMAL REQUEST ; CALLING SEQUENCE: ; R0 -- UIT ADDRESS ; CALL ..DQRN ; EXIT CONDITIONS: ; R1 -- REQUEST NODE ADDRESS ; R2 -- PUD POINTER ADDRESS ; ERROR CONDITIONS: ; CC -- C BIT SET IF NO NODE DEQUEUED ; DISPATCH THE REQUEST ; CALLING SEQUENCE: ; R0 -- UIT ADDRESS ; R1 -- REQUEST NODE ADDRESS ; R2 -- PUD POINTER ADDRESS ; CALL DISPATCH ; MOV #UIT,R0 ; UIT ADDRESS CALL ..DQRN ; DEQUEUE A NORMAL REQUEST BCS 20$ ; NO REQUEST DEQUEUED CALL DISPATCH ; DISPATCH THE REQUEST 20$: ; ; CHECK FOR HANDLER EXIT TSTB EXITFLAG ; EXIT REQUESTED? BEQ MAINSTREAM ; NO TST IOCOUNT ; ANY I/O IN PROGRESS? BNE MAINSTREAM ; YES .PAGE .PSECT XMD ; ; MAIN STREAM DATA ; ; EVENT FLAGS NRMEFN = BIT0 EXPEFN = BIT1 IOEFN = BIT2 ; IOEVF = 3 ; .PSECT XMDB EFNS: .BLKB .PSECT XMD .PAGE .SBTTL EXIT .PSECT XM ;+ ; EXIT CODE: ; 1) TERMINATES INITIALIZED DEVICES ; 2) CANCELS POWER RECOVERY AST ; 3) TAKES DOWN ERROR LOG HANDLING ; 4) DISCONNECTS FROM DEVICES' INTERRUPT VECTORS ; 5) DECLARES THE HANDLER NOT RESIDENT ; 6) EXITS TO THE SYSTEM ;- EXIT: ; ; TERMINATE INITIALIZED DEVICES ; GET FIRST/NEXT DEVICE FOR PROCESSING ; CALLING SEQUENCE: ; R5 -- UNIT INDEX (AFTER FIRST CALL) ; CALL @(SP)+ ; EXIT CONDITIONS: ; R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; R5 -- UNIT INDEX ; ERROR CONDITIONS: ; CC -- C BIT SET ON NO MORE UNITS ; PERFORM TERMINATION CLEAN UP ; CALLING SEQUENCE: ; R0 -- PUD CHARACTERISTICS WORD 3 FLAGS ; R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; R5 -- UNIT INDEX ; CALL IOT ; EXIT CONDITIONS: ; R0 -- MODIFIED ; R1 -- MODIFIED ; R2 -- MODIFIED ; R3 -- MODIFIED ; R4 -- MODIFIED ; PUSH #UITSEARCH ; COROUTINE ADDRESS 10$: CALL @(SP)+ ; GET FIRST/NEXT DEVICE FOR PROCESSING BCS 20$ ; NO MORE DEVICES CLR R0 ; PUD CHARACTERISTICS WORD 3 FLAGS CALL IOT ; PERFORM TERMINATION CLEAN UP BR 10$ 20$: ; ; CANCEL POWER RECOVERY AST ; SPRA$C ,XM ; CANCEL POWER RECOVERY AST .PAGE EXIT3: ; ; TAKE DOWN ERROR LOG HANDLING ; RELEASE A NODE ; CALLING SEQUENCE: ; R1 -- NODE ADDRESS ; R3 -- NUMBER OF NODES ; CALL ..NADV ; MOV STATNODE,R1 ; STATISTICS NODE ADDRESS MOV #<4*UNITS+7>/8.,R3 ;* RELEASE CALL ..NADV ;* NODE EXIT2: ; ; DISCONNECT FROM DEVICES' INTERRUPT VECTORS ; DISCONNECT FROM DEVICE INTERRUPT VECTOR ; CALLING SEQUENCE: ; R0 -- INTERRUPT VECTOR ADDRESS ; CALL ..DINT ; ERROR CONDITIONS: ; NONE ; MOV #UITENTRY,R4 ; FIRST UNIT ENTRY IN UIT MOV #UNITS,R5 ; NUMBER OF UNITS 10$: MOV @R4,R3 ; PUD ADDRESS BEQ 20$ ; NO PUD ADDRESS CMP #C3.FCON,U.C3(R3) ; CONNECT FAILURE? BEQ 20$ ; YES MOV U.TV(R3),R0 ; INTERRUPT VECTOR ADDRESS CALL ..DINT ; DISCONNECT FROM DEVICE INTERRUPT VECTOR (INPUT) ADD #4,R0 ; INTERRUPT VECTOR ADDRESS CALL ..DINT ; DISCONNECT FROM DEVICE INTERRUPT VECTOR (OUTPUT) 20$: ADD #6,R4 ; NEXT UNIT ENTRY IN UIT SOB R5,10$ ; LOOP FOR ALL POSSIBLE UNITS EXIT1: ; ; DECLARE THE HANDLER NOT RESIDENT ; CALLING SEQUENCE: ; R0 -- ADDRESS OF UIT ; CALL ..DNRC ; MOV #UIT,R0 ; UIT ADDRESS CALL ..DNRC ; DECLARE HANDLER NOT RESIDENT EXIT0: ; ; EXIT TO THE SYSTEM ; EXIT$S .PAGE .SBTTL I/O DONE .PSECT XM ;+ ; I/O DONE CODE: ; 1) CHECKS I/O DONE EVENT FLAG ; 2) GETS FIRST/NEXT DEVICE FOR PROCESSING ; 3) PROCESSES NORMAL COMPLETIONS ; 4) PROCESSES FATAL ERRORS ; 5) RETURNS ;- ; DONE: ; ; CHECK I/O DONE EVENT FLAG ; BITB #IOEFN,EFNS ; I/O DONE? BEQ 60$ ; NO, RETURN ; ; GET FIRST/NEXT DEVICE FOR PROCESSING ; CALLING SEQUENCE: ; R5 -- UNIT INDEX (AFTER FIRST CALL) ; CALL @(SP)+ ; EXIT CONDITIONS: ; R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; R5 -- UNIT INDEX ; ERROR CONDITIONS: ; CC -- C BIT SET ON NONE ; PUSH #UITSEARCH ; COROUTINE ADDRESS 10$: CALL @(SP)+ ; GET FIRST/NEXT DEVICE FOR PROCESSING BCS 50$ ; NO MORE DEVICES .PAGE ; ; PROCESS NORMAL COMPLETIONS ; REMOVE ENTRY FROM DEQUE ; CALLING SEQUENCE: ; R0 -- DEQUE LIST HEAD ADDRESS ; CALL DEQUEUE ; EXIT CONDITIONS: ; R1 -- REMOVED ENTRY ADDRESS ; R2 -- MODIFIED ; I/O DONE WITH SUCCESSFUL COMPLETION ; CALLING SEQUENCE: ; R1 -- REQUEST NODE ADDRESS ; R4 -- I/O STATUS BLOCK WORD 1 ; R5 -- UNIT INDEX ; CALL ISSUC ; EXIT CONDITIONS: ; R2 -- MODIFIED ; R3 -- MODIFIED ; PUSH ; SAVE REGISTERS MOV IDLISTS(R5),R0 ; I/O DONE DEQUE ADDRESS 20$: CMP R0,@R0 ; ANY COMPLETED REQUESTS? BEQ 30$ ; NO DEC IOCOUNT ; DECREMENT I/O IN PROGRESS COUNT .INH ;;; INHIBIT INTERRUPTS CALL DEQUEUE ;;; REMOVE ENTRY FROM DEQUE .ENB ;;; ENABLE INTERRUPTS MOV R.PB+2(R1),R4 ; TRANSFER LENGTH AS I/O STATUS BLOCK WORD 1 CALL ISSUC ; I/O DONE WITH SUCCESSFUL COMPLETION BR 20$ ; TRY TO GET ANOTHER COMPLETE REQUEST 30$: POP ; RESTORE REGISTERS .PAGE ; ; PROCESS FATAL ERRORS ; CALLING SEQUENCE: ; R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; R5 -- UNIT INDEX ; CALL FERROR ; EXIT CONDITIONS: ; R0 -- MODIFIED ; R1 -- MODIFIED ; R2 -- MODIFIED ; R3 -- MODIFIED ; R4 -- MODIFIED ; BIT #FATAL,ESTATUS(R5) ; ANY FATAL ERRORS? BEQ 40$ ; NO CALL FERROR ; YES 40$: BR 10$ ; GET NEXT DEVICE 50$: ; ; RETURN ; 60$: RETURN .PAGE .PSECT XMD ; ; I/O DONE DATA ; ; ERROR STATUS ESTATUS: .REPT UNITS .WORD 0 .ENDM .PAGE .SBTTL FATAL ERROR PROCESSING .PSECT XM ;+ ; FATAL ERROR PROCESSING CODE: ; 1) WAITS A SECOND ON DISCONNECT ERROR ; 2) CHECKS FOR DATA LOST ; 3) SETS THE PUD CHARACTERISTICS WORD 3 FLAGS ; 4) PROCESSES ERRORS ; 5) RETURNS ;- ; NOTE -- R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; R5 -- UNIT INDEX ; WARN -- R0 -- MODIFIED ; R1 -- MODIFIED ; R2 -- MODIFIED ; R3 -- MODIFIED ; R4 -- MODIFIED ; .ENABL LSB FERROR: ; ; WAIT A SECOND ON DISCONNECT ERROR ; BIT #BUG,ESTATUS(R5) ; PROGRAM ERROR? BEQ 10$ ; NO ; YES, ASSUME DISCONNECT ERROR MRKT$C WAITEVF,1,2,,XM ;* WAIT ONE WTSE$C WAITEVF,XM ;* SECOND 10$: ; ; CHECK FOR DATA LOST ; DEQUEUE AND RETURN REQUEST ; CALLING SEQUENCE: ; R0 -- DEQUE LIST HEAD ADDRESS ; R3 -- I/O STATUS BLOCK WORD 0 ; R4 -- I/O STATUS BLOCK WORD 1 ; R5 -- UNIT INDEX ; CALL DQRR ; EXIT CONDITIONS: ; R1 -- MODIFIED ; R2 -- MODIFIED ; BIT #LOST,ESTATUS(R5) ; LOST DATA ERROR? BEQ 20$ ; NO PUSH ; SAVE REGISTERS MOV IRLISTS(R5),R0 ; RECEIVE DEQUE LIST HEAD ADDRESS MOV #IE.DAO,R3 ; I/O STATUS BLOCK WORD 0 CLR R4 ; I/O STATUS BLOCK WORD 1 CALL DQRR ; DEQUEUE AND RETURN REQUEST POP ; RESTORE REGISTERS 20$: .PAGE ; ; SET THE PUD CHARACTERISTICS WORD 3 FLAGS ; BIT #PWF,ESTATUS(R5) ; POWER FAIL? BEQ 30$ ; NO MOV #C3.PWF,R0 ; YES, INDICATE POWER FAIL BR 40$ 30$: MOV #C3.ERR,R0 ; INDICATE ERROR 40$: ; ; PROCESS ERRORS ; PERFORM TERMINATION CLEAN UP ; CALLING SEQUENCE: ; R0 -- PUD CHARACTERISTICS WORD 3 FLAGS ; R2 -- I/O STATUS BLOCK WORD 0 (IOT2 ENTRY ONLY) ; R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; R5 -- UNIT INDEX ; CALL IOT1/IOT2 ; EXIT CONDITIONS: ; R0 -- MODIFIED ; R1 -- MODIFIED ; R2 -- MODIFIED ; R3 -- MODIFIED ; R4 -- MODIFIED ; MOV #IE.CNR,R2 ; I/O STATUS BLOCK WORD 0 BIT #START,ESTATUS(R5) ; START ERROR? BNE 50$ ; YES MOV #IE.TMO,R2 ; I/O STATUS BLOCK WORD 0 BIT #TIMEOUT,ESTATUS(R5) ; TIMEOUT ERROR? BNE 50$ ; YES CALL IOT1 ; OTHER ERROR BR 60$ 50$: CALL IOT2 60$: ; ; RETURN ; RETURN .DSABL LSB .PAGE .PSECT XMD ; ; FATAL ERROR PROCESSING DATA ; ; WAIT EVENT FLAG WAITEVF = 4 .PAGE .SBTTL DISPATCH .PSECT XM ;+ ; DISPATCH CODE: ; 1) VERIFIES REQUEST FUNCTION CODE VALIDITY ; 2) VALIDATES THE REQUEST ; 3) GETS UNIT INDEX ; 4) GETS UNIT DATA ; 5) DISPATCHES THE REQUEST ;- ; NOTE -- R0 -- UIT ADDRESS ; R1 -- REQUEST NODE ADDRESS ; R2 -- PUD POINTER ADDRESS ; DISPATCH: ; ; VERIFY REQUEST FUNCTION CODE VALIDITY ; CMPB R.FC+1(R1),#MAXFNC ; IS FUNCTION CODE OUT OF RANGE? BHI JIEIFC ; YES, ILLEGAL FUNCTION CODE ; ; VALIDATE THE REQUEST ; CALLING SEQUENCE: ; R0 -- UIT ADDRESS ; R1 -- REQUEST NODE ADDRESS ; R2 -- PUD POINTER ADDRESS ; CALL ..VACC ; ERROR CONDITIONS: ; CC -- C BIT SET IF INVALID REQUEST ; CALL ..VACC ; VALIDATE THE REQUEST BCS JIEPRI ; INVALID REQUEST ; ; GET UNIT INDEX ; MOV @R2,R5 ; PUD ADDRESS MOVB U.UN(R5),R5 ; UNIT NUMBER ASL R5 ; UNIT INDEX ; ; GET UNIT DATA ; CALLING SEQUENCE: ; R5 -- UNIT INDEX ; CALL RINIT ; EXIT CONDITIONS: ; R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; ERROR CONDITIONS: ; CC -- Z BIT SET ON DEVICE NOT RESIDENT ; CALL RINIT ; GET UNIT DATA BEQ JIEOFL ; DEVICE NOT CONNECTED .PAGE ; ; DISPATCH THE REQUEST ; CALLING SEQUENCE: ; R0 -- UIT ADDRESS ; R1 -- REQUEST NODE ADDRESS ; R2 -- PUD POINTER ADDRESS ; CALLR ..DISP ; CALLR ..DISP ; DISPATCH THE REQUEST .PAGE .PSECT XMD ; ; DISPATCH DATA ; ; DISPATCH TABLE DISPTAB: .WORD 0,0 ; NO SEND/REQUEST SUPPORT .BYTE 0,0 ; EXPRESS REQUESTS .WORD EXPRESS .BYTE 0,20 ; WRITE LOGICAL BLOCK .WORD REDWRT .BYTE 0,20 ; READ LOGICAL BLOCK .WORD REDWRT .BYTE 0,0 ; ATTACH .WORD ATTACH .BYTE 0,0 ; DETACH .WORD DETACH .BYTE 0,0 ; INITIALIZE/TERMINATE DEVICE .WORD INITRM .BYTE 0,0 ; SET MODE .WORD SETMODE ; MAXFNC = <.-DISPTAB>/4-2 .PAGE .SBTTL EXPRESS REQUESTS .PSECT XM ;+ ; EXPRESS REQUESTS CODE: ; 1) VALIDATES AND DISPATCHES THE SUBFUNCTION ; 2) PROCESSES THE SUBFUNCTION ; - PROCESSES AN EXIT SUBFUNCTION ; - PROCESSES A KILL SUBFUNCTION ; - PROCESSES AN I/O RUN DOWN SUBFUNCTION ;- ; NOTE -- R0 -- UIT ADDRESS ; R1 -- REQUEST NODE ADDRESS ; R2 -- PUD POINTER ADDRESS ; R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; R5 -- UNIT INDEX ; EXPRESS: ; ; VALIDATE AND DISPATCH THE SUBFUNCTION ; CMPB R.FC(R1),#IO.KIL ; KILL REQUEST? BEQ IOKIL ; YES, PROCESS A KILL SUBFUNCTION TST R.AT(R1) ; A REQUEST FROM THE EXECUTIVE? BNE JIEIFC ; NO, ILLEGAL SUBFUNCTION CODE CMPB R.FC(R1),#IO.RDN ; AN I/O RUN DOWN REQUEST? BEQ IORDN ; YES, PROCESS AN I/O RUN DOWN SUBFUNCTION CMPB R.FC(R1),#IO.UNL ; AN EXIT REQUEST? BNE JIEIFC ; NO, ILLEGAL SUBFUNCTION CODE ; ; PROCESS AN EXIT SUBFUNCTION ; IOUNL: INCB EXITFLAG ; INDICATE EXIT REQUIRED BR JISSUC ; SUCCESSFUL REQUEST COMPLETION ; ; PROCESS A KILL SUBFUNCTION ; (MAKE THE REQUEST LOOK LIKE AN I/O RUNDOWN REQUEST) ; IOKIL: MOV R.AT(R1),R0 ; ATL NODE ADDRESS OF REQUESTOR MOV R0,R.PB(R1) ; PARM 1 -- ATL NODE ADDRESS MOV A.TD(R0),R.PB+2(R1) ; PARM 2 -- STD ENTRY OF REQUESTOR MOV @R2,R.PB+4(R1) ; PARM 3 -- PUD ENTRY ADDRESS .PAGE ; ; PROCESS AN I/O RUN DOWN SUBFUNCTION ; PERFORM TERMINATION CLEAN UP ; CALLING SEQUENCE: ; R0 -- PUD CHARACTERISTICS WORD 3 FLAGS ; R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; R5 -- UNIT INDEX ; CALL IOT ; EXIT CONDITIONS: ; R0 -- MODIFIED ; R1 -- MODIFIED ; R2 -- MODIFIED ; R3 -- MODIFIED ; R4 -- MODIFIED ; FLUSH UNDEQUEUED REQUESTS ; CALLING SEQUENCE: ; R1 -- REQUEST NODE ADDRESS ; CALL ..FLSH ; IORDN: CMP U.AF-U.C2(R4),R.PB(R1) ; ATL ADDRESS SAME AS ATTACHED? BNE 10$ ; NO PUSH R1 ; SAVE REGISTER MOV #C3.KIL,R0 ; PUD CHARACTERISTICS WORD 3 FLAGS CALL IOT ; PERFORM TERMINATION CLEAN UP POP R1 ; RESTORE REGISTER 10$: CALL ..FLSH ; FLUSH UNDEQUEUED REQUESTS BR ISSUC ; SUCCESSFUL COMPLETION .PAGE .PSECT XMD ; ; EXPRESS REQUESTS DATA ; ; EXIT FLAG .PSECT XMDB EXITFLAG:.BYTE 0 .PSECT XMD .PAGE .SBTTL VECTOR TABLE .PSECT XM ; ; BRANCH VECTORS ; JIEIFC: BR IEIFC JIEPRI: BR IEPRI JIEOFL: BR IEOFL JISSUC: BR ISSUC .PAGE .SBTTL READ/WRITE REQUEST .PSECT XM ;+ ; READ/WRITE REQUEST CODE: ; 1) CHECKS FOR DEVICE ATTACHED ; 2) CHECKS FOR DEVICE ON-LINE ; 3) VALIDATES THE BUFFER ; 4) GETS APPROPRIATE I/O REQUEST LIST ; 5) DISABLES DEVICE INTERRUPTS ; 6) CHECKS IF REQUEST CAN BE SENT TO DEVICE ; 7) INSERTS REQUEST IN WAIT DEQUE ; 8) SETS UP I/O ; 9) MARKS I/O IN PROGRESS ; 10) ENABLES INTERRUPTS ; 11) INCREMENTS I/O IN PROGRESS COUNT ; 12) ENABLES REQUEST DEQUEUEING ; 13) RETURNS ;- ; NOTE -- R0 -- UIT ADDRESS ; R1 -- REQUEST NODE ADDRESS ; R2 -- PUD POINTER ADDRESS ; R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; R5 -- UNIT INDEX ; REDWRT: ; ; CHECK FOR DEVICE ATTACHED ; CMP R.AT(R1),U.AF-U.C2(R4) ; ATTACHED? BNE IEDNA ; NO ; ; CHECK FOR DEVICE ON-LINE ; BIT #C2.ONL,@R4 ; DEVICE ON-LINE? BEQ IEDNR ; NO, ERROR .PAGE ; ; VALIDATE THE BUFFER ; CALLING SEQUENCE: ; R1 -- REQUEST NODE ADDRESS ; R2 -- BUFFER ADDRESS ; R3 -- BUFFER LENGTH ; R5 -- READ/WRITE FLAG (0/1) ; CALL ..VXFR ; EXIT CONDITIONS: ; R4 -- HIGH ORDER BITS OF REAL ADDRESS (BITS 4-9) ; R5 -- LOW ORDER BITS OF REAL ADDRESS ; ERROR CONDITIONS: ; CC -- C BIT SET IF ILLEGAL BUFFER ; PUSH ; SAVE REGISTERS MOV R.PB(R1),R2 ; BUFFER ADDRESS MOV R.PB+2(R1),R3 ; BUFFER LENGTH BLE 30$ ;* INVALID CMP R3,#8192. ;* BUFFER LENGTH? BGE 30$ ; YES CMPB #IO.WLB/256.,R.FC+1(R1) ; WRITE REQUEST? BEQ 10$ ; YES CLR R5 ; NO, INDICATE READ BR 20$ 10$: MOV #1,R5 ; INDICATE WRITE 20$: CALL ..VXFR ; VALIDATE THE BUFFER BCC 40$ ; NO ERROR 30$: POP ; RESTORE REGISTERS BR IESPC ; ILLEGAL BUFFER 40$: MOV R5,R.WA+4(R1) ; SAVE LOWER PART OF REAL ADDRESS ASH #-4,R4 ;* SAVE UPPER PART MOV R4,R.WA+2(R1) ;* OF REAL ADDRESS MOVB #-1,R.WA+1(R1) ; NO UMR ALLOCATED FLAG POP ; RESTORE REGISTERS .PAGE ; ; GET APPROPRIATE I/O REQUEST LIST ; CMPB #IO.WLB/256.,R.FC+1(R1) ; WRITE? BNE 50$ ; NO MOV IXLISTS(R5),R0 ; TRANSMIT REQUEST LIST BR 60$ 50$: MOV IRLISTS(R5),R0 ; RECEIVE REQUEST LIST 60$: ; ; DISABLE DEVICE INTERRUPTS ; DISABLE U.IP-U.C2(R4) ;;; DISABLE DEVICE INTERRUPTS ; ; CHECK IF REQUEST CAN BE SENT TO DEVICE ; CHECK FOR AVAILABLE PORT ; CALLING SEQUENCE: ; R0 -- DEQUE LIST HEAD ADDRESS ; R1 -- REQUEST NODE ADDRESS ; R3 -- DEVICE REGISTERS ADDRESS ; CALL PORT ; EXIT CONDITIONS: ; R2 -- MODIFIED ; ERROR CONDITIONS: ; CC -- C BIT SET ON NOT AVAILABLE ; CMP L.WQ(R0),@L.WQ(R0) ;;; WAIT DEQUE EMPTY? BNE 90$ ;;; NO CALL PORT ;;; PORT AVAILABLE? BCS 90$ ;;; NO BIT #RDYO,SEL2(R3) ;;; OUTPUT TRANSFER READY? BNE 80$ ;;; YES MOV #4,R2 ;;;* 70$: ;;;* BIT #RDYI,@R3 ;;;* WAIT A BIT FOR INPUT READY BNE 100$ ;;;* SOB R2,70$ ;;;* ;;; INPUT NOT READY 80$: BIS #IEI,@R3 ;;;* ENABLE INPUT BIS #IEI,@R3 ;;;* INTERRUPTS 90$: .PAGE ; ; INSERT REQUEST IN WAIT DEQUE ; INSERT ENTRY IN DEQUE (FIFO) ; CALLING SEQUENCE: ; R0 -- DEQUE LIST HEAD ADDRESS ; R1 -- NEW ENTRY ADDRESS ; CALL ENQUEUE ; EXIT CONDITIONS: ; R2 -- MODIFIED ; ADD #L.WQ,R0 ;;; WAIT DEQUE LIST HEAD ADDRESS CALL ENQUEUE ;;; INSERT ENTRY IN DEQUE BR 110$ ; ; SET UP I/O ; CALLING SEQUENCE: ; R0 -- DEQUE LIST HEAD ADDRESS ; R1 -- REQUEST NODE ADDRESS ; R3 -- DEVICE REGISTERS ADDRESS ; CALL SETIO ; EXIT CONDITIONS: ; R2 -- MODIFIED ; 100$: CALL SETIO ;;; SEND REQUEST TO DEVICE ; ; MARK I/O IN PROGRESS ; CALLING SEQUENCE: ; R0 -- DEQUE LIST HEAD ADDRESS ; CALL MARKIO ; CALL MARKIO ;;; MARK I/O IN PROGRESS 110$: ; ; ENABLE INTERRUPTS ; ENABLE ;;; ENABLE INTERRUPTS ; ; INCREMENT I/O IN PROGRESS COUNT ; INC IOCOUNT ; INCREMENT I/O IN PROGRESS COUNT ; ; ENABLE REQUEST DEQUEUEING ; MOV IUITENTRY(R5),R2 ; UIT ENTRY ADDRESS CLR 2(R2) ; ENABLE REQUEST DEQUEUEING ; ; RETURN ; RETURN .PAGE .PSECT XMD ; ; READ/WRITE REQUEST DATA ; ; MAXIMUM NUMBER OF TRANSFERS QUEABLE TO DEVICE MAXTRAN = 1 ; ; REQUEST LISTS L.DQ = 0 ; DONE DEQUE OFFSET L.XQ = 4 ; TRANSMIT DEQUE OFFSET L.RQ = 22. ; RECEIVE DEQUE OFFSET L.SIZE = 40. ; BYTE SIZE OF LIST ENTRY ; L.WQ = 4 ; WAIT DEQUE OFFSET L.FUNC = 8. ; TRANSMIT/RECEIVE FUNCTION CODE OFFSET L.COUNT = 9. ; NUMBER OF TRANSFERS QUEABLE L.UMR = 10. ; PREALLOCATED UMR SLOT/LENGTH WORD L.MK = 12. ;* I/O ACTIVE L.MD = 14. ;* BIT MASK L.STAT = 16. ; STATISTICS COUNT ADDRESS ; LISTS: .REPT UNITS .OFFSET .,.-2 ; DONE DEQUE LIST HEAD .OFFSET .,.-2 ; TRANSMIT DEQUE LIST HEAD .OFFSET .,.-2 ; TRANSMIT WAIT DEQUE LIST HEAD .BYTE XMT,MAXTRAN ; TRANSMIT FUNCTION CODE AND TRANSFER COUNT .BLKW ; TRANSMIT PREALLOCATED UMR SLOT/LENGTH WORD .BLKW 2 ; TRANSMIT I/O ACTIVE BIT MASK .BLKW ; TRANSMIT STATISTICS COUNT ADDRESS .OFFSET .,.-2 ; RECEIVE DEQUE LIST HEAD .OFFSET .,.-2 ; RECEIVE WAIT DEQUE LIST HEAD .BYTE RCV,MAXTRAN ; RECEIVE FUNCTION CODE AND TRANSFER COUNT .BLKW ; RECEIVE PREALLOCATED UMR SLOT/LENGTH WORD .BLKW 2 ; RECEIVE I/O ACTIVE BIT MASK .BLKW ; RECEIVE STATISTICS COUNT ADDRESS .ENDM .PAGE IDLISTS: ADDRESS = LISTS+L.DQ .REPT UNITS .OFFSET ADDRESS ADDRESS = ADDRESS+L.SIZE .ENDM ; IXLISTS: ADDRESS = LISTS+L.XQ .REPT UNITS .OFFSET ADDRESS ADDRESS = ADDRESS+L.SIZE .ENDM ; IRLISTS: ADDRESS = LISTS+L.RQ .REPT UNITS .OFFSET ADDRESS ADDRESS = ADDRESS+L.SIZE .ENDM ; ; I/O IN PROGRESS COUNT IOCOUNT:.WORD 0 .PAGE .SBTTL REQUEST COMPLETION AND RETURN .PSECT XM ;+ ; REQUEST COMPLETION AND RETURN CODE: ; 1) SETS THE RETURN CODE ; 2) REENABLES REQUEST DEQUEUEING ; 3) DECLARES I/O DONE AND RETURNS ;- ; NOTE -- R1 -- REQUEST NODE ADDRESS ; R4 -- I/O STATUS BLOCK WORD 1 ; R5 -- UNIT INDEX ; WARN -- R2 -- MODIFIED ; R3 -- MODIFIED ; ; SET RETURN CODE ; ; ILLEGAL FUNCTION/SUBFUNCTION CODE ; IEIFC: MOV #IE.IFC,R3 ; SET RETURN CODE BR IODONE ; RETURN REQUEST ; ; DEVICE NOT READY ; IEDNR: MOV #IE.DNR,R3 ; SET RETURN CODE BR IODONE ; RETURN REQUEST ; ; ILLEGAL BUFFER DATA ; IESPC: MOV #IE.SPC,R3 ; SET RETURN CODE BR IODONE ; RETURN REQUEST ; ; DETACH FAILURE ; IEDNA: MOV #IE.DNA,R3 ; SET RETURN CODE BR IODONE ; RETURN REQUEST ; ; ATTACH FAILURE ; IEDAA: MOV #IE.DAA,R3 ; SET RETURN CODE BR IODONE ; RETURN REQUEST ; ; PRIVILEGE (ACCESS) VIOLATION ; IEPRI: MOV #IE.PRI,R3 ; SET RETURN CODE BR IODONE ; RETURN REQUEST .PAGE ; ; SHAREABLE RESOURCE IN USE ; IERSU: MOV #IE.RSU,R3 ; SET RETURN CODE BR IODONE ; RETURN REQUEST ; ; DEVICE OFF LINE ; IEOFL: MOV #IE.OFL,R3 ; SET RETURN CODE BR IODONE ; RETURN REQUEST .PAGE ; ; SUCCESSFUL COMPLETION ; ISSUC: MOV #IS.SUC,R3 ; SET RETURN CODE ; RETURN REQUEST ; NOTE -- R3 -- RETURN CODE ; IODONE: ; ; REENABLE REQUEST DEQUEUEING ; MOV R.FC(R1),R2 ;* ISOLATE BIC #^CIQ.Q,R2 ;* EXPRESS BIT ADD IUITENTRY(R5),R2 ; ADD UIT ENTRY OFFSET CLR 2(R2) ; REENABLE REQUEST DEQUEUEING ; ; DECLARE I/O DONE AND RETURN ; CALLING SEQUENCE: ; R1 -- REQUEST NODE ADDRESS ; R2 -- ADJUSTMENT TO UNITY DECREMENT OF I/O COUNT ; R3 -- I/O STATUS BLOCK WORD 0 ; R4 -- I/O STATUS BLOCK WORD 1 ; CALL ..IODN ; CLR R2 ; ZERO ADJUSTMENT TO UNIT DECREMENT CALLR ..IODN ; DECLARE I/O DONE AND RETURN .PAGE .SBTTL ATTACH AND DETACH REQUESTS .PSECT XM ;+ ; ATTACH AND DETACH REQUESTS ;- ; NOTE -- R0 -- UIT ADDRESS ; R1 -- REQUEST NODE ADDRESS ; R2 -- PUD POINTER ADDRESS ; R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; R5 -- UNIT INDEX ; ATTACH: ; ; ATTACH THE DEVICE ; CALLING SEQUENCE: ; R1 -- REQUEST NODE ADDRESS ; R2 -- PUD POINTER ADDRESS ; CALL ..ATUN ; ERROR CONDITIONS: ; CC -- C BIT SET IF ATTACH FAILURE ; CALL ..ATUN ; ATTACH THE DEVICE BCC ISSUC ; SUCCESSFUL COMPLETION BR IEDAA ; DEVICE ALREADY ATTACHED ; DETACH: ; ; DETACH THE DEVICE ; CALLING SEQUENCE: ; R1 -- REQUEST NODE ADDRESS ; R2 -- PUD POINTER ADDRESS ; CALL ..DTUN ; ERROR CONDITIONS ; CC -- C BIT SET IF DETACH FAILURE ; CALL ..DTUN ; DETACH THE DEVICE BCC ISSUC ; SUCCESSFUL COMPLETION BR IEDNA ; DEVICE NOT ATTACHED .PAGE .SBTTL INITIALIZE/TERMINATE DEVICE .PSECT XM ;+ ; INITIALIZE/TERMINATE DEVICE CODE: ; 1) VALIDATES AND DISPATCHES THE SUBFUNCTION ; 2) PROCESSES THE SUBFUNCTION ; - INITIALIZE THE DEVICE ; - TERMINATE THE DEVICE ;- ; NOTE -- R0 -- UIT ADDRESS ; R1 -- REQUEST NODE ADDRESS ; R2 -- PUD POINTER ADDRESS ; R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; R5 -- UNIT INDEX ; INITRM: ; ; VALIDATE AND DISPATCH THE SUBFUNCTION ; CMP #IO.TRM,R.FC(R1) ; TERMINATE SUBFUNCTION? BEQ IOTRM ; YES CMP #IO.INL,R.FC(R1) ; INITIALIZE SUBFUNCTION? BNE IEIFC ; NO, ERROR .PAGE ; ; PROCESS INITIALIZE THE DEVICE SUBFUNCTION ; INITIALIZE BASE TABLE ADDRESSING ; CALLING SEQUENCE: ; CALL INIBASE ; EXIT CONDITIONS: ; R2 -- MODIFIED ; ERROR CONDITIONS: ; CC -- C BIT SET ON ERROR ; ALLOCATE UMR ; CALLING SEQUENCE: ; R3 -- NUMBER OF UMRS TO ALLOCATE ; CALL ..URAL ; EXIT CONDITIONS: ; R3 -- UMR SLOT/LENGTH WORD ; ERROR CONDITIONS: ; CC -- C BIT SET ON ERROR ; INITIALIZE THE DEVICE ; CALLING SEQUENCE: ; R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; R5 -- UNIT INDEX ; CALL INIDEV ; EXIT CONDITIONS: ; R2 -- MODIFIED ; ERROR CONDITIONS: ; CC -- C BIT SET ON ERROR ; PERFORM TERMINATION CLEAN UP ; CALLING SEQUENCE: ; R0 -- TRANSMIT DEQUE LIST HEAD ADDRESS (IOT3 AND IOT4 ENTRIES ONLY) ; CALL IOT3/IOT4/IOT5 ; EXIT CONDITIONS: ; R3 -- MODIFIED (IOT3 AND IOT4 ENTRIES ONLY) ; .PAGE IOINL: BIT #C2.ONL,@R4 ; DEVICE ALREADY ON-LINE? BNE ISSUC ; YES, ALREADY INITIALIZED CALL INIBASE ; INITIALIZE BASE TABLE ADDRESSING BCS IERSU ; UNABLE TO INITIALIZE PUSH R3 ; SAVE REGISTER MOV IXLISTS(R5),R0 ; TRANSMIT DEQUE LIST HEAD ADDRESS MOV #1,R3 ;* TRANSMIT CALL ..URAL ;* UMR BCS 30$ ; ERROR MOV R3,L.UMR(R0) ; SAVE TRANSMIT UMR SLOT/LENGTH WORD MOV #1,R3 ;* RECEIVE CALL ..URAL ;* UMR BCS 20$ ; ERROR MOV R3,-L.XQ+L.RQ+L.UMR(R0) ; SAVE RECEIVE UMR SLOT/LENGTH WORD POP R3 ; RESTORE REGISTER CALL INIDEV ; INITIALIZE THE DEVICE BCS 10$ ; UNABLE TO INITIALIZE BIC #^C,U.C3-U.C2(R4) ; CLEAR ALL BUT MODE BITS CLR ESTATUS(R5) ; CLEAR DEVICE STATUS BR ISSUC ; SUCCESSFUL COMPLETION 10$: CALL IOT3 ; PERFORM TERMINATION CLEAN UP BR IEDNR ; UNABLE TO INITIALIZE ERROR 20$: CALL IOT4 ; PERFORM TERMINATION CLEAN UP BR 40$ 30$: CALL IOT5 ; PERFORM TERMINATION CLEAN UP 40$: POP R3 ; RESTORE REGISTER BR IERSU ; UNABLE TO ALLOCATE UMR .PAGE ; ; PROCESS TERMINATE THE DEVICE SUBFUNCTION ; PERFORM TERMINATION CLEAN UP ; CALLING SEQUENCE: ; R0 -- PUD CHARACTERISTICS WORD 3 FLAGS ; R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; R5 -- UNIT INDEX ; CALL IOT ; EXIT CONDITIONS: ; R0 -- MODIFIED ; R1 -- MODIFIED ; R2 -- MODIFIED ; R3 -- MODIFIED ; R4 -- MODIFIED ; IOTRM: PUSH R1 ; SAVE REGISTER CLR R0 ; PUD CHARACTERISTICS WORD 3 FLAGS CALL IOT ; PERFORM TERMINATION CLEAN UP POP R1 ; RESTORE REGISTER BR ISSUC ; SUCCESSFUL COMPLETION .PAGE .SBTTL SET MODE .PSECT XM ;+ ; SET MODE CODE: ; 1) CHECKS FOR DEVICE OFF-LINE ; 2) VALIDATES AND DISPATCHES THE SUBFUNCTION ; 3) PROCESSES THE SUBFUNCTION ; - SET FULL DUPLEX MODE ; - SET HALF DUPLEX MODE ;- ; NOTE -- R0 -- UIT ADDRESS ; R1 -- REQUEST NODE ADDRESS ; R2 -- PUD POINTER ADDRESS ; R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; R5 -- UNIT INDEX ; SETMODE: ; ; CHECK FOR DEVICE OFF-LINE ; BIT #C2.ONL,@R4 ; DEVICE ON-LINE? BNE IEDNR ; YES, ERROR ; ; VALIDATE AND DISPATCH THE SUBFUNCTION ; CMP #IO.HDX,R.FC(R1) ; SET HALF DUPLEX SUBFUNCTION? BEQ IOHDX ; YES CMP #IO.FDX,R.FC(R1) ; SET FULL DUPLEX SUBFUNCTION? BNE IEIFC ; NO, ERROR ; ; PROCESS SET FULL DUPLEX SUBFUCNTION ; IOFDX: BIT #C2.LIN,@R4 ; DEVICE SYSGENED AS HALF DUPLEX? BNE IEIFC ; YES, ERROR BIC #C2.HDX,(R4)+ ;* SET FULL CLR @R4 ;* DUPLEX BR ISSUC ; SUCCESSFUL COMPLETION ; ; PROCESS SET HALF DUPLEX SUBFUNCTION ; IOHDX: BIS #C2.HDX,(R4)+ ;* SET HALF MOV #C3.HDX,@R4 ;* DUPLEX TST R.PB(R1) ; PRIMARY STATION? BEQ 10$ ; YES BIS #C3.SCNDRY,@R4 ; NO, SECONDARY 10$: TST R.PB+2(R1) ; NORMAL MODE? BEQ 20$ ; YES BIS #C3.MOP,@R4 ; NO, MAINTENANCE MODE 20$: BR ISSUC ; SUCCESSFUL COMPLETION .PAGE .SBTTL INPUT INTERRUPT .PSECT XM ;+ ; INPUT INTERRUPT CODE: ; 1) INITIALIZES AND DISPATCHES THE INTERRUPT ;- XMIN: ; ; INITIALIZE AND DISPATCH THE INTERRUPT ; JSR R0,INTSET ;;; SET UP INTERRUPT PROCESSING ; ; CSR INDEX FOR INTERRUPT TYPE DETERMINATION .WORD SEL0 ;;; INPUT INTERRUPT ; ; DISPATCH TABLE .OFFSET XREADY ;;; TRANSMIT READY .OFFSET IINTRET ;;; IGNORE .OFFSET IINTRET ;;; IGNORE .OFFSET IINTRET ;;; IGNORE .OFFSET RREADY ;;; RECEIVE READY .OFFSET IINTRET ;;; IGNORE .OFFSET IINTRET ;;; IGNORE .OFFSET IINTRET ;;; IGNORE .OFFSET IINTRET ;;; IGNORE .PAGE .SBTTL OUTPUT INTERRUPT .PSECT XM ;+ ; OUTPUT INTERRUPT CODE: ; 1) INITIALIZES AND DISPATCHES THE INTERRUPT ;- XMOUT: ; ; INITIALIZE AND DISPATCH THE INTERRUPT ; JSR R0,INTSET ;;; SET UP INTERRUPT PROCESSING ; ; CSR INDEX FOR INTERRUPT TYPE DETERMINATION .WORD SEL2 ;;; OUTPUT INTERRUPT ; ; DISPATCH TABLE .OFFSET XCOMPLETE ;;; TRANSMIT COMPLETE .OFFSET CNTLO ;;; CONTROL OUT .OFFSET OINTRET ;;; IGNORE .OFFSET OINTRET ;;; IGNORE .OFFSET RCOMPLETE ;;; RECEIVE COMPLETE .OFFSET CNTLO ;;; CONTROL OUT .OFFSET OINTRET ;;; IGNORE .OFFSET OINTRET ;;; IGNORE .OFFSET OINTRET ;;; IGNORE .PAGE .SBTTL SET UP INTERRUPT PROCESSING .PSECT XM ;+ ; SET UP INTERRUPT PROCESSING CODE: ; 1) SAVES REGISTERS ; 2) CHECKS FOR DEVICE ON-LINE ; 3) SETS INTERRUPT TYPE ; 4) DISPATCHES TO INTERRUPT HANDLER ;- ; NOTE -- R0 -- ADDRESS OF CSR INDEX (+0) AND DISPATCH TABLE (+2) ; (SP)- SAVED R0 ; INTSET: ; ; SAVE REGISTERS ; PUSH <@#PS.EXP,R2,R3,R4,R5> ;;; SAVE PS AND R2-R5 MOV 10(SP),R5 ;;; PS MOV R1,10(SP) ;;; SAVE R1 ; ; CHECK FOR DEVICE ON-LINE ; GET UNIT DATA ; CALLING SEQUENCE: ; R5 -- UNIT INDEX ; CALL RINIT ; EXIT CONDITIONS: ; R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; ERROR CONDITIONS: ; CC -- Z BIT SET ON NOT RESIDENT ; BIC #^C^B1110,R5 ;;; UNIT INDEX CALL RINIT ;;; GET UNIT DATA BIT #C2.ONL,@R4 ;;; DEVICE ON-LINE? BEQ 10$ ;;; NO ; ; SET INTERRUPT TYPE ; MOV R3,R1 ;;;* INTERRUPT ADD (R0)+,R1 ;;;* CSR ADDRESS MOV @R1,R1 ;;; * INTERRUPT BIC #^C,R1 ;;; * TYPE BR 20$ 10$: MOV #8.,R1 ;;; INTERRUPT TYPE FOR UNACCEPTABLE UNIT 20$: ; ; DISPATCH TO INTERRUPT HANDLER ; ASL R1 ;;;* ADD R1,R0 ;;;* DISPATCH INTERRUPT CALL @(R0)+ ;;;* .PAGE .SBTTL EXIT INTERRUPT .PSECT XM ;+ ; EXIT INTERRUPT CODE: ; 1) MARKS I/O IN PROGRESS ; 2) RESTORES REGISTERS AND EXITS INTERRUPT ;- ; NOTE -- R5 -- UNIT INDEX ; ; MARK I/O IN PROGRESS ; CALLING SEQUENCE: ; R0 -- DEQUE LIST HEAD ADDRESS ; R5 -- UNIT INDEX ; CALL IMARKIO ; MOV IXLISTS+OFFSET(R5),R0 ;;; TRANSMIT DEQUE LIST HEAD ADDRESS CALL IMARKIO ;;; MARK I/O IN PROGRESS MOV IRLISTS+OFFSET(R5),R0 ;;; RECEIVE DEQUE LIST HEAD ADDRESS CALL IMARKIO ;;; MARK I/O IN PROGRESS ; ; RESTORE REGISTERS AND EXIT INTERRUPT ; POP ;;; RESTORE REGISTERS JMP @#..INTX ;;; EXIT INTERRUPT .PAGE .SBTTL IGNORE INTERRUPTS HANDLERS .PSECT XM ;+ ; IGNORE INTERRUPTS HANDLERS CODE ;- ; NOTE -- R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; R5 -- UNIT INDEX ; ; IGNORE INPUT INTERRUPT ; IINTRET: BIC #RELEASE,@R3 ;;; RELEASE PORT RETURN ; ; IGNORE OUTPUT INTERRUPT ; OINTRET: BIC #RDYO,SEL2(R3) ;;; RELEASE PORT RETURN .PAGE .SBTTL INPUT READY INTERRUPT HANDLER .PSECT XM ;+ ; INPUT READY INTERRUPT HANDLER CODE: ; 1) SETS UP APPROPRIATE LIST HEAD ADDRESS ; 2) REMOVES REQUEST FROM WAIT DEQUE ; 3) SETS UP I/O ; 4) TRIES TO SET UP ANOTHER BUFFER AND RETURNS ;- ; NOTE -- R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; R5 -- UNIT INDEX ; ; SET UP APPROPRITATE LIST HEAD ADDRESS ; XREADY: MOV IXLISTS+OFFSET(R5),R0 ;;; TRANSMIT LIST HEAD ADDRESS BR CREADY RREADY: MOV IRLISTS+OFFSET(R5),R0 ;;; RECEIVE LIST HEAD ADDRESS CREADY: ; ; REMOVE REQUEST FROM WAIT DEQUE ; REMOVE ENTRY FROM DEQUE (FIFO) ; CALLING SEQUENCE: ; R0 -- DEQUE LIST HEAD ADDRESS ; CALL DEQUEUE ; EXIT CONDITIONS: ; R1 -- ENTRY ADDRESS ; R2 -- MODIFIED ; ADD #L.WQ,R0 ;;; WAIT DEQUE LIST HEAD ADDRESS CALL DEQUEUE ;;; REMOVE REQUEST FROM DEQUEUE SUB #L.WQ,R0 ;;; RESTORE LIST HEAD ADDRESS ; ; SET UP I/O ; CALLING SEQUENCE: ; R0 -- DEQUE LIST HEAD ADDRESS ; R1 -- REQUEST NODE ADDRESS ; R3 -- DEVICE REGISTERS ADDRESS ; CALL SETIO ; EXIT CONDITIONS: ; R2 -- MODIFIED ; CALL SETIO ;;; SET UP I/O ; ; TRY TO SET UP ANOTHER BUFFER AND RETURN ; CALLING SEQUENCE: ; R3 -- DEVICE REGISTERS ADDRESS ; R5 -- UNIT INDEX ; CALL ITRY ; EXIT CONDITIONS: ; R0 -- MODIFIED ; R1 -- MODIFIED ; R2 -- MODIFIED ; CALLR ITRY ;;; TRY TO SET UP ANOTHER BUFFER AND RETURN .PAGE .SBTTL I/O COMPLETE INTERRUPT HANDLER .PSECT XM ;+ ; I/O COMPLETE INTERRUPT HANDLER CODE: ; 1) SETS UP APPROPRIATE LIST HEAD ADDRESS ; 2) REMOVES REQUEST FROM DEQUE ; 3) GETS TRANSFER BYTE COUNT ; 4) RELEASES PORT ; 5) INCREMENTS REQUESTS TO BE SENT COUNT ; 6) RELEASES UMR ; 7) INDICATES I/O DONE ; 8) TRIES TO SET UP ANOTHER BUFFER AND RETURNS ;- ; NOTE -- R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; R5 -- UNIT INDEX ; ; SET UP APPROPRIATE LIST HEAD ADDRESS ; XCOMPLETE: MOV IXLISTS+OFFSET(R5),R0 ;;; TRANSMIT LIST HEAD ADDRESS BR CCOMPLETE RCOMPLETE: MOV IRLISTS+OFFSET(R5),R0 ;;; RECEIVE LIST HEAD ADDRESS CCOMPLETE: ; ; REMOVE REQUEST FROM DEQUE ; REMOVE ENTRY FROM DEQUE (FIFO) ; CALLING SEQUENCE: ; R0 -- DEQUE LIST HEAD ADDRESS ; CALL DEQUEUE ; EXIT CONDITIONS: ; R1 -- ENTRY ADDRESS ; R2 -- MODIFIED ; CALL DEQUEUE ;;; REMOVE REQUEST FROM DEQUE ; ; GET TRANSFER BYTE COUNT ; MOV SEL6(R3),R.PB+2(R1) ;;;* BYTE BIC #140000,R.PB+2(R1) ;;;* COUNT ; ; RELEASE PORT ; BIC #RDYO,SEL2(R3) ;;; RELEASE PORT ; ; INCREMENT REQUESTS TO BE SENT COUNT ; INCB L.COUNT(R0) ;;; INCREMENT COUNT .PAGE ; ; RELEASE UMR ; CALLING SEQUENCE: ; R0 -- DEQUE LIST HEAD ADDRESS ; R1 -- REQUEST NODE ADDRESS ; R5 -- UNIT INDEX ; CALL TRMUMR ; EXIT CONDITIONS: ; R2 -- MODIFIED ; CALL TRMUMR ;;; FREE UMR ; ; INDICATE I/O DONE ; INSERT ENTRY IN DEQUE (FIFO) ; CALLING SEQUENCE: ; R0 -- DEQUE LIST HEAD ADDRESS ; R1 -- ENTRY ADDRESS ; CALL ENQUEUE ; EXIT CONDITIONS: ; R2 -- MODIFIED ; INDICATE I/O DONE ; CALLING SEQUENCE: ; CALL IODN ; EXIT CONDITIONS: ; R0 -- MODIFIED ; R4 -- MODIFIED ; MOV IDLISTS+OFFSET(R5),R0 ;;; DONE DEQUE LIST HEAD ADDRESS CALL ENQUEUE ;;; INSERT ENTRY IN DEQUE CALL IODN ;;; INDICATE I/O DONE ; ; TRY TO SET UP ANOTHER BUFFER AND RETURN ; CALLING SEQUENCE: ; R3 -- DEVICE REGISTERS ADDRESS ; R5 -- UNIT INDEX ; CALL ITRY ; EXIT CONDITIONS: ; R0 -- MODIFIED ; R1 -- MODIFIED ; R2 -- MODIFIED ; CALLR ITRY ;;; TRY TO SET UP ANOTHER BUFFER AND RETURN .PAGE .SBTTL CONTROL OUT INTERRUPT HANDLER .PSECT XM ;+ ; CONTROL OUT INTERRUPT HANDLER CODE: ; 1) SAVES ERROR STATUS ; 2) RELEASES PORT ; 3) CHECKS FOR NON-FATAL ERROR ; 4) LOGS ERROR ; 5) PROCESSES FATAL ERROR ; 6) PORCESSES NON-FATAL ERROR ; 7) RETURNS ;- ; NOTE -- R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; R5 -- UNIT INDEX ; CNTLO: ; ; SAVE ERROR STATUS ; MOV SEL6(R3),R2 ;;; ERROR STATUS BIC #140000,R2 ;;; CLEAR BUFFER ADDRESS BITS MOV R2,ESTATUS+OFFSET(R5) ;;; SAVE ERROR STATUS ; ; RELEASE PORT ; BIC #RDYO,SEL2(R3) ;;; RELEASE PORT ; ; CHECK FOR NON-FATAL ERROR ; BIT #FATAL,R2 ;;; FATAL ERROR? BEQ 40$ ;;; NO .PAGE ; ; LOG ERROR ; GET ERROR LOG BUFFER ; CALLING SEQUENCE: ; R1 -- REQUEST NODE ADDRESS ; R3 -- NUMBER OF DEVICE REGISTERS TO BE SAVED ; R4 -- STATISTICS COUNT ADDRESS ; R5 -- RETRY COUNT ; CALL ..ERLI ; EXIT CONDITIONS: ; R5 -- ERROR LOG BUFFER DEVICE REGISTERS ENTRY ADDRESS ; ERROR CONDITIONS: ; CC -- C BIT SET ON ERROR ; MOV @IRLISTS+OFFSET(R5),R1 ;;;* A RECEIVE DEQUE CMP @R1,R1 ;;;* REQUEST NODE? BNE 10$ ;;; YES MOV L.WQ(R1),R1 ;;;* A RECEIVE WAIT DEQUE CMP @R1,R1 ;;;* REQUEST NODE? BNE 10$ ;;; YES MOV @IXLISTS+OFFSET(R5),R1 ;;;* A TRANSMIT DEQUE CMP @R1,R1 ;;;* REQUEST NODE? BNE 10$ ;;; YES MOV L.WQ(R1),R1 ;;;* A TRANSMIT WAIT DEQUE CMP @R1,R1 ;;;* REQUEST NODE? BEQ 30$ ;;; NO 10$: PUSH R5 ;;; SAVE REGISTER MOV #1,R3 ;;; NUMBER OF DEVICE REGISTERS MOV #1*256.+1,R5 ;;; RETRY COUNT CALL @#..ERLI ;;; GET ERROR LOG BUFFER MOV R5,R4 ;;; BUFFER DEVICE REGISTERS ENTRY ADDRESS POP R5 ;;; RESTORE REGISTER BCS 20$ ;;; NO ERROR LOG BUFFER MOV #1*16.+5,.ELOF(R4) ;;; SET UNIT DESCRIPTOR WORD MOV R2,@R4 ;;; SAVE ERROR REGISTER 20$: 30$: .PAGE ; ; PROCESS FATAL ERROR ; INDICATE I/O DONE ; CALLING SEQUENCE: ; CALL IODN ; EXIT CONDITIONS: ; R0 -- MODIFIED ; R4 -- MODIFIED ; CALL IODN ;;; INDICATE I/O DONE BR 60$ ; ; PROCESS NON-FATAL ERROR ; 40$: BIT #DISCON,R2 ;;; LINE DISCONNECTED? BEQ 50$ ;;; NO MOVB #PERR!IEI,@R3 ;;; YES, FORCE PROCEDURE ERROR 50$: ; ; RETURN ; 60$: RETURN .PAGE .SBTTL INDICATE I/O DONE .PSECT XM ;+ ; INDICATE I/O DONE CODE: ; 1) SETS HANDLER EVENT FLAG AND RETURNS ;- ; WARN -- R0 -- MODIFIED ; R4 -- MODIFIED ; IODN: ; ; SET HANDLER EVENT FLAG AND RETURN ; SET TASK EVENT FLAG ; CALLING SEQUENCE: ; R0 -- EVENT FLAG NUMBER ; R4 -- TASK ATL ENTRY ADDRESS ; CALL ..SEFN ; MOV #IOEVF,R0 ;;; EVENT FLAG NUMBER MOV ATLADR,R4 ;;; HANDLER ATL ENTRY ADDRESS CALLR @#..SEFN ;;; SET HANDLER EVENT FLAG AND RETURN .PAGE .SBTTL TRY TO SET UP ANOTHER BUFFER .PSECT XM ;+ ; TRY TO SET UP ANOTHER BUFFER CODE: ; 1) TRIES TO SET UP A RECEIVE ; 2) TRIES TO SET UP A TRANSMIT ; 3) ENABLES INPUT INTERRUPTS ; 4) RETURNS ;- ; NOTE -- R3 -- DEVICE REGISTERS ADDRESS ; R5 -- UNIT INDEX ; WARN -- R0 -- MODIFIED ; R1 -- MODIFIED ; R2 -- MODIFIED ; ITRY: ; ; TRY TO SET UP A RECEIVE ; CHECK FOR AVAILABLE PORT ; CALLING SEQUENCE: ; R0 -- DEQUE LIST HEAD ADDRESS ; R3 -- DEVICE REGISTERS ADDRESS ; CALL IPORT ; EXIT CONDITIONS: ; R1 -- MODIFIED ; R2 -- MODIFIED ; ERROR CONDITIONS: ; CC -- C BIT SET IF PORT UNAVAILABLE ; MOV IRLISTS+OFFSET(R5),R0 ;;; RECEIVE DEQUE LIST HEAD ADDRESS CALL IPORT ;;; PORT AVAILABLE? BCC 10$ ;;; YES ; ; TRY TO SET UP A TRANSMIT ; CHECK FOR AVAILABLE PORT ; CALLING SEQUENCE: ; R0 -- I/O DEQUE LIST HEAD ADDRESS ; R3 -- DEVICE REGISTERS ADDRESS ; CALL IPORT ; EXIT CONDITIONS: ; R1 -- MODIFIED ; R2 -- MODIFIED ; ERROR CONDITIONS: ; CC -- C BIT SET IF PORT UNAVAILABLE ; ADD #-L.RQ+L.XQ,R0 ;;; TRANSMIT DEQUE LIST HEAD ADDRESS CALL IPORT ;;; PORT AVAILABLE? BCS 20$ ;;; NO ; ; ENABLE INPUT INTERRUPTS ; 10$: BIS #IEI,@R3 ;;;* ENABLE INPUT BIS #IEI,@R3 ;;;* INTERRUPTS ; ; RETURN ; 20$: RETURN .PAGE .SBTTL CHECK FOR AVAILABLE PORT .PSECT XM ;+ ; CHECK FOR AVAILABLE PORT CODE: ; 1) CHECKS IF ANY REQUESTS IN WAIT DEQUE ; 2) CHECKS IF UMR ALLOCATED ; 3) CHECKS IF MAXIMUM REQUESTS ALREADY SENT TO DEVICE ; 4) CHECKS IF PORT ALREADY IN USE ; 5) SETS REQUEST TYPE AND INTERRUPT REQUEST ; 6) RETURNS ;- ; NOTE -- R0 -- DEQUE LIST HEAD ADDRESS ; R1 -- REQUEST NODE ADDRESS (PORT ENTRY ONLY) ; R3 -- DEVICE REGISTERS ADDRESS ; WARN -- R1 -- MODIFIED (IPORT ENTRY ONLY) ; R2 -- MODIFIED ; CC -- C SET ON FAILURE ; .ENABLE LSB IPORT: ; ; CHECK IF ANY REQUESTS IN WAIT DEQUE ; MOV L.WQ(R0),R1 ;;;* ANY REQUEST IN CMP @R1,R1 ;;;* WAIT DEQUE? BEQ 10$ ;;; NO .PAGE PORT: ; ; CHECK IF UMR ALLOCATED ; GET UMR ; CALLING SEQUENCE: ; R0 -- DEQUE LIST HEAD ADDRESS ; R1 -- REQUEST NODE ADDRESS ; R5 -- UNIT INDEX ; CALL INIUMR ; EXIT CONDITIONS: ; R2 -- MODIFIED ; ERROR CONDITIONS: ; CC -- C BIT SET ON FAILURE ; CALL INIUMR ;;; GET UMR BCS 20$ ;;; ERROR ; ; CHECK IF MAXIMUM REQUESTS ALREADY SENT TO DEVICE ; TSTB L.COUNT(R0) ;;; ANY MORE REQUESTS CAN BE SENT? BEQ 10$ ;;; NO ; ; CHECK IF PORT ALREADY IN USE ; BIT #RDYI!RQI,@R3 ;;; PORT ALREADY IN USE? BNE 10$ ;;; YES ; ; SET REQUEST TYPE AND INTERRUPT REQUEST ; MOVB L.FUNC(R0),@R3 ;;; SET REQUEST TYPE AND INTERRUPT REQUEST ; ; RETURN ; CLC ;;; INDICATE SUCCESSFUL COMPLETION BR 20$ 10$: SEC ;;; INDICATE FAILURE 20$: RETURN .DSABL LSB .PAGE .SBTTL GET UMR .PSECT XM ;+ ; GET UMR CODE: ; 1) CHECKS FOR UMR ALREADY ALLOCATED ; 2) GETS TRANSMIT/RECEIVE DEQUE LIST HEAD ADDRESS ; 3) ALLOCATES UMR ; 4) LOADS UMR WITH BUFFER ADDRESS ; 5) COMPUTES BUFFER UNIBUS ADDRESS ; 6) RETURNS ;- ; NOTE -- R0 -- DEQUE LIST HEAD ADDRESS ; R1 -- REQUEST NODE ADDRESS ; R5 -- UNIT INDEX ; WARN -- R2 -- MODIFIED ; CC -- C SET ON ERROR ; INIUMR: ; ; CHECK FOR UMR ALREADY ALLOCATED ; TSTB R.WA+1(R1) ;;; UMR ALREADY ALLOCATED? ;;; (TSTB CLEARS C) BPL 60$ ;;; YES ; ; GET TRANSMIT/RECEIVE DEQUE LIST HEAD ADDRESS ; MOV IRLISTS+OFFSET(R5),R2 ;;; RECEIVE DEQUE LIST HEAD ADDRESS CMP R0,R2 ;;; RECEIVE OR RECEIVE-WAIT DEQUE? BHIS 10$ ;;; YES MOV IXLISTS+OFFSET(R5),R2 ;;; TRANSMIT DEQUE LIST HEAD ADDRESS 10$: ; ; ALLOCATE UMR ; CALLING SEQUENCE: ; R3 -- NUMBER OF UMRS TO ALLOCATE ; CALL ..URAL ; EXIT CONDITIONS: ; R3 -- UMR SLOT/LENGTH WORD ; ERROR CONDITIONS: ; CC -- C BIT SET ON ERROR ; PUSH R3 ;;; SAVE REGISTER MOV L.UMR(R2),R3 ;;; PREALLOCATED UMR AVAILABLE? BNE 20$ ;;; YES ;;; NO MOV #1,R3 ;;; NUMBER OF UMRS TO ALLOCATE CALL @#..URAL ;;; ALLOCATE UMR BCC 30$ ;;; NO ERROR BR 50$ ;;; ERROR 20$: CLR L.UMR(R2) ;;; INDICATE NO PREALLOCATED UMR 30$: MOVB R3,R.WA+1(R1) ;;; INDICATE UMR ALLOCATED .PAGE ; ; LOAD UMR WITH BUFFER ADDRESS ; FILL UMR WITH REAL ADDRESS ; CALLING SEQUENCE: ; R3 -- UMR SLOT/LENGTH WORD ; R4 -- HIGH ORDER BITS OF REAL ADDRESS (BITS 0-5) ; R5 -- LOW ORDER BITS OF REAL ADDRESS ; CALL ..URF2 ; PUSH ;;; SAVE REGISTERS MOV R.WA+2(R1),R4 ;;;* BUFFER REAL MOV R.WA+4(R1),R5 ;;;* ADDRESS CALL @#..URF2 ;;; FILL UMR WITH REAL ADDRESS ; ; COMPUTE BUFFER UNIBUS ADDRESS ; CONVERT UMR SLOT/LENGTH WORD TO UNIBUS ADDRESS ; CALLING SEQUENCE: ; R3 -- UMR SLOT/LENGTH WORD ; CALL ..URAD ; EXIT CONDITIONS: ; R4 -- HIGH ORDER BITS OF UNIBUS ADDRESS (BITS 4-5) ; R5 -- LOW ORDER BITS OF UNIBUS ADDRESS ; CALL @#..URAD ;;; CONVERT UMR SLOT/LENGTH WORD TO UNIBUS ADDRESS BIT #1,R.WA+4(R1) ;;;* BEQ 40$ ;;;* CHECK FOR ODD BUFFER ADDRESS INC R5 ;;;* 40$: ASH #15.-5,R4 ;;; HIGH ORDER BITS TO BITS 14-15 MOV R4,R.WA+2(R1) ;;;* BUFFER UNIBUS MOV R5,R.WA+4(R1) ;;;* ADDRESS ; ; RETURN ; POP ;;; RESTORE REGISTERS CLC ;;; INDICATE SUCCESSFUL COMPLETION 50$: POP R3 ;;; RESTORE REGISTER 60$: RETURN .PAGE .SBTTL RELEASE UMR .PSECT XM ;+ ; RELEASE UMR CODE: ; 1) CHECKS FOR NO UMR ALLOCATED ; 2) GETS TRANSMIT/RECEIVE DEQUE LIST HEAD ADDRESS ; 3) FREES UMR ; 4) RETURNS ;- ; NOTE -- R0 -- DEQUE LIST HEAD ADDRESS ; R1 -- REQUEST NODE ADDRESS ; R5 -- UNIT INDEX ; WARN -- R2 -- MODIFIED ; TRMUMR: ; ; CHECK FOR NO UMR ALLOCATED ; PUSH R3 ;;; SAVE REGISTER MOVB R.WA+1(R1),R3 ;;; UMR ALLOCATED? BMI 40$ ;;; NO ; ; GET TRANSMIT/RECEIVE DEQUE LIST HEAD ADDRESS ; MOV IRLISTS+OFFSET(R5),R2 ;;; RECEIVE DEQUE LIST HEAD ADDRESS CMP R0,R2 ;;; RECEIVE OR RECEIVE-WAIT DEQUE? BHIS 10$ ;;; YES MOV IXLISTS+OFFSET(R5),R2 ;;; TRANSMIT DEQUE LIST HEAD ADDRESS 10$: ; ; FREE UMR ; CALLING SEQUENCE: ; R3 -- UMR SLOT/LENGTH WORD ; CALL ..URDA ; BIS #400,R3 ;;; UMR SLOT/LENGTH WORD TST L.UMR(R2) ;;; A PREALLOCATED UMR AVAILABLE? BEQ 20$ ;;; NO CALL @#..URDA ;;; FREE UMR BR 30$ 20$: MOV R3,L.UMR(R2) ;;; SAVE PREALLOCATED UMR 30$: ; ; RETURN ; 40$: POP R3 ;;; RESTORE REGISTER RETURN .PAGE .SBTTL SET UP I/O ;+ ; SET UP I/O CODE: ; 1) LOADS BUFFER ADDRESS AND LENGTH ; 2) RELEASES THE PORT ; 3) DECREMENTS REQUESTS TO BE SENT COUNT ; 4) INCREMENTS STATISTICS COUNT ; 5) QUEUES THE REQUEST AND RETURNS ;- ; NOTE -- R0 -- DEQUE LIST HEAD ADDRESS ; R1 -- REQUEST NODE ADDRESS ; R3 -- DEVICE REGISTERS ADDRESS ; WARN -- R2 -- MODIFIED ; SETIO: ; ; LOAD BUFFER ADDRESS AND LENGTH ; MOV R.WA+2(R1),SEL6(R3) ;;;* BUFFER MOV R.WA+4(R1),SEL4(R3) ;;;* ADDRESS BIS R.PB+2(R1),SEL6(R3) ;;; BUFFER LENGTH ; ; RELEASE THE PORT ; BIC #RELEASE,@R3 ;;; RELEASE THE PORT ; ; DECREMENT REQUESTS TO BE SENT COUNT ; DECB L.COUNT(R0) ;;; DECREMENT COUNT ; ; INCREMENT STATISTICS COUNT ; MOV L.STAT(R0),R2 ;;; STATISTICS COUNT ADDRESS ADD #1,2(R2) ;;;* INCREMENT ADC @R2 ;;;* COUNT ; ; QUEUE THE REQUEST AND RETURN ; INSERT ENTRY IN DEQUE (FIFO) ; CALLING SEQUENCE: ; R0 -- DEQUE LIST HEAD ADDRESS ; R1 -- NEW ENTRY ADDRESS ; CALL ENQUEUE ; EXIT CONDITIONS: ; R2 -- MODIFIED ; CALLR ENQUEUE ;;; INSERT ENTRY IN DEQUE AND RETURN .PAGE .SBTTL MARK I/O IN PROGRESS .PSECT XM ;+ ; MARK I/O IN PROGRESS CODE: ; 1) CLEARS I/O IN PROGRESS FLAG ; 2) CHECKS FOR FATAL ERROR ; 3) CHECKS FOR I/O IN PROGRESS ; 4) SETS I/O IN PROGRESS FLAG ; 5) RETURNS ;- ; NOTE -- R0 -- DEQUE LIST HEAD ADDRESS ; R5 -- UNIT INDEX (IMARKIO ENTRY ONLY) ; .ENABL LSB IMARKIO: ; ; CLEAR I/O IN PROGRESS FLAG ; BIC L.MK(R0),@L.MD(R0) ;;; CLEAR FLAG ; ; CHECK FOR FATAL ERROR ; BIT #FATAL,ESTATUS+OFFSET(R5) ;;; FATAL ERROR? BNE 10$ ;;; YES ; ; CHECK FOR I/O IN PROGRESS ; CMPB L.COUNT(R0),#MAXTRAN ;;; MAXIMUM TRANSFERS? BEQ 10$ ;;; YES, NO I/O IN PROGRESS ; ; SET I/O IN PROGRESS FLAG ; MARKIO: BIS L.MK(R0),@L.MD(R0) ;;; SET FLAG ; ; RETURN ; 10$: RETURN .DSABL LSB .PAGE .SBTTL INITIALIZE BASE TABLE ADDRESSING .PSECT XM ;+ ; INITIALIZE BASE TABLE ADDRESSING CODE: ; 1) CHECKS FOR PRIOR INITIALIZATION ; 2) ALLOCATES UMR ; 3) LOADS THE UMR WITH THE BASE TABLE BASE ADDRESS ; 4) SETS UP THE BASE TABLE UMR ADDRESSES ; 5) RETURNS ;- ; WARN -- R2 -- MODIFIED ; CC -- C SET ON INITIALIZATION ERROR ; INIBASE: ; ; CHECK FOR PRIOR INITIALIZATION ; CLC ; INDICATE SUCCESSFUL COMPLETION INCB CBASE ; INCREMENT INITIALIZATION COUNTER BGT 30$ ; PRIOR INITIALIZATION PUSH ; SAVE REGISTERS ; ; ALLOCATE UMR ; CALLING SEQUENCE: ; R3 -- NUMBER OF UMRS TO BE ALLOCATED ; CALL ..URAL ; EXIT CONDITIONS: ; R3 -- UMR SLOT/LENGTH WORD ; ERROR CONDITIONS: ; CC -- C BIT SET ON ALLOCATION FAILURE ; MOV #1,R3 ; NUMBER OF UMRS TO BE ALLOCATED CALL ..URAL ; ALLOCATE UMR BCS 20$ ; ERROR MOV R3,BASEUMR ; SAVE UMR SLOT/LENGTH WORD .PAGE ; ; LOAD THE UMR WITH THE BASE TABLE BASE ADDRESS ; CALCULATE REAL ADDRESS ; CALLING SEQUENCE: ; R1 -- REQUEST NODE ADDRESS (USED ONLY BY IAS, IGNORED HERE) ; R2 -- VIRTUAL ADDRESS ; R4 -- TASK ATL NODE ADDRESS ; CALL ..REAL ; EXIT CONDITONS: ; R4 -- HIGH ORDER BITS OF REAL ADDRESS (BITS 0-5) ; R5 -- LOW ORDER BITS OF REAL ADDRESS ; FILL UMR WITH REAL ADDRESS ; CALLING SEQUENCE: ; R3 -- UMR SLOT/LENGTH WORD ; R4 -- HIGH ORDER BITS OF REAL ADDRESS (BITS 0-5) ; R5 -- LOW ORDER BITS OF REAL ADDRESS ; CALL ..URF2 ; MOV #BASE,R2 ; VIRTUAL ADDRESS MOV ATLADR,R4 ; HANDLER ATL NODE ADDRESS CALL ..REAL ; CALCULATE REAL ADDRESS CALL ..URF2 ; FILL UMR WITH REAL ADDRESS ; ; SET UP THE UMR BASE TABLE ADDRESSES ; CONVERT UMR SLOT/LENGTH WORD TO UNIBUS ADDRESS ; CALLING SEQUENCE: ; R3 -- UMR SLOT/LENGTH WORD ; CALL ..URAD ; EXIT CONDITIONS: ; R4 -- HIGH ORDER BITS OF UNIBUS ADDRESS (BITS 4-5) ; R5 -- LOW ORDER BITS OF UNIBUS ADDRESS ; CALL ..URAD ; CONVERT UMR SLOT/LENGTH WORD TO UNIBUS ADDRESS ASH #15.-5,R4 ; MOVE HIGH ORDER ADDRESS BITS TO BITS 14-15 MOV #UNITS,R3 ; NUMBER OF UNITS MOV #BASEADR,R2 ; BASE TABLE ADDRESSES TABLE 10$: MOV R4,(R2)+ ;* BASE TABLE MOV R5,(R2)+ ;* ADDRESS ADD #128.*2,R5 ; NEXT BASE TABLE SOB R3,10$ ; LOOP FOR ALL UNITS ; ; RETURN ; CLC ; INDICATE SUCCESSFUL COMPLETION 20$: POP ; RESTORE REGISTERS 30$: RETURN .PAGE .PSECT XMD ; ; INITIALIZE BASE TABLE ADDRESSING DATA ; ; INITIALIZATION COUNT .PSECT XMDB CBASE: .BYTE -1 .PSECT XMD ; ; UMR SLOT/LENGTH WORD FOR BASE TABLE ADDRESSING BASEUMR:.BLKW ; ; MICROPROCESSOR BASE TABLE BASE: .REPT UNITS .BLKW 128. .ENDM ; BASEADR: .REPT UNITS .BLKW 2 .ENDM ; IBASEADR: ADDRESS = BASEADR .REPT UNITS .OFFSET ADDRESS ADDRESS = ADDRESS+4 .ENDM .PAGE .SBTTL TERMINATE BASE TABLE ADDRESSING .PSECT XM ;+ ; TERMINATE BASE TABLE ADDRESSING CODE: ; 1) CHECKS FOR STILL IN USE ; 2) DEALLOCATES UMR ; 3) RETURNS ;- ; TRMBASE: ; ; CHECK FOR STILL IN USE ; DECB CBASE ; DECREMENT INITIALIZATION COUNT BGE 10$ ; STILL IN USE ; ; DEALLOCATE UMR ; CALLING SEQUENCE: ; R3 -- UMR SLOT/LENGTH WORD ; CALL ..URDA ; PUSH R3 ; SAVE REGISTER MOV BASEUMR,R3 ; UMR SLOT/LENGTH WORD CALL ..URDA ; DEALLOCATE UMR POP R3 ; RESTORE REGISTER ; ; RETURN ; 10$: RETURN .PAGE .SBTTL INITIALIZE THE DEVICE .PSECT XM ;+ ; INITIALIZE THE DEVICE CODE: ; 1) TERMINATES THE DEVICE ; 2) ENABLES OUTPUT INTERRUPTS ; 3) SPECIFIES BASE TABLE ADDRESS ; 4) SPECIFIES OPERATING MODE ; 5) INDICATES DEVICE ON-LINE ; 6) TERMINATES THE DEVICE ON ERROR ; 7) RETURNS ;- ; NOTE -- R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; R5 -- UNIT INDEX ; WARN -- R2 -- MODIFIED ; CC -- C SET ON INITIALIZATION FAILURE ; INIDEV: ; ; TERMINATE THE DEVICE ; CALLING SEQUENCE: ; R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; CALL TRMDEV ; CALL TRMDEV ; TERMINATE THE DEVICE MOV #RUN,(R3) ; START DEVICE ; ; ENABLE OUTPUT INTERRUPTS ; BIS #IEO,SEL2(R3) ; ENABLE OUTPUT INTERRUPTS ; ; SPECIFY BASE TABLE ADDRESS ; MOVB #BASEI,@R3 ; REQUEST PORT FOR BASE TABLE ADDRESS CALL WRDYIS ; WAIT FOR READY BCS 10$ ; ERROR MOV IBASEADR(R5),R2 ;* MOV (R2)+,SEL6(R3) ;* BASE TABLE ADDRESS MOV @R2,SEL4(R3) ;* CALL WRDYIC ; RELEASE PORT BCS 10$ ; ERROR .PAGE ; ; SPECIFY OPERATING MODE ; MOVB #CNTLI,@R3 ; REQUEST PORT FOR CONTROL FUNCTION CALL WRDYIS ; WAIT FOR READY BCS 10$ ; ERROR MOV U.C3-U.C2(R4),R2 ;* BIC #^C,R2 ;* OPERATING MODE MOV R2,SEL6(R3) ;* CALL WRDYIC ; RELEASE PORT BCS 10$ ; ERROR ; ; INDICATE DEVICE ON-LINE ; BIS #C2.ONL,@R4 ; INDICATE DEVICE ON-LINE BR 20$ ; ; TERMINATE THE DEVICE ON ERROR ; TERMINATE THE DEVICE ; CALLING SEQUENCE: ; R3 -- DEVICE REIGSTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; CALL TRMDEV ; 10$: CALL TRMDEV ; TERMINATE THE DEVICE 20$: ; ; RETURN ; RETURN .PAGE ; ; WAIT FOR READY (WAIT FOR RDYI SET) ; NOTE -- R3 -- DEVICE REGISTERS ADDRESS ; WARN -- R2 -- MODIFIED ; WRDYIS: CLC ; INDICATE SUCCESSFUL COMPLETION MOV #S.WAIT,R2 ; SET TIMEOUT 10$: BIT #RDYI,@R3 ; RDYI SET? BNE 20$ ; YES, DONE SOB R2,10$ ; NO, LOOP SEC ; ERROR 20$: RETURN ; ; RELEASE PORT (INDICATE RELEASE AND WAIT FOR RDYI CLEAR) ; NOTE -- R3 -- DEVICE REGISTERS ADDRESS ; WARN -- R2 -- MODIFIED ; WRDYIC: CLC ; INDICATE SUCCESSFUL COMPLETION BIC #RELEASE,@R3 ; RELEASE PORT MOV #C.WAIT,R2 ; CLEAR TIMEOUT 10$: BIT #RDYI,@R3 ; RDYI CLEAR? BEQ 20$ ; YES, DONE SOB R2,10$ ; NO, LOOP SEC ; ERROR 20$: RETURN .PAGE .SBTTL TERMINATE THE DEVICE .PSECT XM ;+ ; TERMINATE THE DEVICE CODE: ; 1) MASTER CLEARS DEVICE ; 2) INDICATES DEVICE OFF-LINE ; 3) RETURNS ;- ; NOTE -- R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; TRMDEV: ; ; MASTER CLEAR DEVICE ; BIS #MC,@R3 ; MASTER CLEAR DEVICE ; ; INDICATE DEVICE OFF-LINE ; BIC #C2.ONL,@R4 ; INDICATE DEVICE OFF-LINE ; ; RETURN ; RETURN .PAGE .SBTTL PERFORM TERMINATION CLEAN UP .PSECT XM ;+ ; PERFORM TERMINATION CLEAN UP CODE: ; 1) KILLS DEVICE ; 2) GETS TRANSMIT DEQUE LIST HEAD ADDRESS ; 3) DEALLOCATES UMRS ; 4) TERMINATES BASE TABLE ADDRESSING ; 5) RETURNS ;- ; NOTE -- R0 -- PUD CHARACTERISTICS WORD 3 FLAGS (IOT, IOT1, IOT2 ENTRIES ONLY) ; -- TRANSMIT DEQUE LIST HEAD ADDRESS (IOT3, IOT4 ENTRIES ONLY) ; R2 -- I/O STATUS BLOCK WORD 0 (IOT2 ENTRY ONLY) ; R3 -- DEVICE REGISTERS ADDRESS (IOT, IOT1, IOT2 ENTRIES ONLY) ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS (IOT, IOT1, IOT2 ENTRIES ONLY) ; R5 -- UNIT INDEX (IOT, IOT1, IOT2 ENTRIES ONLY) ; WARN -- R0 -- MODIFIED (IOT, IOT1, IOT2 ENTRIES ONLY) ; R1 -- MODIFIED (IOT, IOT1, IOT2 ENTRIES ONLY) ; R2 -- MODIFIED (IOT, IOT1, IOT2 ENTRIES ONLY) ; R3 -- MODIFIED (IOT, IOT1, IOT2, IOT3, IOT4 ENTRIES ONLY) ; R4 -- MODIFIED (IOT, IOT1, IOT2 ENTRIES ONLY) ; ; KILL DEVICE ; CALLING SEQUENCE: ; R0 -- PUD CHARACTERISTICS WORD 3 FLAGS ; R2 -- I/O STATUS BLOCK WORD 0 (IOT2 ENTRY ONLY) ; R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; R5 -- UNIT INDEX ; CALL KILL/KILOTHER ; EXIT CONDITIONS: ; R0 -- MODIFIED ; R1 -- MODIFIED ; R2 -- MODIFIED ; R3 -- MODIFIED ; R4 -- MODIFIED ; .PAGE .ENABL LSB IOT: BIT #C2.ONL,@R4 ; DEVICE ON-LINE? BEQ 20$ ; NO IOT1: CALL KILL ; KILL DEVICE BR 10$ IOT2: CALL KILOTHER ; KILL DEVICE 10$: ; ; GET TRANSMIT DEQUE LIST HEAD ADDRESS ; MOV IXLISTS(R5),R0 ; TRANSMIT DEQUE LIST HEAD ADDRESS ; ; DEALLOCATE UMRS ; DEALLOCATE UMR ; CALLING SEQUENCE: ; R3 -- UMR SLOT/LENGTH WORD ; CALL ..URDA ; IOT3: MOV -L.XQ+L.RQ+L.UMR(R0),R3 ;* RECEIVE CALL ..URDA ;* UMR IOT4: MOV L.UMR(R0),R3 ;* TRANSMIT CALL ..URDA ;* UMR ; ; TERMINATE BASE TABLE ADDRESSING ; CALLING SEQUENCE: ; CALL TRMBASE ; IOT5: CALL TRMBASE ; TERMINATE BASE TABLE ADDRESSING ; ; RETURN ; 20$: RETURN .DSABL LSB .PAGE .SBTTL KILL DEVICE .PSECT XM ;+ ; KILL DEVICE CODE: ; 1) SETS I/O STATUS BLOCK WORD 0 ; 2) TERMINATES THE DEVICE ; 3) SETS PUD CHARACTERISTICS WORD 3 FLAGS ; 4) TERMINATES ALL PENDING I/O REQUESTS AND RETURNS ;- ; NOTE -- R0 -- PUD CHARACTERISTICS WORD 3 FLAGS ; R2 -- I/O STAUS BLOCK WORD 0 (KILOTHER ENTRY ONLY) ; R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; R5 -- UNIT INDEX ; WARN -- R0 -- MODIFIED ; R1 -- MODIFIED ; R2 -- MODIFIED ; R3 -- MODIFIED ; R4 -- MODIFIED ; KILL: ; ; SET I/O STATUS BLOCK WORD 0 ; MOV #IE.ABO,R2 ; I/O STATUS BLOCK WORD 0 KILOTHER: ; ; TERMINATE THE DEVICE ; CALLING SEQUENCE: ; R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; CALL TRMDEV ; CALL TRMDEV ; TERMINATE THE DEVICE ; ; SET PUD CHARACTERISTICS WORD 3 FLAGS ; BIS R0,U.C3-U.C2(R4) ; PUD CHARACTERISTICS WORD 3 FLAGS .PAGE ; ; TERMINATE ALL PENDING I/O REQUESTS AND RETURN ; DEQUEUE AND RETURN REQUEST ; CALLING SEQUENCE: ; R0 -- DEQUE LIST HEAD ADDRESS ; R3 -- I/O STATUS BLOCK WORD 0 ; R4 -- I/O STATUS BLOCK WORD 1 ; R5 -- UNIT INDEX ; CALL DQRR ; EXIT CONDITIONS: ; R1 -- MODIFIED ; R2 -- MODIFIED ; MOV R2,R3 ; I/O STATUS BLOCK WORD 0 CLR R4 ; I/O STATUS BLOCK WORD 1 MOV IXLISTS(R5),R0 ; TRANSMIT DEQUE LIST HEAD ADDRESS CALL 10$ ; DEQUEUE AND RETURN ALL PENDING TRANSMIT REQUESTS MOV IRLISTS(R5),R0 ; RECEIVE DEQUE LIST HEAD ADDRESS ; DEQUEUE AND RETURN ALL PENDING RECEIVE REQUESTS 10$: MOVB #MAXTRAN,L.COUNT(R0) ; RESET MAXIMUM TRANSFER COUNT CALL 20$ ; DEQUEUE AND RETURN ALL PENDING REQUESTS ON DEQUE ADD #L.WQ,R0 ; TRANSMIT/RECEIVE WAIT DEQUE LIST HEAD ADDRESS 20$: 30$: CMP @R0,R0 ; DEQUE EMPTY? BEQ 40$ ; YES CALL DQRR ; DEQUEUE AND RETURN REQUEST BR 30$ 40$: RETURN .PAGE .SBTTL DEQUEUE AND RETURN REQUEST .PSECT XM ;+ ; DEQUEUE AND RETURN REQUEST CODE: ; 1) DECREMENTS I/O IN PROGRESS COUNT ; 2) REMOVES ENTRY FROM DEQUE ; 3) RELEASES UMR ; 4) DECLARES I/O DONE AND RETURNS ;- ; NOTE -- R0 -- DEQUE LIST HEAD ADDRESS ; R3 -- I/O STATUS BLOCK WORD 0 ; R4 -- I/O STATUS BLOCK WORD 1 ; R5 -- UNIT INDEX ; WARN -- R1 -- MODIFIED ; R2 -- MODIFIED ; DQRR: ; ; DECREMENT I/O IN PROGRESS COUNT ; DEC IOCOUNT ; DECREMENT I/O IN PROGRESS COUNT ; ; REMOVE ENTRY FROM DEQUE ; CALLING SEQUENCE: ; R0 -- DEQUE LIST HEAD ADDRESS ; CALL DEQUEUE ; EXIT CONDITIONS: ; R1 -- REMOVED ENTRY ADDRESS ; R2 -- MODIFIED ; CALL DEQUEUE ; REMOVE ENTRY FROM DEQUE ; ; RELEASE UMR ; CALLING SEQUENCE: ; R0 -- DEQUE LIST HEAD ADDRESS ; R1 -- REQUEST NODE ADDRESS ; R5 -- UNIT INDEX ; CALL TRMUMR ; EXIT CONDITIONS: ; R2 -- MODIFIED ; CALL TRMUMR ; RELEASE UMR ; ; DECLARE I/O DONE AND RETURN ; CALLING SEQUENCE: ; R1 -- REQUEST NODE ADDRESS ; R3 -- I/O STATUS BLOCK WORD 0 ; R4 -- I/O STATUS BLOCK WORD 1 ; R5 -- UNIT INDEX ; CALL IODONE ; EXIT CONDITIONS: ; R2 -- MODIFIED ; CALLR IODONE ; DECLARE I/O DONE AND RETURN .PAGE .SBTTL INSERT ENTRY IN DEQUE .PSECT XM ;+ ; INSERT ENTRY IN DEQUE CODE: ; 1) INSERTS ENTRY AT END OF DEQUE ; 2) RETURNS ;- ; NOTE -- R0 -- DEQUE LIST HEAD ADDRESS ; R1 -- NEW ENTRY ADDRESS ; WARN -- R2 -- MODIFIED ; ENQUEUE: ; ; INSERT ENTRY AT END OF DEQUE ; MOV 2(R0),R2 ;;; LAST ENTRY ADDRESS MOV R0,@R1 ;;; NEW ENTRY FORWARD POINT TO LIST HEAD MOV R1,@R2 ;;; LAST ENTRY FORWARD POINT TO NEW ENTRY MOV R2,2(R1) ;;; NEW ENTRY BACKWARD POINT TO LAST ENTRY MOV R1,2(R0) ;;; LIST HEAD BACKWARD POINT TO NEW ENTRY ; ; RETURN ; RETURN .PAGE .SBTTL REMOVE ENTRY FROM DEQUE .PSECT XM ;+ ; REMOVE ENTRY FROM DEQUE CODE: ; 1) REMOVES FIRST ENTRY FROM DEQUE ; 2) RETURNS ;- ; NOTE -- R0 -- DEQUE LIST HEAD ADDRESS ; WARN -- R1 -- REMOVED ENTRY ADDRESS ; R2 -- MODIFIED ; DEQUEUE: ; ; REMOVE FIRST ENTRY FROM DEQUE ; MOV @R0,R1 ;;; ENTRY TO REMOVE ADDRESS MOV @R1,R2 ;;; NEXT ENTRY ADDRESS MOV R2,@R0 ;;; LIST HEAD FORWARD POINT TO NEXT ENTRY MOV R0,2(R2) ;;; NEXT ENTRY BACKWARD POINT TO LIST HEAD ; ; RETURN ; RETURN .PAGE .SBTTL GET FIRST/NEXT DEVICE FOR PROCESSING .PSECT XM ;+ ; GET FIRST/NEXT DEVICE FOR PROCESSING CODE: ; 1) INITIALIZES UNIT INDEX ; 2) GETS UNIT DATA ; 3) DOES A COROUTINE RETURN TO THE CALLER ; 4) GETS NEXT UNIT ; 5) DOES A NORMAL RETURN TO THE CALLER ON COMPLETION ;- ; NOTE -- R5 -- UNIT INDEX (AFTER FIRST CALL) ; WARN -- R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; R5 -- UNIT INDEX ; CC -- C SET ON NO MORE UNITS ; UITSEARCH: ; ; INITIALIZE UNIT INDEX ; MOV #2*UNITS-2,R5 ; INITIALIZE UNIT INDEX 10$: ; ; GET UNIT DATA ; CALLING SEQUENCE: ; R5 -- UNIT INDEX ; CALL RINIT ; EXIT CONDITIONS: ; R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; ERROR CONDITIONS: ; CC -- Z BIT SET ON UNIT NOT RESIDENT ; CALL RINIT ; GET UNIT DATA ; ; DO A COROUTINE RETURN TO THE CALLER ; BEQ 20$ ; UNIT NOT RESIDENT CLC ; INDICATE UNIT FOUND CALL @(SP)+ ; COROUTINE RETURN 20$: ; ; GET NEXT UNIT ; SUB #2,R5 ; GET NEXT UNIT INDEX BGE 10$ ; ANOTHER UNIT ; ; DO A NORMAL RETURN TO THE CALLER ON COMPLETION ; SEC ; INDICATE END RETURN .PAGE .SBTTL GET UNIT DATA .PSECT XM ;+ ; GET UNIT DATA CODE: ; 1) CHECKS FOR UNIT RESIDENT ; 2) SETS PUD CHARACTERISTICS WORD 2 ADDRESS ; 3) SETS DEVICE REGISTERS ADDRESS ; 4) RETURNS ;- ; NOTE -- R5 -- UNIT INDEX ; WARN -- R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; CC -- Z SET ON UNIT NOT RESIDENT ; RINIT: ; ; CHECK FOR UNIT RESIDENT ; MOV @IUITENTRY+OFFSET(R5),R4 ;;; UNIT'S PUD ADDRESS BEQ 10$ ;;; UNIT NOT RESIDENT CMP U.C3(R4),#C3.FCON ;;; CONNECT SUCCESSFUL? BEQ 10$ ;;; NO ; ; SET PUD CHARACTERISTICS WORD 2 ADDRESS ; ADD #U.C2,R4 ;;; PUD CHARACTERISTICS WORD 2 ADDRESS ; ; SET DEVICE REGISTERS ADDRESS ; MOV U.DA-U.C2(R4),R3 ;;; DEVICE REGISTERS ADDRESS ; ; RETURN ; 10$: RETURN .PAGE .SBTTL POWER RECOVERY AST .PSECT XM ;+ ; POWER RECOVERY AST CODE: ; 1) DISABLES INTERRUPTS ; 2) FLAGS POWER FAILURE ; 3) ENABLES INTERRUPTS ; 4) INDICATES I/O DONE ; 5) EXITS FROM THE AST ;- ; POWERUP: PUSH ; SAVE REGISTERS ; ; DISABLE INTERRUPTS ; .INH ; ; FLAG POWER FAILURE ; GET FIRST/NEXT DEVICE FOR PROCESSING ; CALLING SEQUENCE: ; R5 -- UNIT INDEX (AFTER FIRST CALL) ; EXIT CONDITIONS: ; R3 -- DEVICE REGISTERS ADDRESS ; R4 -- PUD CHARACTERISTICS WORD 2 ADDRESS ; R5 -- UNIT INDEX ; ERROR CONDITIONS: ; CC -- C BIT SET ON NO MORE UNITS ; PUSH #UITSEARCH ; COROUTINE ADDRESS 10$: CALL @(SP)+ ; GET NEXT DEVICE FOR PROCESSING BCS 20$ ; END CALL TRMDEV ; TERMINATE DEVICE MOV #PWF,ESTATUS(R5) ; INDICATE POWER FAIL BR 10$ 20$: ; ; ENABLE INTERRUPTS ; .ENB ; ; INDICATE I/O DONE ; CALLING SEQUENCE: ; CALL IODN ; EXIT CONDITIONS: ; R0 -- MODIFIED ; R4 -- MODIFIED ; ; CALL IODN ; ; EXIT FROM THE AST ; POP ; RESTORE REGISTERS ASTX$S .END ENTRY