Trailing-Edge
-
PDP-10 Archives
-
tops10_703a_sys_ap115_bb-ju01b-bb
-
rpxkon.x15
There are 2 other files named rpxkon.x15 in the archive. Click here to see a list.
TITLE RPXKON - DRIVER FOR RP04'S V207
SUBTTL T WACHS/TW 8 JULY 86
SEARCH F,S,ICHPRM
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
.CPYRT<1974,1986>
;COPYRIGHT (C) 1974,1975,1976,1977,1978,1979,1980,1982,1984,1986
;BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
;ALL RIGHTS RESERVED.
;
XP VRPKON,207
;ASSEMBLY INSTRUCTIONS: RPXKON,RPXKON_KONPAR,RPXKON
ENTRY RPXKON
RPXKON::
;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)
;DRIVE REGISTERS
DOCR==000000 ;DRIVE CONTROL REGISTER
DOSR==010000 ;STATUS
DOER==020000 ;ERROR
DOER2==140000 ;ERROR REG 2
DOER3==150000 ;ERROR REG 3
DOAS==040000 ;ATTENTION SUMMARY
DODA==050000 ;DESIRED ADDRESS (TRACK/SECTOR)
DODT==060000 ;DRIVE TYPE
DOLA==070000 ;LOOK-AHEAD (SECTOR COUNTER)
DOSN==100000 ;SERIAL NUMBER
DOOF==110000 ;OFFSET
DODC==120000 ;DESIRED CYLINDER
DOECP==160000 ;ECC POSITION
DOECB==170000 ;ECC BURST (PATTERN)
;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
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
IFN FTKL10,<
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,DODC ;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,DODC ;SET FOR DATAO TO DESIRED CYL
RPXMOV: PUSH P,T2 ;SAVE CYLINDER
MOVSI T2,DOOF ;CLEAR OFFSET REGISTER
PUSHJ P,DODTO
MOVSI T2,DODA ;CLEAR POSSIBLE ILLEGAL
PUSHJ P,DODTO ; SECTOR FROM DESIRED ADR REG
IFN FTKL10,<
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
IFN FTKL10,<
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
IFN FTKL10,<
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 KONEBK
;HERE TO ENABLE ATTEN INTERRUPTS
;HERE FROM RPXI11 WITH T1=RPXGON
ATNENB: LDB T4,KOYPI##
IFN FTKL10,<
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
IFN FTKL10,<
PUSHJ P,SETP14 ;NO. SET UP IVI
MOVSI T1,200000 ;ENABLE FOR ATTENS
>
PJRST ATNENB ;GIVE IT A PI AND EXIT
RPXLTM::LDB T3,UNYPUN## ;UNIT NUMBER
MOVEI T4,3 ;MAKE SURE WE DONT TRY TOO MUCH
MOVSI T2,DOLA(T3) ;READ LOOK-AHEAD REGISTER
IFN FTKL10,<
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)
IFE FTKL10,<
TLNE T1,DIERRS ;ERROR?
>
IFN FTKL10,<
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 - 556 PER SECTOR
IMULI T1,(T2) ;TIMES MICRO-SECS PER SECTOR
PJRST CPOPJ1## ;GOOD RETURN
RPXLT3:
IFN FTKL10,<
SKIPE P1
PUSHJ P,CLRRAE
>
JRST TPOPJ##
RPXRDF::SKIPA T1,[FNCRHD] ;READ HEADERS AND DATA
RPXWTF::MOVEI T1,FNCWTF ;WRITE HEADERS AND DATA (FORMAT)
IFN FTKL10,<
MOVE T2,KONCNT##(J) ;IF WRITING-READING HEADERS AND DATA
IDIVI T2,202 ; SECTORS ARE 202 WORDS LONG
SKIPE T3 ; FILIO COMPUTED CHNNUM BASED 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,UNYBPT## ;IF NOT RP04/6
CAIE T2,^D20
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
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
DPB T3,[POINT 5,T4,27] ;SET T4 FOR DESIRED ADDRESS REGISTER
HRLI T2,DODC ;SET DESIRED CYLINDER
PUSHJ P,DODTO
MOVSI T2,DOOF
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
IFN FTKL10,<
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,KONIOC##(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,DODA ;SET TO DATAO THE RIGHT REGISTER
RPXGO:
IFE FTKL10,<
SETZ T4, ;TURN OF PI FOR THE RH10
>
IFN FTKL10,<
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
LDB T4,UNYPUN## ;UNIT 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
IFN FTKL10,<
JFCL ;KL10 TIMING PROBLEM
>
XCT RPXCO4##(J) ;TURN ON THE PI
PJRST CPOPJ1## ;AND SKIP RETURN
IFN FTKL10,<
;ROUTINE TO SET UP THE INTERRUPT VECTOR ADDRESS FOR AN RH20
RPXIVI: LDB T2,KOYPI##
LSH T2,1 ;CAUSE INTERRUPT AT 40+2N
ADDI T2,40
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:
IFN FTKL10,<
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:
IFN FTKL10,<
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: LDB T1,UNYPUN## ;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
IFE FTKL10,<
PUSHJ P,SETCO ;SET PIA, ATTEN ENABLE
>
IFN FTKL10,<
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,KONEBK##+1(J) ;SET RH (T3) = STATUS
HRL T3,KONEBK##+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:
IFN FTKL10,<
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?
IFE FTKL10,<
TRNN T2,CI.BSY ;YES, KONTROLLER BUSY?
>
IFN FTKL10,<
TRNN T2,CI.BSY+CI.DON ;KONTROL BUSY OR DONE?
>
JRST CONEC1 ;NO, ALL IS OK
IFE FTKL10,<
MOVSI T2,DOCRC
>
IFN FTKL10,<
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
IFN FTKL10,<
XCT RPXCI2##(J) ;RESET T2 TO CONI
>
MOVEI T4,CO.STP+CO.MBE ;YES, CLEAR BUSY, SET DONE
IFN FTKL10,<
TRNE T2,CI.BSY
>
XCT RPXCO4##(J)
AOS UNIHNG##(U) ;BUMP A COUNTER
XCT RPXCI2##(J) ;CONI
IFE FTKL10,<
MOVEI T4,RPALCL
>
IFN FTKL10,<
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
IFN FTKL10,<
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:
IFN FTKL10,<
MOVSI T2,DOSN ;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,DOSR ;SET TO READ DRIVE'S STATUS REGISTER
PUSHJ P,DODTI
TRZ T2,LST+PGM ;DON'T CARE ABOUT LAST SECTOR TRANSFERRED OR PGM
CAIE T2,GUDSTS ;DRIVE OK?
JRST CONERR ;NO
CONEC2: MOVE T2,UNIBLK##(U) ;YES, GET DESIRED BLOCK
LDB T3,UNYBPY## ;BLOCKS PER CYLINDER
TLNE T1,F22 ;IF 22-SECTOR MODE,
IDIVI T2,^D418 ; ADDRESSING IS DIFFERENT
TLNN T1,F22
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:
IFN FTKL10,<
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,DOSN ;WRITE A READ-ONLY REGISTER SO WILL GET
PUSHJ P,DODTO ; INTERRUPT ON RELEASE FROM OTHER PORT
MOVSI T2,DOSR ;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:>
LDB T4,UNYPUN## ;GET UNIT 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,DOSR ;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
LDB T4,UNYPUN##
PUSHJ P,RDREG ;READ DRIVE REGISTERS
PUSHJ P,DVCLR ;NO, CLEAR THE DRIVE
POP P,T1
MOVSI T2,DOSR ;READ STATUS REG
PUSHJ P,DODTI
TRZ T2,LST+PGM
CAIN T2,GUDSTS ;DID DRIVE CLEAR FIX IT?
JRST CONER4 ;YES, RETRY
HRL T2,KONEBK##+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
IFN FTKL10,<
;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,KONEBK##(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: LDB T3,UNYPUN## ;UNIT NUMBER
TLOA T2,(T3) ;SET TO READ IT
DODI4: TLO T2,(T4)
DODIC:
IFN FTKL10,<
SKIPE P1 ;RH20?
TLO T2,(DO.DRE) ;YES, DONT INTERRUPT ON RAE
>
XCT RPXDO2##(J) ;INDICATE WHICH REGISTER WE WANT
IFE FTKL10,<
STALL ;WAIT 3 MICRO-SECS
>
IFN FTKL10,<
PUSH P,T2 ;SAVE REGISTER WE WANT TO READ
IMULI T2,1 ;WAIT (IN CASE RH10)
>
XCT RPXDI2##(J) ;READ THE REGISTER
IFN FTKL10,<
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
IFN FTKL10,<
;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:
IFN FTKL10,<
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: LDB T3,UNYPUN## ;UNIT
TLOA T2,<(DO.LDR)>(T3) ;SET TO WRITE THE REGISTER
DODO4: TLO T2,<(DO.LDR)>(T4)
IFN FTKL10,<
SKIPE P1 ;RH20?
TLO T2,(DO.DRE) ;YES, DONT INTERRUPT ON RAE
>
XCT RPXDO2##(J) ;ZAP
IFN FTKL10,<
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
IFN FTKL10,<
;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
LDB P1,[POINT 3,RPXDI2##(J),5]
CAIE P1,5 ;RH20 DEV CODES ALL START WITH 5
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: LDB T4,KOYPI## ;GET PIA
IFN FTKL10,<
TRO T4,CO.MBE ;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##
LDB T4,UNYPUN##
MOVEI T2,FNCREL ;RELEASE
PUSHJ P,DODO4
PJRST CHKATN
>
;HERE ON INTERRUPT FOR AN RP04
RPXINT::
IFN FTKL10,<
PUSHJ P,SETP1 ;SET P1=0 OR 1 FOR RH10 OR 20
>
XCT RPXDI2##(J) ;SAVE REGISTER THE RH10 WAS CONNECTED TO
PUSH P,T2 ; (MIGHT INTERRUPT BETWEEN DATAO AND ITS DATAI)
PUSH P,J ;SAVE J
PUSHJ P,RPXIN1 ;DO THE REAL INTERRUPT STUFF
POP P,J ;RESTORE J
HLLZ T2,(P) ;GET DRIVE NUMBER, REGISTER NUMBER
TLZ T2,007770
IFN FTDUAL,<
TLNN T2,770000 ;CAN'T WRITE REGISTER 0
TLO T2,010000 ; SINCE THAT WOULD SIEZE THE DRIVE
>
XCT RPXDO2##(J) ;SET THR RH10 BACK TO THAT REGISTER
PJRST TPOPJ## ;AND RETURN (DISMISS INTERRUPT)
;THE "REAL" INTERRUPT ROUTINE....
RPXIN1: MOVSI T2,DOAS ;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?
IFN FTKL10,<
SKIPL RPXGON##(J) ;AND NO (POSSIBLE) POSTPONED ATTN INTERRUPTS
>
JUMPE T2,NOATTN ;NO
HRLI T2,DOAS+<(DO.LDR)> ;YES, SET TO CLEAR WHAT WE READ
PUSH P,T2 ;SAVE IT (CLEAR IF NO ERRORS LATER ON)
IFN FTKL10,<
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,DOAS ;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,KONTBP##(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,UNICHN##(U) ;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,DOSR(T4) ;THIS DRIVE INTERRUPTED
PUSHJ P,DODIC ;READ ITS STATUS REGISTER
HRRZ U,KONTBP##(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,DOAS+<(DO.LDR)>(T4) ; (WILL INTERRUPT AGAIN FOR THE OTHERS)
XCT RPXDO2##(J) ;CLEAR IT
MOVSI T2,DOER3
PUSHJ P,DODI4 ;IF SEEK INCOMPLETE IS ON
TRNN T2,SKI
JRST RPXIN3
MOVSI T2,DOER
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:
IFE FTAUTC,<
JRST RPXIN8 ;CHUCK IT
>
IFN FTAUTC,<
MOVSI T2,DODT ;READ DRIVE TYPE REGISTER
PUSHJ P,DODI4
PUSH P,T1
PUSH P,T4
MOVE T1,T2 ;WHERE AUTCON WANTS IT
MOVS T2,T4 ;UNIT NUMBER, SLAVE 0
PUSH P,J
PUSHJ P,NEWDSK## ;TELL THE WORLD WE'RE HERE
POP P,J
POP P,T4
POP P,T1
JUMPE U,RPXIN8 ;AND TELL FILSER THE DRIVE IS OFF-LINE
>
;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,DOSR(T4) ;DID IT CLEAR?
PUSHJ P,DODIC
TRNN T2,ERR
JRST RPXI3Z ;YES
MOVSI T2,DOER3 ;NO, CLEAR IT THE HARD WAY
PUSHJ P,DODO4
MOVSI T2,DOER2
PUSHJ P,DODO4
MOVSI T2,DOER
PUSHJ P,DODO4
MOVSI T2,DOSR(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##
SYSPIN
MOVE T2,.CPCPN## ;CPU
SETZM CLKMIN##(T2)
POP P,T2 ;PRUNE STACK
LDB T2,KOYPI##
IFN FTKL10,<TRO T2,CO.MBE>
XCT RPXCO2##(J) ;DISABLE ATTENTION INTERRUPTS
PJRST FILDN## ;TELL FILSER AND DISMISS
;HERE ONE SECOND LATER TO RE-ENABLE
RPXENB: HRRZ J,UNIKON##(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
IFN FTKL10,<
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,7 ;START AT HIGH-ORDER DRIVE
LSHC T2,-^D8
RPXI10: JUMPGE T3,RPXI11 ;THIS DRIVE INTERRUPT?
MOVSI T2,DOSR ;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,KONTBP##(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
>
IFN FTKL10,<
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:
IFE FTKL10,<
MOVSI T2,DOCRC ;SET TO READ RH10 CNTRL REG
>
IFN FTKL10,<
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
IFN FTKL10,<
SKIPL RPXFNC##(J) ;IF CALLED FROM RPXSTP
JRST [MOVE U,KONCUA##(J)
SKIPL UNILAS##(U) ;IF DRIVE WAS ON OTHER PORT
LDB T4,UNYPUN## ; 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,DOOF+<(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,DOSR ;READ THE DRIVE STATUS REGISTER
PUSHJ P,DODI4
MOVE T1,T2 ;SAVE STATUS
MOVSI T2,DOER ;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
IFE FTKL10,<
TRNN T2,ALLERR ;ANY ERROR?
>
IFN FTKL10,<
JUMPE P1,DATIN2 ;EASY IF RH10
MOVE T1,KONIOC##(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: LDB T4,KOYPI## ;GET PI CHAN
IFE FTKL10,<
TRO T4,ATTNEN+RPALCL ;CLEAR ERRORS, ENABLE FOR ATTN INTERRUPTS
>
IFN FTKL10,<
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
IFE FTKL10,<
TRNN T2,CHNERR ;CHAN-DETECTED ERROR?
>
IFN FTKL10,<
TDNN T2,[CHNERR
CS.MPE!CS.NXM!CS.OVR](P1)
>
JRST ERROR1 ;NO
IFN FTKL10,<
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
IFN FTKL10,<
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,KONEBK##+16(J) ;GET POSITION
SOJL T1,CPOPJ## ;ERROR IF 0
MOVE T4,KONEBK##+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,DOOF ;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,DOOF ; 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,DOAS ;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,DOAS+<(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
IFN FTKL10,<
PUSHJ P,SETP1
>
SOJN T1,RPXER1 ;IF FIRST ERROR,
MOVSI T2,DOOF ;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,DOOF ;SET TO DO OFFSET
MOVEI T1,FNCOFS ;FUNCTION = OFFSET
TRNE T2,-1 ;IS THIS OFFSET=0?
JRST RPXR2A ;NO--GO DO IT
MOVE T2,KONEBK##+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
RPXCFG:: ;DUMMY ENTRY POINT FOR AUTCON
;HERE TO CHECK CAPACITY & STATUS OF RH10/RP04
RPXCPY::
IFN FTKL10,<
PUSHJ P,SETP1 ;DO MASSBUS ENABLE IF RH20, SET UP P1
>
MOVSI T2,DODT ;READ DRIVE-TYPE REGISTER
PUSHJ P,DODTI4
LDB T3,[POINT 9,T2,35]
CAIE T3,42 ;RP07?
JRST RPXCP1 ;NO
MOVSI T4,U2PNRM##
IORM T4,UNIDS2##(U) ;YES. INDICATE NON-REMOVABLE MEDIA
MOVEI T4,3 ;UNIT TYPE =3
JRST RPXCP2
RPXCP1: CAIL T3,20 ;IN RANGE OF RP04-PR06 ?
CAILE T3,22
JRST RPXCP4 ;NO, NO SUCH DRIVE
CAIE T3,22 ;YES, RP06 ?
TDZA T4,T4 ;NO
MOVEI T4,1 ;YES, UNIT TYPE=1
RPXCP2:
IFN FTDUAL,<
>
MOVEM T2,UNIEBK##+6(U) ;SAVE FOR SYSERR
MOVSI T2,DOSR ;YES, 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
LDB T4,UNYPUN## ; SO DO A PACK ACKNOWLEDGE
PUSHJ P,NOWUP ; SO THAT RELEASE WILL WORK
POP P,T4
RPXCP3:>
MOVSI T2,DOSN ;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,UNISER##(U) ;RETURN SN IN UNISER
>
XCT RPXCI2##(J) ;CONI FN'N T2
TLNE T2,4000 ;22 BIT CHAN?
TLO T4,KOP22B## ;YES
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
CAMN T1,BLKPR7
SKIPA W,[^D43,,^D1376] ;(RP07) BLK/TRK,,BLK/CYL
MOVE W,[^D20,,^D380] ;BLKS PER TRK,, BLKS PER CYL
AOS (P) ;SET FOR SKIP RETURN
JRST RPXCP5 ;CLEAR POSSIBLE RAE AND EXIT
RPXCP4: MOVSI T4,KOPUHE##+KOPNSU## ;OFF LINE OR DOWN
SETZB T1,T2 ;NO BLOCKS PGR UNIT - CANT READ
RPXCP5:
IFN FTKL10,<
IFE FTDUAL,<
JUMPE P1,CPOPJ## ;NO SWEAT IF AN RH10
>
IFN FTDUAL,<
JUMPE P1,RLESE
>
TLO T4,KOP22B## ;RH20'S ARE 22 BIT CHANNEL
PUSH P,T4 ;PRESERVE T4
PUSH P,T2 ;SAVE T2
LDB T4,UNYPUN##
MOVEI T2,1
LSH T2,(T4) ;POSITION BIT TO CLEAR ATTN-SUMMARY REG
HRLI T2,DOAS+<(DO.DRE+DO.LDR)>
XCT RPXDO2##(J) ; WHICH MIGHT BE ON
IFN FTDUAL,<
LDB T4,UNYPUN##
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
PJRST T4POPJ## ;RESTORE T4 AND RETURN
> ;END IFN FTKL10
IFE FTKL10,<
IFN FTDUAL,<
PUSHJ P,RLESE ;DO A DUAL-PORT RELEASE
>
POPJ P,
>
;ENTRY TO READ DRIVE REGS
RPXREG::
IFN FTKL10,<
PUSHJ P,SETP1 ;MASSBUS ENABLE IF RH20
>
LDB T4,UNYPUN## ;DRIVE NUMBER
PUSHJ P,RDREG ;READ REGS
IFE FTDUAL,<
POPJ P, ;RETURN
>
IFN FTDUAL,<
MOVE T2,KONEBK##+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,KONEBK##(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
IFE FTKL10,<
MOVSI T2,DOCRC ;READ RH10 CONTROL REG
>
IFN FTKL10,<
MOVE T2,[DOCRC,, ;OR RH20 PTCR
.DOPTC](P1)
>
PUSHJ P,DODTIC
MOVEM T2,KONECR##(J) ;SAVE IN KDB
IFE FTKL10,<
MOVSI T2,DODB ;READ DATA BUFFER
>
IFN FTKL10,<
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
BLKPRU: DEC 154280 ;406 CYLINDERS
DEC 307800 ;810 CYLINDERS
0 ;(RM03)
BLKPR7: DEC 865504 ;629 CYL, 32 SURF, 43 SECT
BLKPUM: DEC 156180 ;411 CYLINDERS
DEC 309700 ;815 CYLINDERS
0 ;(RM03)
DEC 866880 ;630 CYL *1376
BLKPUC: DEC 171798 ;22*19*411
DEC 340670 ;22*19*815
0
0
$LIT
RPXEND: END