1
0
mirror of https://github.com/PDP-10/stacken.git synced 2026-03-08 03:29:27 +00:00
Files
Lars Brinkhoff 6e18f5ebef Extract files from tape images.
Some tapes could not be extracted.
2021-01-29 10:47:33 +01:00

1451 lines
47 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
TITLE RPXKON - DRIVER FOR MASSBUS DISKS V237
SUBTTL T WACHS/TW/JAD 23-AUGUST-88
SEARCH F,S,DEVPRM
$RELOC
$HIGH
;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
; 1974,1975,1976,1977,1978,1979,1980,1982,1984,1986,1988.
;ALL RIGHTS RESERVED.
.CPYRT<1974,1988>
XP VRPKON,237
;ASSEMBLY INSTRUCTIONS: RPXKON,RPXKON_KONPAR,RPXKON
RPXKON::ENTRY RPXKON
SUBTTL AUTOCONFIGURATION TABLES
SUBTTL DEFINITIONS
;PARAMETERS TO CONTROL XXKON MACRO:
RPFIX==KOPPWX ;POSITIONING DEVICE, CAN SEEK WHILE XFERRING
RPOFS==0 ;CAN OFFSET FOR ERROR RECOVERY
RPRDC==0 ;10/11 COMPATABILITY MODE
RPUNL==0 ;DRIVE CAN BE UNLOADED
RPCPY==0 ;CAN TELL UNIT TYPE EVEN IF KONTROL IS BUSY
RPMX==0 ;CANNOT DO MULTIPLE TRANSFERS
RPDRB==0 ;DOESN'T USE DISK I/O REQUEST BLOCKS
RPBMX==0 ;NOT A BLOCK MULTIPLEX KONTROLLER
RPECA==0 ;TRY OFFSET/RECAL BEFORE TRYING ECC
RPERNO==^D16 ;16 DRIVE REGISTERS TO SAVE ON ERROR
RPXDMX==10 ;MAXIMUM DRIVES PER KONTROLLER
RPXHDN==RPXDMX-1 ;HIGHEST DRIVE NUMBER ON KONTROLLER
;DRIVER CHARACTERISTICS
; RPX = RPXCNF
; DSK = DISK
; 0 = MAXIMUM DEVICES IN SYSTEM (NO LIMIT)
; TYPRP = KONTROLLER TYPE
; RPXDMX = MAXIMUM DRIVES PER KONTROLLER
; RPXHDN = HIGHEST DRIVE NUMBER ON KONTROLLER
; MDSEC0 = SECTION FOR KDB/UDB
; MDSEC0 = SECTION FOR DDB
DRVCHR (RPX,DSK,0,TYPRP,RPXDMX,RPXHDN,MDSEC0,MDSEC0,DR.MCD)
.ORG KONUDB ;START OF RP0X/RM0X SPECIFIC DATA
RPXUTB:!BLOCK RPXDMX ;TABLE OF POINTERS TO UDBS
RPXEBK:!BLOCK RPERNO ;STORAGE FOR ERROR REGISTERS
RPXIOB:! ;START OF SPECIAL I/O INSTRUCTIONS
RPXCO4:!BLOCK 1
RPXCI2:!BLOCK 1
RPXCO2:!BLOCK 1
RPXDI1:!BLOCK 1
RPXDI2:!BLOCK 1
RPXDO1:!BLOCK 1
RPXDO2:!BLOCK 1
RPXRAE:!BLOCK 1 ;TEST RAE IF RH20
RPXIOE:! ;END OF SPECIAL I/O INSTRUCTIONS
RPXFNC:!BLOCK 1 ;CURRENT FUNCTION AND FLAGS
RPXFLG:!BLOCK 1
RPXGON:!BLOCK 1
RAECNT:!BLOCK 1 ;RAE ERRS - CBPE,,NO TRA
RPXIUM:! BLOCK RPXDMW ;IGNORE DRIVE MASK
RPXNUM:! BLOCK RPXDMW ;NEW DRIVE MASK
RPXKLN:! ;LENGTH OF KDB
.ORG
;PROTOTYPE KDB
RPXKDB: XXKON (RP)
SETWRD (RPXCO4,<CONO 000,(T4)>)
SETWRD (RPXCI2,<CONI 000,T2>)
SETWRD (RPXCO2,<CONO 000,(T2)>)
SETWRD (RPXDI1,<DATAI 000,T1>)
SETWRD (RPXDI2,<DATAI 000,T2>)
SETWRD (RPXDO1,<DATAO 000,T1>)
SETWRD (RPXDO2,<DATAO 000,T2>)
SETWRD (RPXRAE,<CONSZ 000,CI.RAE>)
SETWRD (RPXFLG,<-1>)
KDBEND
RPXCCM==CYLCM##
EQUATE (LOCAL,0,<RPXUDB,RPXULP,RPXULB>)
EQUATE (LOCAL,CPOPJ##,<RPXINI,RPXRLD,RPXEDL>)
RPXICD==DSKICD## ;PROTOTYPE INTERRUPT CODE
RPXICL==DSKICL##
RPXUDB==0 ;NO PROTOTYPE UDB
RPXULN==UNIEBK+RPERNO ;LENGTH OF UDB
RPXDSP::DRVDSP (RPX,DSKCHN##,DSKDDB##,DDBLEN##,DSKDIA##)
;DEFAULT MONGEN'ED DEVICE TABLE
DEFMDT: MDKL10 (7,270,0,0,<MD.KON>) ;RH10 DEVICE CODE 270
MDKL10 (7,274,0,0,<MD.KON>) ;RH10 DEVICE CODE 274
MDKL10 (7,360,0,0,<MD.KON>) ;RH10 DEVICE CODE 360
MDTERM ;TERMINATE TABLE
RPXCKT: EXP TYPRP, 0 ;COMPATIBLE KONTROLLER TABLE
SUBTTL DEFINITIONS
;FUNCTIONS (OP CODES IN THE CONTROL REGISTER)
FNCUNL==3 ;UNLOAD
FNCSEK==5 ;SEEK
FNCRCL==7 ;RECALIBRATE
FNCCLR==11 ;DRIVE CLEAR
FNCREL==13 ;RELEASE (DUAL PORT)
FNCOFS==15 ;OFFSET
FNCRTC==17 ;RETURN TO CENTERLINE
FNCPST==21 ;READIN PRESET
FNCACK==23 ;PACK ACKNOWLEDGE
FNCSRC==31 ;SEARCH
FNCWRT==61 ;WRITE DATA
FNCWTF==63 ;WRITE FORMAT
FNCRED==71 ;READ DATA
FNCRHD==73 ;READ FORMAT
F22==100 ;COMPATABILITY MODE (SOFTWARE ONLY, NEVER STORED IN DDB)
;DATAI/DATAO BITS
DIERRS==3600 ;DIB ERRORS
;RP04 STATUS REGISTER BITS
ATA==1B20 ;ATTN ACTIVE
ERR==1B21 ;ERROR
PIP==1B22 ;POSITION IN PROGRESS
MOL==1B23 ;MEDIUM ON LINE
WRL==1B24 ;WRITE LOCK
LST==1B25 ;LAST SECTOR TRANSFERED
PGM==1B26 ;PROGRAMMABLE
DPR==1B27 ;DRIVE PRESENT
DRY==1B28 ;DRIVE READY
VV==1B29 ;VOLUME VALID
OM==1B35 ;OFFSET MODE ON AN RM03
GUDSTS==MOL!DPR!DRY!VV
;ERROR REG STATUS BITS
DCK==1B20 ;DATA CHECK
UNS==1B21 ;UNSAFE
OPI==1B22 ;OPERATION INCOMPLETE
DTE==1B23 ;DRIVE TIMING ERR
HCRC==1B27 ;HEADER CRC ERROR
HCE==1B28 ;HEADER COMPARE ERROR
ECH==1B29 ;ECC HARD
FER==1B31 ;FORMAT ERROR
PAR==1B32 ;PARITY
;ERROR REG 3 STATUS BITS
OCYL==1B20 ;OFF CYLINDER
SKI==1B21 ;SEEK CYLINDER
;OFFSET REGISTER
FMT22==1B23 ;22-SECTOR MODE
ECI==1B24 ;ECC INHIBIT
DEFINE STALL,<
XLIST
IMULI P,1
IMULI P,1
LIST
>
;RH10
DOCRC==400000 ;CONTROL REGISTER - CONTROLLER
DODB==500000 ;DATA BUFFER
DORA==540000 ;RAE ERROR STATUS
;CONI/CONO BITS
CHNPAR==6 ;(LH) CHAN-DETECTED PARITY
CHNNXM==1 ;(LH) CHAN-DETECTED NXM
CHNERR==120000 ;CHAN ERROR OR OVERRUN
OVERUN==20000
ALLERR==736320 ;ALL ERRORS
RPALCL==734210 ;CLEAR ALL ERRORS
ATTNEN==40
SDRAE==200 ;(LH) SELECTED DRIVE REG ACCESS ERR
CI.PWF==2000 ;POWERFAIL
;RH20
;CONI/CONO
CI.ERR==CI.DBP!CI.LWC!CI.DRE!CI.RAE!CI.OVR
CO.CLR==CO.RAE!CO.TEC!CO.CCD
;CHANNEL LOGOUT AREA
CS.ERR==CS.MPE!CS.NAE!CS.NXM!CS.RHE!CS.LWC!CS.SWC!CS.OVR
;ALL CHAN LOGOUT ERRS
RPXUNL: SKIPA T1,[FNCUNL] ;UNLOAD
RPXRCL: MOVEI T1,FNCRCL ;RECAL
PUSHJ P,CONECT ;CONECT TO THE DRIVE
JRST RPXDWN ;UNIT IS DOWN
MOVSI T2,(.DIDCR) ;SET TO CLEAR DESIRED CYLINDER REG
JRST RPXMOV ;AND CONTINUE
RPXPOS: MOVEI T1,FNCSEK ;SET TO DO A SEEK
PUSHJ P,CONECT ;CONECT TO THE DRIVE
JRST RPXDWN ;DOWN
HRLI T2,(.DIDCR) ;SET FOR DATAO TO DESIRED CYL
RPXMOV: PUSH P,T2 ;SAVE CYLINDER
MOVSI T2,(.DIOFS) ;CLEAR OFFSET REGISTER
PUSHJ P,DODTO
MOVSI T2,(.DIDAR) ;CLEAR POSSIBLE ILLEGAL
PUSHJ P,DODTO ; SECTOR FROM DESIRED ADR REG
MOVEI T2,1 ;SINCE WE COULD TALK TO THE DRIVE
LSH T2,(T3) ; IF WE WERE WAITING FOR THE FRONT-END
ANDCAB T2,RPXGON(J) ; THERE WAS A MISSED INTERRUPT. CLEAR FLAG
TRNN T2,-1 ;WAITING FOR ANY DRIVE?
SETZM RPXGON(J) ;NO, ZERO THE FLAG
POP P,T2 ;RESTORE DATAO DESIRED CYL
JRST RPXGO ;AND CONTINUE
RPXSTP: XCT RPXCI2(J) ;(BEFORE) CONI
PUSH P,T2
MOVEI T4,CO.MBE ;IF AFTER POWER-FAIL
XCT RPXCO4(J) ; THE RH20 LOST THE IVI
PUSHJ P,RPXIVI ; SO RESET IT
MOVEI T4,CO.STP
XCT RPXCO4(J) ;ZAP
XCT RPXCI2(J) ;DID IT CLEAR?
TRNN T2,CI.BSY
AOS -1(P) ;YES, SKIP RETURN
POP P,T2 ;RESTORE CONI
SKIPL UNILAS(U) ;IF DRIVE WAS ON OTHER PORT
SETZM RPXGON(J) ;CLEAR DATA XFER ON OTHER PORT FLAG
MOVSI T4,400000 ;CLEAR SIGN BIT OF RPXFNC
ANDCAM T4,RPXFNC(J) ; AS A FLAG THAT WE'RE IN RPXSTP (HNGDSK)
SETZB T3,T1 ;GET DATAI'S FROM RPXEBK
;HERE TO ENABLE ATTEN INTERRUPTS
;HERE FROM RPXI11 WITH T1=RPXGON
ATNENB: MOVEI T4,DSKCHN##
TLNE T1,200000 ;IF DEFERRED IO NOW GOING
TROA T4,CO.MBE ; DON'T ENABLE ATTENTION
TRO T4,CO.AIE!CO.MBE ;RE-ENABLE FOR INTERRUPTS
XCT RPXCO4(J)
POPJ P,
;HERE TO MAKE SURE KONTROLLER IS ALIVE
RPXALV: XCT RPXCI2(J) ;CONI
TRNE T2,7 ;ALIVE AND WELL?
POPJ P, ;YES
PUSHJ P,SETP14 ;NO. SET UP IVI
MOVSI T1,200000 ;ENABLE FOR ATTENS
PJRST ATNENB ;GIVE IT A PI AND EXIT
RPXLTM: MOVE T3,UDBPDN(U) ;PHYSICAL DRIVE NUMBER
MOVEI T4,3 ;MAKE SURE WE DONT TRY TOO MUCH
MOVSI T2,<(.DILAR)>(T3) ;READ LOOK-AHEAD REGISTER
PUSHJ P,SETP1
SKIPE P1
TLO T2,(DO.DRE)
PUSH P,T1 ;SAVE TARGET BLOCK
RPXLT1: XCT RPXDO2(J)
STALL ;WAIT A WHILE
XCT RPXDI1(J)
SKIPE P1
TLC T1,(DI.TRA)
TDNE T1,[DIERRS,,
DI.TRA!DI.CPE](P1)
JRST RPXLT3 ;YES, ERROR
ANDI T1,3777 ;NO, MASK OUT USEFUL PART
CAIN T3,(T1) ;SAME AS LAST TIME (OR 1ST TIME)?
JRST RPXLT2 ;YES, WE HAVE A GOOD NUMBER
HRRZ T3,T1 ;NO, SAVE PREVIOUS LA CONTENTS
SOJG T4,RPXLT1 ;AND TRY AGAIN
MOVEI T1,^D8380 ;WONT SETTLE - ASSUME 1/2 REVOLUTION
PJRST T2POJ1## ;AND SKIP
RPXLT2: LSHC T3,-6 ;GET SECTOR CNTR, FRACTION TO T4
SKIPGE T4 ;OVER HALF 1 SECTOR?
ADDI T3,1 ;YES, BUMP SECTOR COUNT
LDB T4,UNYBPT## ;NO OF BLOCKS PER TRACK
POP P,T1 ;RESTORE TARGET BLOCK
ADDI T1,-2(T4) ;ALLOW A 2-SECTOR FUDGE FACTOR
IDIVI T1,(T4) ;COMPUTE DESIRED SECTOR
SUBI T2,(T3) ;DISTANCE
SKIPGE T2 ;IF NEGATIVE
ADDI T2,(T4) ; 1 MORE REVOLUTION
CAIN T4,^D20 ;IF RP04/RP06
SKIPA T1,[^D838] ; 838 PER SECTOR
MOVEI T1,^D556 ;RP07/RM03 - 556 PER SECTOR
IMULI T1,(T2) ;TIMES MICRO-SECS PER SECTOR
PJRST CPOPJ1## ;GOOD RETURN
RPXLT3: SKIPE P1
PUSHJ P,CLRRAE
JRST TPOPJ##
RPXRDF: SKIPA T1,[FNCRHD] ;READ HEADERS AND DATA
RPXWTF: MOVEI T1,FNCWTF ;WRITE HEADERS AND DATA (FORMAT)
MOVE T2,KONCNT(J) ;IF WRITING-READING HEADERS AND DATA
LDB T3,UNYUTP## ;GET UNIT TYPE
CAIN T3,2 ;201 WORDS/SECTOR FOR RM03
SKIPA T3,[201]
MOVEI T3,202 ;202 WORDS/SECTOR FOR RP04/6/7
IDIV T2,T3 ;DIVIDE BY SECTOR SIZE
SKIPE T3 ; FILIO COMPUTED CHNNUM ASED ON 200 WDS/SECTOR
ADDI T2,1 ; AND THE RH20 HAS TO BE TOLD THE REAL NUMBER
HRRM T2,CHNNUM(P1) ; SO RECOMPUTE CHNNUM BASED ON 202 WORDS
JRST RPXDGO
RPXRDC: SKIPA T1,[FNCRED] ;READ 22-SECTOR MODE
RPXWTC: MOVEI T1,FNCWRT ;WRITE 22-SECTOR MODE
LDB T2,UNYUTP## ;GET UNIT TYPE
CAIN T2,3 ;SKIP UNLESS AN RP07
JRST [SETZ T3, ;16-BIT MODE IS ILLEGAL
POPJ P,]
TLO T1,F22 ;INDICATE 22-SECTOR MODE
JRST RPXDGO
RPXRED: SKIPA T1,[FNCRED+DO.DTE] ;READ, DONT STOP ON ERROR
RPXWRT: MOVEI T1,FNCWRT+DO.DTE ;WRITE, DONT STOP ON ERROR
JRST RPXDGO
RPXRDS: SKIPA T1,[FNCRED] ;READ, STOP ON ERROR
RPXWTS: MOVEI T1,FNCWRT ;WRITE, STOP ON ERROR
RPXDGO: SETZM RPXFLG(J) ;INDICATE DATA-XFER FUNCTION
PUSHJ P,CONECT ;CONECT TO THE DRIVE
JRST RPDWND ;DOWN
TRNE T1,DO.DTE ;STOP ON ERROR?
AOS RPXFLG(J) ;NO, SET RPXFLG POSITIVE
LDB T4,UNYUTP## ;GET UNIT TYPE
CAIN T4,2 ;RM03?
JRST RPXDG0 ;YES
TLNE T1,F22 ;IF 22-SECTOR MODE,
MOVEI T4,^D22 ; ADDRESSING IS DIFFERENT
TLNN T1,F22
LDB T4,UNYBPT## ;BLOCKS PER TRACK
IDIVI T3,(T4) ;COMPUTE SECTOR, BLOCK
JRST RPXD0A ;PROCEED
RPXDG0: TLNE T1,F22 ;IF 22-SECTOR MODE,
IDIVI T3,^D32 ;32 SECTORS/TRACK
TLNN T1,F22 ;IF NOT 22-SECTOR MODE,
IDIVI T3,^D30 ;30 SECTORS/TRACK
RPXD0A: DPB T3,[POINT 5,T4,27] ;SET T4 FOR DESIRED ADDRESS REGISTER
HRLI T2,(.DIDCR) ;SET DESIRED CYLINDER
PUSHJ P,DODTO
MOVSI T2,(.DIOFS)
TLNE T1,F22 ;IF 22-SECTOR I/O
TROA T2,ECI+FMT22 ; LIGHT FMT22 IN OFFSET REGISTER
TRNE T1,DO.DTE ;IF NOT STOPPING ON ERROR
TRCA T2,ECI ;CLEAR OFFSET, SET ECI
TRNN T1,10 ;IF WRITING
PUSHJ P,DODTO ;CLEAR OFFSET REGISTER
JUMPE P1,RPXDG1
MOVE T2,-1(P) ;LOC OF CHANNEL DATA BLOCK
MOVN T2,CHNNUM(T2)
DPB T2,[POINT 10,T1,29]
TLO T1,(.DOSTC!DO.RCP!DO.SCS!DO.DRE)
JRST RPXDG2
RPXDG1: MOVE T2,KDBICP(J) ;LOC OF THE ICWA
LSH T2,6 ;POSITION IT
TRO T1,(T2) ;INTO COMMAND
TLO T1,DOCRC ;T1=DATAO RH CNTRL REG
RPXDG2: MOVE T2,T4 ;DESIRED ADDRESS
HRLI T2,(.DIDAR) ;SET TO DATAO THE RIGHT REGISTER
RPXGO:
MOVEI T4,CO.MBE ;MAKE SURE THE MASSBUS IS ENABLED
;(BIT IGNORED FOR RH10)
SKIPE P1 ;IF AN RH20
TLO T1,(DO.DRE) ; DISABLE REGISTER ACCESS ERROR INTERRUPT
XCT RPXCO4(J)
PUSHJ P,DODTO ;DO THE DATAO IN T2
MOVE T4,UDBPDN(U) ;PHYSICAL DRIVE NUMBER
TLO T1,<(DO.LDR)>(T4) ;SET TO DATAO CNTRL REG (RH OR DRIVE)
PUSHJ P,SETCO ;SET PIA, ATTN ENABLE
TRNE T1,40 ;IF A DATA XFER COMMAND,
MOVEM T1,RPXFNC(J) ;SAVE COMMAND IN RPXFNC
MOVEM T1,UNILAS(U) ;SAVE AS LAST COMMAND FOR THE DRIVE
TLZ T1,F22 ;MAKE SURE SOFTWARE BIT ISNT DATAO'D
XCT RPXDO1(J) ;START THINGS HAPPENING
JFCL ;KL10 TIMING PROBLEM
XCT RPXCO4(J) ;TURN ON THE PI
PJRST CPOPJ1## ;AND SKIP RETURN
;ROUTINE TO SET UP THE INTERRUPT VECTOR ADDRESS FOR AN RH20
RPXIVI: MOVEI T2,40+DSKCHN##_1 ;CAUSE INTERRUPT AT 40+2N
HRLI T2,(.DOIVI) ;SET UP DATAO INTERRUPT VECTOR REGISTER
PJRST DODTOC ;DO THE DATAO AND RETURN
;HERE IF A DRIVE IS DOWN WHEN WE'RE TRYING TO START IO
RPDWND: JUMPN T1,RPDWN1 ;IF DRIVE IS ON ANOTHER PORT
MOVSI T1,400000 ;INDICATE DATA-OP WE'RE WAITING FOR
MOVEM T1,RPXGON(J)
JRST RPDWN2 ;SET RPXGON RH AND RETURN TO FILIO
RPDWN1: SETOM RPXFLG(J) ;NOT DOING IO NOW
;HERE IF A DRIVE IS DOWN WHEN WE'RE TRYING TO SEEK/RECAL
RPXDWN: JUMPN T1,RPDWN4 ;CONTINUE IF NOT ON ANOTHER PORT
SKIPE RPXGON(J) ;IF ALREADY WAITING FOR A DRIVE,
JRST RPDWN3 ; IGNORE THIS (IMPLIED SEEK LATER WILL WIN)
RPDWN2: MOVE T1,UDBPDN(U) ;DRIVE IS ON ANOTHER PORT
MOVEI T2,1 ;SET A BIT IN RPXGON INIDCATING WHICH
LSH T2,(T1) ; DRIVE WE'RE WAITING TO INTERRUPT
IORM T2,RPXGON(J)
RPDWN3: PUSHJ P,SETCO
XCT RPXCO4(J)
PJRST CPOPJ1## ;AND LIE TO FILIO SAYING WE STARTED THE OPERATION
RPDWN4: MOVE T1,T3 ;ERROR FLAGS INTO T1
PUSHJ P,CLRRAE ;SET PIA, ATTNEN, CLEAR POSSIBLE RAE
XCT RPXCO4(J) ;ENSURE THAT RH10 HAS A PI (POWER FAIL RECOVERY)
XCT RPXCI2(J) ;GET CONI STATUS
MOVE T3,RPXEBK+1(J) ;SET RH (T3) = STATUS
HRL T3,RPXEBK+2(J) ; AND LH = ERROR REGISTER
POPJ P, ;AND NON-SKIP RETURN TO FILSER
;ENTER T1=FUNCTION
;EXIT CPOPJ IF DRIVE/CONTROLLER DOWN
;EXIT CPOPJ1 IF OK, T1=FUNCTION, T2=CYL, T3=REMAINDER OF CYL COMP.
CONECT: POP P,T4 ;SAVE RETURN ADDR (SETP1 LEAVES SAVE1 ON STACK)
PUSHJ P,SETP1 ;SET P1=0 OR 1 FOR RH10 OR 20
PUSH P,T4 ;RESTORE RETURN ADDRESS
CONECX: MOVEI T4,CO.MBE ;IF ON UUO LEVEL
XCT RPXCO4(J) ; GUARD AGAINST INTERRUPTS
CONEC0: XCT RPXCI2(J) ;CONI RP,T2
TRNE T1,40 ;TRYING TO DO IO?
TRNN T2,CI.BSY+CI.DON ;KONTROL BUSY OR DONE?
JRST CONEC1 ;NO, ALL IS OK
MOVE T2,[DOCRC,, ;READ CONTROL REGISTER
.DOPTC](P1)
PUSHJ P,DODTIC
LDB T4,[POINT 3,T2,17] ;NUMBER OF LAST UNIT
MOVE T3,T1
PUSHJ P,RDREG ;READ ITS REGISTERS
MOVE T1,T3
MOVSI T2,UNPHNG+UNPFIR ;IF NOT IN ERROR RECOVERY
SKIPGE UNIECT(U)
MOVEM T2,UNIECT(U) ;SET FLAG FOR FILIO
XCT RPXCI2(J) ;RESET T2 TO CONI
MOVEI T4,CO.STP+CO.MBE ;YES, CLEAR BUSY, SET DONE
TRNE T2,CI.BSY
XCT RPXCO4(J)
AOS UNIHNG(U) ;BUMP A COUNTER
XCT RPXCI2(J) ;CONI
MOVE T4,[RPALCL
CO.CLR+CO.MBE](P1)
XCT RPXCO4(J) ;RH20S NEED 2
XCT RPXCO4(J)
TRNE T2,CI.BSY ;DID BUSY CLEAR?
JRST CONER2 ;NO, CALL DRIVE OFF-LINE
XCT RPXCI2(J)
TRNN T2,CI.DON ;DID WE WIN?
JRST CONEC1 ;YES
MOVEI T4,CO.MBI ;NO. I HATE TO DO IT
XCT RPXCO4(J) ; BUT MASSBUS INIT IS THE ONLY WAY
MOVEI T4,CO.MBE+CO.STP
XCT RPXCO4(J) ;NOW GET THE RH20 USABLE AGAIN
MOVEI T4, CO.MBE+CO.CLR
XCT RPXCO4(J)
CONEC1: MOVSI T2,(.DISNR) ;WRITE A READ-ONLY REGISTER TO SIEZE THE DRIVE
PUSHJ P,DODTO ; SO THE FRONT-END CANT AB IT OUT FROM UNDER US
MOVSI T2,(.DISTR) ;SET TO READ DRIVE'S STATUS REGISTER
PUSHJ P,DODTI
TRZ T2,LST+PGM+OM ;DON'T CARE ABOUT LAST SECTOR TRANSFERRED
; OR PGM OR OFFSET MODE
CAIE T2,GUDSTS ;DRIVE OK?
JRST CONERR ;NO
CONEC2: MOVE T2,UNIBLK(U) ;YES, GET DESIRED BLOCK
LDB T3,UNYBPY## ;BLOCKS PER CYLINDER
TLNN T1,F22 ;SKIP IF 22-SECTOR MODE
JRST CONC2A ;NOT
LDB T3,UNYUTP## ;GET UNIT TYPE
CAIE T3,2 ;SKIP IF AN RM03
SKIPA T3,[^D418] ;NOT AN RM03
MOVEI T3,^D160 ;AN RM03
CONC2A: IDIVI T2,(T3) ;COMPUTE CYLINDER IN T2
MOVEM T2,UNICYL(U) ;SAVE IN UDB
PJRST CPOPJ1## ;AND SKIP-RETURN
;HERE IF ERROR TRYING TO CONNECT
CONERR: JUMPN T2,CONER0 ;GO IF NOT SEIZED TO ANOTHER PORT
MOVSI T2,U2PPGA ;DID THE OTHER PORT DISAPPEAR FROM UNDER US?
TDNE T2,UNIDS2(U)
JRST [MOVEI T3,KOPOFL ;YES, INDICATE THE DRIVE IS OFF-LINE
POPJ P,] ;TELL FILIO
TLNE T1,F22 ;NO, IT MUST BE SIEZED BY FRONT END
TRO T1,F22 ;SAVE STATE OF F22 IN RH(T1)
HRL T1,(P) ;SAVE CONTINUE ADDRESS FOR WHEN WE GET IT
MOVSM T1,UNILAS(U) ; SAVE FUNCTION+FLAG+ADDRESS
MOVSI T2,(.DISNR) ;WRITE A READ-ONLY REGISTER SO WILL GET
PUSHJ P,DODTO ; INTERRUPT ON RELEASE FROM OTHER PORT
MOVSI T2,(.DISTR) ;IF DRIVE RELEASED BEFORE WRITE
PUSHJ P,DODTI ; WE WONT GET ATTN INTERRUPTS
JUMPN T2,CONER3 ;IT DID, TRY OPERATION NOW
SETZ T1, ;T1=0 IS A FLAG
AOS INTFNC## ;BUMP INTERFERENCE-COUNT
POPJ P, ;AND TAKE NO-GOOD RETURN
CONER0: MOVE T4,UDBPDN(U) ;PHYSICAL DRIVE NUMBER
CAIE T2,GUDSTS+WRL ;STATUS OK EXCEPT FOR WRITE-LOCK?
JRST CONER1 ;NO, REALLY IS BAD
LDB T3,[POINT 3,T1,32] ;YES, IS THIS A WRITE?
CAIE T3,6
JRST CONEC2 ;NO, ITS OK
SETZ T3, ;WRITE-INDICATE NOT OFF-LINE,
POPJ P, ; BUT BAD
CONER1: MOVEI T3,KOPOFL ;ASSUME OFF-LINE
TRNE T2,MOL ;MEDIUM ON-LINE?
TRNE T2,VV ;YES, VOLUME VALID?
JRST CONER2 ;YES
PUSHJ P,NOWUP ;ACKNOWLEDGE THE DRIVE
MOVSI T2,(.DISTR) ;READ THE STATUS REG
PUSHJ P,DODTI
TRNE T2,VV ;DRIVE IS DOWN IF VV DIDNT SET
JRST CONEC1 ;AND GO TRY AGAIN
CONER2: PUSH P,T1
MOVE T4,UDBPDN(U) ;PHYSICAL DRIVE NUMBER
PUSHJ P,RDREG ;READ DRIVE REGISTERS
PUSHJ P,DVCLR ;NO, CLEAR THE DRIVE
POP P,T1
MOVSI T2,(.DISTR) ;READ STATUS REG
PUSHJ P,DODTI
TRZ T2,LST+PGM+OM
CAIN T2,GUDSTS ;DID DRIVE CLEAR FIX IT?
JRST CONER4 ;YES, RETRY
HRL T2,RPXEBK+2(J) ;MOL AND VV ON, BUT STATUS SAYS ERROR
;READ THE ERROR REGISTER
MOVEI T3,KOPOFL ;PRETEND THE UNIT IS OFF-LINE
TLNE T2,UNS ;UNSAFE?
TRO T3,KOPFUS ;YES, SO INDICATE
TRNE T2,MOL ;REALLY OFF-LINE?
TRO T3,KOPUSI ;NO, STATUS INCONSISTENT
AOJA T1,CPOPJ## ;AND NON-SKIP, INSURING THAT T1 ISNT 0
;HERE IF WE GOT DRIVE BACK AFTER THE FE HAD IT
CONER3: HRRZS T1 ;CLEAR LH
TRZE T1,F22 ;RESTORE STATE OF F22
TLO T1,F22
JRST CONEC1 ;NOW TRY IT AGAIN
CONER4: SKIPL UNIECT(U) ;IN ERROR RECOVERY?
JRST CONEC2 ;YES, CANT SAVE REGS
SETZM UNIECT(U) ;NO. FLAG FILIO TO KICK DAEMON
MOVSI T2,RPXEBK(J) ;STORE REGS IN "AT ERROR" HALF
HRRI T2,UNIEBK(U) ; OF UDB FOR DAEMON
BLT T2,UNIEBK+17(U)
JRST CONEC2 ;AND DO THE OPERATION
;ROUTINE TO DO A DATAI FOR THE DRIVE
;ENTER T2=REGISTER TO READ, RETURN T2=CONTENTS OF THE REGISTER
;PRESERVES T1,T4
;DODI4 - ENTER WITH T4=DRIVE NUMBER.PRESERVES ALL ACS (EXCEPT T2)
;DODIC - NO DRIVE INVOLVED. PRESERVES ALL ACS BUT T2
DODTI4: ;ENTRY POINT FOR ONCMOD
DODTI: MOVE T3,UDBPDN(U) ;PHYSICAL DRIVE NUMBER
TLOA T2,(T3) ;SET TO READ IT
DODI4: TLO T2,(T4)
DODIC: SKIPE P1 ;RH20?
TLO T2,(DO.DRE) ;YES, DONT INTERRUPT ON RAE
XCT RPXDO2(J) ;INDICATE WHICH REGISTER WE WANT
PUSH P,T2 ;SAVE REGISTER WE WANT TO READ
IMULI T2,1 ;WAIT (IN CASE RH10)
XCT RPXDI2(J) ;READ THE REGISTER
JUMPE P1,DODIX ;SKIP RAE TEST IF RH10
XCT RPXRAE(J) ;REGISTER ACCESS ERROR?
JRST DTIERR ;YES
DODIX: POP P,(P) ;NO, REMOVE JUNK FROM LIST
ANDI T2,177777 ;CLEAR GARBAGE BITS
POPJ P, ;AND RETURN
;HERE ON RAE
DTIERR: TLNE T2,(DI.TRA) ;TRA UP?
MOVSI P1,1 ;NO, COUNT PAR ERROR IN LH (P1=1 FOR RH20)
ADDM P1,RAECNT(J) ;COUNT THE ERROR
MOVEI P1,^D10 ;UP TO 10 RETRIES
PUSH P,T4 ;NEED TO PRESERVE T4
MOVEI T4,CO.MBE!CO.RAE
DTIER1: XCT RPXCO4(J) ;CLEAR THE RAE
MOVE T2,-1(P) ;REGISTER WE WANT TO READ
XCT RPXDO2(J)
STALL
XCT RPXDI2(J) ;READ IT
XCT RPXRAE(J) ;ERROR?
SOJG P1,DTIER1 ;YES, TRY AGAIN
XCT RPXCO4(J) ;CLEAR IT
POP P,T4 ;RESTORE T4
MOVEI P1,1 ;RESTORE P1
JRST DODIX ;REMOVE GARBAGE AND RETURN
;READ CONTROLLER REG
DODTIC: SKIPE P1 ;RH20?
TLO T2,(DO.DRE) ;YES, DONT INTERRUPT ON RAE
XCT RPXDO2(J) ;WHICH REGISTER
XCT RPXDI2(J) ;CONTROL INFO COMES BACK WITH NO WAITING
POPJ P,
;ROUTINE TO WRITE A CONTROLLER REGISTER
DODTOC: TDZA T3,T3 ;USE UNIT 0
;ROUTINE TO WRITE A DRIVE REGISTER
;ENTER T2=REGISTER TO WRITE,,DATA TO WRITE
;PRESERVES T1,T4
;DODO4 - ENTER WITH T4=DRIVE. PRESERVES ALL ACS
DODTO: MOVE T3,UDBPDN(U) ;PHYSICAL DRIVE NUMBER
TLOA T2,<(DO.LDR)>(T3) ;SET TO WRITE THE REGISTER
DODO4: TLO T2,<(DO.LDR)>(T4)
SKIPE P1 ;RH20?
TLO T2,(DO.DRE) ;YES, DONT INTERRUPT ON RAE
XCT RPXDO2(J) ;ZAP
JUMPE P1,CPOPJ## ;SKIP RAE TEST IF RH10
XCT RPXRAE(J) ;REGISTER ACCESS ERROR?
AOSA RAECNT(J) ;YES, COUNT A NO-TRA ERROR
POPJ P, ;NO, DONE
MOVEI P1,^D10 ;UP TO 10 RETRIES
PUSH P,T4 ;PRESERVE T4
MOVEI T4,CO.MBE!CO.RAE
DOERR1: XCT RPXCO4(J) ;CLEAR THE ERROR
XCT RPXDO2(J) ;RETRY
XCT RPXRAE(J) ;ERROR?
SOJG P1,DOERR1 ;YES, RETRY
XCT RPXCO4(J) ;CLEAR THE RAE
POP P,T4 ;RESTORE T4
MOVEI P1,1 ;RESTORE P1
POPJ P, ;AND RETURN
;ROUTINE CALLED WHEN VV ISNT ON FOR A DRIVE - DOES A DRIVE CLEAR, ACKNOWLEDGE
;ENTER T4=DRIVE NUMBER
;PRESERVES T1,T4
NOWUP: PUSHJ P,DVCLR ;CLEAR THE DRIVE
MOVEI T2,FNCACK
PJRST DODO4 ;DO A PACK ACKNOWLEDGE AND RETURN
$INIT
;CHECK FOR KONTROLLER UP
RPXUPA: PUSHJ P,SAVE2##
SETOM RPXFLG(J)
PUSHJ P,RPXSTW ;SET P1=0 IF RH10, =1 IF RH20
MOVEI T4,DSKCHN## ;GET PI CHANNEL
SKIPE P1 ;IF AN RH20,
TROA T4,CO.RAE!CO.MBE!CO.AIE!CO.CCD ; CLEAR THESE BITS
TRO T4,RPALCL+40 ;CLEAR ALL ERROR BITS, ATTEN ENABLE
XCT RPXCO4(J) ;CONO RPX,(T4)
XCT RPXCI2(J) ;CONI RPX,T2
TDNN T2,[EXP 2030,CI.DBP!CI.LWC!CI.DRE!CI.RAE!CI.OVR!CI.BSY](P1)
TRNN T2,7 ;NO, PI UP?
POPJ P, ;DOWN
PJSP T1,CPOPJ1## ;UP, SET T1 NON-0 (WH LOCKOUT), AND RETURN
;CHECK HARDWARE WRITE PROTECT
RPXHWP: PUSHJ P,RPXSTW ;MASSBUS ENABLE IF AN RH20
MOVSI T2,(.DISTR) ;READ STATUS REGISTER
PUSHJ P,DODTI4
TRNE T2,WRL
AOS (P) ;WRITE LOCKED
POPJ P, ;RETURN
$HIGH
;ROUTINE TO SET P1 =0 FOR RH10, =1 FOR RH20
;PRESERVES ALL BUT P1
RPXSTW: ;CALLED BY ONCMOD (RPXUPA)
SETP1: EXCH P1,(P) ;SAVE P1, GET CALLERS PC
PUSH P,P1 ;SAVE PC
MOVE P1,KDBDVC(J) ;GET DEVICE CODE/4
CAIL P1,FSTICD/4 ;RH20 DEVICE CODE?
CAILE P1,LSTICD/4
TDZA P1,P1 ;RH10
MOVEI P1,1 ;RH20
JUMPE P1,SETP12 ;RETURN IF AN RH10
PUSHJ P,SETP13 ;SET UP IVI
PUSH P,T4 ;RH20, SAVE T4
PUSHJ P,SETCO ;SET UP FOR CONO (MAKE SURE CO.MBE IS ON)
XCT RPXCO4(J) ;ENABLE MASSBUS, LIGHT PIA
POP P,T4 ;RESTORE T4
SETP12: POP P,(P) ;MAKE STACK RIGHT
PUSHJ P,@1(P) ;GO TO CALLER
CAIA
AOS -1(P)
JRST P1POPJ## ;RESTORE P1
SETP13: PUSHJ P,SAVT##
SETP14: MOVEI T4,CO.MBE ;SO WE CAN TALK TO IT
XCT RPXCO4(J)
PJRST RPXIVI ;TELL IT WHERE TO GO
;ROUTINE TO CLEAR RAE
CLRRAE: PUSHJ P,SETCO ;"REGULAR" BITS
TRO T4,CO.RAE ;CLEAR RAE
XCT RPXCO4(J) ;ZAP THE ERROR, PRESERVE THE REST
POPJ P, ;AND RETURN
;ROUTINE TO SET UP BITS FOR CONO
;PRESERVES ALL BUT T4
SETCO: MOVEI T4,CO.MBE+DSKCHN## ;BIT NEEDED FOR RH20, IGNORED FOR RH10
HLL T4,RPXGON(J) ;IF WE ARE WAITING FOR THE FRONT END
TLNE T4,400000 ; AND WE ANT TO DO A DATA XFER
TLNE T4,200000 ;ENABLE FOR ATTENS IF XFER NOT STARTED
SKIPGE RPXFLG(J)
TRO T4,CO.AIE ;ENABLE FOR ATN IF NO XFER
POPJ P, ;AND RETURN
IFN FTDUAL,<
;ROUTINE TO ISSUE A RELEASE FOR DUAL-PORT OPERATION
;PRESERVES ALL ACS
RLESE: PUSHJ P,SAVT##
MOVE T4,UDBPDN(U) ;PHYSICAL DRIVE NUMBER
MOVEI T2,FNCREL ;RELEASE
PUSHJ P,DODO4
PJRST CHKATN
>
;HERE ON INTERRUPT FOR A MASSBUS DISK
RPXINT: PUSHJ P,SETP1 ;SET P1=0 OR 1 FOR RH10 OR 20
MOVE W,J ;SET UP KDB ADDRESS
PUSHJ P,SVMBR## ;SAVE CURRENT MBR FOR UUO LEVEL
MOVSI T2,(.DIASR) ;SET TO READ ATTN SUMMARY REGISTER
PUSHJ P,DODIC ;(ATTN NOT ON IN CONI IF NOT ENABLED)
SETZB S,T4
ANDI T2,377 ;ANY ATTENTION ON?
SKIPL RPXGON(J) ;AND NO (POSSIBLE) POSTPONED ATTN INTERRUPTS
JUMPE T2,NOATTN ;NO
HRLI T2,(.DIASR!DO.LDR) ;YES, SET TO CLEAR WHAT WE READ
PUSH P,T2 ;SAVE IT (CLEAR IF NO ERRORS LATER ON)
SKIPN T1,RPXGON(J) ;ARE WE LYING TO FILSER ABOUT SOME DRIVE?
JRST DUAINX ;NO, CONTINUE
TLZE T1,200000 ;YES, DID WE START THE "REAL" OPERATION?
JRST DUAIN4 ;YES, FINISH UP
TRNE T2,(T1) ;NO, IS THERE AN ATTEN FROM THAT DRIVE?
JRST DUAIN1 ;YES
JUMPG T1,DUAINX ;NO, REGULAR SERVICE IF IT WAS A SEEK
HRLZ T1,T2 ;DATA XFER - REMEMBER THE DRIVES
IORM T1,RPXGON(J) ; SO WE CAN TELL FILSER AFTER THE XFER
JUMPN T1,RPXIN9 ;ISSUE RELEASES AND EXIT THE INTERRUPT
JRST DUAIN4 ;DONE INTERRUPT WE ARE CONFUSED
;HERE IF WE TRIED TO START AN OPERATION ON A DRIVE WHICH WAS BUSY ON THE
;OTHER PORT (FRONT END). WE WROTE A READ-ONLY REGISTER IN ORDER TO GET THIS
;ATTENTION INTERRUPT WHEN THE DRIVE WAS RELEASED FROM THE OTHER PORT
DUAIN1: HRRZS T2,T1 ;DRIVE WE WERE WAITING FOR
ANDCAM T2,(P) ;CLEAR IT FROM STUFF TO DO AT END
HRLI T2,(.DIASR) ;CLEAR ATA IN DRIVE
PUSHJ P,DODO4
JFFO T1,.+2 ;COMPUTE DRIVE NUMBER
STOPCD DUAIN2,DEBUG,NFD, ;++NO FRONT-END DRIVE
MOVNI T2,-^D35(T2)
HRRZ U,KDBIUN(J) ;POINT AT UDB
ADD T2,U ;...
HRRZ U,(T2) ;SET U TO THE DRIVE
SKIPG UNILAS(U)
JRST DUAIN5 ;SOMEONE IS CONFUSED
HLRZ T1,UNILAS(U) ;FUNCTION
TRZE T1,F22
TLO T1,F22 ;SET 22-SECTOR MODE IF NEEDED
PUSHJ P,CONEC0 ;SET UP TO TALK TO DRIVE
JRST DUAIN3 ;NOT RIGHT, LET IT TIME OUT
PUSH P,KDBCHN(J) ;DATA OPS NEED CHAN DB LOC ON PDL
MOVSI T4,200000 ;INDICATE THAT THE DATA XFER HAS STARTED
SKIPG RPXGON(J) ; IF WE ARE ABOUT TO START IT
IORM T4,RPXGON(J) ; SO THAT SETCO WONT ENABLE FOR ATTENTIONS
HRRZ T4,UNILAS(U) ;CONTINUE ADDRESS
PUSHJ P,1(T4) ;START OPERATION NOW
JFCL ;LOSE (SYSTEM ERROR?)
POP P,(P) ;REMOVE CHNXCB FROM LIST
DUAIN2: SKIPGE RPXGON(J) ;WAITING FOR DATA XFER?
JRST DUAIN9 ;YES, ISSUE RELEASES AND WAIT FOR DONE
DUAIN3: SETZB T4,RPXGON(J) ;NO, CLEAR UP THE EVIDENCE
HRRZ T2,(P) ;RESTORE OTHER DRIVE ATTN BITS
JRST DUAINX ;AND PROCESS NORMALLY
;HERE AFTER COMPLETION OF DATA XFER WHICH WAS DELAYED WHEN FRONT END HAD DRIVE
DUAIN4: HLRZS T1 ;SEEKS WHICH COMPLETED WHILE WE WAITED
TRO T2,400000(T1) ; PROCESS AS IF THEY JUST FINISHED
DUAIN5: SETZM RPXGON(J) ;NOT WAITING NOW
DUAINX: HRRZ T1,T2 ;BITS FOR ATTN-DRIVES
RPXIN2: LSHC T1,-1 ;TEST THE NEXT DRIVE
JUMPGE T2,RPXIN8 ;NOT THIS ONE
MOVSI T2,<(.DISTR)>(T4) ;THIS DRIVE INTERRUPTED
PUSHJ P,DODIC ;READ ITS STATUS REGISTER
HRRZ U,KDBIUN(J) ;SET UP U TO UDB
ADDI U,(T4)
SKIPN U,(U)
JRST RPXIN6 ;NEW UNIT - BUILD A UDB FOR IT
TRNN T2,MOL ;ON-LINE?
JRST RPXIN7 ;OFF-LINE INTERRUPT, TELL FILSER
TRNE T2,VV ;YES, VOLUME VALID?
TRNN T2,ERR ;YES, ERROR?
JRST RPXIN4 ;FREE INTERRUPT OR NO ERR
MOVSI T3,(T4) ;ERROR - WAS THE DRIVE DOING IO?
XOR T3,RPXFNC(J)
MOVE F,RPXFLG(J)
TLNN T3,7 ;IF SAME UNIT
JUMPGE F,RPXIN8 ;ERROR ON XFERRING DRIVE IF RPXFLG NON-NEG
MOVEI T3,1 ;IF A DATA XFER IS IN PROGRESS
LSH T3,(T4) ; WE HAVE TO TELL FILSER ABOUT THAT FIRST
JUMPGE F,[ANDCAM T3,(P) ; SO DONT CLEAR ATTN FOR THIS
JRST RPXIN8] ; DRIVE. IT WILL INTERRUPT LATER
;HERE IF INTERRUPT & NO XFER IN PROGRESS AND THE DRIVE HAD AN ERROR
MOVEM T2,(P) ;SAVE STATUS OF DRIVE
MOVE T2,T3 ;CLEAR JUST THIS 1 ATTENTION BIT
HRLI T2,<(.DIASR!DO.LDR)>(T4) ; (WILL INTERRUPT AGAIN FOR THE OTHERS)
XCT RPXDO2(J) ;CLEAR IT
MOVSI T2,(.DIER3)
PUSHJ P,DODI4 ;IF SEEK INCOMPLETE IS ON
TRNN T2,SKI
JRST RPXIN3
MOVSI T2,(.DIERR)
PUSHJ P,DODI4 ; AND UNSAFE IS OFF
TRNE T2,UNS
JRST RPXIN3
MOVE T2,(P)
TRNN T2,DRY ;IF DRIVE READY IS OFF THE UNIT IS RECALIBRATING
JRST TPOPJ## ; SO WAIT FOR NEXT INTERRUPT
PUSHJ P,DVCLR ;RECAL DONE, CLEAR THE DRIVE
;(UNIT IS NOT ON RIGHT CYLINDER, BUT IMPLIED SEEK WILL WIN)
SKIPA T1,[1]
RPXIN3: MOVSI T1,1
ADDM T1,UNIPCT(U) ;UPDATE NUMBER OF POSITIONING ERRORS
PUSHJ P,DVCLR ;MAKE SURE THE ERROR IS RESET
PUSHJ P,RDIPST ;CLEAR POSSIBLE GARBAGE FROM DA & DC
IFN FTDUAL,<
PUSHJ P,RLESE ;DO A DUAL-PORT RELEASE
>
MOVEI T1,OPPOS+IODERR;INDICATE AN ERROR FOR FILSER
HRLI T1,(T4) ;DRIVE WHICH ERRORED
IOR T1,BITTBL##(T4) ;SET THE ATTN BIT FOR THE DRIVE
POP P,T3 ;RETURN DATAI STATUS IN T3
XCT RPXCI2(J) ; AND CONI STATUS IN T2
PJRST FILINT## ;CALL FILIO
;HERE FOR ATTENTION INTERRUPT, NO ERROR INDICATED FOR DRIVE
RPXIN4:
IFN FTDUAL,<
SKIPN T3,UNI2ND(U) ;POINTER 2 SECOND PORT
JRST RPXIN5 ;NONE
MOVSI F,U2PPGA## ;SET OR CLEAR PORT-GONE-AWAY BIT
TRNN T2,PGM ;STILL DUAL (PORT SWITCH ECO)?
JRST [IORM F,UNIDS2(T3) ;NO. SO INDICATE
MOVEI F,O2COD ;MARK PORT DOWN FOR REST OF WORLD TO SEE
MOVEM F,UNISTS(T3)
JRST RPXIN5] ;AND KEEP ON
ANDCAM F,UNIDS2(T3) ;DUAL - MAKE SURE BIT IS CLEAR
RPXIN5:>
TRNN T2,VV ;FREE INTERRUPT?
PUSHJ P,NOWUP ;YES, DO A PACK ACKNOWLEDGE
IOR S,BITTBL##(T4) ;LIGHT THE ATTN BIT FOR FILIO
JRST RPXIN8 ;AND CONTINUE
;HERE FOR INTERUPT ON AN UNKNOWN UNIT
RPXIN6: MOVE T2,BITTBL##(T4) ;TRANSLATE MASSBUS UNIT (DRIVE) TO BIT
IORM T2,RPXNUM(J) ;REMEMBER TO CONFIGURE LATER
HRROS KDBNUM(J) ;FLAG IT FOR THE REST OF THE WORLD TO SEE
JRST RPXIN8 ;GO SEE IF OTHER ATTENTION BITS TO PROCESS
;HERE WHEN A UNIT GOES OFF-LINE
RPXIN7: TRNN T2,ERR ;IS THERE AN ERROR?
JRST RPXI3Z ;NO
PUSHJ P,DVCLR ;YES, CLEAR IT
MOVSI T2,<(.DISTR)>(T4) ;DID IT CLEAR?
PUSHJ P,DODIC
TRNN T2,ERR
JRST RPXI3Z ;YES
MOVSI T2,(.DIER3) ;NO, CLEAR IT THE HARD WAY
PUSHJ P,DODO4
MOVSI T2,(.DIER2)
PUSHJ P,DODO4
MOVSI T2,(.DIERR)
PUSHJ P,DODO4
MOVSI T2,<(.DISTR)>(T4) ;DID IT CLEAR?
PUSHJ P,DODIC
TRNE T2,ATA
TRNN T2,ERR
JRST RPXI3Z ;YES
;HERE WHEN AN RP07 WITH BAD UCODE GETS SPUN UP.
;DISABLE ATTENTION INTERRUPTS FOR ONE SECOND
JUMPN S,RPXI3Z ;GO IF OTHER DRIVES INTERRUPT
JUMPN T1,RPXI3Z
SKIPL RPXFLG(J) ;GO IF DATA TRANSFER
JRST RPXI3Z
MOVE T2,.CPCPN## ;CPU
ROT T2,-4
TLO T2,(1B0) ;ONLY THIS CPU
HRR T2,U ;FAILING UNIT
MOVE T3,TICSEC## ;ONE SECOND
HRLI T3,RPXENB ;ADDR OF ROUTINE TO CALL
SYSPIF ;STORE CLOCK REQUEST
IDPB T3,CLOCK##
IDPB T2,CLOCK##
MOVE T2,.CPCPN## ;CPU
SETZM CLKMIN##(T2)
SYSPIN
POP P,T2 ;PRUNE STACK
MOVEI T2,CO.MBE+DSKCHN##
XCT RPXCO2(J) ;DISABLE ATTENTION INTERRUPTS
PJRST FILDN## ;TELL FILSER AND DISMISS
;HERE ONE SECOND LATER TO RE-ENABLE
RPXENB: MOVE J,UDBKDB(T1) ;KDB
DSKOFF ;MAKE SURE RPXFLG DOESN'T CHANGE
PUSHJ P,SETCO ;SET UP FOR CONO
XCT RPXCO4(J) ;RE-ENABLE
PJRST DOPOPJ##
RPXI3Z: PUSHJ P,FILDN## ;TELL FILSER UNIT WENT AWAY
RPXIN8: JUMPE T1,RPXIN9 ;GO IF NO MORE ATTNS
AOJA T4,RPXIN2 ;AT LEAST 1 MORE - TRY THE NEXT DRIVE
DUAIN9: HRLZ T1,(P)
IORM T1,RPXGON(J)
RPXIN9: POP P,T2 ;NO ERRORS - CLEAR THE ATTN SUMMARY REGISTER
XCT RPXDO2(J) ; OF ALL THE DRIVES WE JUST LOOKED AT
IFN FTDUAL,<
SETZ T3, ;T3 WILL HAVE ATTENTION BITS
MOVEI T4,RPXDMX-1 ;START AT HIGH-ORDER DRIVE
LSHC T2,-^D8
RPXI10: JUMPGE T3,RPXI11 ;THIS DRIVE INTERRUPT?
MOVSI T2,(.DISTR) ;YES, READ STATUS REG
PUSHJ P,DODI4
TRNE T2,PGM ;IF A DUAL-PORT DRIVE
TRNE T2,ERR ;WHICH HAS NO ERROR BITS UP IN IT
JRST RPXI11
MOVEI T2,FNCREL ;DO A RELEASE SO OTHER PORT CAN GET IT
PUSHJ P,DODO4
HRRZ U,KDBIUN(J) ;AN INCREDIBLE CROCK, BUT
ADDI U,(T4) ;IF AN UNLOAD WAS DONE
MOVE U,(U)
HRRZ T2,UNILAS(U) ; THEN WE ONLY GET A FREE INTERLOCK
CAIN T2,FNCUNL ; ON THAT PORT
SKIPN T2,UNI2ND(U) ;IF THE DRIVE IS STILL IN A/B
CAIA
SETZM UNISTS(T2) ;MAKE THE OTHER PORT IDLE
RPXI11: LSH T3,1 ;STEP TO NEXT DRIVE
TLNE T3,-1 ;ANOTHER ATTN BIT?
SOJGE T4,RPXI10 ;YES, TEST THIS DRIVE
>
SKIPL T1,RPXGON(J) ;LIE TO FILSER WHILE WAITING FOR FE TO RELEASE DRIVE?
SKIPGE RPXFLG(J) ;DATA XFER IN PROGRESS?
JUMPE S,ATNENB ;NO, DISMISS INTERRUPT IF JUST A POWER-DOWN ATTN
NOATTN: SKIPL RPXFLG(J) ;DATA XFER IN PROGRESS?
JRST DATINT ;YES
XCT RPXCI2(J) ;NO, GET CONI STATUS
HRRI S,OPPOS ;INDICATE POSITION INTERRUPT
JRST CALLIO ;AND TELL FILSER
DATINT:
MOVE T2,[DOCRC,, ;READ RH10 CNTRL REG
.DOPTC](P1) ; OR PRIMARY TRANSFER CNTRL REG
PUSHJ P,DODTIC
LDB T4,[POINT 3,T2,17] ;DRIVE NUMBER WE'RE TALKING ABOUT
SKIPL RPXFNC(J) ;IF CALLED FROM RPXSTP
JRST [MOVE U,KONCUA(J)
SKIPL UNILAS(U) ;IF DRIVE WAS ON OTHER PORT
MOVE T4,UDBPDN(U) ; WE NEVER TALKED TO IT, SO
MOVEI T2,CO.CLR+CO.MBE
SKIPE P1 ;IF AN RH20 DONE MUST=0
XCT RPXCO2(J) ; OR XFER WON'T START
JRST .+1] ; SET UNIT TO WHAT IT SHOULD BE
MOVE U,RPXFNC(J)
TRNN U,10 ;IS IT A WRITE?
TRO S,OPWRT ;(OPRED=0)
MOVSI T2,<(.DIOFS!DO.LDR)>(T4) ;CLEAR ECI AND/OR FMT22
TRNN U,DO.DTE
TLNE U,F22 ; IF THEY WERE ON FOR THE DRIVE
XCT RPXDO2(J)
TLO S,(T4) ;DRIVE NUMBER IN LH
MOVSI T2,(.DISTR) ;READ THE DRIVE STATUS REGISTER
PUSHJ P,DODI4
MOVE T1,T2 ;SAVE STATUS
MOVSI T2,(.DIERR) ;READ THE ERROR REGISTER
PUSHJ P,DODI4
HRL T3,T2 ;T3=ERROR,,STATUS
HRR T3,T1
XCT RPXCI2(J) ;T2=CONI STATUS
MOVE U,KONCUA(J) ;UNIT WE'RE TALKING TO
JUMPE P1,DATIN2 ;EASY IF RH10
MOVE T1,KDBICP(J) ;GET ICWA
HLL T2,1(T1) ;GET BITS FROM CHAN LOGOUT AREA
TLC T2,(CS.NAE) ;MAKE THE BIT=1 IF ERROR
;AND FALL INTO DATIN2
DATIN2: TDNN T2,[ALLERR ;ANY ERROR?
CS.ERR!CI.ERR](P1)
TRNE T3,ERR
JRST ERROR ;YES
SKIPL RPXFNC(J) ;CALL FROM RPXSTP (FROM HNGDSK)?
JRST ERROR ;YES, CAUSE ERROR SO WILL RETRY
SKIPG UNIECT(U) ;IN ERROR RECOVERY?
JRST DATDON ;NO
PUSH P,T2 ;YES, READ ALL DRIVE REGS
PUSHJ P,RDREG ; SINCE WE JUST WON
POP P,T2
DATDON: SETOM RPXFLG(J) ;NO, INDICATE NO XFER NOW IN PROGRESS
IFN FTDUAL,<
TRNN T3,PGM ;DUAL PORT DRIVE IN A/B?
JRST CALLIO ;NO
PUSH P,T2 ;YES, SAVE CONI
MOVEI T2,FNCREL ;ISSUE A RELEASE
PUSHJ P,DODO4
POP P,T2 ;RESTORE CONI
>
CALLIO: MOVEI T4,DSKCHN## ;GET PI CHAN
TDO T4,[ATTNEN+RPALCL
CO.AIE+CO.CLR+CO.MBE](P1)
XCT RPXCO4(J)
MOVE T1,S ;T1=ATTN+DRIVE,,ERROR+FUNCT
PJRST FILINT## ;GO TELL FILSER
ERROR: TLNE T3,DCK ;DATA CHECK ERROR?
TROA S,IODTER ;YES
TRO S,IODERR ;NO
TLNE T3,FER ;FORMAT ERROR?
TROA S,IODTER+IODERR ;YES, LIGHT BOTH ERROR BITS
TDNN T2,[CHNERR
CS.MPE!CS.NXM!CS.OVR](P1)
JRST ERROR1 ;NO
JUMPE P1,ERRH10 ;ALL DIFFERENT FOR RH10S
TLNE T2,(CS.MPE) ;CHECK LOGOUT AREA FOR NXM
TRO S,IOCHMP
TLNE T2,(CS.NXM)
TRO S,IOCHNX
TLNE T2,(CS.OVR) ;CHECKK LOGOUT AREA FOR OVERRUN
TRO S,IOVRUN
JRST ERRDON ;AND FINISH UP
ERRH10: TLNE T2,CHNPAR ;YES, CHAN PARITY ERROR?
TRO S,IOCHMP ;YES
TLNE T2,CHNNXM
TRO S,IOCHNX
TRNE T2,OVERUN
TRO S,IOVRUN
JRST ERRDON ;FINISH UP
ERROR1: MOVE T1,T3 ;ERROR BITS
SKIPL UNIDS2(U) ;RP07?
TLZ T1,OPI!DTE ;NO OPI,DTE ARENT HEADER ERRORS
TLNN T1,HCE+HCRC!OPI!DTE ;HEADER ERROR?
JRST ERROR2
TRO S,IOHDER+IODTER ;YES
TRZ S,IODERR
ERROR2: SKIPG RPXFLG(J) ;IF STOPPING ON ERROR,
TRNE S,IODERR ;AND DATA ERROR IS UP
JRST ERRDON
SKIPGE UNIECT(U) ;IF INITIAL ERROR
JRST ERRDON ; REREAD BEFORE TRYING ECC
TLNE T3,DCK ;DATA CHECK
TLNE T3,ECH ;HARD DATA CHECK?
CAIA
TRO S,IOECCX ;NO, INDICATE RECOVERABLE ERROR
ERRDON: PUSH P,T2 ;SAVE CONI STATUS
PUSH P,T3 ;SAVE STATUS, ERROR REGISTERS
JUMPE P1,ERRDN0
TLC T2,(CS.NAE) ;RECOMPLEMENT BIT
MOVEM T2,-1(P) ;SO SYSERR WILL REPORT IT
TRNN T2,CI.RAE ;REGISTER ACCESS ERROR?
JRST ERRDN1 ;NO
PUSHJ P,CLRRAE ;YES, CLEAR IT
JRST ERRDN1 ;AND CONTINUE
ERRDN0: TLNN T2,SDRAE ;REGISTER ACCESS ERROR?
JRST ERRDN2 ;NO
MOVEI T2,1 ;YES, CLEAR THE BIT IN RAE REGISTER
LSH T2,(T4)
HRLI T2,DORA+<(DO.LDR)>
XCT RPXDO2(J)
ERRDN2: TRNN T2,CI.PWF ;POWERFAIL BIT SET
JRST ERRDN1 ;NO, CONTINUE
MOVEI T2,CO.MBI ;YES, SET UP FOR MASSBUS INIT
XCT RPXCO2(J) ;DO THE INIT
ERRDN1: PUSHJ P,RDREG
PUSHJ P,DVCLR ;CLEAR THE DRIVE
POP P,T3 ;RESTORE DRIVE REGISTERS
POP P,T2 ;RESTORE CONI
JRST DATDON ;AND GO TELL FILSER
;HERE TO COMPUTE ECC MASK, POSITION
RPXECC: MOVE T1,RPXEBK+16(J) ;GET POSITION
SOJL T1,CPOPJ## ;ERROR IF 0
;THE FIRE CODE IN THE MASSBUS DISKS CAN GENERATE THE WRONG ECC CORRECTION.
;STATISTICALLY, THIS ONLY HAPPENS FOR AN ERROR ENVELOPE OF GREATER THAN
;FOUR BITS. THIS CODE COUNTS THE WIDTH OF THE MASK AND DECLARES THE ERROR
;NON-ECC CORRECTABLE IF THE CORRECTION PART OF THE MASK IS WIDER THAN THIS.
MOVE T2,RPXEBK+17(J) ;GET PATTERN
JFFO T2,.+1 ;FIND FIRST BIT OF PATTERN
MOVE T4,T3 ;PRESERVE NUMBER OF FIRST BIT IN PATTERN
TDZ T2,BITTBL##(T3) ;WIPE OUT THAT BIT
RPXEC8: JUMPE T2,RPXEC9 ;JUMP WHEN PATTERN IS ZERO
JFFO T2,.+1 ;FIND NEXT BIT OF PATTERN
TDZ T2,BITTBL##(T3) ;WIPE OUT THAT BIT
JRST RPXEC8 ;LOOK FOR ANOTHER
RPXEC9: SUB T3,T4 ;GET WIDTH-1 OF PATTERN
CAILE T3,4-1 ;IS PATTERN LESS THAN/EQUAL TO FOUR BITS WIDE?
POPJ P, ;NO, THEN IT IS NOT ECC CORRECTABLE
;HERE IF THE ERROR IS TRULY ECC CORRECTABLE.
MOVE T4,RPXEBK+17(J) ;GET PATTERN
SETZ T3, ;CLEAR MASK EXTENSION
MOVSI T2,DEPCPT## ;16-BIT DISK?
TDNE T2,DEVCPT##(F)
JRST RPXEC6 ;DO 16-BIT ECC
IDIVI T1,^D36 ;COMPUTE WORD LOC, POSITION IN WORD
EXCH T2,T4 ;T2,,T3 = MASK; T4 = BIT OFFSET
ROTC T2,(T4) ;POSITION MASK
PJRST CPOPJ1## ;AND SKIP-RETURN
;HERE TO DO 16-BIT ECC
RPXEC6: IDIVI T1,^D32 ;COMPUTE WORD, BIT OFFSETS (32 DATA BITS)
EXCH T2,T4 ;T2,,T3 = MASK; T4 = BIT OFFSET
JUMPLE T4,CPOPJ1## ;IF NO SHIFT NEEDED, WE'RE DONE
RPXEC7: ROTC T2,1 ;ROTATE PATTERN TOWARD ERROR
TLZE T2,200000 ;IF CARRY OUT OF HI LH
TRO T3,1 ; CARRY INTO LO RH
TRZE T2,200000 ;IF CARRY OUT OF HI RH
TLO T2,1 ; CARRY INTO HI LH
SOJG T4,RPXEC7 ;LOOP UNTIL MASK IS IN PLACE
JRST CPOPJ1## ;AND SKIP-RETURN
;ROUTINE TO CLEAR POSSIBLE GARBAGE FROM DRIVE REGS
RDIPST: SKIPA T2,[FNCPST] ;ENSURE DA & DC REGS DON'T
;ROUTINE TO CLEAR A DRIVE AND MAKE SURE IT REALLY CLEARED
;PRESERVES T1
DVCLR: MOVEI T2,FNCCLR
PUSH P,T2
MOVSI T2,(.DIOFS) ;DRIVE CLEAR ZEROES OFFSET REG
PUSHJ P,DODI4 ; SO READ IT
EXCH T2,0(P) ; AND SAVE
PUSHJ P,DODO4 ;ZAP
PUSHJ P,DODO4 ;SOME DRIVES NEED 2!
POP P,T2 ;RESTORE OFFSET REG
HRLI T2,(.DIOFS) ; SO SYSERR WILL REPORT IT
PUSHJ P,DODO4 ; AND TEST ON 1ST ERROR WILL WORK
;ROUTINE TO MAKE SURE ATTN IS NOT UP OR DRIVE
;ENTER WITH T4 = DRIVE NO.
CHKATN: MOVSI T2,(.DIASR) ;READ ATTN SUMMARY REGISTER
PUSHJ P,DODI4
MOVEI T3,1 ;IS ATTN NOW UP?
LSH T3,(T4)
TDNN T2,T3
POPJ P, ;NO, EVERYTHING IS OK
MOVE T2,T3 ;YES, THIS ERROR CAN'T BE CLEARED
HRLI T2,(.DIASR!DO.LDR)
XCT RPXDO2(J) ;CLEAR BIT IN ATTN SUMMARY REG
POPJ P, ; AND RETURN
;HERE WITH T1=NUMBER OF THE RETRY IF A DATA ERROR. TELL FILSER WHAT TO DO
RPXERR: TLO M,400000
PUSHJ P,SETP1
SOJN T1,RPXER1 ;IF FIRST ERROR,
MOVSI T2,(.DIOFS) ;READ THE OFFSET REGISTER
PUSHJ P,DODTI ;(IF LAST OP WAS SOFT ERROR
TRNN T2,60 ; THE DRIVE IS LEFT IN OFFSET STATE)
JRST RPXER1 ;DRIVE ISNT OFFSET - CONTINUE
MOVEI T1,RTCNDX ;DRIVE IS OFFSET - RETURN TO CENTERLINE
JRST RPXER2
;HERE IF NOT 1ST ERROR, OR 1ST AND DRIVE ISNT OFFSET
RPXER1: SUBI T1,^D15 ;IF LESS THAN 16TH RETRY,
JUMPL T1,RETRY ;RETURN 0 (JUST RETRY)
SKIPGE UNIDS2(U) ;IF RP07
ADDI T1,^D14 ; DON'T BOTHER WITH OFFSET
CAILE T1,^D13 ;IF TRIED EVERYTHING AND DIDNT RECOVER
JRST RPXER3 ;GIVE UP
CAIN T1,^D13 ;IF THE LAST TIME
JRST LASTIM ; TRY LAST TIME
TRNE T1,1 ;IF DIDNT TRY TWICE AT THIS OFFSET,
JRST RETRY ;TRY A SECOND TIME
LSH T1,-1 ;TRIED TWICE - DO NEXT OFFSET
RPXER2: PUSHJ P,CONECX ;CONNECT TO DRIVE
JRST RETRY ;DOWN - PRETEND JUST STRAIGHT RETRY
MOVE T2,OFSTBL(T1) ;OK, GET OFFSET
LDB T1,UNYUTP## ;UNIT TYPE
SKIPE T1 ;RP06?
HLRS T2 ;YES, GET OTHER OFFSET VALUE
HRLI T2,(.DIOFS) ;SET TO DO OFFSET
MOVEI T1,FNCOFS ;FUNCTION = OFFSET
TRNE T2,-1 ;IS THIS OFFSET=0?
JRST RPXR2A ;NO--GO DO IT
MOVE T2,RPXEBK+2(J) ;YES--RETURN TO CENTERLINE
TRNE T2,HCE ; UNLESS HCE=1, HCRC=0
TRNE T2,HCRC
SKIPA T1,[FNCRTC]
MOVEI T1,FNCRCL ;IN WHICH CASE DO A RECAL
RPXR2A: HRROS RPXFLG(J) ;SET RPXFLG NEGATIVE
PUSHJ P,RPXGO ;START THE OFFSET
JFCL
JRST OFFSET ;AND TELL FILSER OFFSET IS IN PROGRESS
;HERE ON A HARD ERROR
RPXER3: CAIN T1,^D14 ;DO.DTE ON (30TH TIME)?
JRST RETRY ;YES, THIS TIME STOP ON ERROR
JRST GIVEUP ;NO, TELL DAEMON ABOUT IT
;HERE TO CHECK CAPACITY & STATUS OF RH10/RP04
RPXCPY: PUSHJ P,SETP1 ;DO MASSBUS ENABLE IF RH20, SET UP P1
;*** PROBABLY STILL NEEDED SINCE SOMEONE CAN TWIDDLE LAP PLUG
;*** AND CHANGE AN RM03 INTO AN RP06 AND VICE VERSA?
MOVSI T2,(.DIDTR) ;READ DRIVE-TYPE REGISTER
PUSHJ P,DODTI4
LDB T3,[POINT 9,T2,35] ;GET DRIVE TYPE CODE
CAIN T3,TY.RP5 ;RP05?
MOVEI T3,TY.RP4 ;YES, JUST CALL IT AN RP04
MOVSI T4,-TYPTBL ;-VE LENGTH OF DRIVE TYPE TABLE
MOVE T1,TYPTAB(T4) ;GET AN ENTRY
CAIE T3,(T1) ;DRIVE TYPES MATCH?
AOBJN T4,.-2 ;NO, LOOP FOR A MATCH
JUMPGE T4,RPXCP5 ;NOT A LEGAL UNIT TYPE, NO SUCH DRIVE
HRRZS T4 ;ISOLATE UNIT TYPE INDEX
MOVEM T2,UNIEBK+6(U) ;SAVE DRIVE TYPE REGISTER FOR SYSERR
MOVSI T2,(.DISTR) ;READ STATUS REGISTER
PUSHJ P,DODTI4
JUMPE T2,RPXCP4 ;NO SUCH DRIVE IF CAN'T READ STATUS (SEIZED TO OTHER PORT)
MOVE T1,T2 ;PRESERVE STATUS REGISTER (PROGRAMMABLE BIT)
TRCN T2,MOL ;MOL?
TLO T4,KOPUHE ;NO, INIT IS OFF-LINE OR DOWN
IFN FTDUAL,<
TRNE T2,MOL!VV ;IF VV=0 BUT MOL=1
JRST RPXCP3
PUSH P,T4 ;THEN THE DRIVE WON'T DO A RELEASE
MOVE T4,UDBPDN(U) ; SO DO A PACK ACKNOWLEDGE
PUSHJ P,NOWUP ; SO THAT RELEASE WILL WORK
POP P,T4
RPXCP3:>
MOVSI T2,(.DISNR) ;READ DRIVE SERIAL NUMBER
PUSHJ P,DODTI4
MOVEM T2,UNIEBK+10(U) ;AND STORE IN UDB
IFN FTDUAL,<
TRNE T1,PGM ;DUAL-PORTED DRIVE?
JUMPE T2,RPXCP4 ;YES. SN=0 IF DRIVE GOT SEIZED TO OTHER PORT
HRRZM T2,UDBDSN+1(U) ;RETURN SN IN UNISER
> ;END IFN FTDUAL
AOSA (P) ;SET FOR SKIP RETURN
RPXCP4: MOVSI T4,KOPUHE+KOPNSU ;OFF LINE OR DOWN
MOVE T1,BLKPRU(T4) ;BLOCKS PER UNIT
MOVE T2,BLKPUM(T4) ;BLOCKS PER UNIT INCLUDING MAINT CYLS
MOVE T3,BLKPUC(T4) ;BLOCKS PER UNIT IN 10/11 COMPAT MODE
MOVE W,BLKPTC(T4) ;BLKS PER TRK,, BLKS PER CYL
JRST RPXCP6 ;CLEAR POSSIBLE RAE AND EXIT
RPXCP5: PUSHJ P,CLRRAE ;CLEAR RAE
MOVSI T4,KOPUHE+KOPNSU ;OFF LINE OR DOWN
SETZB T1,T2 ;NO BLOCKS PGR UNIT - CANT READ
RPXCP6:
IFE FTDUAL,<
JUMPE P1,CPOPJ## ;NO SWEAT IF AN RH10
>
IFN FTDUAL,<
JUMPE P1,RLESE
>
PUSH P,T4 ;PRESERVE T4
PUSH P,T3 ;SAVE T3
PUSH P,T2 ;SAVE T2
MOVE T4,UDBPDN(U) ;PHYSICAL DRIVE NUMBER
MOVEI T2,1
LSH T2,(T4) ;POSITION BIT TO CLEAR ATTN-SUMMARY REG
HRLI T2,(.DIASR!DO.DRE!DO.LDR)
XCT RPXDO2(J) ; WHICH MIGHT BE ON
IFN FTDUAL,<
MOVE T4,UDBPDN(U) ;PHYSICAL DRIVE NUMBER
PUSHJ P,DVCLR ;MAKE SURE ERR ISNT UP SO RELEASE WILL WIN
PUSHJ P,RLESE ;DO A DUAL-PORT RELEASE
>
PUSHJ P,CLRRAE ;CLEAR RAE, LIT IF NON-EX DRIVE
POP P,T2
POP P,T3
PJRST T4POPJ## ;RESTORE T4 AND RETURN
;ENTRY TO READ DRIVE REGS
RPXREG: PUSHJ P,SETP1 ;MASSBUS ENABLE IF RH20
MOVE T4,UDBPDN(U) ;PHYSICAL DRIVE NUMBER
PUSHJ P,RDREG ;READ REGS
IFE FTDUAL,<
POPJ P, ;RETURN
>
IFN FTDUAL,<
MOVE T2,RPXEBK+1(J) ;GET STATUS REG
TRNE T2,PGM ;IF DUAL PORTED
TRNE T2,ERR ; AND NO ERROR
POPJ P,
PJRST RLESE ;DO A RELEASE (READ REG 0 SIEZES THE DRIVE)
>
;SUBROUTINE TO READ ALL DRIVE REGISTERS
;PRESERVES T3
RDREG: PUSH P,U
MOVE T1,KONREG(J) ;NUMBER OF DRIVE REGISTERS TO READ
MOVEI U,RPXEBK(J) ;WHERE TO STORE THEM
ADDI U,-1(T1) ;POINT AT TOP OF BLOCK
RDREG1: MOVSI T2,-1(T1) ;READ A REGISTER
LSH T2,^D12
PUSHJ P,DODI4
MOVEM T2,(U) ;SAVE IN KONTROLLER DB
SUBI U,1
SOJG T1,RDREG1 ;AND GO READ ANOTHER
MOVE T2,[DOCRC,, ;OR RH20 PTCR
.DOPTC](P1)
PUSHJ P,DODTIC
MOVEM T2,KONECR(J) ;SAVE IN KDB
MOVE T2,[DODB,, ;OR RH20 PBAR
.DOPBA](P1)
PUSHJ P,DODTIC
MOVEM T2,KONEDB(J) ; AND SAVE
PJRST UPOPJ## ;RETURN
ERCODE RETRY,0 ;RETRY
ERCODE OFFSET,1 ;OFFSET
ERCODE LASTIM,2 ;LAST TIME
ERCODE GIVEUP,3 ;GIVE UP
OFSTBL: 10,,20 ;+400 MICRO INCHES
210,,220 ;-400
20,,40 ;+800
220,,240 ;-800
30,,60 ;+1200
230,,260 ;-1200
0,,0 ;RTC
RTCNDX==.-OFSTBL-1
;TABLES INDEXED BY UNIT TYPE CODE
;0 = RP04/RP05, 1 = RP06, 2 = RM03, 3 = RP07
;DRIVE TYPE
TYPTAB: TY.RP4 ;RP04 (RP05 KLUDGED THE SAME)
TY.RP6 ;RP06
TY.RM3 ;RM03
1B0+TY.RP7 ;RP07 (NON-REMOVABLE MEDIA)
TYPTBL==.-TYPTAB ;LENGTH OF TABLE
;BLOCKS PER UNIT
BLKPRU: DEC 154280 ;(RP04/05) 406 CYLINDERS
DEC 307800 ;(RP06) 810 CYLINDERS
DEC 123150 ;(RM03) 821 CYLINDERS
DEC 865504 ;(RP07) 629 CYL, 32 SURF, 43 SECT
;BLOCKS PER UNIT IN MAINTENANCE MODE
BLKPUM: DEC 156180 ;(RP04/RP05) 411 CYLINDERS
DEC 309700 ;(RP06) 815 CYLINDERS
DEC 123450 ;(RM03) 823 CYLINDERS
DEC 866880 ;(RP07) 630 CYLINDERS
;BLOCKS PER UNIT IN COMPATIBILITY MODE
BLKPUC: DEC 171798 ;(RP04/RP05) 22*19*411
DEC 340670 ;(RP06) 22*19*815
DEC 131680 ;(RM03) 32*5*823
0 ;(RP07) NO COMPATIBILITY MODE
;BLOCKS PER TRACK,,BLOCKS PER CYLINDER
BLKPTC: XWD ^D20,^D380 ;(RP04)
XWD ^D20,^D380 ;(RP06)
XWD ^D30,^D150 ;(RM03)
XWD ^D43,^D1376 ;(RP07)
SUBTTL AUTOCONFIGURATION
;ENTERED WITH DEVICE CODE/4 IN T1, AND CONI DEV, IN T2
RPXCFG: CAIL T1,FSTICD/4 ;RH20?
CAILE T1,LSTICD/4
JRST RPXCF1 ;NO, MIGHT BE RH10
TLNE T2,(CI.PPT) ;BETTER NOT BE IPA CHANNEL
JRST CPOPJ1## ;SORRY, I'M NOT INTERESTED
MOVSI T1,CP.RH2 ;GET CHANNEL TYPE BITS FOR RH20
JRST RPXCF2 ;GO BUILD CHN/KDB AND UNITS
RPXCF1: XMOVEI T1,RPXMDT## ;MONGEN'ED DEVICE TABLE
XMOVEI T2,DEFMDT ;DEFAULT TABLE
MOVSI T3,-1 ;MATCH ON ANY MASSBUS UNIT
MOVEI T4,MD.KON ;MATCH ON KONTROLLER DEFINITION
PUSHJ P,AUTMDT## ;SCAN THE TABLES
JRST CPOPJ1## ;NO MATCHES
XCT .CPCNI## ;GET CONI ,T1
TLNN T1,4000 ;CHECK FOR DF10 OR DF10C IN 18-BIT MODE
JRST AUTEBD## ;18-BIT DF10/DF10C, INFORM OF ERROR AND RETURN
MOVSI T1,0 ;GET CHANNEL TYPE BITS FOR RH10
RPXCF2: PUSHJ P,AUTCHN## ;BUILD A CHANNEL DATA BLOCK
POPJ P, ;NO CORE
PUSHJ P,SAVE1## ;FREE UP P1
SETZB J,P1 ;NO KDB YET, START WITH MASSBUS UNIT 0
RPXCF3: PUSHJ P,RPXUNI ;CONFIGURE A SINGLE UNIT
JFCL ;IGNORE ERRORS
AOBJN P1,.+1 ;ADVANCE TO NEXT UNIT
HLLZS P1 ;KEEP JUST MASSBUS UNIT NUMBER
TLNN P1,10 ;DONE THEM ALL?
JRST RPXCF3 ;NO, DO ANOTHER
SKIPN J ;HAVE A KDB?
AOS (P) ;NO--SO CHECK WITH OTHER DRIVERS
POPJ P, ;RETURN
;HERE TO CONFIGURE A SINGLE NEW UNIT
RPXUNI: JUMPE J,RPXUN1 ;SKIP TEST IF NO KDB YET
HLRZ T1,P1 ;GET UNIT
MOVE T1,BITTBL##(T1) ;AND IT'S BIT
TDNE T1,RPXIUM(J) ;WANT TO IGNORE THIS DRIVE?
POPJ P, ;SAY IT DOESN'T EXIST
RPXUN1: MOVE W,J ;AUTCON WANTS W SETUP
PUSHJ P,RDDTR## ;READ DRIVE TYPE REGISTER
CAIN T2,TY.RP5 ;RP05?
MOVEI T2,TY.RP4 ;YES, JUST CALL IT AN RP04
MOVSI T1,-TYPTBL ;-VE LENGTH OF DRIVE TYPE TABLE
MOVE T3,TYPTAB(T1) ;GET AN ENTRY
CAIE T2,(T3) ;DRIVE TYPES MATCH?
AOBJN T1,.-2 ;NO, LOOP FOR A MATCH
JUMPGE T1,RPXUN4 ;IGNORE THIS UNIT IF UNKNOWN TYPE
MOVE T2,T1 ;COPY TYPTAB INDEX (UNIT TYPE CODE, UNYUTP)
HLL T2,TYPTAB(T1) ;COPY UNIT TYPE FLAGS
HLLZ T1,P1 ;COPY UNIT NUMBER
HLRS T1 ;ALSO USE AS UDB TABLE OFFSET
JUMPN J,RPXUN3 ;IF WE ALREADY HAVE A KDB, PROCEED
PUSH P,T1 ;SAVE THE USEFUL ACS
PUSH P,T2
MOVNI T1,1 ;NO MASSBUS UNIT NUMBER
MOVEI T2,TYPRP ;KONTROLLER TYPE CODE
PUSHJ P,DSKKON## ;BUILD A KONTROLLER DATA BLOCK
JRST TTPOPJ## ;NO CORE
MOVSI T1,-<RPXIOE-RPXIOB> ;NUMBER OF WORDS TO CHECK
XMOVEI T2,RPXIOB(J) ;STARTING WORD
HRRZ T3,.CPDVC## ;<DEVICE CODE>/4
PUSHJ P,AUTDVC## ;SET DEVICE CODES
MOVE T1,.CPCHA## ;GET CHANNEL DATA BLOCK ADDRESS
MOVE T1,CHNTYP(T1) ;GET CHANNEL TYPE BITS
TLNE T1,CP.RH2 ;RH20?
SKIPA T2,[CI.RAE!CI.ATN!CI.DON] ;YES, GET INTERRUPT FLAGS FOR RH20
;*** NEED SYMBOL - CBOV, RAE, ATTN, DONE
MOVEI T2,350 ;NO, GET INTERRUPT FLAGS FOR RH10
MOVE T3,KDBCSO(J) ;GET ADDRESS OF CONSO SKIP CHAIN
HRRM T2,DICDIF##(T3) ;SET CORRECT INTERRUPT FLAGS
TLNN T1,CP.RH2 ;RH20?
JRST RPXUN2 ;NO
HRRZ T1,.CPDVC## ;GET DEVICE CODE/4
MOVE T2,[CONSZ 0,CI.RAE!CI.AIE!CI.DON] ;CONSZ TEST FOR ATTN INTS
DPB T1,[POINT 7,T2,9] ;PLUG IN THE DEVICE CODE
MOVEM T2,DICDAE##(T3) ;NO, NEUTER TEST ON ATTN INTERRUPTS DISABLED
RPXUN2: POP P,T2 ;RESTORE THE ACS
POP P,T1
RPXUN3: PUSHJ P,DSKDRV## ;BUILD AND LINK THE UDB
JRST RPXUN4 ;NO CORE
MOVSI T2,(.DISNR) ;READ SERIAL NUMBER REGISTER
PUSHJ P,RDMBR##
SETZ T1, ;REALLY A ONE-WORD QUANTITY
MOVE T3,UDBPDN(U) ;GET PHYSICAL DRIVE NUMBER
PUSHJ P,AUTDSN## ;FAKE UP S/N IF A ZERO
DMOVEM T1,UDBDSN(U) ;SET SERIAL NUMBER IN UDB
JRST CPOPJ1## ;RETURN
RPXUN4: SETZ U, ;INDICATE NO UDB
POPJ P, ;RETURN
;ONCE A SECOND CODE
RPXSEC: SKIPL @KDBCHN(J) ;CHANNEL BUSY?
POPJ P, ;LEAVE IT ALONE
SKIPE T1,RPXNUM(J) ;GET BIT MASK
JFFO T1,RPXSE1 ;FIND FIRST UNIT NUMBER
HRRZS KDBNUM(J) ;INDICATE NO DRIVES TO CONFIGURE
POPJ P, ;DONE
RPXSE1: PUSHJ P,AUTLOK## ;GET AUTCON INTERLOCK
POPJ P, ;TRY AGAIN NEXT TIME
PUSHJ P,SAVW## ;PRESERVE W
MOVE W,J ;COPY KDB ADDRESS TO W FOR AUTCON
MOVSS T2 ;MASSBUS UNIT = DRIVE NUMBER FOR RPX DISKS
PUSH P,T2 ;SAVE
MOVE T1,KDBDVC(J) ;DEVICE CODE
XMOVEI T2,RPXDSP ;DISPATCH
MOVE T3,KDBCHN(J) ;CHANNEL DATA BLOCK
PUSHJ P,AUTSET## ;SET UP CPU VARIABLES
EXCH P1,(P) ;SAVE P1, GET MASSBUS UNIT
PUSH P,KDBUNI(J) ;SAVE KDBUNI
MOVEM P1,KDBUNI(J) ;SET FOR THIS MASSBUS UNIT NUMBER (FOR RDMBR)
PUSHJ P,RPXUNI ;CONFIGURE A NEW UNIT
JFCL ;IGNORE ERRORS
PUSHJ P,AUTULK## ;RELEASE AUTCON INTERLOCK
POP P,KDBUNI(J) ;RESTORE KDBUNI
PJRST P1POPJ## ;RESTORE P1 AND RETURN
$LIT
RPXEND: END