Trailing-Edge
-
PDP-10 Archives
-
BB-JR93L-BB_1990
-
10,7/mon/rpxkon.mac
There are 11 other files named rpxkon.mac in the archive. Click here to see a list.
TITLE RPXKON - DRIVER FOR MASSBUS DISKS V243
SUBTTL T WACHS/TW/JAD 17-APRIL-90
SEARCH F,S,DEVPRM,SAXPRM
$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,1990.
;ALL RIGHTS RESERVED.
.CPYRT<1974,1990>
XP VRPKON,243
;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
RPXELG==MDEELG## ;ERROR LOG ROUTINE IS IN FILIO
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,(.DISTR) ;READ DRIVE'S STATUS REGISTER
PUSHJ P,DODTI
TRNE T2,OM ;OFFSET RM03?
JRST RPXER0 ;YES
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
RPXER0: 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
CAIN T3,TY.RM2 ;RM02?
MOVEI T3,TY.RM3 ;IT'S A SLOW RM03
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
;DRIVE TYPE
TYPTAB: TY.RP4 ;RP04 (RP05 KLUDGED THE SAME)
TY.RP6 ;RP06
TY.RM3 ;RM03
1B0+TY.RP7 ;RP07 (NON-REMOVABLE MEDIA)
TY.RM5 ;RM05
1B0+TY.RM8 ;RM80 (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
DEC 467970 ;(RM05) 821 CYL, 19 SURF, 20 SECT
DEC 234780 ;(RM80) 559 CYL, 14 SURF, 30 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
DEC 469110 ;(RM05) 815 CYLINDERS
DEC 235620 ;(RM80) 561 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
DEC 500384 ;(RM05) 32*19*815
DEC 243474 ;(RM80) 31*14*561
;BLOCKS PER TRACK,,BLOCKS PER CYLINDER
BLKPTC: XWD ^D20,^D380 ;(RP04)
XWD ^D20,^D380 ;(RP06)
XWD ^D30,^D150 ;(RM03)
XWD ^D43,^D1376 ;(RP07)
XWD ^D30,^D570 ;(RM05)
XWD ^D30,^D420 ;(RM80)
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: TLNE T2,(SI.SAX) ;SA10 CHANNEL?
JRST CPOPJ1## ;IGNORE IT
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
CAIN T3,TY.RM2 ;RM02?
MOVEI T3,TY.RM3 ;IT'S A SLOW RM03
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