Trailing-Edge
-
PDP-10 Archives
-
BB-M080O-SM
-
monitor-sources/phyp2.mac
There are 25 other files named phyp2.mac in the archive. Click here to see a list.
;------------------------- Autopatch Tape # 13 -------------------------
;------------------------- Autopatch Tape # 12 -------------------------
; Edit 7157 to PHYP2.MAC by TBOYLE on 15-Oct-85 (TCO 6-1-1526)
; Remove IORB Retry, edit 7137 did not make it in.
;Remove IORB retry code as it causes more problems than it solves:
; Change DX2CON to mark IORB in error when cannot connect.
; Change DX2HNG to always restart of microcode. Removes TCO 6.1.1366.
; Change ISDEAD error to mark IORB with hard error.
; Change CALLRET @ERCTAB to CALL with RET, RETSKP return.
; Change CALLRET (T1) at DX2INT to CALL with RET, RETSKP return.
; Edit 7137 to PHYP2.MAC by TBOYLE on 15-Aug-85 (TCO 6-1-1526)
; Remove IORB retry code.
; UPD ID= 2163, SNARK:<6.1.MONITOR>PHYP2.MAC.53, 5-Jun-85 10:43:17 by MCCOLLUM
;TCO 6.1.1406 - Update copyright notice.
; UPD ID= 1925, SNARK:<6.1.MONITOR>PHYP2.MAC.52, 7-May-85 21:37:49 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1916, SNARK:<6.1.MONITOR>PHYP2.MAC.51, 7-May-85 16:49:01 by TBOYLE
;TCO 6.1.1369 - Fixup ISUNUS to catch the data errors we have been missing.
; UPD ID= 1912, SNARK:<6.1.MONITOR>PHYP2.MAC.50, 6-May-85 17:05:46 by TBOYLE
;TCO 6.1.1366 - Add support to detect overdue IORBs, and restart microcode.
; UPD ID= 1796, SNARK:<6.1.MONITOR>PHYP2.MAC.49, 23-Apr-85 13:28:37 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1770, SNARK:<6.1.MONITOR>PHYP2.MAC.48, 22-Apr-85 10:53:51 by MCCOLLUM
;TCO 6.1.1238 - Fix BUG. documentation
; UPD ID= 1554, SNARK:<6.1.MONITOR>PHYP2.MAC.47, 20-Feb-85 17:28:13 by GRANT
;TCO 6.1.1200 - In NEWDRV, call SETDSN
; UPD ID= 1552, SNARK:<6.1.MONITOR>PHYP2.MAC.46, 20-Feb-85 17:20:28 by TBOYLE
;More TCO 6.1.1167 - Simplify the code.
; UPD ID= 1488, SNARK:<6.1.MONITOR>PHYP2.MAC.45, 7-Feb-85 11:52:39 by TBOYLE
;More TCO 6.1.1167 - Fix CI.OVR at ISRETY to retry as device error.
; UPD ID= 1478, SNARK:<6.1.MONITOR>PHYP2.MAC.43, 5-Feb-85 13:37:02 by TBOYLE
;TCO 6.1.1175 - Report all 80 extended status bytes on RP20 errors.
; UPD ID= 1438, SNARK:<6.1.MONITOR>PHYP2.MAC.42, 31-Jan-85 16:03:56 by TBOYLE
;TCO 6.1.1167 - Support for new microcode in CLASS 5 errors. Fix BAT BLOCKS.
; UPD ID= 1432, SNARK:<6.1.MONITOR>PHYP2.MAC.41, 31-Jan-85 13:11:23 by GRANT
;TCO 6.1.1165 - Cause homeblock checking when a unit comes online.
; UPD ID= 1429, SNARK:<6.1.MONITOR>PHYP2.MAC.40, 31-Jan-85 07:53:44 by GRANT
;TCO 6.1.1164 - Make up RP20 drive serial number when UDB is created.
; UPD ID= 993, SNARK:<6.1.MONITOR>PHYP2.MAC.39, 7-Nov-84 13:46:18 by MCLEAN
;INSURE THAT HOMEBLOCKS GET CHECKED FIRST!!
; UPD ID= 5040, SNARK:<6.MONITOR>PHYP2.MAC.38, 30-Oct-84 15:19:09 by MCLEAN
;UPDATE COUNT OF SENSE BYTES
; UPD ID= 4943, SNARK:<6.MONITOR>PHYP2.MAC.37, 16-Oct-84 15:25:29 by MCLEAN
;SUPPORT FOR RETRY OF OVERDUE DATA REQUESTS
; UPD ID= 4709, SNARK:<6.MONITOR>PHYP2.MAC.36, 17-Aug-84 21:27:12 by MCLEAN
;DUAL SUPPORT BETWEEN SYSTEMS NOT SUPPORTED SO DON'T SET US.2PT
; UPD ID= 4546, SNARK:<6.MONITOR>PHYP2.MAC.35, 15-Jul-84 22:18:23 by PURRETTA
;Update copyright notice
; UPD ID= 4250, SNARK:<6.MONITOR>PHYP2.MAC.34, 29-May-84 22:13:43 by MCLEAN
;ADD SUPPORT FOR DOP%PS
; UPD ID= 3141, SNARK:<6.MONITOR>PHYP2.MAC.33, 14-Nov-83 12:01:36 by MCLEAN
;FIX A HRLZ THAT SHOULD BE A HLRZ IN DX2LAT
; UPD ID= 3132, SNARK:<6.MONITOR>PHYP2.MAC.32, 9-Nov-83 20:03:59 by MCLEAN
;TCO 6.1818 MAKE SOME CHANGES FOR NON ZERO SECTIONS
; UPD ID= 3110, SNARK:<6.MONITOR>PHYP2.MAC.31, 7-Nov-83 21:25:08 by MCLEAN
;ADD DISPATCH FOR PORT RELEASE
; UPD ID= 2483, SNARK:<6.MONITOR>PHYP2.MAC.30, 17-May-83 21:42:41 by MILLER
;FIx call to PHYBLK at NOPREF to not get ILMNRF
; UPD ID= 2425, SNARK:<6.MONITOR>PHYP2.MAC.29, 5-May-83 19:31:25 by MILLER
;More TCO 6.1603. make test for dual-ported drive correct
; UPD ID= 2203, SNARK:<6.MONITOR>PHYP2.MAC.28, 8-Apr-83 05:46:53 by WACHS
;TCO 6.1603 - Light US.2PT
; UPD ID= 1105, SNARK:<6.MONITOR>PHYP2.MAC.27, 24-Aug-82 12:17:25 by PAETZOLD
;More TCO 6.1228 - Do not count skip reads in UDBRED
; UPD ID= 1087, SNARK:<6.MONITOR>PHYP2.MAC.26, 17-Aug-82 18:30:17 by PAETZOLD
;TCO 6.1228 - Update UDBRCT as well as UDBRVC for skip reads
; UPD ID= 1049, SNARK:<6.MONITOR>PHYP2.MAC.25, 6-Aug-82 15:30:10 by PAETZOLD
;More TCO 6.1217 - Fix a typo
; UPD ID= 1046, SNARK:<6.MONITOR>PHYP2.MAC.24, 6-Aug-82 14:47:16 by PAETZOLD
;TCO 6.1217 - Update UDBRVC for skip reads and not UDBRCT
; UPD ID= 905, SNARK:<6.MONITOR>PHYP2.MAC.23, 9-Jun-82 23:36:56 by MURPHY
;TCO 6.1147 - Move bugdefs from BUGS.MAC to here and put them in-line.
; UPD ID= 2196, SNARK:<5.MONITOR>PHYP2.MAC.22, 12-Jun-81 15:38:34 by LYONS
; UPD ID= 1824, SNARK:<5.MONITOR>PHYP2.MAC.21, 17-Apr-81 09:55:22 by WACHS
; UPD ID= 1335, SNARK:<5.MONITOR>PHYP2.MAC.20, 1-Dec-80 17:40:55 by LYONS
; UPD ID= 1211, SNARK:<5.MONITOR>PHYP2.MAC.19, 31-Oct-80 07:07:29 by UHLER
;TCO 5.1184 - DON'T READ REGISTER 30 UNLESS THE DX20 IS ALREADY HALTED
; UPD ID= 978, SNARK:<5.MONITOR>PHYP2.MAC.18, 2-Sep-80 07:48:47 by UHLER
;MAKE ECC CORRECTION WORK
; UPD ID= 736, SNARK:<5.MONITOR>PHYP2.MAC.17, 7-Jul-80 00:47:21 by DBELL
;TCO 5.1096 - INSERT ROUTINE TO CHECK FOR HALTED MICROCODE
; UPD ID= 731, SNARK:<5.MONITOR>PHYP2.MAC.16, 3-Jul-80 16:06:46 by DBELL
;DISABLE ECC RECOVERY UNTIL IT IS PROVEN TO WORK
; UPD ID= 677, SNARK:<5.MONITOR>PHYP2.MAC.15, 19-Jun-80 12:33:56 by DBELL
;MORE RECALIBRATION WORK
;READ THE CORRECT NUMBER OF SENSE BYTES
;GET PCTR AND PBAR VALUES FOR SYSERR PROPERLY
;MAKE RECALIBRATES WORK PROPERLY
;HANDLE WRITE-LOCKED DISKS BY MAKING THEM SAY OPR ACTION REQUESTED
; UPD ID= 640, SNARK:<5.MONITOR>PHYP2.MAC.11, 15-Jun-80 00:23:08 by DBELL
;FIX TYPO IN ASYNDO ROUTINE
; UPD ID= 636, SNARK:<5.MONITOR>PHYP2.MAC.10, 13-Jun-80 13:17:43 by DBELL
;TCO 5.1065 - CLEAR WRITE-LOCK BIT ON UNEXPECTED ASYCHRONOUS INTERRUPTS
;FIX SOME PROBLEMS IN ERROR RECOVERY
; UPD ID= 609, SNARK:<5.MONITOR>PHYP2.MAC.9, 5-Jun-80 16:25:01 by DBELL
;STORE FINAL CHANNEL STATUS WORDS WHEN ENDING SYSERR BLOCK
;READ ASYCHRONOUS STATUS REGISTER AGAIN IF NO STATUS FLAGS FIRST TIME
;ADD ADDITIONAL DATA FOR BUGCHKS AND BUGINFS
;<DBELL.M4>PHYP2.MAC.19, 6-May-80 23:37:56, EDIT BY DBELL
;<4.1.MONITOR>PHYP2.MAC.2, 30-Apr-80 21:48:04, EDIT BY DBELL
;TCO 4.1.1119 - WRITE RP20 DRIVER
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
;OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1976, 1985.
;ALL RIGHTS RESERVED.
SEARCH PROLOG,PHYPAR,SERCOD ;SYSTEM PARAMETERS
TTITLE (PHYP2,,< - DEVICE DEPENDENT CODE FOR DX20B/RP20 DISKS>)
SUBTTL DAVID I. BELL/GMU 11-AUG-80
ENTRY DXBDSP ;FOR LIBRARY SEARCH
;PARAMETERS:
MAXDRV==^D256 ;MAXIMUM NUMBER OF DRIVES POSSIBLE
NUMDRV==^D16 ;MOST NUMBER OF DRIVES WE CAN USE
DUADRV==20 ;FIRST DRIVE NUMBER WHICH CAN BE DUAL PORTED
STADDR==5 ;NORMAL START ADDRESS OF DX20 MICROCODE
BYTSEC==^D2304 ;NUMBER OF 8-BIT BYTES PER SECTOR
SNSNUM==^D80 ;NUMBER OF EXTENDED STATUS BYTES
RTYCNT==^D10 ;NUMBER OF RETRIES BEFORE RECALIBRATION
RCLCNT==^D2 ;NUMBER OF RECALIBRATES BEFORE GIVING UP
;DEFINITIONS FOR THE RP2FNC TABLE TO TRANSFER PHYSIO FUNCTIONS TO
;THE CORRESPONDING HARDWARE FUNCTIONS:
DEFSTR (TBDTF,RP2FNC,0,1) ;FUNCTION TRANSFERS DATA (SIGN BIT)
DEFSTR (TBFNC,RP2FNC,^D17,^D8) ;RP20 FUNCTION CODE
DEFSTR (TBDSP,RP2FNC,^D35,^D18) ;DISPATCH ADDRESS
;USEFUL MACROS:
DEFINE RDRG(REGN),< ;;MACRO TO READ REGISTER OF UNIT IN Q2
MOVX T2,<REGN> ;;SET UP REGISTER NUMBER
CALL RDREG3 ;;READ IT INTO T1
>
DEFINE REG(NAME,LENGTH<1>),< ;;MACRO TO ALLOCATE REGISTER OFFSETS
NAME==.REG. ;;DEFINE THIS OFFSET
.REG.==.REG.+LENGTH ;;THEN ADVANCE OFFSET BY GIVEN AMOUNT
>
DEFINE SAVREG(REGS),< ;;MACRO TO SPECIFY REGISTERS FOR SYSERR
REGNUM==<SAVBIT==0> ;;INITIALIZE BIT MASK AND COUNTER
IRP REGS,<SAVBIT==SAVBIT!<1B<^O<REGS>>> ;;MARK BIT FOR REGISTER
REG.'REGS==REGNUM ;;DEFINE OFFSET FOR USE LATER
REGNUM==REGNUM+1 ;;INCREMENT COUNTER
> ;;LOOP OVER ALL REGISTERS
> ;;RETURN BITS AND COUNT
SAVREG <0,1,2,3,4,5,6,20,21,22,23,24,26,27,30,31,32,33,34,35,36,37>
SUBTTL UDB AND KDB EXTENSIONS
;UDB DEVICE DEPENDENT PORTION:
.REG.==UDBDDD ;START OFFSETS AT DEVICE DEPENDENT PART
; REG U.XXXX ;ANY UDB LOCATIONS GET DEFINED HERE
LU.DX2==.REG. ;LENGTH OF RP20 UDB
;STATUS BITS IN LEFT HALF OF UDBERR:
UE.HRD==1B0 ;HARD ERROR
UE.ECC==1B1 ;ECC-CORRECTABLE ERROR
UE.DAT==1B2 ;DATA ERROR
UE.HDR==1B3 ;HEADER ERROR
UE.DEV==1B4 ;DEVICE ERROR (NEITHER DATA NOR HEADER)
UE.POS==1B5 ;POSITIONING ERROR
;KDB DEVICE DEPENDENT PORTION:
.REG.==KDBDDP ;START OFFSETS AT DEVICE DEPENDENT PART
REG K.DUDB,NUMDRV ;UDB TABLE (NUMDRV WORDS LONG)
REG K.DXAD ;MASSBUSS ADDRESS OF THE DX20
REG K.STCT ;NUMBER OF TIMES MICROCODE WAS RESTARTED
REG K.STCL ;CLOCK TIMER FOR RESTARTS ON OVERDUES
REG K.DNUM ;NUMBER OF DRIVES IN EXISTENCE
REG K.SAVQ ;STORAGE FOR Q1 ON ATTENTION INTERRUPTS
REG K.DVER ;DX20 MICROCODE VERSION NUMBER
REG K.DREG,REGNUM ;DRIVE REGISTERS READ ON ERROR
REG K.DEXS,<SNSNUM+3>/4 ;EXTENDED STATUS BYTES (MUST FOLLOW K.DREG)
REG K.DCNI ;CONI OF RH READ ON AN ERROR
REG K.DCS1 ;DATAI OF RH CONTROL REGISTER
REG K.DDBF ;DATAI OF RH DATA REGISTER
LK.DX2==.REG. ;LENGTH OF DX20 KDB
SUBTTL MASSBUS-DX20 REGISTER DEFINITIONS
;MASSBUS DEVICE REGISTER ASSIGNMENTS. MISSING REGISTER DEFINITIONS
;ARE EITHER UNUSED OR ARE FOR DIAGNOSTICS
.DXCTL==0B5 ;CONTROL REGISTER
.DXSTS==1B5 ;STATUS REGISTER
.DXERR==2B5 ;ERROR REGISTER
.DXMAI==3B5 ;MAINTENANCE REGISTER
.DXATN==4B5 ;ATTENTION SUMMARY REGISTER
.DXREC==5B5 ;HEAD/RECORD REGISTER (SAME AS REG 25)
.DXTYP==6B5 ;DRIVE TYPE REGISTER
;REGISTERS 7-17 ARE UNUSED
.DXEND==20B5 ;ENDING STATUS REGISTER
.DXASY==21B5 ;ASYNCHRONOUS STATUS REGISTER
.DXFLG==22B5 ;FLAGS AND ARGUMENT REGISTER
.DXDRV==23B5 ;DRIVE NUMBER REGISTER
.DXCYL==24B5 ;CYLINDER REGISTER
;REGISTER 25 IS SAME AS REGISTER 5
.DXES0==26B5 ;EXTENDED STATUS REGISTER 0
.DXES1==27B5 ;EXTENDED STATUS REGISTER 1
.DXDG0==30B5 ;DIAGNOSTIC REGISTER 0 (CONTENTS OF MICROSTORE)
.DXDG1==31B5 ;DIAGNOSTIC REGISTER 1 (PC AND FLAGS)
;REGISTERS 32-36 ARE FOR DIAGNOSTIC USE
.DXDG7==37B5 ;DIAGNOSTIC REGISTER 7 (PARITY ERROR FLAG)
;REGISTER 0 (.DXCTL) BIT DEFINITIONS:
DX.GO==1B35 ;GO BIT
DEFSTR (DXFNC,,^D35,6) ;FUNCTION CODE (INCLUDING GO BIT)
;FUNCTION CODES (INCLUDING THE GO BIT). SOME OF THE FUNCTIONS HAVE
;SUB-CODES WHICH MUST BE LOADED INTO THE FLAG REGISTER (.DXFLG) PRIOR
;TO LOADING THE FUNCTION CODE ITSELF. POSSIBLE SUB-CODES ARE INDENTED
;FOLLOWING THEIR MAJOR CODE.
XF.NOP==1 ;FUNCTION FOR NO OPERATION SUB-CODES
XS.TIO==0 ;TEST I/O
XS.NOP==3 ;NO OPERATION
XF.SEK==5 ;SEEK
XF.REC==7 ;RECALIBRATE
XF.CLR==11 ;DRIVE CLEAR
XF.SRC==31 ;SEARCH
XF.SEN==47 ;FUNCTION FOR SENSE SUB-CODES
XS.SEN==4 ;SENSE
XS.REL==224 ;DRIVE RELEASE
XS.BUF==244 ;READ AND RESET BUFFER LOG
XS.RSV==264 ;DRIVE RESERVE
XF.WRT==61 ;WRITE DATA
XF.WRF==63 ;WRITE FORMAT
XF.WRS==65 ;WRITE SPECIAL
XF.RED==71 ;READ DATA
XF.RDF==73 ;READ FORMAT
XF.RDS==75 ;READ SPECIAL
;REGISTER 1 (.DXSTS) BIT DEFINITIONS:
ST.ATN==1B20 ;ATTENTION (.DXATN IS NONZERO)
ST.ERR==1B21 ;COMPOSITE ERROR (.DXERR IS NONZERO)
ST.LNK==1B22 ;LINK PRESENT (ALWAYS ON)
ST.RUN==1B23 ;MICROPROCESSOR IS RUNNING
;REGISTER 2 (.DXERR) BIT DEFINITIONS:
DEFSTR (ERCOD,,^D27,4) ;ERROR CLASS CODE FIELD
DEFSTR (ERSUB,,^D23,4) ;ERROR SUB-CLASS FIELD
ER.NEW==1B28 ;NEW ERROR DETECTED BY MICROPROCESSOR
ER.STP==1B29 ;MICROPROCESSOR STOPPED
ER.MPE==1B30 ;MICROBUS PARITY ERROR
ER.DPE==1B31 ;DATABUS PARITY ERROR
ER.CPE==1B32 ;CONTROL BUS PARITY ERROR
ER.RMR==1B33 ;REGISTER MODIFICATION REFUSED
ER.ILR==1B34 ;REFERENCE TO ILLEGAL REGISTER
ER.ILF==1B35 ;ILLEGAL FUNCTION ATTEMPTED
ER.ALL==ER.NEW!ER.STP!ER.MPE!ER.DPE!ER.CPE!ER.RMR!ER.ILR!ER.ILF ;ALL
;ERROR CLASS AND SUB-CLASS CODES (FROM ERCOD AND ERSUB). VALUES
;IN THE SUB-CLASS ARE INDENTED.
ER.UDS==1 ;UNUSUAL DEVICE STATUS
ES.FSS==0 ;STATUS IS FROM FINAL SEQUENCE
ES.ISS==1 ;STATUS IS FROM INITIAL SEQUENCE
ER.RLE==2 ;RECORD LENGTH ERROR
ER.DSE==3 ;DRIVE SELECTION ERROR (NONEXISTENT DRIVE)
ER.RER==4 ;RECOVERABLE ERROR
ES.DPE==0 ;DATA PATH PARITY ERROR
ES.EPE==1 ;ENDING STATUS BYTE PARITY ERROR
ES.AMM==2 ;ADDRESS MISMATCH
ES.APE==3 ;ADDRESS PARITY ERROR
ES.IPE==4 ;INITIAL STATUS BYTE PARITY ERROR
ES.DMP==5 ;DATA PATH DETECTED MICRO BUS PARITY ERROR
ES.IMP==6 ;DEV BUS INTERFACE FOUND MICRO BUS PARITY ERROR
ES.HTO==7 ;DEVICE BUS HANDSHAKE TIME-OUT
ES.ADI==10 ;DEVICE ASSERTED DISCONNECT IN
ES.RWR==11 ;RUN WASN'T RECEIVED FROM RH20
ER.CRR==5 ;COMMAND RETRY REQUEST
ER.NER==6 ;NON-RECOVERABLE ERROR
ES.PE1==0 ;PARITY ERROR RECEIVING DRIVE ADDRESS
ES.PE2==1 ;SAME THING
ER.RIA==7 ;RETRY LOG INFORMATION AVAILABLE
ER.FTL==10 ;FATAL ERRORS (BAD MICROCODE OR BROKEN HARDWARE)
ES.WDT==0 ;HARDWARE DRIVE TYPE DOESN'T MATCH EXPECTED TYPE
ES.FCU==1 ;FOREIGN CONTROL UNIT
ES.MPF==2 ;MASSBUS CONTROLLER POWER FAILED
ES.II0==3 ;MICROPROCESSOR INTERRUPTED FROM INTERFACE 0
;REGISTER 3 (.DXMAI) BIT DEFINITIONS:
MR.SS==1B31 ;SINGLE STEP MICRO PROCESSOR
MR.WEP==1B32 ;WRITE EVEN PARITY ON ALU OPERATION
MR.ST==1B33 ;START/STOP MICRO PROCESSOR
MR.RES==1B34 ;HALT MICRO PROCESSOR AND CLEAR REGISTERS
;REGISTER 4 (.DXATN) BIT DEFINITIONS:
AT.0==1B35 ;DRIVE 0 NEEDS ATTENTION. FOR OTHER DRIVES,
;SHIFT LEFT BY DRIVE NUMBER.
;REGISTER 5 (.DXREC) BIT DEFINITIONS:
DEFSTR (RCHED,,^D27,^D8) ;HEAD NUMBER
DEFSTR (RCREC,,^D35,^D8) ;RECORD NUMBER
;REGISTER 20 (.DXEND) BIT DEFINITIONS (THESE STATUS FLAGS ARE ALSO
;RETURNED IN REGISTER .DXASY ON ANCHRONOUS STATUS):
DEFSTR (ESIDX,,^D35,7) ;EXTENDED STATUS TABLE INDEX
ES.STM==1B21 ;STATUS MODIFIER FLAG
ES.CUE==1B22 ;CONTROL UNIT END
ES.BSY==1B23 ;CONTROL UNIT OR DEVICE IS BUSY
ES.CHE==1B24 ;CHANNEL END
ES.DVE==1B25 ;DEVICE END
ES.UNC==1B26 ;UNIT CHECK
ES.UNE==1B27 ;UNIT EXCEPTION
ES.SUI==1B28 ;STATUS UPDATE INTERLOCK
;REGISTER 21 (.DXASY) BIT DEFINITIONS (BITS 20-28 ARE STATUS BITS
;DEFINED THE SAME AS IN REGISTER .DXEND):
DEFSTR (ASDRV,,^D35,^D8) ;DRIVE NUMBER PRESENTING STATUS
;REGISTER 22 (.DXFLG) BIT DEFINITIONS:
DEFSTR (DFCOD,,^D35,^D8) ;SUB-FUNCTION TO PERFORM
DF.IGL==1B21 ;IGNORE LENGTH ERRORS
DF.DIA==1B22 ;DIAGNOSTIC MODE FOR READ AND WRITE SPECIAL
DF.RTY==1B23 ;COMMAND RETRY REQUESTED
DF.DSN==1B25 ;DISABLE SENSE ON UNIT CHECKS
DF.FSN==1B26 ;FORCE SENSE OPERATION ON COMMAND COMPLETION
DF.WHT==1B27 ;READ OR WRITE THE WHOLE TRACK
;REGISTER 23 (.DXDRV) BIT DEFINITIONS:
DEFSTR (DRVNM,,^D35,^D8) ;DRIVE NUMBER
;REGISTER 31 (.DXDG0) BIT DEFINITIONS:
DG.UIR==1B20 ;READ OR WRITE INSTRUCTION REGISTER
DG.MSE==1B21 ;ENABLE MICROSTORE FOR WRITING
DG.PCS==1B22 ;SET DX20 PC
DG.PCI==1B23 ;INCREMENT PC AFTER USING INSTRUCTION REGISTER
DG.PC==7777B35 ;PC VALUE
;REGISTER 37 (.DXDG7) BIT DEFINITIONS:
DG.IRP==1B22 ;IR PARITY ERROR OCCURED
;DEFINITIONS FOR SENSE BYTES 0-3. WHEN READ INTO AN AC, BITS 2-9
;CONTAIN BYTE 0, BITS 10-17 CONTAIN BYTE 1, BITS 20-27 CONTAIN
;BYTE 2, AND BITS 28-35 CONTAIN BYTE 3.
S0.REJ==1B2 ;COMMAND REJECT
S0.IVR==1B3 ;INTERVENTION REQUIRED
S0.BPE==1B4 ;BUS OUT PARITY ERROR
S0.ECK==1B5 ;EQUIPMENT CHECK
S0.DCK==1B6 ;DATA CHECK OCCURED
S0.OVR==1B7 ;OVERRUN OCCURED
S1.PRM==1B10 ;PERMANENT ERROR (DCU RETRY COUNT EXHAUSTED)
S1.ITF==1B11 ;INVALID TRACK FORMAT
S1.EOC==1B12 ;END OF CYLINDER
S1.NRF==1B14 ;NO RECORD FOUND
S1.FPE==1B15 ;FILE PROTECTED ERROR
S1.WLK==1B16 ;DRIVE WAS WRITE LOCKED
S1.OPI==1B17 ;OPERATION INCOMPLETE
S2.COR==1B21 ;ERROR IS CORRECTABLE
S2.EDP==1B23 ;ENVIRONMENTAL DATA PRESENT (BYTES 8 - 23)
S2.CMP==1B24 ;DRIVE IS IN 3330 COMPATIBLE MODE
DEFSTR (S3RSC,,^D35,^D8) ;RESTART COMMAND
;OTHER SENSE BYTE INFORMATION OF INTEREST. ALL OF THESE DEFINITIONS
;ASSUME THAT ALL OF THE SENSE BYTES WERE READ INTO THE K.DEXS TABLE
;IN THE KDB. THIS TABLE CONTAINS FOUR SENSE BYTES PER WORD.
DEFSTR (SBECOD,K.DEXS+1(P2),^D35,^D8) ;SENSE BYTE 7:
;ERROR TYPE FIELD
DEFSTR (SBEPOS,K.DEXS+4(P2),^D35,^D16) ;SENSE BYTES 18 AND 19:
;BYTE POSITION OF ECC ERROR
DEFSTR (SBEMSK,K.DEXS+5(P2),^D17,^D16) ;SENSE BYTES 20 AND 21:
;MASK TO FIX ECC ERROR WITH
FC.ECC==123 ;VALUE IN SBECOD FOR ECC ERROR
FC.IVC==001 ;FORMAT 0, MESSAGE 1: INVALID COMMAND
FC.FPR==012 ;FORMAT 0, MESSAGE A: MPL FILE PERM RD CK
CI.OVR==1B26 ;DATA OVERRUN
SUBTTL DISPATCH FOR DX20B
;THE FOLLOWING TABLE IS THE DISPATCH TABLE FOR THIS DRIVER. THE OFFSETS
;INTO THE TABLE ARE DEFINED IN PHYPAR. THE CALLING SEQUENCE TO USE THIS
;TABLE IS:
;
; HRRZ AC,UDBDSP(P3) ;GET DISPATCH ADDRESS
; CALL UDSXXX(AC) ;CALL ROUTINE
; (NON-SKIP RETURN) ;ROUTINE DIDN'T SKIP
; (SKIP RETURN) ;ROUTINE SKIPPED
;
;YOU CAN REPLACE THE "HRRZ AC,UDBDSP(P3)" INSTRUCTION WITH "HRRZ AC,KDBDSP(P2)"
;WHEN NECESSARY, SINCE THE KDB AND THE UDB USE THE SAME DISPATCH TABLE.
DXBDSP::JRST DX2INI ;0 - INITIALIZATION
JRST DX2SIO ;1 - START DATA TRANSFER OPERATION
JRST DX2INT ;2 - HANDLE INTERRUPT
JRST DX2ERR ;3 - ERROR RECOVERY
JRST DX2HNG ;4 - HUNG DEVICE
JRST DX2CNV ;5 - CONVERT SECTOR NUMBER TO BLOCK/SEC-SURFACE
JRST DX2LAT ;6 - LATENCY COMPUTATION
JRST DX2POS ;7 - START POSITION OPERATION (SEARCH)
JRST DX2ATN ;10 - ATTENTION INTERRUPT
JRST DX2PCK ;11 - SKIP IF POSITIONING NEEDED
JRST DX2STK ;12 - STACK SECOND COMMAND
JRST DX2EXT ;13 - CHECK LEGALITY AND EXISTENCE OF A UNIT
JRST DX2CCK ;14 - SEE IF DX20 IS HALTED
JRST R ;15 - RELEASE PORT
SUBTTL DX20 INITIALIZATION
;DX2INI - INITIALIZATION ROUTINE. THIS ROUTINE IS CALLED ONCE PER
;DX20 DRIVE ON THE SYSTEM AND BUILDS A KDB FOR THE DX20 AND A UDB
;FOR EACH RP20 DRIVE. CALL:
; P1/ CDB
; Q2/ DX20 NUMBER
; P5/ UNIT NUMBER TO INITIALIZE, OR -1 FOR ALL UNITS
;RETURNS:
; +1: ALWAYS
; T1/ KDB
DX2INI: SAVEQ ;SAVE REGISTERS
JUMPL P5,INILB ;SKIP ON IF INITIALIZING ALL UNITS
MOVE P2,CDBIUN(P1) ;GET KDB ADDRESS IF IT EXISTS
ADD P2,Q2 ;POINT TO CORRECT UNIT
MOVE P2,0(P2) ;GET ENTRY
SKIPE P3,P2 ;FOUND ONE?
JRST INILA ;ALREADY GOT ONE
INILB: CALL CHKMIC ;CHECK THE DX20 MICROCODE (STOPS IT TOO)
JRST [ HRRZ T1,CDBADR(P1) ;BAD MICROCODE, GET CHANNEL READY
BUG.(CHK,DXBDMI,PHYP2,SOFT,<PHYP2 - DX20B microcode is invalid>,<<T1,CHAN>,<Q2,DX20>>,<
Cause: TOPS-20 could not verify the microcode in a DX20B (RP20 controller).
Data: CHAN - Channel number
DX20 - DX20 number
>) ;COMPLAIN
RET] ;AND IGNORE THIS DX20
MOVEI T1,LK.DX2 ;LENGTH OF KDB
CALL PHYALC ;ALLOCATE SPACE
RET ;FAILED
MOVE P2,T1 ;SAVE ADDRESS OF KDB IN PROPER AC
MOVE P3,T1 ;NEED POINTER OF KDB ALSO IN P3
MOVEI T1,.BTKDB ;MARK AS A KDB
DPB T1,USYBKT ;SET .BTKDB IN KDB
MOVEI T1,.UTDXB ;GET CODE FOR DX20B CONTROLLER
STOR T1,USTYP,(P2) ;AND STORE IT INTO THE KDB
MOVX T1,KS.DSK ;GET FLAG READY
IORM T1,KDBSTS(P2) ;REMEMBER THAT THIS CONTROLLER DRIVES DISKS
MOVEI T1,DXBDSP ;INSERT DISPATCH VECTOR
MOVEM T1,KDBDSP(P2) ; ...
HRRZM Q2,K.DXAD(P2) ;SAVE MASSBUSS ADDRESS OF THE KDB
CALL GETVER ;READ THE MICROCODE VERSION IN THE DX20
MOVEM T1,K.DVER(P2) ;REMEMBER IT IN THE KDB FOR SYSERR STUFF
MOVEI T1,STADDR ;GET STARTING ADDRESS OF DX20
CALL DXSTRT ;START THE DX20 MICROCODE
MOVSI T1,1 ;** TEMPORARY
SOJG T1,. ;** GIVE DX20 TIME TO START UP HAPPILY
MOVSI T1,-NUMDRV ;SET UP AOBJN INDEX
HRRI T1,K.DUDB(P2) ;MAKE RH POINT TO UDB ENTRIES IN KDB
MOVEM T1,KDBIUN(P2) ;INITIAL POINTER
MOVEM T1,KDBCUN(P2) ;CURRENT POINTER
SETZM K.DNUM(P2) ;CLEAR NUMBER OF UDB'S IN EXISTENCE
INILA: SKIPL Q1,P5 ;GET POSSIBLE SPECIFIC UNIT TO INITIALIZE
TLOA Q1,-1 ;WAS ONE, DO ONLY 1 TIME
MOVSI Q1,-MAXDRV ;WANTS ALL DRIVES, SET UP AOBJN INDEX
MOVEI Q3,4 ;GET MAXIMUM DRIVES TO COMPLAIN ABOUT
;FALL INTO LOOP
;LOOP TO EXAMINE ALL UNITS:
INILP: SETZ P5, ;NO UDBSTS BITS YET
MOVX T2,.DXDRV ;GET DRIVE NUMBER REGISTER READY
STOR Q1,DRVNM,T2 ;INSERT DRIVE NUMBER
CALL WTREG3 ;SET IT
MOVX T2,.DXFLG+<FLD(XS.NOP,DFCOD)> ;GET SUB-FUNCTION NEEDED
CALL WTREG3 ;PLACE INTO ARGUMENT REGISTER
MOVX T2,.DXCTL+<FLD(XF.NOP,DXFNC)> ;GET FUNCTION FOR NOP
CALL WTREG3 ;TELL DX20 TO DO A NOP ON THE DRIVE
CALL ATTNWT ;WAIT FOR COMPLETION
JRST SIKDRV ;FAILED, COMPLAIN
RDRG .DXERR ;READ ERROR REGISTER NOW
TXNE T1,ER.ALL-ER.NEW ;ANY FATAL ERRORS?
JRST SIKDRV ;YES, GO COMPLAIN
TXNN T1,ER.NEW ;ANY NEW ERROR STATUS?
JRST ISDRV ;NO, THEN DRIVE EXISTS AND IS OK
LOAD T2,ERCOD,T1 ;EXTRACT ERROR CODE
CAIN T2,ER.DSE ;NONEXISTENT DRIVE?
JRST NXTDRV ;YEP, JUST IGNORE IT
CAIE T2,ER.UDS ;UNUSUAL DEVICE STATUS?
JRST SIKDRV ;NO, SOMETHING ELSE, GO COMPLAIN
RDRG .DXEND ;GET ENDING STATUS
TXNN T1,ES.UNC ;WAS THE ERROR UNIT CHECK?
JRST NXTDRV ;NOPE, SO NO SUCH UNIT, EXAMINE NEXT ONE
CALL RDSNS ;YES, READ IN SENSE BYTES
JRST NXTDRV ;FAILED, SKIP THIS DRIVE
TXNE T1,S0.OVR!S0.DCK!S0.ECK!S0.BPE!S0.REJ!S1.OPI!S1.FPE!S1.NRF!S1.EOC!S1.ITF!S1.PRM ;ANY AWFUL STATUS?
JRST SIKDRV ;YES, CALL IT SICK
MOVX P5,US.OFS ;DRIVE IS OFF-LINE, GET STATUS TO SET
;HERE FOR EACH EXISTENT DRIVE. DECIDE IF THIS DRIVE IS DUAL PORTED, AND
;IF SO EITHER IGNORE THIS ACCESS PATH TO IT, OR ELSE MOVE THE UDB FROM
;THE ALTERNATE ACCESS PATH TO THIS ONE (WHICH WILL IMPROVE PERFORMANCE).
;CALLED WITH INITIAL UDBSTS FLAGS IN P5.
ISDRV: HRRZ T1,Q1 ;GET DRIVE NUMBER
CALL CKDUAL ;SEE IF THE DRIVE ALREADY EXISTS ON ANOTHER PORT
JRST NEWDRV ;NO, BUILD A UDB THEN
MOVE P3,T1 ;REMEMBER UDB (HOWEVER, P1 AND P2 DON'T MATCH!)
TLC Q1,-1 ;GET READY FOR TEST
TLCE Q1,-1 ;DOING ONLY ONE UNIT (OR LAST UNIT OF SERIES)?
TRNE Q1,1 ;OR IS THE DRIVE NUMBER ODD?
JRST NXTDRV ;YES, LET OTHER CHANNEL KEEP OWNERSHIP OF DRIVE
MOVE T1,K.DNUM(P2) ;GET NUMBER OF DRIVES ON THIS CONTROLLER
CAIL T1,NUMDRV ;ANYMORE ROOM IN UDB TABLE?
JRST NXTDRV ;NO, LEAVE DRIVE ON ORIGINAL CHANNEL
MOVE T1,UDBSTS(P3) ;PARANOIA CHECK - IS THE UNIT NOW ACTIVE?
TXNE T1,US.ACT!US.POS!US.MAI ;WELL?
JRST NXTDRV ;YES, DON'T SWITCH THE UDB!!
HRRZ T1,UDBKDB(P3) ;GET OLD KDB ADDRESS FROM UDB WE ARE MOVING
MOVE T2,KDBIUN(T1) ;SETUP TO SEARCH ITS UDB TABLE
CAME P3,(T2) ;FIND OLD KDB'S POINTER TO UDB?
AOBJN T2,.-1 ;NO, KEEP LOOKING
JUMPGE T2,NXTDRV ;IF NOT FOUND (??) LEAVE UDB ALONE
SOS T3,K.DNUM(T1) ;DECREMENT COUNTER OF UNITS IN OTHER KDB
ADDI T3,K.DUDB(T1) ;COMPUTE ADDRESS OF LAST UDB POINTER USED
MOVE T4,(T3) ;GRAB THE POINTER
MOVEM T4,(T2) ;OVERWRITE STOLEN UDB'S POINTER WITH IT
SETZM (T3) ;AND CLEAR LAST ENTRY IN UDB TABLE
HRRZM P1,UDBCDB(P3) ;SETUP NEW CHANNEL IN STOLEN UDB
HRRZM Q2,UDBADR(P3) ;AND NEW CONTROLLER NUMBER
MOVEM Q2,UDBAKA(P3) ;SET UP THIS WORD ALSO
HRLM Q2,UDBAKA(P3) ;WITH COPIES OF THESE NUMBERS
JRST DONDRV ;JOIN OTHER CODE TO FINISH UP
;HERE TO BUILD THE UDB FOR A DRIVE:
; Q1/ -n,,DRIVE-NUMBER
NEWDRV: MOVE T3,K.DNUM(P2) ;GET NUMBER OF DRIVES FOUND SO FAR
CAIL T3,NUMDRV ;ROOM IN K.DUDB TABLE?
JRST [ BUG.(CHK,DXBTTS,PHYP2,HARD,<PHYP2 - Tables too small for this many drives>,<<T3,NUMDRV>>,<
Cause: The number of RP20 drives on a DX20 controller exceeds the number
supported by TOPS-20.
Data: NUMDRV - Number of drives allowed per controller
>) ;NO, COMPLAIN
MOVE T1,P2 ;TELL RETURN TO PUT KDB INTO CDB
RET] ;GIVE UP NOW
MOVE T3,[DXBDSP,,LU.DX2] ;SET UP ADDRESS,,LENGTH
CALL PHYUDB ;AND ASK FOR UDB ALLOCATION
RET ;RETURN IF NO SPACE FOUND
MOVX T1,.UTP20 ;RP20 DISK IS ONLY POSSIBLE DEVICE
STOR T1,USTYP,(P3) ;PUT UNIT TYPE IN UDB
MOVSI T2,-NDSKUT ;GET READY FOR SEARCH
CAME T1,DSKUTP(T2) ;LOOK FOR DISK TYPE IN TABLE
AOBJN T2,.-1 ;KEEP SEARCHING
SKIPL T2 ;FIND IT?
BUG.(HLT,DXBTNF,PHYP2,SOFT,<PHYP2 - Unit type not found in table>,,<
Cause: The routine DX2INI was called to initialize a UDB for an RP20 disk.
It converted the hardware drive type into the internal drive
type and then looked in the physical parameter table (DSKUTP)
for that type so that the disk parameters could be obtained.
The drive type could not be found.
>) ;NO, COMPLAIN
MOVE T2,DSKSIZ(T2) ;GET POINTER TO PHYSICAL PARAMETER TABLE
MOVEM T2,UDBSIZ(P3) ;SAVE IN UDB
TXO P5,US.DSK!US.PRQ ;SET UNIT IS A DISK AND REQUIRES POSITIONING
IORM P5,UDBSTS(P3) ;REMEMBER FLAGS
DONDRV: AOS T1,K.DNUM(P2) ;ADVANCE TO NEXT FREE UDB ENTRY
ADDI T1,K.DUDB-1(P2) ;POINT TO THE NEW TABLE ENTRY
HRRZM P3,(T1) ;SAVE LINK
HRRZM P2,UDBKDB(P3) ;SAVE BKWDS LINK
HRRZM Q1,UDBSLV(P3) ;REMEMBER SLAVE ADDRESS
MOVX T1,<<.UTP20!400>_20> ;GET DRIVE TYPE
HRRZ T2,Q1 ;MAKE UP
ADDI T2,^D8000 ; SERIAL NUMBER
CALL SETDSN ;(T1,T2,P3/) SET DSN
JRST NXTDRV ;GO EXAMINE NEXT DRIVE
;HERE TO COMPLAIN IF NECESSARY ABOUT A SICK DRIVE, CLEAR ANY POSSIBLE
;ERROR STATUS, AND LOOP FOR THE NEXT UNIT.
SIKDRV: SOJL Q3,NXTDRV ;ONLY COMPLAIN ABOUT FIRST FEW DRIVES
HRRZ T1,CDBADR(P1) ;SET UP CHANNEL
HRRZ T2,Q1 ;AND UNIT NUMBER
BUG.(CHK,DXBEUI,PHYP2,HARD,<PHYP2 - Error trying to initialize a unit>,<<T1,CHAN>,<Q2,DX20>,<T2,UNIT>>,<
Cause: TOPS-20 detected a drive error while trying to initialize an RP20
disk.
Data: CHAN - Channel number
DX20 - DX20 number
UNIT - Drive number
>) ;COMPLAIN
NXTDRV: MOVX T2,.DXERR ;WANT TO CLEAR THE ERROR REGISTER
CALL WTREG3 ;DO IT
AOBJN Q1,INILP ;TRY NEXT SLAVE
MOVE T1,P2 ;TELL RETURN TO PUT KDB INTO CDB
RET
SUBTTL ROUTINE TO START I/O
;CALLED TO START A DATA TRANSFER FOR A DRIVE. CALL:
; P1/ CDB
; P2/ KDB
; P3/ CDB
; P4/ IORB
;RETURNS:
; +1: FAILED, IORB MARKED AS FAILED
; +2: I/O SUCCESSFULLY STARTED
DX2SIO: SAVEQ ;SAVE SOME REGISTERS
MOVE Q2,K.DXAD(P2) ;SET UP DX20 UNIT NUMBER
HRRZ T1,UDBERR(P3) ;GET FUNCTION IF ERROR RECOVERY
JUMPN T1,DS2SI1 ;GO IF SO
LDB T1,IRYFCN ;NORMAL, GET FUNCTION
CAIGE T1,MNRP2V
CAIG T1,MXEXTF ;MAKE SURE IT IS WITHIN RANGE
SKIPN RP2FNC(T1) ;AND LEGAL
BUG.(HLT,DXBFEX,PHYP2,SOFT,<PHYP2 - Illegal function starting IO>,,<
Cause: The routine DX2SIO in PHYP2 was called to start a transfer
operation for an IORB but the function code from the IORB
was illegal.
>) ;NO, DIE
DS2SI1: LOAD Q1,TBFNC,(T1) ;TRANSLATE TO HARDWARE FUNCTION
CALL DX2CON ;CONNECT TO THE DRIVE
RET ;FAILED
;RETURNS: T2/ CYLINDER, T3/ SECTOR WITHIN IT
CALL GTHWSC ;COMPUTE .DXREC VALUE (HEAD, RECORD NUMBERS)
MOVE T4,T1 ;SAVE FOR AWHILE
TXO T2,.DXCYL ;ADD REGISTER TO CYLINDER NUMBER
CALL WTREG ;SET CYLINDER INTO DX20
MOVE T2,T4 ;GET BACK .DXREC DATA
HRRZM P3,KDBACT(P2) ;REMEMBER WHICH UDB WE ARE DOING I/O ON
JRST CHSTRT ;GO START CHANNEL AND SKIP IF SUCCESSFUL
SUBTTL ROUTINE TO STACK SECOND TRANSFER COMMAND
;CALLED WHEN PRIMARY COMMAND IS BUSY, TO SET UP A SECOND TRANSFER
;COMMAND. SAME CALL AS DX2SIO.
DX2STK: SAVEQ ;SAVE ACS
MOVE Q2,K.DXAD(P2) ;SET UP DX20 UNIT NUMBER
LDB T1,IRYFCN ;GET FUNCTION TO PERFORM
CAIGE T1,MNRP2V ;VARIFY?
CAIG T1,MXEXTF ;VERIFY THAT IS IS NOT TOO LARGE
SKIPN RP2FNC(T1) ;AND THAT IS IS VALID
BUG.(HLT,DXBIF2,PHYP2,SOFT,<PHYP2 - Illegal function stacking IO>,,<
Cause: The routine DX2STK in PHYP2 was called to stack a second
transfer command but the function in the IORB was illegal.
>) ;IT'S BAD
LOAD Q1,TBFNC,(T1) ;TRANSLATE TO HARDWARE FUNCTION
CALL PHYBLK ;OBTAIN UNIT RELATIVE ADDRESS IN T2
TXZ T2,IRBPAD ;REMOVE PHYSICAL ADDRESSING BIT
MOVE T3,UDBSIZ(P3) ;GET POINTER TO DISK SIZE DATA
IDIV T2,SECCYL(T3) ;DIVIDE BY SECTORS PER CYLINDER
MOVEM T3,UDBPS2(P3) ;UPDATE SECTOR
CALL GTHWSC ;COMPUTE VALUE FOR .DXREC REGISTER
MOVE T2,T1 ;PUT INTO PROPER AC
JRST CHSTRT ;GO STACK THE COMMAND
SUBTTL ROUTINE TO START A POSITION OPERATION
;SEEKS ARE POSSIBLE FOR THE RP20, BUT ARE NOT USED BECAUSE ONCE THE
;DISK IS ON CYLINDER, THERE IS NO WAY TO TELL WHEN THE DESIRED SECTOR
;IS NEAR THE HEADS (IE, LATENCY OPTIMIZATION IS NOT POSSIBLE AS IT WAS
;FOR RPO6 AND SIMILAR DISKS). THEREFORE TO PROGRAM THE RP20 DISKS
;EFFICIENTLY, THE SEARCH FUNCTION IS USED INSTEAD. THIS FUNCTION WILL
;DO A SEEK IF NECESSARY, AND THEN WILL INTERRUPT THE CPU WHEN THE
;DESIRED SECTOR IS "NEAR" THE HEADS. THEN A TRANSFER OPERATION CAN
;BE INITIATED QUICKLY, AND VERY LITTLE ROTATIONAL TIME WILL BE LOST.
;CALL TO START THE SEARCH:
; P1/ CDB
; P2/ KDB
; P3/ UDB
; P4/ IORB
;RETURNS:
; +1: FAILED
; +2: SEARCH STARTED SUCCESSFULLY
DX2POS: SAVEQ ;SAVE ACS
MOVE Q2,K.DXAD(P2) ;SET UP DX20 UNIT NUMBER
MOVEI Q1,XF.SRC ;GET SEARCH FUNCTION
CALL DX2CON ;CONNECT TO DRIVE AND RETURN CYLINDER IN T2
RET ;CAN'T DO IT
DOPOS: CALL GTHWSC ;COMPUTE .DXREC VALUE (HEAD AND RECORD NUMBERS)
MOVE T4,T1 ;SAVE FOR AWHILE
TXO T2,.DXCYL ;INSERT REGISTER NUMBER
CALL WTREG ;SET CYLINDER INTO DX20
MOVE T2,T4 ;GET BACK .DXREC DATA
TXO T2,.DXCYL ;INSERT REGISTER NUMBER
HRRZM P3,KDBACT(P2) ;REMEMBER UDB WE HAVE TO WAIT FOR
JRST CHSTRT ;START CHANNEL AND SKIP IF SUCCESSFUL
SUBTTL SUBROUTINE TO CONNECT TO A DRIVE
;DX2CON - LOAD DRIVE NUMBER INTO DX20, COMPUTES CYLINDER AND SECTOR.
;CALL:
; P1/ CDB
; P2/ KDB
; P3/ UDB
; P4/ IORB
; Q1/ FUNCTION TABLE ENTRY
; Q2/ DX20 UNIT NUMBER
;RETURNS:
; +1: FAILED TO CONNECT
; +2: DONE, T1/ UNIT ADDRESS
; T2/ CYLINDER
; T3/ SECTOR WITHIN CYLINDER
DX2CON: CALL HLTCHK ;MAKE SURE MICROCODE IS STILL HAPPY
JRST [ MOVX T1,<IS.ERR!IS.DVE!IS.NRT> ;GET FATAL DEVICE ERROR FLAGS
IORM T1,IRBSTS(P4)
RET]
RDRG .DXERR ;READ ERROR REGISTER
TXNN T1,ER.ALL ;ANY ERRORS?
JRST CONNOE ;NO, PROCEED NORMALLY
MOVE T4,T1 ;COPY ERROR
RDRG .DXEND ;GET ENDING STATUS ALSO
HRL T4,T1 ;PUT WITH OTHER DATA
CALL FNDCKU ;COLLECT NUMBERS
BUG.(CHK,DXBEWC,PHYP2,HARD,<PHYP2 - Error present when connecting to a unit>,<<T1,CHAN>,<T2,CTRL>,<T3,UNIT>,<T4,20AND2>>,<
Cause: One or more flags is turned on in a DX20 drive error register.
TOPS-20 is ignoring the errors and proceeding.
Data: CHAN - Channel number
CTRL - Controller number
UNIT - Unit number
20AND2 - RH of DX20 ending status,,RH of DX20 error register
>) ;COMPLAIN
MOVX T2,.DXERR ;CLEAR THE ERROR REGISTER
CALL WTREG ;SO NO CONFUSION RESULTS
;AND PROCEED
CONNOE: MOVE T1,UDBSTS(P3) ;GET CURRENT UNIT STATUS
CAIE Q1,XF.WRT ;STANDARD WRITE FUNCTION?
CAIN Q1,XF.WRF ;OR FORMATTING WRITE?
TXNN T1,US.WLK ;YES, SEE IF THE DISK IS WRITE-LOCKED
TXNE T1,US.OFS ;AND ALWAYS SEE IF IT IS OFF-LINE
RET ;IF SO, OPERATOR INTERVENTION IS NEEDED
MOVX T2,.DXDRV ;WANT TO WRITE THE DRIVE REGISTER
MOVE T1,UDBSLV(P3) ;GET SLAVE UNIT NUMBER
STOR T1,DRVNM,T2 ;STORE WITH REGISTER NUMBER
CALL WTREG ;TELL DX20 WHICH DRIVE TO TALK TO
CALL PHYBLK ;RETURN PHYSICAL DISK ADDRESS TO USE IN T2
TXZ T2,IRBPAD ;REMOVE PHYSICAL ADDRESSING BIT
MOVE T1,T2 ;REMEMBER IT IN T1
MOVE T4,UDBSIZ(P3) ;GET POINTER TO DISK SIZE DATA
IDIV T2,SECCYL(T4) ;DIVIDE BY SECTORS PER CYLINDER
MOVEM T2,UDBPS1(P3) ;SAVE CYLINDER
MOVEM T3,UDBPS2(P3) ;AND SECTOR WITHIN CYLINDER
RETSKP ;SUCCESS RETURN
SUBTTL ROUTINE TO COMPUTE LATENCY OPTIMIZATION
;ROUTINE CALLED FROM PHYSIO TO EXAMINE ALL IORBS AND PICK THE ONE
;WITH THE SMALLEST LATENCY GREATER THAN A SPECIFIED MINIMUM. CALL:
; P1/ CDB
; P2/ KDB
; P3/ UDB
; T1/ MINIMUM LATENCY IN MICROSECONDS, OR ZERO TO PERFORM THE COMMAND
; STACKING COMPUTATION
;RETURNS:
; +1: NO REQUESTS ARE AVAILABLE
; +2: T1/ LATENCY OF CLOSEST REQUEST GREATER THAN SPECIFIED MINIMUM,
; WITH ZERO RETURNED IF THIS IORB IS THE PREFERRED ONE
; T2/ PREDECESSOR OF IORB CORRESPONDING TO TIME IN T1
; T3/ IORB CORRESPONDING TO TIME IN T1
;
;NOTICE: IT IS IMPOSSIBLE TO ASK THE RP20 WHICH SECTOR IS NEAR THE
;HEADS, SO THAT LATENCY OPTIMIZATION CANNOT WORK AS WELL AS FOR OTHER
;TYPES OF DISK. INSTEAD, IORBS ARE SCANNED LOOKING FOR A REQUEST NEAR
;THE LAST KNOWN POSITION OF THE DISK. THE UNIT WHICH LAST DID I/O IS
;GIVEN PRIORITY, SINCE ITS POSITION HAS MORE ACCURACY. FINALLY, HIGHEST
;PRIORITY IS GIVEN TO THE IORB WHICH JUST COMPLETED A SEARCH OPERATION.
;ACS ARE USED AS FOLLOWS:
;
; T3/ BEST SECTOR DISTANCE SO FAR,,SECTOR ON SURFACE TO AIM FOR
; T4/ MINIMUM LATENCY FLAG,,DSKSIZ POINTER
; P4/ PREDECESSOR TO CURRENT IORB,,CURRENT IORB TO EXAMINE
; P5/ PREDECESSOR TO BEST IORB SO FAR,,BEST IORB SO FAR FOUND
DX2LAT: SAVEAC <Q1> ;SAVE A FEW TEMP
MOVE T4,UDBSIZ(P3) ;GET POINTER TO DISK SIZE TABLE
HRLZ Q1,T1 ;SAVE LATENCY AS A FLAG (ZERO MEANS DO STACKING)
MOVEI P4,UDBTWQ(P3) ;GET POINTER TO FIRST IORB
TLNN Q1,-1 ;COMMAND STACKING COMPUTATION?
HRRZ P4,IRBLNK(P4) ;YES, SKIP FIRST IORB SINCE IT'S DOING I/O
SETZ P5, ;INITIALIZE BEST IORB
MOVE T1,UDBPS2(P3) ;GET CURRENT SECTOR WITHIN THE CYLINDER
ADD T1,SECPAG(T4) ;COMPUTE SECTOR OF NEXT PAGE
TLNN Q1,-1 ;STACKING COMPUTATION?
JRST [ CAML T1,SECCYL(T4) ;YES, NEXT SECTOR ON SAME CYLINDER?
RET ;NO, CAN'T STACK THEN
JRST LATBEG] ;YES, PROCEED
ADD T1,SECPAG(T4) ;NO, SKIP TO NEXT SECTOR
LATBEG: IDIV T1,SECSRF(T4) ;GET SECTOR WITHIN SURFACE TO AIM FOR IN T2
HRROI T3,(T2) ;INITIALIZE BEST DISTANCE AND DESIRED SECTOR
;THEN FALL INTO LOOP
;NOW LOOP OVER ALL IORBS LOOKING FOR THE BEST ONE.
LATLOP: HRRZ P4,P4 ;FIXUP ADDRESS
HRL P4,IRBLNK(P4) ;FOLLOW LINK TO NEXT IORB
TLNN P4,-1 ;ANOTHER IORB TO EXAMINE?
JRST LATFIN ;NO, GO RETURN RESULT
MOVS P4,P4 ;YES, SET UP PREDECESSOR AND CURRENT IORB
CAMN P4,UDBCHB ;CHECK FOR HOMEBLOCK REQUEST
JRST PREFHB ;PREFERENCE TO HOMEBLOCKS ALWAYS!!!
TLNN Q1,-1 ;COMMAND STACKING COMPUTATION?
JRST NOPREF ;YES, DON'T CHECK PREFERRED IORB
HRRZ T2,CDBIRB(T1) ;GET PREFERRED IORB IF ANY
CAIE T2,(P4) ;IS THIS IT?
JRST NOPREF ;NO, PROCEED NORMALLY
PREFHB: MOVEI T1,0 ;FLAG PREFERRED IORB WITH ZERO LATENCY
HLRZ T2,P4 ;GET PREVIOUS IORB
HRRZ T3,P4 ;AND THE PREFERRED IORB
RETSKP ;RETURN IT
NOPREF: BLOCK. ;Need a context
SAVEAC <P4> ;Save IORB addresses
HRRZS P4 ;Isolate IORB address
CALL PHYBLK ;COMPUTE UNIT RELATIVE ADDRESS FOR THIS IORB
ENDBK.
TXZ T2,IRBPAD ;REMOVE PHYSICAL ADDRESSING BIT
MOVE T1,T2 ;COPY IT
IDIV T1,SECCYL(T4) ;COMPUTE SECTOR WITHIN CYLINDER
MOVE T1,T2 ;COPY RESULT AGAIN
IDIV T1,SECSRF(T4) ;COMPUTE SECTOR WITHIN SURFACE
CAIGE T2,(T3) ;SECTOR NUMBER BELOW OUR GOAL?
ADD T2,SECSRF(T4) ;YES, ADD ONE REVOLUTION'S WORTH OF SECTORS
SUBI T2,(T3) ;SUBTRACT TO GET SECTORS BETWEEN LOCATIONS
HLRZ T1,T3 ;GET BACK OLD BEST DISTANCE
CAML T2,T1 ;THIS IORB CLOSER THAN PREVIOUS ONES?
JRST LATLOP ;NOPE, LOOK AT NEXT IORB THEN
MOVE P5,P4 ;IT'S BETTER, REMEMBER IORB AND PREDECESSOR
HRL T3,T2 ;REMEMBER NEW BEST DISTANCE ALSO
JUMPN T2,LATLOP ;LOOK FOR BETTER ONE UNLESS FOUND A BEST CASE
LATFIN: JUMPE P5,[BUG.(HLT,DXBLTF,PHYP2,SOFT,<PHYP2 - Latency optimization failure>,,<
Cause: The routine DX2LAT in PHYP2 was called by PHYSIO to find the best
IORB for a unit. However, after scanning all IORBs in the transfer
wait queue for the unit, no IORB was found that could be returned.
>) ;IF FOUND NO IORB, COMPLAIN
RET] ;AND ERROR RETURN
HLRZ T1,T3 ;GET BEST DISTANCE
IMULI T1,^D2700 ;CONVERT SECTORS INTO MICROSECONDS OF LATENCY
HRRZ T2,CDBLUN(P1) ;GET UNIT WHICH LAST DID I/O ON THE CHANNEL
CAIN T2,(P3) ;WAS IT THIS UNIT?
AOSA T1 ;YES, ADD ONE TO INSURE NONZERO RESULT
ADDI T1,2 ;NO, ADD EXTRA ONE TO PENALIZE UNIT
HLRZ T2,P5 ;GET PREDECESSOR OF BEST IORB
HRRZ T3,P5 ;AND THE BEST IORB ITSELF
RETSKP ;SUCCESSFUL RETURN
SUBTTL ROUTINE TO HANDLE NORMAL INTERRUPTS
;ROUTINE CALLED TO PROCESS A DONE INTERRUPT. ONLY THE COMPLETION OF A
;DATA OPERATION COMES HERE.
;CALL:
; P1/ CDB
; P2/ KDB
;RETURNS:
; +1: IORB HAD ERRORS
; P3/ UDB
; +2: I/O WAS SUCCESSFUL
; P3/ UDB
DX2INT: PUSH P,Q1 ;SAVE REGISTERS
PUSH P,Q2 ;THAT WE WILL TRASH (NOTE AOS -2(P) BELOW)
MOVE Q2,K.DXAD(P2) ;SET UP DX20 UNIT NUMBER
CALL DOINT ;HANDLE THE INTERRUPT
SKIPA ;NON-SKIP
AOS -2(P) ;SKIP RETURN, PASS IT ON
RDRG .DXCTL ;READ CONTROL REGISTER
TXNN T1,DX.GO ;DX20 FREE?
CALL ASYNST ;YES, CHECK ON ASYCHRONOUS STATUS TOO
MOVX T1,CS.AC2 ;GET READY FOR CHECK
TDNN T1,CDBSTS(P1) ;STILL DOING I/O BECAUSE OF STACKED COMMAND?
SETZM KDBACT(P2) ;NO, CLEAR ACTIVE UDB
POP P,Q2 ;RESTORE ACS
POP P,Q1 ;THAT WE SAVED
RET ;DONE
;HERE TO HANDLE THE DONE INTERRUPT. DX20 UNIT NUMBER IS IN Q2.
DOINT: SKIPN P3,KDBACT(P2) ;GET THE UDB I/O WAS BEING DONE FOR
JRST [ HRRZ T1,CDBADR(P1) ;NONE, GET CHANNEL READY
BUG.(CHK,DXBNUD,PHYP2,HARD,<PHYP2 - No unit active for Done interrupt>,<<T1,CHAN>,<Q2,DX20>>,<
Cause: A done interrupt occurred on a DX20 but there is no active UDB for
this controller.
Data: CHAN - Channel number
DX20 - DX20 number
>) ;COMPLAIN
RET] ;AND GIVE ERROR
MOVE T1,UDBSTS(P3) ;GET UDB STATUS FLAGS
TXNE T1,US.ACT ;MAKE SURE UDB WAS ACTIVE
TXNE T1,US.POS ;AND THAT IT WAS NOT POSITIONING
JRST [ CALL FNDCKU ;NOPE, COLLECT CKU NUMBERS
BUG.(CHK,DXBUA1,PHYP2,HARD,<PHYP2 - Done interrupt and unit was not active>,<<T1,CHAN>,<T2,CTRL>,<T3,UNIT>>,<
Cause: A done interrupt occurred on a DX20 but the UDB for the drive
marked in the KDB as active is not.
Data: CHAN - Channel number
CTRL - Controller number
UNIT - Unit number
>) ;COMPLAIN
RET] ;AND ERROR RETURN
CALL SETIRB ;SET UP THE CURRENT IORB
HRRZ T1,UDBERR(P3) ;GET FUNCTION IF DOING ERROR RECOVERY
SKIPN T1 ;DOING IT?
LDB T1,IRYFCN ;NO, GET FUNCTION FROM IORB
CAIG T1,MXFUNC ;A LEGAL FUNCTION?
JRST DOINT2 ;YES
CAIGE T1,MNRP2V ;MAKE SURE IT IS LEGAL
JRST INTBDF ;NOPE
DOINT2: CALL HARCHK ;CHECK FOR ANY ERRORS
RET ;HAD SOME, ERROR RETURN
HRRZ T1,UDBERR(P3) ;GET BACK FUNCTION
SKIPN T1 ;ERROR RECOVERY?
LDB T1,IRYFCN ;NO, NORMAL FUNCTION FROM IORB THEN
SKIPGE T1,RP2FNC(T1) ;GET DISPATCH ADDRESS
TRNN T1,-1 ;ALSO MAKE SURE HAVE AN ADDRESS
INTBDF: BUG.(HLT,DXBILF,PHYP2,SOFT,<PHYP2 - Illegal function at Done interrupt>,,<
Cause: The routine DX2INT in PHYP2 was called to handle a done interrupt
for a drive. The IORB which finished I/O contained a function
code which was illegal.
>) ;NO, LOSE
CALL (T1) ;CALL PROPER ROUTINE
RET ;FAILED, ERROR RETURN
RETSKP ;SUCCESSFUL RETURN
;HERE ON THE VARIOUS CASES OF INTERRUPTS:
RP2WRT: MOVX T1,US.WLK ;GET WRITE LOCKED FLAG
ANDCAM T1,UDBSTS(P3) ;CLEAR SINCE WRITE HAS COMPLETED
RP2RED: RDRG .DXSTS ;GET STATUS REGISTER
TXNN T1,ST.ERR ;ANY DRIVE ERRORS?
CALL CKERR ;OR ANY CHANNEL ERRORS?
JRST RP2DER ;YES, GO HANDLE THEM
CALL PHYCNT ;COMPUTE LENGTH OF TRANSFER
ADDI T1,PGSIZ-1 ;ROUND UP PARTIAL SECTORS
LSH T1,-PGSFT ;CONVERT TO SECTORS (PAGES) TRANSFERED
LDB T2,IRYFCN ;GET FUNCTION
CAIE T2,IRFRVC
CAIN T2,IRFRED ;READING?
JRST [ ADDM T1,UDBRED(P3) ;YES, INCREMENT SECTORS READ
CAIN T2,IRFRED ;READ?
AOS UDBRCT(P3) ;YES, SO COUNT READS DONE ALSO
CAIN T2,IRFRVC ;IS IT A SKIP READ?
AOS UDBRVC(P3) ;YES SO INCREMENT SKIP READS DONE
RETSKP]
ADDM T1,UDBWRT(P3) ;YES, INCREMENT SECTORS WRITTEN
AOS UDBWCT(P3) ;YES, COUNT WRITES DONE
RETSKP ;SUCCESSFUL
;HERE IF HAD SOME KIND OF ERROR:
RP2DER: CALL REDALL ;READ ALL REGISTERS AND SENSE BYTES
MOVX T1,IS.ERR ;GET ERROR FLAG
IORM T1,IRBSTS(P4) ;FLAG THIS IORB AS FAILED
RET ;FAIL RETURN
SUBTTL ROUTINE TO HANDLE ATTENTION INTERRUPTS
;ROUTINE CALLED ON AN ATTENTION INTERRUPT. SUCH INTERRUPTS OCCUR FOR
;THE FOLLOWING REASONS:
; 1. THE CURRENT DATA OPERATION TERMINATED WITH ERRORS. WE WILL FLAG
; THE FACT THAT AN ERROR OCCURED, AND WILL DISMISS THE INTERRUPT.
; A NORMAL INTERRUPT WILL IMMEDIATELY OCCUR, AND WE WILL BE RECALLED
; AT THE DX2INT ROUTINE, WHICH WILL NOTICE AND HANDLE THE ERROR.
; 2. THE DRIVE THAT A SEEK/SEARCH WAS OPERATION WAS GIVEN TO HAS
; DISCONNECTED ITSELF FROM THE CONTROLLER, SO THAT THE CONTROLLER
; IS NOW FREE TO ACCEPT MORE COMMANDS. IT IS POSSIBLE THAT THE
; SEEK/SEARCH HAS COMPLETED AT THIS TIME ALSO (BUT IS UNLIKELY).
; 3. ASYCHRONOUS STATUS FOR A DRIVE HAS APPEARED.
;
;CALL:
; P1/ CDB
; P2/ KDB
;RETURNS:
; +1: ALWAYS
; P3/ 0
; P4/ 0 (THIS INDICATES NO IORB WAS IN ERROR)
; Q1/ LEFT HALF SET TO -1 IF SCHEDULING DESIRED BECAUSE OF A
; COMPLETED SEEK OPERATION
DX2ATN: MOVEM Q1,K.SAVQ(P2) ;SAVE Q1 IN AN ACCESSIBLE LOCATION
PUSH P,Q2 ;SAVE ONE ON THE STACK TOO
MOVE Q2,K.DXAD(P2) ;SET UP DX20 UNIT NUMBER
MOVX T2,AT.0 ;GET ATTENTION BIT READY
LSH T2,(Q2) ;POSITION IT
TXO T2,.DXATN ;INSERT REGISTER NUMBER
CALL WTREG3 ;CLEAR THE ATTENTION
RDRG .DXCTL ;READ CONTROL REGISTER
TXNE T1,DX.GO ;CONTROLLER STILL BUSY?
JRST ATNXIT ;YES, IGNORE THIS INTERRUPT
CALL DOATTN ;CHECK ON NORMAL ATTENTIONS
CALL ASYNST ;THEN CHECK ON ASYCHRONOUS STATUS
ATNXIT: POP P,Q2 ;RESTORE ONE AC
MOVE Q1,K.SAVQ(P2) ;RESTORE Q1 WHICH MAYBE HAD LH SET TO -1
SETZB P3,P4 ;NO IORB ERRORS TO RETURN
RET ;DONE
;ROUTINE TO HANDLE NORMAL (NON ASYCHRONOUS) ATTENTION INTERRUPTS.
;DX20 UNIT NUMBER IS IN Q2.
DOATTN: SKIPN P3,KDBACT(P2) ;GET ACTIVE UDB IF ANY
RET ;NONE
MOVX T1,US.ACT ;VERIFY UDB IS REALLY ACTIVE
TDNN T1,UDBSTS(P3) ;WELL?
JRST [ CALL FNDCKU ;NO, COLLECT CKU NUMBERS
BUG.(CHK,DXBUNA,PHYP2,HARD,<PHYP2 - Attention interrupt and unit was not active>,<<T1,CHAN>,<T2,CTRL>,<T3,UNIT>>,<
Cause: An attention interrupt occurred for a DX20 drive but the unit
listed in the KDB as active is not.
Data: CHAN - Channel number
CTRL - Controller number
UNIT - Unit number
>) ;COMPLAIN
SETZB P3,KDBACT(P2) ;CLEAR ACTIVE UDB
RET] ;AND RETURN
RDRG .DXEND ;READ ENDING STATUS
TXNN T1,ES.CHE!ES.DVE!ES.UNC!ES.UNE ;DX20 HAVE STATUS FOR US?
RET ;NO, DON'T EXAMINE DRIVE YET
MOVE Q3,T1 ;SAVE STATUS
SKIPE T1,UDBERR(P3) ;DOING ERROR RECOVERY?
JRST ATNERC ;YES, NEED TO USE DISPATCH ADDRESS
CALL SETIRB ;GET THE CURRENT IORB
MOVX T2,US.POS ;GET READY FOR CHECK
TDNE T2,UDBSTS(P3) ;WAS THIS A POSITION OPERATION?
JRST ATNPOS ;YES, GO HANDLE IT
RET ;WAS FAILED DATA OPERATION, IGNORE ATTENTION
;SINCE DX2INT CODE WILL NOTICE ERROR
;HERE ON AN ATTENTION INTERRUPT DURING ERROR RECOVERY:
ATNERC: SKIPL T1,RP2FNC(T1) ;GET DISPATCH ADDRESS READY
TRNN T1,-1 ;DATA OPERATION OR NO DISPATCH ADDRESS?
RET ;YES, IGNORE INTERRUPT
CALL SETIRB ;GET THE CURRENT IORB
JRST (T1) ;THEN GO TO ROUTINE
;HERE ON AN ATTENTION CAUSED BY A POSITION DONE INTERRUPT:
ATNPOS: MOVX T1,KS.ACT ;GET ACTIVE FLAG FOR THE CONTROLLER
ANDCAM T1,KDBSTS(P2) ;CONTROLLER NO LONGER BUSY
SETZM KDBACT(P2) ;NO MORE ACTIVE UDB EITHER
TXNE Q3,ES.DVE!ES.UNC!ES.UNE ;DEVICE END UP OR ERRORS?
JRST ATNSRC ;YES, SEARCH IS FINISHED
HRROS K.SAVQ(P2) ;SEARCH STILL GOING, REMEMBER TO SCHEDULE
RET ;DONE
;HERE WHEN A POSITION REQUEST IS COMPLETED (SEARCH FOUND THE SPECIFIED
;SECTOR AND WE HAVE TO START I/O QUICKLY).
ATNSRC: TXNE Q3,ES.UNC!ES.UNE ;ANY UNIT ERROR?
JRST SRCBAD ;YES, GO GIVE SEARCH ERROR
CALLRET SRCDON ;NOPE, MARK SEARCH AS DONE
SUBTTL ROUTINE TO HANDLE ASYCHRONOUS STATUS
;THIS ROUTINE MUST BE CALLED AT THE END OF EVERY INTERRUPT (IF THE DX20
;IS NOT BUSY) TO LOOK FOR ASYCHRONOUS STATUS. THE DX20 GIVES US SUCH
;STATUS FOR A DRIVE WHICH COMES ONLINE OR HAS COMPLETED A SEARCH/SEEK.
;ASYCHRONOUS STATUS IS PRESENTED BY THE DX20 ONLY IF THE ATTENTION BIT
;AND THE ASYCHRONOUS REGISTER ARE BOTH CLEAR. THUS AFTER READING THE
;STATUS, WE HAVE TO ZERO THESE TO ALLOW MORE STATUS TO APPEAR. CALL:
; P1/ CDB
; P2/ KDB
;RETURNS:
; +1: ALWAYS
ASYNST: MOVE Q2,K.DXAD(P2) ;SET UP DX20 UNIT NUMBER
RDRG .DXASY ;READ ASYNCHRONOUS STATUS IF ANY
JUMPE T1,R ;NOTHING TO DO IF NO STATUS
MOVX T2,.DXASY ;SET UP IN CASE NEED TO READ IT AGAIN
TXNN T1,ES.CUE!ES.BSY!ES.CHE!ES.DVE!ES.UNC!ES.UNE ;STATUS YET?
CALL RDREG3 ;NO, READ AGAIN SINCE HE WASN'T YET DONE
PUSH P,Q3 ;SAVE AN AC
PUSH P,P3 ;AND ANOTHER ONE
PUSH P,P4 ;AND ANOTHER ONE
MOVE Q3,T1 ;MOVE STATUS TO SAFE PLACE
MOVX T2,AT.0 ;GET ATTENTION BIT
LSH T2,(Q2) ;POSITION FOR THIS DX20
TXO T2,.DXATN ;INSERT REGISTER NUMBER
CALL WTREG3 ;CLEAR ANY ATTENTION CAUSE BY THE STATUS
MOVX T2,.DXASY ;WANT TO CLEAR ASYCHRONOUS STATUS REGISTER
CALL WTREG3 ;CLEAR IT TO ALLOW NEW STATUS
LOAD T4,ASDRV,Q3 ;GET DRIVE PRESENTING CURRENT STATUS
CALL DRVSRC ;FIND THE UDB
JRST [ CALL NEWONL ;NOT FOUND, CREATE UDB IF POSSIBLE
JRST ASYNS2] ;AND FINISH UP
CALL ASYNDO ;FOUND IT, HANDLE STATUS FOR THE DRIVE
ASYNS2: POP P,P4 ;RESTORE AC
POP P,P3 ;RESTORE AC
POP P,Q3 ;AND ANOTHER
JRST ASYNST ;CHECK FOR MORE STATUS
;ROUTINE TO HANDLE ASYCHRONOUS STATUS FOR A PARTICULAR UNIT. CALL:
; P1/ CDB
; P2/ KDB
; P3/ UDB
; Q2/ DX20 NUMBER
; Q3/ ASYCHRONOUS STATUS FOR THIS DRIVE (FROM .DXASY REGISTER)
;RETURNS:
; +1: ALWAYS
ASYNDO: MOVE T2,UDBSTS(P3) ;GET STATUS
TXNN T2,US.ACT ;WERE WE EXPECTING AN INTERRUPT?
JRST ONLINE ;NO, GO SEE IF DRIVE IS USABLE AGAIN
SKIPE T1,UDBERR(P3) ;IN ERROR RECOVERY?
JRST ATNERC ;YES, GO TO SPECIAL CODE
CAMN P3,KDBACT(P2) ;GETTING STATUS FROM CURRENTLY ACTIVE UDB?
RET ;YES, IGNORE SINCE IT IS EXTRANEOUS
TXNN T2,US.POS ;DOING A SEEK FOR THIS DRIVE?
JRST [ CALL FNDCKU ;NO, COLLECT CKU NUMBERS
BUG.(CHK,DXBASD,PHYP2,HARD,<PHYP2 - Asynchronous status from non-positioning drive>,<<T1,CHAN>,<T2,CTRL>,<T3,UNIT>>,<
Cause: An asynchronous interrupt occurred from a DX20 drive that was not
in the process of doing a seek operation.
Data: CHAN - Channel number
CTRL - Controller number
UNIT - Unit number
>) ;COMPLAIN
RET] ;AND RETURN
CALL SETIRB ;YES, GET THE ACTIVE IORB
TXNE Q3,ES.DVE ;DEVICE END NOT SET?
TXNE Q3,ES.UNC!ES.UNE ;OR ANY UNIT ERRORS?
JRST SRCBAD ;YES, THEN HAVE A FAILED SEEK
;NOPE, THEN IS A FINISHED SEEK
;HERE WHEN A SEARCH HAS FINISHED SUCCESSFULLY:
SRCDON: HRRZM P4,CDBIRB(P1) ;WE WANT TO START TRANSFERS ON THIS IORB
AOS UDBSEK(P3) ;INCREMENT SEEKS (SEARCHES) DONE
CALL PHYSDN ;INFORM PHYSIO SEARCH IS DONE
HRROS K.SAVQ(P2) ;REMEMBER TO SCHEDULE MORE STUFF
RET ;DONE
;HERE IF HAD AN ERROR ON A SEARCH OPERATON. THE CURRENT WORKINGS OF PHYSIO
;DO NOT ALLOW SEEK ERRORS TO BE RETURNED FOR INDIVIDUAL UNITS OF A CONTROLLER.
;THEREFORE MAKE A SYSERR ENTRY, COUNT SEEK ERRORS, BUT MARK THE IORB AS
;SUCCESSFUL. THE FOLLOWING TRANSFER WILL THEN DO AN IMPLIED SEEK, WHICH
;WILL CATCH THE ERROR IF IT WAS HARD.
SRCBAD: AOS UDBSPE(P3) ;CALL THIS A SOFT POSITIONING ERROR
CALL ERRSET ;ALLOCATE AN ERROR BLOCK
SKIPN Q1,T1 ;MOVE ADDRESS TO RIGHT AC
JRST SRCDON ;IF NO SYSERR BLOCK, ACT LIKE SEARCH IS DONE
MOVEM Q1,UDBERP(P3) ;SAVE ADDRESS IN THE UDB
PUSH P,IRBSTS(P4) ;REMEMBER CURRENT STATUS OF IORB
MOVX T1,IS.ERR!IS.DVE ;GET SOME ERROR FLAGS
IORM T1,IRBSTS(P4) ;PLACE INTO IORB TEMPORARILY FOR LOGGING
CALL REDALL ;READ ALL REGISTERS AND SENSE BYTES
CALL RDRINI ;STORE THEM INTO SYSERR BLOCK
CALL RDRFIN ;MAKE THEM THE FINAL REGISTERS ALSO
CALL ERRFIN ;TERMINATE ERROR LOGGING
POP P,IRBSTS(P4) ;RESTORE ORIGINAL FLAGS
JRST SRCDON ;THEN ACT LIKE SEARCH WAS SUCCESSFUL
;ROUTINES TO HANDLE ON-LINE TRANSITIONS, EITHER FROM AN OLD EXISTENT DRIVE
;OR FROM A TOTALLY UNKNOWN DRIVE. IF CALLED FOR AN UNKNOWN DRIVE, WE
;HAVE TO BUILD A UDB FOR THE UNIT.
NEWONL: TXNE Q3,ES.DVE ;DEVICE END UP?
TXNE Q3,ES.UNC!ES.UNE ;AND NO ERRORS DETECTED?
RET ;NO, DON'T CREATE UDB THEN
PUSH P,Q3 ;PRESERVE DRIVE NUMBER AND STATUS
PUSH P,P5 ;SAVE SOME ACS
PUSH P,Q1 ;THAT WILL BE USED
LOAD Q1,ASDRV,Q3 ;GET UNIT NUMBER
TLO Q1,-1 ;CREATE AOBJN WORD FOR THIS UNIT ONLY
MOVX P5,US.OFS ;BEGIN STATUS WITH DRIVE OFF-LINE
SETZ Q3, ;PREVENT A BUGCHK ON SICK DRIVES
CALL ISDRV ;TRY TO BUILD A NEW UDB FOR THIS DRIVE
POP P,Q1 ;RESTORE ACS
POP P,P5 ;THAT WE SAVED
POP P,Q3 ;RESTORE UNIT NUMBER AND STATUS
LOAD T4,ASDRV,Q3 ;GET DRIVE NUMBER
CALL DRVSRC ;NOW SEE IF THE UDB GOT BUILT
RET ;NOPE, IGNORE IT
;YES, NOW FALL INTO NORMAL ON-LINE CODE
ONLINE: MOVX T1,US.WLK ;ASSUME DRIVE IS WRITABLE AGAIN
ANDCAB T1,UDBSTS(P3) ;SO CLEAR WRITE LOCK AND GET OTHER BITS
TXNE Q3,ES.DVE ;HAVE DEVICE END?
TXNE Q3,ES.UNC!ES.UNE ;AND NO ERROR BITS?
RET ;NO, DRIVE IS STILL OFF-LINE THEN
TXNN T1,US.OFS ;DID WE THINK THE DRIVE WAS OFF-LINE?
RET ;NO, IGNORE SPURIOUS STATUS THEN
MOVX T1,US.CHB ;YES, NEED TO DO
IORM T1,UDBSTS(P3) ; HOMEBLOCK CHECK
CALL PHYONL ;MARK THE DEVICE ON-LINE AGAIN
HRROS K.SAVQ(P2) ;REMEMBER TO TELL PHYSIO TO SCHEDULE
RET ;DONE
SUBTTL ROUTINE TO CHECK FOR DATA ERRORS
;ROUTINE TO SEE IF A TRANSFER OPERATION HAD ANY DRIVE OR CONTROLLER
;ERRORS. CALL:
; P1/ CDB
; P2/ KDB
; P3/ UDB
; P4/ IORB
;RETURNS:
; +1: ERRORS FOUND AND FLAGGED
; +2: NO ERRORS FOUND OR OF NO IMPORTANCE
HARCHK: MOVX T1,IS.DVE!IS.DTE ;GET IORB ERROR BITS
ANDCAM T1,IRBSTS(P4) ;CLEAR THEM TO BEGIN
MOVX T2,.DXERR ;SET UP TO READ ERROR REGISTER
CALL RDREG ;READ IT
TXNN T1,ER.ALL ;ANY ERRORS?
RETSKP ;NO, SUCCESSFUL RETURN
TXNE T1,ER.STP!ER.MPE ;DX20 HALTED OR HAS MEMORY PROBLEMS?
JRST ISDEAD ;YES, GO MARK THE CONTROLLER DOWN
TXNE T1,ER.ILF!ER.ILR ;ILLEGAL FUNCTION OR REGISTER?
JRST ISHARD ;YES, CALL THIS A HARD ERROR
TXNE T1,ER.RMR!ER.CPE!ER.DPE ;RMR ERROR OR BUS PARITY ERRORS?
JRST ISFAIL ;YES, TRY THE OPERATION AGAIN
LOAD T2,ERCOD,T1 ;GET POSSIBLE ERROR CODE
TXNE T1,ER.NEW ;NO ERROR CODE STORED?
CAILE T2,ERCMAX ;OR CODE IS OUT OF RANGE?
MOVEI T2,0 ;YES, TURN INTO CODE ZERO FOR UNKNOWN
CALL @ERCTAB(T2) ;DISPATCH ON ERROR CODE TYPE
RET ;ERROR RETURN
RETSKP ;SUCCESS RETURN
;DISPATCH TABLE FOR ERROR CLASS CODES. CODE IS OBTAINED FROM THE
;ERCOD FIELD OF THE ERROR REGISTER (.DXERR). THIS FIELD IS VALID ONLY
;IF THE ER.NEW FLAG IS SET IN THE ERROR REGISTER.
ERCTAB: IFIW ISUNKN ;(0) ILLEGAL OR UNKNOWN ERROR
IFIW ISUNUS ;(1) UNUSUAL DEVICE STATUS
IFIW ISIGNR ;(2) RECORD LENGTH ERROR
IFIW ISOFFL ;(3) DRIVE SELECTION ERROR
IFIW ISFAIL ;(4) RECOVERABLE ERROR
IFIW ISRETY ;(5) COMMAND RETRY REQUEST
IFIW ISFAIL ;(6) NON-RECOVERABLE ERROR
IFIW ISIGNR ;(7) RETRY LOG INFORMATION AVAILABLE
IFIW ISDEAD ;(10) FATAL ERRORS
ERCMAX==.-ERCTAB-1 ;HIGHEST KNOWN ERROR CODE
;HERE WHEN THE ERROR IS UNKNOWN:
ISUNKN: HRRZ T2,CDBADR(P1) ;GET CHANNEL
BUG.(CHK,DXBIEC,PHYP2,SOFT,<PHYP2 - Unknown error code from DX20>,<<T2,CHAN>,<Q2,DX20>,<T1,STATUS>>,<
Cause: A transfer operation on a RP20 drive had drive failed. This
indicates a drive or controller error but the error code provided
by the DX20 is not valid.
Data: DX20 - DX20 number
STATUS - DX20 error register
>) ;COMPLAIN
JRST ISHARD ;AND MAKE THIS A HARD ERROR
;HERE TO HANDLE UNUSUAL DEVICE STATUS (ERROR CLASS 1). THIS IS THE
;NORMAL ERROR CODE FOR TYPICAL DEVICE AND DATA ERRORS. INFORMATION ON
;THE PARTICULAR ERROR IS OBTAINED FROM THE ENDING STATUS REGISTER AND
;THE SENSE BYTES.
ISUNUS: MOVX T2,.DXEND ;WANT TO READ ENDING STATUS
CALL RDREG ;DO IT
TXNE T1,ES.BSY ;IS CONTROLLER BUSY?
JRST ISFAIL ;YES, VERY OBSCURE, RETRY IT
TXNN T1,ES.UNC!ES.UNE ;UNIT CHECK OR EXCEPTION?
JRST ISIGNR ;NO, IGNORE SPURIOUS ERROR
CALL REDALL ;READ ALL REGISTERS AND CLEAR ERRORS
MOVE T2,K.DEXS(P2) ;GET SENSE BYTES 0 THROUGH 3
TXNE T2,S0.IVR ;INTERVENTION REQUIRED?
JRST ISOFF2 ;YES, MARK DRIVE OFF-LINE
TXNE T2,S0.REJ ;COMMAND REJECTED?
JRST ISRJEC ;YES, GO SEE IF WRITE-LOCKED
LOAD T1,SBECOD ;GET ERROR FORMAT AND MESSAGE
CAIL T1,FC.IVC ;FORMAT 0, MESSAGE 1 THRU
CAILE T1,FC.FPR ;FORMAT 0, MESSAGE A ARE DEVICE ERRORS
SKIPA
CALLRET ISFAI2 ;RETRY AS DEVICE ERROR
LSH T1,-4 ;GET FORMAT NUMBER
CAIN T1,2 ;FORMAT 2 ARE DCU ERRORS
CALLRET ISFAI2 ;RETRY AS DEVICE ERROR
TXNE T2,S0.BPE!S1.FPE!S1.WLK ;CHECK FOR OTHER POSSIBLE DEVICE ERRORS
CALLRET ISFAI2 ;RETRY AS DEVICE ERRORS.
CALLRET ISDATC ;FLAG ALL OTHERS AS DATA CHECKS.
;HERE IF THE DRIVE HAS GONE OFF-LINE:
ISOFFL: CALL REDALL ;READ ALL REGISTERS AND CLEAR THE ERROR
ISOFF2: CALL PHYOFL ;MARK THE DRIVE OFF-LINE
JRST ISFAI2 ;CALL IT A RECOVERABLE ERROR, SO ON THE
;NEXT RETRY THE UNIT WILL BE MARKED AS
;WAITING FOR OPERATOR INTERVENTION
;HERE IF THE COMMAND WAS REJECTED, PROBABLY DUE TO A WRITE-LOCKED DRIVE.
;IF SO, CLEAR THE ACTIVE STATUS OF THE IORB AND REQUEST ANOTHER SCHEDULER
;CYCLE, WHICH WILL THEN MARK THE DRIVE AS NEEDING OPERATOR INTERVENTION.
;THE DRIVE WILL STAY THAT WAY UNTIL RANDOM ASYCHRONOUS STATUS APPEARS DUE
;TO THE OPERATOR HITTING THE ATTN BUTTON OR POWERING UP THE DRIVE. THIS
;ROUNDABOUT PROCEDURE IS NECESSARY BECAUSE YOU CAN'T TELL IF AN RP20 IS
;WRITE-LOCKED WITHOUT ACTUALLY TRYING TO WRITE ON IT!!!
ISRJEC: TXNN T2,S1.WLK ;IS DRIVE REALLY WRITE-LOCKED?
JRST ISFAI2 ;NO, GO TO NORMAL ERROR STUFF
SKIPE UDBERR(P3) ;YES, SEE IF IN MIDDLE OF ERROR RECOVERY
JRST ISHAR2 ;IF SO, DON'T CONFUSE THINGS!
MOVX T1,IS.WLK ;GET FLAG READY
IORM T1,IRBSTS(P4) ;REMEMBER IN IORB FOR STATUS WATCHERS
MOVX T1,US.WLK ;GET WRITE-LOCK FLAG FOR UDB
IORM T1,UDBSTS(P3) ;PREVENT ANY FURTHER WRITES FOR THIS UNIT
CALL CLRACT ;MARK THE DRIVE IDLE
SETZM P3 ;FORGET ABOUT THIS UNIT
SETOM P4 ;REQUEST A SCHEDULER CYCLE
RET ;AND STOP STACKED COMMAND BY DOING ERROR RETURN
;HERE ON A NORMAL DATA CHECK ERROR:
ISDATC: MOVX T1,IS.DTE!IS.ERR ;GET ERROR FLAGS
IORM T1,IRBSTS(P4) ;FLAG THAT A DATA ERROR OCCURRED
MOVX T1,UE.DAT ;GET ANOTHER FLAG
IORM T1,UDBERR(P3) ;REMEMBER IN UDB ALSO
RET ;RETURN ERROR
;HERE IN CASES WHERE THE OPERATION FAILED DUE TO SOME DEVICE ERROR,
;BUT THERE IS REASON TO THINK THAT RETRYING THE OPERATION MIGHT WIN.
ISFAIL: CALL REDALL ;READ IN REGISTERS AND CLEAR THE ERROR
ISFAI2: MOVX T1,UE.DEV ;GET FLAG READY
IORM T1,UDBERR(P3) ;REMEMBER THAT THIS IS A DEVICE ERROR
MOVX T1,IS.ERR!IS.DVE ;GET IORB FLAGS
IORM T1,IRBSTS(P4) ;MARK THE ERROR IN THE IORB
RET ;DONE
;HERE FOR RETRY REQUEST ERROR (ERROR CLASS 5).
;
;AS OF DXMCE MICROCODE EDIT 16 WE WILL APPEAR HERE UNDER THE FOLLOWING:
;1. A DATA ERROR OR OVERRUN OCCURED THAT THE DX CANNOT RETRY BECAUSE THE
; DATA PATH WAS REQUIRED. CHANNEL HAS ABORTED CONNECTION.
;2. A DATA ERROR OR OVERRUN OCCURED IN THE COUNT/KEY FIELDS, THE DX HAS
; RETRIED 39 TIMES WITHOUT SUCCESS.
;3. AN ERROR OCCURED AS IN 2, DX RECOVERED ONLY TO FIND AN ERROR IN THE
; DATA FIELD. COULD BE ECC RECOVERABLE.
;
;NOTE THAT THE CHANNEL ABORT REQUEST IS IGNORED. THE CHANNEL CONNECTION
;IS ALWAYS ABORTED ON A RETRY.
ISRETY: CALL REDALL ;READ SENSE INFORMATION
MOVE T1,K.DCNI(P2) ;GET CONI STATUS WORD
TXNE T1,CI.OVR ;IF DUE TO OVERRUN
CALLRET ISFAI2 ;THEN RETRY AS DEVICE ERROR
CALLRET ISDATC ;FLAG AS DATA ERROR
;HERE ON ERROR CONDITIONS WHICH ARE NOT REALLY ERRORS, OR WHICH ARE
;DETECTED ELSEWHERE (SUCH AS OVERRUNS). JUST CLEAR THE ERROR REGISTER
;AND SAY THE OPERATION SUCCEEDED.
ISIGNR: MOVX T2,.DXERR ;GET ERROR REGISTER
CALL WTREG ;CLEAR IT OUT
RETSKP ;RETURN SAYING NO ERRORS FOUND
;HERE ON FATAL ERRORS WHICH INDICATE THAT THE MICROPROCESSOR IS
;MALFUNCTIONING. COMPLAIN AND MARK THE CONTROLLER AS HALTED.
ISDEAD: CALL REGALL ;READ THE MASSBUSS REGISTERS ONLY
MOVX T2,.DXMAI!MR.RES ;GET READY TO STOP THE PROCESSOR
CALL WTREG ;MAKE SURE IT IS STOPPED
MOVX T1,KS.HLT ;GET HALT FLAG
IORM T1,KDBSTS(P2) ;REMEMBER THAT THE CONTROLLER IS DEAD
HRRZ T1,CDBADR(P1) ;GET CHANNEL NUMBER
BUG.(CHK,DXBDIE,PHYP2,HARD,<PHYP2 - DX20B microcode halted>,<<T1,CHAN>,<Q2,DX20>>,<
Cause: The microcode in a DX20B has halted. This indicates a hardware
problem with the DX20 microprocessor.
Action: Contact Field Service.
Data: CHAN - Channel number
DX20 - DX20 number
>) ;COMPLAIN THAT THE DX20 DIED
JRST ISHAR2 ;KILL REQUEST
;HERE ON DEVICE ERRORS WHICH WE CANNOT EXPECT TO RECOVER FROM. FLAG
;THE ERROR AS FATAL.
ISHARD: CALL REDALL ;READ IN ALL REGISTERS
ISHAR2: MOVX T1,IS.DVE!IS.ERR!IS.NRT ;GET FLAGS FOR FATAL ERROR
IORM T1,IRBSTS(P4) ;MARK THEM IN THE IORB
MOVX T1,UE.HRD!UE.DEV ;GET HARD ERROR AND DEVICE ERROR FLAGS
IORM T1,UDBERR(P3) ;REMEMBER IN THE UDB
RET ;ERROR RETURN
SUBTTL ERROR RECOVERY
;ROUTINE CALLED BY PHYSIO TO RECOVER FROM ERRORS. THIS ROUTINE IS CALLED
;IN THE FOLLOWING CASES:
; 1. WHEN A NEW OPERATION FAILED, AFTER THE INITIAL ERROR STATUS
; AND CAUSE HAS BEEN SAVED.
; 2. ON EACH RETRY OPERATION THEREAFTER, EVEN IF THE RETRY SUCCEEDED.
; IS.ERR WILL BE SET IN THE IORB IF THE OPERATION FAILED. IF IS.ERR
; IS NOT SET, THEN WE HAVE RECOVERED AND THE ERROR WAS SOFT.
;RETURNS:
; +1: ERROR RECOVERY STILL IN PROGRESS
; +2: ERROR RECOVERY IS FINISHED (IS.ERR SET IF UNSUCCESSFUL)
DX2ERR: SAVEQ ;SAVE REGISTERS
HRRZ Q1,UDBERP(P3) ;GET ERROR BLOCK (IF ANY)
MOVE Q2,UDBSTS(P3) ;GET UDB STATUS
AOS Q3,UDBERC(P3) ;INCREMENT RETRY COUNTER
CAIN Q3,1 ;FIRST TIME?
CALL RDRINI ;YES, COPY INITIAL REGISTERS
MOVE T1,IRBSTS(P4) ;GET STATUS OF IORB
TXNE T1,IS.IER!IS.NRT ;ERROR RECOVERY INHIBITED OR NO MORE RETRIES?
JRST HRDERR ;YES, THIS ERROR IS HARD THEN
TXNN T1,IS.ERR ;DID THE LAST RETRY SUCCEED?
JRST SFTERR ;YES, THIS WAS A SOFT ERROR
TXNE Q2,US.POS ;ERROR DURING A TRANSFER?
JRST POSERR ;NO, GO HANDLE POSITIONING ERROR
MOVE T1,UDBERR(P3) ;TRANSFER ERROR, GET ERROR STATUS
TXNN T1,UE.DEV ;DEVICE ERROR?
TXNN T1,UE.DAT ;OR NOT A DATA ERROR?
JRST DEVERR ;YES, A DEVICE ERROR
LDB T1,IRYFCN ;GET FUNCTION FROM IORB
LOAD T2,SBECOD ;AND ERROR CLASS CODE FROM 7TH SENSE BYTE
CAIN T1,IRFRED ;WAS THIS A VANILLA READ OPERATION?
CAIE T2,FC.ECC ;AND DOES THE DX20 THINK IT'S ECC CORRECTABLE?
JRST DATERR ;NO, JUST PLAIN DATA ERROR THEN
LOAD Q3,SBEPOS ;YES, GET ECC POSITION FROM BYTES 18 AND 19
CAILE Q3,BYTSEC ;REASONABLE ECC POSITION?
JRST DATERR ;NO, TREAT AS NORMAL DATA ERROR
JRST ECCERR ;YES, GO DO THE ECC CORRECTION
;HERE ON A DEVICE ERROR DURING A SEARCH OR SEEK OPERATION. WE DO NOT
;GENERATE SEEK ERRORS, SO THAT SUPPOSEDLY IT IS IMPOSSIBLE TO GET HERE.
;THEREFORE, JUST GIVE A HARD ERROR WITHOUT RETRYING.
POSERR: MOVX T1,UE.POS!UE.DEV ;MARK A POSITIONING ERROR
IORM T1,UDBERR(P3) ;IN THE UDB ERROR LOCATION
MOVX T1,IS.DVE ;MARK A DEVICE ERROR
IORM T1,IRBSTS(P4) ;IN THE IORB STATUS
JRST HRDERR ;AND CAUSE A HARD ERROR
;HERE TO HANDLE DEVICE OR SIMPLE DATA ERRORS FROM A DATA TRANSFER OPERATION.
;FLAG THE ERROR AND INITIATE THE NEXT STEP IN ERROR RECOVERY. THE ALGORITHM
;IS SIMPLE, SINCE THERE ARE NO FANCY OFFSETS OR SUCH TO TRY. JUST TRY THE
;OPERATION OVER AGAIN MANY TIMES, WITH OCCASIONAL RECALIBRATIONS.
DATERR: MOVX T1,UE.DAT ;GET DATA ERROR FLAG
MOVX T2,IS.DTE ;ANOTHER ONE TOO
JRST ERR ;JOIN OTHER CODE
DEVERR: MOVX T1,UE.DEV ;GET DEVICE ERROR FLAG
MOVX T2,IS.DVE ;AND ANOTHER ONE
ERR: IORM T1,UDBERR(P3) ;FLAG THE ERROR IN THE UDB
IORM T2,IRBSTS(P4) ;AND IN THE IORB
MOVE T1,UDBERC(P3) ;GET CURRENT RETRY COUNT
IDIVI T1,RTYCNT ;SPLIT INTO TWO NUMBERS
JUMPN T2,RETRY ;DO STRAIGHT RETRY MOST OF THE TIME
CAIG T1,RCLCNT ;RECALIBRATION TIME, MORE TO DO?
JRST RECAL ;YES, GO DO ONE
JRST HRDERR ;NO, GIVE UP
;HERE ON A DATA ERROR WHICH IS ECC CORRECTABLE. TO CORRECT AN ECC ERROR,
;THE DX20 PROVIDES THE FOLLOWING INFORMATION IN THE SENSE BYTES:
; 18-19 FIRST BYTE IN ERROR COUNTED FROM THE LAST BYTE IN THE SECTOR
; (FROM 0 TO ^D2304). ZERO MEANS THE ERROR WAS IN THE ECC BYTE
; ITSELF, AND THEREFORE THE DATA IS ACTUALLY OK.
; 20-21 MASK WHICH WHEN XORED WITH THE DATA ACTUALLY READ WILL
; CORRECT THE DATA.
;SENSE BYTES 18-19 ARE ALREADY IN AC Q3.
ECCERR: JUMPE Q3,ECCER2 ;SKIP ON IF ERROR WAS IN ECC BYTE
MOVNI T1,-BYTSEC(Q3) ;COMPUTE BYTES FROM START OF PAGE
LSH T1,3 ;CONVERT TO BITS
TLZ T1,-1 ;CLEAR JUNK
IDIVI T1,^D36 ;COMPUTE OFFSET IN SECTOR AND POSITION IN WORD
MOVE Q3,T1 ;SAVE OFFSET IN SECTOR
MOVNI T2,-^D<36-16>(T2) ;COMPUTE SHIFT VALUE FOR MASK
LOAD P5,SBEMSK ;GET THE ECC MASK FROM BYTES 20 AND 21
SKIPN P5 ;MASK SHOULD BE NONZERO
BUG.(CHK,DXBZEC,PHYP2,HARD,<PHYP2 - Zero ECC byte returned>,,<
Cause: An ECC correctable error occurred on a DX20 drive. The byte number
in error in the sector was zero. This indicates the error was in
the ECC byte itself and the data is actually correct.
>) ;NOPE, THEN WHY WERE WE CALLED?
SETZ P6, ;CLEAR SECOND WORD OF MASK
LSHC P5,(T2) ;SHIFT MASK TO PROPER POSITION
CALL ECCADR ;GET ADDRESS OF BEGINNING OF SECTOR TRANSFERED
ADDI T1,(Q3) ;POINT TO ADDRESS OF FIRST WORD TO BE FIXED
JUMPE P5,ECCER1 ;SKIP SOME IF NO CORRECTION NECESSARY
CALL PHYMOV ;GET THE DATA WORD
XOR T2,P5 ;APPLY THE ECC MASK TO THE WORD
CALL PHYSTO ;AND STORE BACK THE CORRECTED DATA
ECCER1: JUMPE P6,ECCER2 ;SKIP SOME IF NO CORRECTION NECESSARY
ADDI T1,1 ;INCREMENT TO SECOND WORD
CALL PHYMOV ;GET THE DATA WORD
XOR T2,P6 ;APPLY THE ECC MASK TO THE WORD
CALL PHYSTO ;AND STORE BACK THE CORRECTED DATA
ECCER2: CALL ECCUCL ;UPDATE CCW LIST, RETURN WORDS TRANSFERED OK
JRST ECCDON ;WAS IN LAST SECTOR, FINISH UP
BUG.(HLT,DXBMSR,PHYP2,SOFT,<PHYP2 - Multiple sectors indicated in ECC recovery>,,<
Cause: The routine ECCERR in PHYP2 was called to recover from an ECC error
on a unit. After correcting the error, the routine ECCUCL in PHYSIO
was called to update the CCW list. That routine skipped, indicating
that more sectors must be read to complete the transfer. However,
the RP20 is formatted in pages and no transfer is ever longer than
a page, so the skip return should never occur.
>) ;NEVER GET HERE SINCE ALWAYS READING ONE SECTOR
ECCDON: MOVX T1,UE.ECC ;GET ERROR FLAG
IORM T1,UDBERR(P3) ;REMEMBER WE HAD AN ECC-CORRECTABLE ERROR
MOVX T1,IS.ERR!IS.DTE ;GET ERROR BIT IN IORB
ANDCAM T1,IRBSTS(P4) ;AND CLEAR IT SINCE WE RECOVERED
AOS UDBSRE(P3) ;INCREMENT SOFT READ ERROR COUNTER
RETSKP ;SKIP RETURN TO SAY ALL DONE
;HERE IF THE LAST RETRY SUCCEEDED SO THAT THE ERROR WAS SOFT:
SFTERR: MOVEI T1,T1 ;PROTECT IN CASE NOTHING MATCHES
LDB T2,IRYFCN ;GET FUNCTION FROM IORB
CAIE T2,IRFRVC ;READ VALIDITY CHECK?
CAIN T2,IRFRED ;READ?
MOVEI T1,UDBSRE(P3) ;YES, POINT TO SOFT READ COUNTER
CAIE T2,IRFWVC ;WRITE VALIDITY CHECK?
CAIN T2,IRFWRT ;WRITE?
MOVEI T1,UDBSWE(P3) ;YES, POINT TO SOFT WRITE COUNTER
TXNE Q2,US.POS ;WAS THIS A SEEK OPERATION?
MOVEI T1,UDBSPE(P3) ;YES, POINT TO SOFT POSITION COUNTER
AOS (T1) ;INCREMENT PROPER COUNTER
CALL RDRFIN ;READ FINAL REGISTERS NOW
RETSKP ;SKIP RETURN TO INDICATE RECOVERY FINISHED
;HERE ON A HARD ERROR WHEN NO AMOUNT OF RETRIES SUCCEEDED, OR IF
;ERROR RECOVERY WAS INHIBITED:
HRDERR: MOVX T1,IS.ERR!IS.NRT ;INDICATE HARD ERROR WITH NO RETRIES
IORM T1,IRBSTS(P4) ;PUT IN IORB
MOVX T1,UE.HRD ;GET HARD ERROR FLAG
IORM T1,UDBERR(P3) ;REMEMBER IN ERROR WORD
MOVEI T1,T1 ;PROTECT IN CASE OF NO MATCH
LDB T2,IRYFCN ;GET FUNCTION FROM IORB
CAIE T2,IRFRVC ;READ VALIDITY?
CAIN T2,IRFRED ;READ?
MOVEI T1,UDBHRE(P3) ;YES, POINT TO HARD READ COUNTER
CAIE T2,IRFWVC ;WRITE VALIDITY CHECK?
CAIN T2,IRFWRT ;WRITE?
MOVEI T1,UDBHWE(P3) ;YES, POINT TO HARD WRITE COUNTER
TXNE Q2,US.POS ;POSITIONING?
MOVEI T1,UDBHPE(P3) ;YES, POINT TO HARD POSITIONING COUNTER
AOS (T1) ;INCREMENT COUNTER
CALL RDRFIN ;READ FINAL REGISTERS
RETSKP ;SKIP RETURN TO INDICATE ALL DONE
;HERE TO RECALIBRATE A DRIVE AFTER MANY UNSUCCESSFUL OPERATIONS:
RECAL: MOVEI T1,RCLNDX ;GET INDEX FOR RECALIBRATION
HRRM T1,UDBERR(P3) ;REMEMBER FUNCTION FOR ERROR RECOVERY
CALL SETIO ;MARK THE IORB ACTIVE
HRRZ T1,UDBERR(P3) ;GET FUNCTION BACK
LOAD Q1,TBFNC,(T1) ;TRANSLATE TO HARDWARE FUNCTION
MOVE Q2,K.DXAD(P2) ;SET UP DX20 UNIT NUMBER
CALL DX2CON ;CONNECT TO THE DRIVE
JRST HRDERR ;FAILED, CALL THE ERROR HARD
CALL DOPOS ;START THE OPERATION
JFCL ;CHSTRT ALWAYS SKIPS
RET ;DONE
;HERE ON THE ATTENTION INTERRUPT AFTER THE RECAL IS INITIATED. SEE
;IF THE OPERATION IS TOTALLY FINISHED. IF NOT, WE HAVE TO WAIT FOR
;THE ASYCHRONOUS STATUS TO APPEAR.
RTYRCL: TXNE Q3,ES.DVE!ES.UNC!ES.UNE ;IS OPERATION COMPLETE?
JRST RCLFIN ;YES, SKIP ONWARD
MOVEI T1,RC2NDX ;NO, GET FUNCTION CODE READY
HRRM T1,UDBERR(P3) ;CHANGE DISPATCH FOR NEXT INTERRUPT
SETZM P4 ;WANT TO WAIT FOR ASYCHRONOUS STATUS
RET ;RETURN
;HERE WHEN DEVICE END IS UP, EITHER FROM THE INITIAL ATTENTION
;INTERRUPT, OR ON THE ASYCHRONOUS STATUS INTERRUPT. GO BACK
;AND RETRY THE OPERATION WHICH FAILED.
RCLFIN: MOVX T1,US.POS ;SEE IF ORIGINAL OPERATION WAS A SEARCH
TDNN T1,UDBSTS(P3) ;WAS IT?
JRST RETRY ;NO, THEN GO RESTART A TRANSFER OPERATION
JRST HRDERR ;YES, CALL IT A HARD ERROR THEN
;HERE TO RETRY A TRANSFER OPERATION:
RETRY: HRRZ Q1,UDBSTS(P3) ;GET ERROR BLOCK IF PRESENT
LDB T1,IRYFCN ;GET ORIGINAL OPERATION
HRRM T1,UDBERR(P3) ;REMEMBER FUNCTION FOR ERROR RECOVERY
CALL SETIO ;MARK THE IORB ACTIVE
HRRZ T1,CDBDSP(P1) ;GET CHANNEL DISPATCH
CALL CDSSIO(T1) ;TRY TO RESTART THE I/O
JRST HRDERR ;FAILED, CALL IT HARD ERROR
SETZM P4 ;WANT TO DISMISS THIS INTERRUPT
RET ;DONE
SUBTTL SUBROUTINES TO LOAD UP THE SYSERR BLOCKS
;RDRINI - ROUTINE CALLED ON FIRST ERROR TO LOAD UP THE SYSERR BLOCK.
;THE MASSBUSS REGISTERS AND DX20 SENSE BYTES HAVE ALREADY BEEN SAVED
;IN THE KDB. THIS ROUTINE COPIES THEM INTO THE SYSERR BLOCK AS THE
;INITIAL STATUS FOR THE ERROR.
RDRINI: JUMPE Q1,R ;CAN'T DO THIS IF NO ERROR BLOCK
MOVE T1,Q1 ;COPY ADDRESS OF BLOCK
MOVE T2,[-NEDAT,,EDAT] ;SET UP POINTER TO CONTROL TABLE
CALL SEBCPY ;COPY THE DATA
JFCL ;FAILURE
CALL PHYBLK ;GET PHYSICAL ADDRESS
TXZ T2,IRBPAD ;REMOVE PHYSICAL ADDRESSING BIT
MOVEM T2,SEBDAT+MB%LOC(Q1) ;SAVE IT
MOVE T1,[REGNUM,,DX%MBR] ;GET COUNT AND OFFSET READY
MOVEM T1,SEBDAT+DX%MBI(Q1) ;SAVE POINTER TO MASSBUS REGISTERS
MOVE T1,[<<SNSNUM+3>/4>,,DX%ESR] ;GET OTHER COUNT READY TOO
MOVEM T1,SEBDAT+DX%ESI(Q1) ;SAVE POINTER TO SENSE BYTE REGISTERS
MOVEI T1,SEBDAT+DX%MBR(Q1) ;POINT TO STORAGE AREA FOR REGISTERS
MOVE T2,T1 ;COPY ADDRESS
HRLI T1,K.DREG(P2) ;INSERT SOURCE ADDRESS FOR BLT
BLT T1,REGNUM+<<SNSNUM+3>/4>-1(T2) ;MOVE TO SYSERR BLOCK
RET ;DONE
;TABLE OF DATA TO COPY AT INITIAL ERROR RECOVERY TIME:
EDAT: SEBPTR MB%CNI,SBTWD,K.DCNI(P2) ;CONI
SEBPTR MB%D1I,SBTWD,K.DCS1(P2) ;TCR
SEBPTR MB%D2I,SBTWD,K.DDBF(P2) ;BAR/DBF
SEBPTR MB%CS0,SBTWD,CDBCS0(P1) ;CHANNEL STATUS 0
SEBPTR MB%CS1,SBTWD,CDBCS1(P1) ;CHANNEL STATUS 1
SEBPTR MB%CS2,SBTWD,CDBCS2(P1) ;CHANNEL STATUS 2
SEBPTR MB%CC1,SBTWD,CDBCC1(P1) ;CCW 1
SEBPTR MB%CC2,SBTWD,CDBCC2(P1) ;CCW 2
SEBPTR MB%ICR,SBTWD,CDBICR(P1) ;INITIAL CONTROL REGISTER
NEDAT==.-EDAT ;NUMBER OF ENTRIES IN TABLE
;RDRFIN - ROUTINE TO STORE REGISTERS AT END OF RETRY. CALLED AT THE END
;OF ERROR RECOVERY TO COPY THE FINAL MASSBUSS REGISTER VALUES INTO THE
;SYSERR BLOCK ALONGSIDE THE INITIAL REGISTERS. THE FINAL REGISTERS HAVE
;ALREADY BEEN READ INTO THE KDB.
RDRFIN: HRRZ Q1,UDBERP(P3) ;GET ERROR BLOCK AGAIN IF ANY
JUMPE Q1,R ;DONE IF NO BLOCK
MOVEI T1,K.DREG(P2) ;POINT TO REGISTERS TO SAVE
HRLI T1,-REGNUM ;INSERT COUNTER FOR LOOP
MOVEI T2,SEBDAT+DX%MBR(Q1) ;POINT TO STORAGE IN SYSERR BLOCK
RDRFIL: MOVE T3,(T1) ;GET REGISTER
HRLM T3,(T2) ;SAVE AWAY ALONGSIDE INITIAL VALUE
ADDI T2,1 ;INCREMENT TO NEXT ADDRESS
AOBJN T1,RDRFIL ;LOOP OVER ALL REGISTERS
MOVE T1,K.DCNI(P2) ;GET FINAL CONI
MOVEM T1,SEBDAT+MB%CIF(Q1) ;SAVE IN SYSERR BLOCK
MOVE T1,K.DCS1(P2) ;GET FINAL TCR
MOVEM T1,SEBDAT+MB%D1F(Q1) ;SAVE
MOVE T1,K.DDBF(P2) ;GET FINAL BAR
MOVEM T1,SEBDAT+MB%D2F(Q1) ;SAVE IT TOO
RET ;DONE
SUBTTL ROUTINE TO CHECK FOR DUAL PORTING
;THIS ROUTINE IS CALLED TO SEARCH ALL CURRENTLY BUILT UDBS LOOKING FOR
;THE OTHER END OF A DUAL PORTED DRIVE. (THIS ASSUMES THAT NO UDB IS YET
;BUILT FOR THIS SIDE OF THE DUAL PORTED DRIVE).
;CALL:
; T1/ RP20 UNIT NUMBER
;RETURNS:
; +1: UNIT IS NOT YET KNOWN TO BE DUAL PORTED
; +2: UNIT DEFINITELY DUAL PORTED
; T1/ UDB OF THE UNIT
;
;NOTE: THERE IS NO WAY TO ASK THE HARDWARE WHETHER OR NOT AN RP20 SPINDLE
;IS DUAL PORTED. THEREFORE THE MONITOR DEPENDS ON THE FOLLOWING CONVENTION
;BASED ON THE DRIVE NUMBER TO MAKE ITS DECISIONS (WHICH SHOULD BE ENFORCED
;BY FIELD SERVICE!):
;
; DRIVE NUMBER LESS THAN 20: DRIVE IS SINGLE PORTED.
; OTHERWISE: IF TWO DIFFERENT COMBINATIONS OF RH20 AND DX20 EXIST
; SUCH THAT THE SAME DRIVE NUMBER EXISTS ON EACH COMBINATION, THEN
; THOSE TWO COMBINATIONS ARE THE TWO PORTS FOR THAT DRIVE.
CKDUAL: CAIGE T1,DUADRV ;IS DRIVE NUMBER IN RANGE OF DUAL PORT DRIVES?
RET ;NO, SAY DRIVE ISN'T DUAL PORTED
SAVEPQ ;PRESERVE REGISTERS
HRRZ Q1,T1 ;SAVE DRIVE NUMBER AND SAY NO UDB FOUND YET
MOVSI Q2,-CHNN ;GET READY FOR SEARCH OF ALL CHANNELS
CKDUA2: SKIPN P1,CHNTAB(Q2) ;THIS CHANNEL EXIST?
JRST CKDUA3 ;NO, GO LOOK AT NEXT ONE
CALL DGUMAP ;LOOP OVER ALL UNITS ON THE CHANNEL
CALL CKDUAU ;INSTRUCTION TO XCT FOR EACH UNIT
TLNN Q1,-1 ;CHECKED ALL UNITS ON CHANNEL, FIND THE UNIT?
JRST CKDUA3 ;NOPE, LOOK AT NEXT CHANNEL
HLRZ T1,Q1 ;YES, SET UP UDB ADDRESS
RETSKP ;AND RETURN SAYING DRIVE IS DUAL PORTED
CKDUA3: AOBJN Q2,CKDUA2 ;LOOP OVER ALL CHANNELS
RET ;DRIVE NOT FOUND, SO ISN'T DUAL PORTED YET
;SUBROUTINE CALLED BY DGUMAP TO CHECK EACH UDB. IF THIS UDB IS FOR THE
;DRIVE WE ARE SEARCHING FOR, THE UDB ADDRESS IS SAVED IN LEFT HALF OF Q1.
CKDUAU: LOAD T1,USTYP,(P3) ;GET UNIT TYPE
CAIE T1,.UTP20 ;IS THIS AN RP20?
RET ;NO, IGNORE IT
HRRZ T1,UDBSLV(P3) ;YES, GET SLAVE NUMBER
CAIN T1,(Q1) ;IS THIS THE ONE WE ARE LOOKING FOR?
HRL Q1,P3 ;YES, REMEMBER UDB ADDRESS
RET ;DONE
SUBTTL MISC ROUTINES
;DRVSRC - FIND THE UDB GIVEN THE DRIVE NUMBER OF A DRIVE.
;GIVEN THE 8-BIT DRIVE NUMBER, THIS ROUTINE RETURNS THE UDB FOR
;THAT DRIVE. INDEXING INTO K.DUDB WILL NOT WORK SINCE A TABLE
;256 ENTRIES LONG WOULD BE NEEDED.
; T4/ DRIVE NUMBER, P2/ KDB
;RETURNS:
; +1: NO UDB FOUND WITH THIS DRIVE NUMBER
; +2: P3/ ADDRESS OF THE FOUND UDB
;DESTROYS T1.
DRVSRC: MOVSI T1,-NUMDRV ;BUILD AOBJN POINTER
ADDI T1,K.DUDB(P2) ;POINT TO UDB TABLE
SKIPE P3,(T1) ;ANY UDB THERE?
CAME T4,UDBSLV(P3) ;YES, IS IT THIS UNIT?
AOBJN T1,.-2 ;NO, LOOK MORE
JUMPL T1,RSKP ;GOOD RETURN IF FOUND IT
RET ;ERROR RETURN
;HERE TO SEE IF A PARTICULAR UNIT EXISTS ON THIS DX20.
; Q2/ UNIT TO CHECK
;RETURNS:
; +1: T1/ 0 UNIT IS ILLEGAL
; T1/ -1 NONEXISTENT UNIT
; +2: UNIT EXISTS
DX2EXT: SKIPL T4,Q2 ;MOVE TO RIGHT AC AND CHECK LEGALITY
CAIL T4,MAXDRV
JRST RFALSE ;UNIT NUMBER IS ILLEGAL
CALL DRVSRC ;SEE IF THIS UNIT IS EXISTENT
JRST RTRUE ;NO
RETSKP ;YES, SKIP RETURN
;DX2CNV - ROUTINE TO CONVERT A SECTOR NUMBER INTO CYLINDER NUMBER AND
;REMAINDER. CALLED FROM PHYSIO. CALL:
; P3/ UDB
; P4/ IORB
;RETURNS:
; +1: ALWAYS, WITH:
; T2/ CYLINDER NUMBER (UDBPS1)
; T3/ SECTOR WITHIN CYLINDER (UDBPS2)
DX2CNV: CALL PHYBLK ;GET THE DISK ADDRESS INTO T2
TXZ T2,IRBPAD ;REMOVE PHYSICAL ADDRESSING BIT
MOVE T3,UDBSIZ(P3) ;THEN GET POINTER TO DISK SIZE TABLE
IDIV T2,SECCYL(T3) ;DIVIDE BY SECTORS/CYLINDER TO GET RESULTS
RET ;DONE
;GTHWSC - ROUTINE TO CONVERT A SECTOR WITHIN A CYLINDER INTO THE FORMAT
;NEEDED FOR SETTING UP THE .DXREC REGISTER (HEAD AND RECORD NUMBERS,
;WITH THE PROPER REGISTER NUMBER). CALL:
; T3/ SECTOR IN CYLINDER
;RETURNS:
; +1: ALWAYS, T1/ .DXREC DATA READY FOR USE
;PRESERVES T2.
GTHWSC: MOVE T4,UDBSIZ(P3) ;GET ADDRESS OF SIZE TABLE
IDIV T3,SECSRF(T4) ;SPLIT INTO SURFACE AND RECORD VALUES
MOVX T1,.DXREC ;GET REGISTER NUMBER
STOR T3,RCHED,T1 ;INSERT HEAD NUMBER (SURFACE NUMBER)
STOR T4,RCREC,T1 ;AND RECORD WITHIN SURFACE
RET ;DONE
;DX2CCK - CALLED ONCE A MINUTE FROM PHYCHK TO SEE IF THE DX20
;HAS HALTED, AND IF SO TO TRY AND RESTART IT.
;ARGUMENTS:
; P1/ CDB
; P2/ KDB
; P3/ UDB (ANY ONE WILL DO)
;RETURNS:
; +1: ALWAYS
;TRASHES Q2
DX2CCK: MOVE Q2,K.DXAD(P2) ;GET CONTROLLER NUMBER
CALL HLTCHK ;IS MICROCODE STILL HAPPY?
CALL CHKMIC ;OR IS IT REAL SICK?
RET ;YES, NOTHING TO DO
AOS T1,K.STCT(P2) ;INCREMENT RESTART COUNTER
MOVEI T1,STADDR ;GET START ADDRESS
CALL DXSTRT ;RESTART THE MICROCODE
MOVX T1,KS.HLT ;GET HALT FLAG
ANDCAM T1,KDBSTS(P2) ;SAY MICROCODE IS RUNNING AGAIN
RET ;AND RETURN
;DX2HNG - ROUTINE CALLED ON A HUNG IORB. FORCE THE DX20 TO RESTART.
;CALL:
; P1/ CDB
; P2/ KDB
;RETURNS:
; +1: ALWAYS
DX2HNG: MOVE T1,KDBSTS(P2) ;GET STATUS
TXNE T1,KS.HLT ;DID DX20 STOP RUNNING?
RET ;YES, LEAVE IT ALONE THEN
MOVE Q2,K.DXAD(P2) ;SET UP DX20 NUMBER
MOVEI T1,STADDR ;GET START ADDRESS
CALL DXSTRT ;CLEAR THE DX20 AND RESTART IT
RET ;DONE
;DX2PCK - ROUTINE TO SKIP IF POSITIONING IS NEEDED. CALLED FROM PHYSIO.
;CALL:
; P3/ UDB
; P4/ IORB
;RETURNS:
; +1: POSITIONING NOT NEEDED, SO APPEND REQUEST TO TWQ
; +2: POSITIONING NECESSARY, APPEND TO PWQ
DX2PCK: MOVX T1,US.POS ;GET POSITIONING FLAG READY
TDNE T1,UDBSTS(P3) ;UNIT ALREADY POSITIONING?
RETSKP ;YES, THEN NEED TO POSITION THIS TOO
CALL DX2CNV ;RETURN CYLINDER OF THIS REQUEST
CAME T2,UDBPS1(P3) ;SAME AS CURRENT ONE?
RETSKP ;NO, POSITIONING NECESSARY
RET ;YES, NO POSITIONING NEEDED
SUBTTL SUBROUTINES FOR MANIPULATING THE DX20
;CHKMIC - CHECKS THE MICROCODE IN DX20, TO SEE IF IT IS THE RIGHT ONE
;BY LOOKING INTO CRAM LOCATIONS 7 AND 10. CRAM LOCATION 7 MUST MATCH THE
;DRIVE TYPE REGISTER, AND CRAM LOCATION 10 MUST CONTAIN THE VALUE 220.
;(VALUE 220 IS FOR TOPS-20 FORMAT DISKS, VALUE 210 IS FOR TOPS-10 FORMAT)
;THIS ROUTINE LEAVES THE MICROCODE HALTED.
;CALL:
; P1/ CDB
; Q2/ DX20 UNIT NUMBER
;RETURNS:
; +1: MICROCODE IS BAD
; +2: MICROCODE IS VALID
CHKMIC: MOVX T2,.DXMAI!MR.RES ;SET UP BIT AND REGISTER NUMBER
CALL WTREG3 ;RESET THE DX20
MOVX T2,.DXDG1!DG.UIR!DG.PCS!DG.PCI+7 ;GET FLAGS AND PC VALUE OF 7
CALL WTREG3 ;SET PC AND ENABLE MICROSTORE READING
RDRG .DXDG0 ;READ IR REG. SO TO GET LOCATION 7 OF CRAM
PUSH P,T1 ;SAVE IT
RDRG .DXTYP ;GET DRIVE TYPE REG.
POP P,T2 ;RESTORE LOCATION 7 OF CRAM
CAME T1,T2 ;DRIVE TYPE MATCH?
RET ;NO, ERROR RETURN
RDRG .DXDG7 ;NOW CHECK FOR PARITY ERRORS
TXNE T1,DG.IRP ;IRPER=1B22
RET ;ERROR
RDRG .DXDG0 ;READ AGAIN TO GET LOCATION 10 (AUTO-INCREMENTS)
CAIE T1,220 ;CONTAIN PROPER CONSTANT?
RET ;NO, ERROR
RDRG .DXDG7 ;CHECK IR PARITY ERROR AGAIN
TXNE T1,DG.IRP ;IRPER=1B22
RET ;ERROR
RETSKP ;GOOD RETURN
;HLTCHK - SEES IF THE MICROCODE IS STILL RUNNING IN THE DX20.
; P1/ CDB
; P2/ KDB
; P3/ UDB
; Q2/ DX20 UNIT NUMBER
;RETURNS:
; +1: MICROCODE HALTED, BUGINF PRINTED IF FIRST TIME NOTICED
; +2: MICROCODE IS RUNNING FINE
;
;PRESERVES T4.
HLTCHK: RDRG .DXSTS ;READ THE STATUS REGISTER
MOVX T2,KS.HLT ;GET HALTED FLAG READY
TXNN T1,ST.RUN ;IS IT RUNNING?
JRST DX2STP ;NO IT QUIT ON US
ANDCAM T2,KDBSTS(P2) ;NOT HALTED, REMEMBER THAT
RETSKP ;GOOD RETURN
DX2STP: TDNE T2,KDBSTS(P2) ;ALREADY KNEW THAT IT WAS STOPPED?
RET ;YES, JUST RETURN
IORM T2,KDBSTS(P2) ;NOW WE KNOW
PUSH P,T4 ;SAVE T4
PUSH P,T1 ;SAVE STATUS
RDRG .DXERR ;READ ERROR REGISTER
HRLZ T4,T1 ;SAVE ERROR REGISTER
RDRG .DXES0 ;FINALLY GET POSSIBLE ERROR REASON
HRR T4,T1 ;SAVE IT
CALL FNDCKU ;SET UP CHANNEL AND CONTROLLER NUMBERS
POP P,T3 ;RESTORE STATUS REGISTER
BUG.(INF,DXBHLT,PHYP2,HARD,<PHYP2 - DX20B controller halted>,<<T1,CHAN>,<T2,DX20>,<T3,REG1>,<T4,2AND26>>,<
Cause: A DX20B controller has halted.
Data: CHAN - Channel number
REG1 - Status register
2AND26 - Right half of error register,,RH of error reason register
>) ;COMPLAIN
POP P,T4 ;RESTORE AC
RET ;ERROR RETURN
;ROUTINE TO START THE DX20 MICROCODE. CALL:
; T1/ PC TO START AT
; P1/ CDB
; P2/ KDB
; Q2/ UNIT NUMBER OF DX20
;RETURNS:
; +1: ALWAYS
DXSTRT: PUSH P,T1 ;SAVE THE PC
MOVX T2,.DXMAI!MR.RES ;GET MAINTAINANCE REGISTER AND FLAG
CALL WTREG3 ;STOP AND RESET THE DX20
POP P,T2 ;RESTORE PC
ANDX T2,DG.PC ;MAKE SURE NOT TOO LARGE
TXO T2,.DXDG1!DG.PCS!DG.PCI!DG.UIR ;SET REGISTER AND FLAGS
CALL WTREG3 ;LOAD STARTING ADDRESS INTO DX20
MOVX T2,.DXMAI!MR.ST ;GET START FLAG
CALLRET WTREG3 ;START IT UP
;ROUTINE TO READ THE VERSION OF THE DX20 MICROCODE. THIS IS STORED IN
;LOCATION 0 OF THE CRAM. THIS ROUTINE STOPS THE DX20 MICROPROCESSOR.
;CALL:
; P1/ CDB
; Q2/ DX20 UNIT NUMBER
;RETURNS:
; +1: ALWAYS
; T1/ CONTENTS OF LOCATION 0 OF THE CRAM
GETVER: MOVX T2,.DXMAI!MR.RES ;GET MAINTAINANCE REGISTER AND FLAG
CALL WTREG3 ;STOP AND RESET THE DX20
MOVX T2,.DXDG1!DG.PCS!DG.UIR ;WANT TO CHANGE THE PC
CALL WTREG3 ;SET THE PC TO ZERO
RDRG .DXDG0 ;FINALLY READ IR REGISTER TO GET VALUE
RET ;DONE
;GTSNS - DOES SENSE OPERATION FOR A DRIVE AND RETURNS SENSE BYTES.
;THIS ROUTINE RETURNS SENSE BYTES 0-3 IN AC T1 FOR A DRIVE. CALL:
; T4/ RP20 UNIT NUMBER
; P1/ CDB
; Q2/ DX20 NUMBER
;RETURNS:
; +1: FAILED TO READ THEM, BUGCHK GIVEN
; +2: SUCCESSFUL RETURN, BYTES IN T1
GTSNS: CALL HLTCHK ;SEE IF MICROCODE IS STILL ALIVE
RET ;NO, FAIL
MOVX T2,.DXDRV ;GET DRIVE NUMBER REGISTER READY
STOR T4,DRVNM,T2 ;INSERT DRIVE NUMBER
CALL WTREG3 ;SET IT
MOVX T2,.DXFLG+<FLD(XS.SEN,DFCOD)> ;GET SUB-FUNCTION CODE
CALL WTREG3 ;PLACE INTO ARGUMENT REGISTER
MOVX T2,.DXCTL+<FLD(XF.SEN,DXFNC)> ;GET FUNCTION FOR SENSE
CALL WTREG3 ;TELL DX20 TO GET THE BYTES NOW
CALL ATTNWT ;WAIT FOR COMPLETION
JRST [ BUG.(CHK,DXBFGS,PHYP2,HARD,<PHYP2 - Failed to get sense bytes>,,<
Cause: A timeout occurred while waiting for an attention interrupt from
a DX20B after requesting the sense bytes.
>) ;FAILED, COMPLAIN
RET] ;ERROR RETURN
JRST RDSNS ;OK, JOIN COMMON CODE
;GETEXS - READ IN FOUR BYTES OF EXTENDED STATUS.
;THE SENSE BYTES ARE ASSUMED TO BE VALID FOR THIS CALL (EITHER AN
;ERROR JUST OCCURED ON A DRIVE AND SO THE DX20 AUTOMATICALLY READ
;THE NEW BYTES, OR ELSE A SENSE OPERATION WAS DONE EXPLICITLY).
; T1/ INDEX FOR EXTENDED STATUS
; P1/ CDB
; Q2/ DX20 UNIT NUMBER
;RETURNS:
; +1: FAILED, BUGCHK DONE
; +2: SUCCESSFUL, 4 SENSE BYTES IN T1
GETEXS: MOVX T2,.DXEND!ES.SUI ;GET BIT TO REQUEST NEW SENSE BYTES
STOR T1,ESIDX,T2 ;PLACE INDEX INTO WORD
CALL WTREG3 ;TELL DX20 TO GET THE BYTES NOW
RDSNS: MOVX T4,100 ;GET COUNTER TO TIME OUT COMPLETION
RDSNS1: RDRG .DXEND ;READ BACK REGISTER
TXNN T1,ES.SUI ;DX20 DONE READING SENSE BYTES YET?
JRST RDSNS2 ;YES, GO GET THEM
SOJG T4,RDSNS1 ;NO, KEEP LOOPING
BUG.(CHK,DXBFUS,PHYP2,HARD,<PHYP2 - Failed to update sense bytes>,,<
Cause: A timeout occurred while waiting for a DX20 to update the sense
bytes provided to it by TOPS-20.
>) ;TIMED OUT, COMPLAIN
RET ;AND GIVE ERROR RETURN
RDSNS2: RDRG .DXES0 ;READ FIRST TWO SENSE BYTES
MOVE T4,T1 ;SAVE THEM
RDRG .DXES1 ;READ LAST TWO SENSE BYTES
HRL T1,T4 ;GET BACK FIRST TWO
RETSKP ;DONE
;REDALL - ROUTINE CALLED ON ERRORS TO READ ALL REGISTERS AND EXTENDED
;STATUS INTO THE KDB, AND CLEAR THE ERROR. CALL:
; P1/ CDB
; P2/ KDB
; P3/ UDB
;RETURNS: +1: ALWAYS, WITH REGISTERS READ AND ERROR CLEARED
REDALL: CALL REGALL ;FIRST READ THE DRIVE REGISTERS
MOVX T2,.DXERR ;SET UP ERROR REGISTER NUMBER
CALL WTREG ;CLEAR THE DX20 ERROR REGISTER
CALLRET EXSALL ;THEN READ IN EXTENDED STATUS
;REGALL - ROUTINE TO READ ALL RELEVANT DX20 REGISTERS INTO THE K.DREG
;AREA OF THE KDB. ALSO SAVES THE CHANNEL CONI AND DATAI WORDS. CALLED
;TO STORE INFORMATION ON AN ERROR. CALL:
; P1/ CDB
; P2/ KDB
; P3/ UDB
;RETURNS: +1: ALWAYS
REGALL: SAVEQ ;SAVE REGISTERS
MOVEI Q1,K.DREG(P2) ;SET UP POINTER TO STORAGE AREA
MOVX Q2,SAVBIT ;GET BITS SAYING WHICH REGISTERS TO SAVE
SETZ Q3, ;SET UP FIRST REGISTER NUMBER
REGALP: JUMPGE Q2,REGALN ;SKIP IF NOT SAVING THIS REGISTER
HLLZ T2,Q3 ;GET REGISTER NUMBER INTO RIGHT AC
CAMN T2,[.DXDG0] ;ABOUT TO READ REGISTER 30?
TDZA T1,T1 ;YES, READ IT LATER
CALL RDREG ;READ IT
MOVEM T1,(Q1) ;SAVE IN THE KDB
ADDI Q1,1 ;ADVANCE TO NEXT STORAGE LOCATION
REGALN: ADD Q3,[EXP 1B5] ;INCREMENT TO NEXT REGISTER NUMBER
LSH Q2,1 ;SHIFT BIT REGISTER OVER
JUMPN Q2,REGALP ;LOOP IF STILL MORE TO READ
CALL ERRCNI ;READ CONI AND DATAI INFO FOR CHANNEL
MOVEM T1,K.DCNI(P2) ;SAVE CONI
MOVEM T2,K.DCS1(P2) ;AND PCTR
MOVEM T3,K.DDBF(P2) ;AND PBAR
DMOVE T1,K.DREG+REG.0(P2) ;GET CONTROL AND STATUS REGISTERS
TXNN T1,DX.GO ;IS GO STILL UP?
TXNE T2,ST.RUN ;NO, IS THE MICROPROCESSOR STILL RUNNING
RET ;YES, CAN'T READ REGISTER 30 THEN
MOVX T2,.DXDG1 ;SETUP TO READ THE PC REGISTER
CALL RDREG ;READ IT
TXZ T1,DG.UIR ;TURN OFF IR ENABLE
MOVX T2,.DXDG1 ;SET TO WRITE PC REGISTER
IOR T2,T1 ;WITH ALL THE BITS BUT IR ENABLE
CALL WTREG ;WRITE IT BACK
MOVX T2,.DXDG0 ;SETUP TO READ THE IR
CALL RDREG ;READ IT NOW
MOVEM T1,K.DREG+REG.30(P2) ;STORE IT WHERE IT BELONGS
RET ;AND FINALLY RETURN
;EXSALL - ROUTINE TO READ IN ALL EXTENDED STATUS BYTES INTO THE K.DEXS
;AREA OF THE KDB. CALLED AFTER AN ERROR OCCURS. CALL:
; P1/ CDB
; P2/ KDB
; P3/ UDB
;RETURNS: +1: ALWAYS
EXSALL: SAVEQ ;SAVE REGISTERS
MOVSI Q1,-<SNSNUM+3>/4 ;SET UP AN AOBJN POINTER FOR SENSE BYTES
MOVE Q2,K.DXAD(P2) ;GET DX20 UNIT NUMBER
MOVEI Q3,K.DEXS(P2) ;POINT TO AREA IN KDB TO STORE THEM
EXSALP: HRRZ T1,Q1 ;GET CURRENT INDEX FOR EXTENDED STATUS
CALL GETEXS ;READ IN THE NEXT FOUR SENSE BYTES
JRST EXSALF ;FAILED, GO CLEAR THE TABLE
MOVEM T1,(Q3) ;SAVE THESE FOUR BYTES
ADDI Q3,1 ;INCREMENT TO NEXT STORAGE ADDRESS IN THE KDB
AOBJN Q1,EXSALP ;CONTINUE IF HAVE TO GET MORE SENSE BYTES
RET ;DONE
EXSALF: HLL Q3,Q1 ;CAN'T GET THE INFO, COPY REMAINING COUNT
SETZM (Q3) ;CLEAR THIS WORD
AOBJN Q3,.-1 ;DO THE REST ALSO
RET ;AND RETURN
;ATTNWT - ROUTINE TO WAIT FOR AN ATTENTION FROM THE DX20.
;CALLED WHEN A NO OPERATION OR SENSE IS DONE, TO WAIT UNTIL THE
;ATTENTION BIT COMES UP SAYING THE OPERATION IS COMPLETE. THEN
;THE ATTENTION BIT IS CLEARED. CALL:
; P1/ CDB
; Q2/ DX20 NUMBER
;RETURNS:
; +1: TIMED OUT WAITING FOR ATTENTION
; +2: ATTENTION SEEN AND CLEARED
ATTNWT: PUSH P,P4 ;SAVE A REGISTER
MOVEI P4,AT.0 ;GET BIT FOR UNIT 0
LSH P4,(Q2) ;POSITION PROPERLY FOR THIS DX20
MOVEI T4,4000 ;SET UP COUNTER
ATTNW1: RDRG .DXATN ;READ THE ATTENTION REGISTER
TDNN T1,P4 ;ATTENTION UP YET?
SOJG T4,ATTNW1 ;NO, LOOK SOME MORE
MOVE T2,P4 ;MOVE ATTENTION BIT
POP P,P4 ;RESTORE AC
JUMPLE T4,R ;FAIL IF COUNTER REACHED ZERO
TXO T2,.DXATN ;INSERT REGISTER NUMBER
CALL WTREG3 ;CLEAR ATTENTION
RETSKP ;GOOD RETURN
SUBTTL DATA
;FUNCTION TABLE. USED TO CONVERT PHYSIO'S FUNCTIONS TO THE ACTUAL RP20
;HARDWARE FUNCTIONS, AND TO REMEMBER DATA ABOUT EACH FUNCTION. THE FF
;MACRO HAS THE FOLLOWING ARGUMENTS:
;
; FF (FLAG,FUNCTION,DISPATCH,NAME)
;WHERE:
; FLAG IS SET IF THE FUNCTION TRANSFERS DATA. LOAD WITH TBDTF
; FUNC IS HARDWARE FUNCTION (XF.???). LOAD WITH TBFNC
; DISP IS ADDRESS TO PROCESS THE FUNCTION ON INTERRUPT. LOAD WITH TBDSP
; NAME IS USED TO DEFINE A VARIABLE FOR THIS OFFSET INTO THE TABLE
DEFINE FF(FLAG,FUNC,DISP,NAME),<
IFNB <NAME>,<NAME==.-RP2FNC> ;;DEFINE OFFSET
EXP <FLD(FLAG,TBDTF)>+<FLD(FUNC,TBFNC)>+<FLD(DISP,TBDSP)> ;;DATA
>
RP2FNC: EXP 0 ;0 - ILLEGAL
FF (1,XF.RED,RP2RED) ;1 - READ
FF (1,XF.RDF,RP2RED) ;2 - READ FORMAT
FF (1,XF.WRT,RP2WRT) ;3 - WRITE
FF (1,XF.WRF,RP2WRT) ;4 - WRITE FORMAT
FF (0,XF.SRC,HRDERR,SRCNDX) ;5 - SEEK (SEARCH, ACTUALLY)
MXEXTF==.-RP2FNC-1 ;HIGHEST EXTERNAL FUNCTION
FF (0,XF.REC,RTYRCL,RCLNDX) ;6 - RECALIBRATE DURING ERROR RECOVERY
FF (0,XF.REC,RCLFIN,RC2NDX) ;7 - SECOND STAGE OF RECALIBRATION
MXFUNC==.-RP2FNC-1 ;HIGHEST LEGAL FUNCTION
EXP 0,0,0,0,0,0 ;ILLEGAL FUNCTIONS
MNRP2V==.-RP2FNC ;LOWEST LEGAL DATA VALIDITY FUNCTION
FF (1,XF.WRT,RP2WRT) ;16 - WRITE VALIDITY CHECK
FF (1,XF.RED,RP2RED) ;17 - READ VALIDITY CHECK
TNXEND
END