Trailing-Edge
-
PDP-10 Archives
-
dec-10-omona-u-mc9
-
tm2kon.mac
There are 13 other files named tm2kon.mac in the archive. Click here to see a list.
TITLE TM2KON - RH10/TM02 (TU16) DRIVER FOR TAPSER V020
SUBTTL T WACHS/TW 30 NOV 76
SEARCH F,S
$RELOC
$HIGH
;***COPYRIGHT 1975,1976,1977 DIGITAL EQUIPMENT CORP, MAYNARD MASS.****
XP VTM2KN,020
SALL
ENTRY TM2KON
TM2KON::
;DISPATCH TABLE FOR TAPSER CALLS
TM2DSP::JRST TM2INI
JRST TM2RES
JRST TM2SIO
JRST TM2INT
POPJ P,
POPJ P, ;IDLENESS **********
JRST CPOPJ1## ;TEST IF CTL IS ON-LINE
JRST TM2SCH ;CAUSE A SCHEDULE CYCLE
DEFINE STALL,<
XLIST
IMULI P,1
IFN FTKL10,<
IMULI P,1
>
LIST
>
;OFFSETS INTO TKBCCL
TKBFLG==TKBCCL##+2 ;FLAGS FROM FNCTBL
TKBCHR==TKBCCL##+3 ;CHARACTER (FRAME) COUNT
TKBSCH==TKBCCL##+4 ;-1 IF A SCHEDULE CYCLE
SUBTTL PARAMETERS
;DRIVE REGISTERS USED IN DATAO'S
DO.CS1==0B5 ;DRIVE CONTROL REGISTER
DO.DS==1B5 ;STATUS REGISTER
DO.ER==2B5 ;ERROR REGISTER
DO.MR==3B5 ;MAINTENANCE REG
DO.AS==4B5 ;ATTN SUMMARY
DO.FC==5B5 ;FRAME COUNTER
DO.DT==6B5 ;DRIVE TYPE
DO.CK==7B5 ;CHK CHARACTER REG
DO.SN==10B5 ;SERIAL NUMBER
DO.TC==11B5 ;TAPE CONTROL REGISTER
;DRIVE FUNCTIONS LOADED INTO DRIVE CONTROL REG
DF.NOP==1 ;NO-OP
DF.UNL==3 ;UNLOAD (REWIND OFF-LINE)
DF.INT==5 ;ILLEGAL FUNCTION TO CAUSE AN INTERRUPT
DF.REW==7 ;REWIND
DF.CLR==11 ;DRV CLR
DF.RIPS==21 ;READ-IN, PRESET
DF.ERA==25 ;ERASE
DF.WTM==27 ;WRITE TAPE MARK
DF.SPF==31 ;SPACE FWD
DF.SPR==33 ;SPACE REVERSE
DF.WCF==51 ;WRITE CHK FWD (READ FWD)
DF.WCR==57 ;WRITE CHK REV (READ REV)
DF.WTF==61 ;WRITE FORWARD
DF.RDF==71 ;READ FORWARD
DF.RDR==77 ;READ REVERSE
DXES==200000 ;DISABLE XFER ON ERROR STOP BIT
;TAPE CONTROL REGISTER
TC.PAR==1B32 ;ON IF WRITE EVEN PARITY
;DRIVE STATUS REGISTER
DS.ATA==1B20 ;ATTENTION
DS.ERR==1B21 ;COMPOSITE ERROR
DS.PIP==1B22 ;POSITIONING IN PROGRESS
DS.MOL==1B23 ;MEDIUM ON LINE
DS.WRL==1B24 ;WRITE LOCKED
DS.EOT==1B25 ;END OF TAPE
DS.DPR==1B27 ;DRIVE PRESENT
DS.DRY==1B28 ;DRIVE READY (NOT GO)
DS.SSC==1B29 ;SLAVE STATUS CHANGE
DS.PES==1B30 ;PHASE ENCODED STATUS
DS.SDN==1B31 ;SHUTDOWN BIT
DS.IDB==1B32 ;IDENT BURST (FOR PE)
DS.TM==1B33 ;TAPE MARK
DS.BOT==1B34 ;BEGINNING OF TAPE
DS.SLA==1B35 ;SLAVE ATTENTION
DS.OK==DS.EOT!DS.PES!DS.TM!DS.BOT!DS.SSC!DS.SDN!DS.IDB ;BITS WHICH DON'T MATTER
DS.GUD==DS.MOL!DS.DPR!DS.DRY ;THESE BITS MUST BE ON
;DRIVE ERROR REGISTER
ER.COR==1B20 ;CORRECTABLE DATA/ CRC ERROR
ER.UNS==1B21 ;UNSAFE
ER.OPI==1B22 ;OPERATION INCOMPLETE
ER.DTE==1B23 ;DRIVE TIMING ERROR
ER.NEF==1B24 ;NON-EXISTANT FUNCTION
ER.CS==1B25 ;CORRECTABLE SKEW/ ILLEGAL TAPE MARK
ER.FCE==1B26 ;FRAME COUNT ERROR
ER.NSG==1B27 ;NON-STANDARD GAP (CRAP IN THE GAP)
ER.LRC==1B28 ;LRC ERROR/ FORMAT (PREAMBLE POSTAMBLE) ERROR
ER.INC==1B29 ;INCORRECTABLE DATA/ VERTICAL PARITY ERROR
ER.DPA==1B30 ;DATA BUS PARITY ERROR
ER.FMT==1B31 ;FORMAT ERROR
ER.CPA==1B32 ;CBUS PARITY ERROR
ER.RMR==1B33 ;REG MODIFICATION REFUSED
ER.ILR==1B34 ;ILLEGAL REGISTER ADR
ER.ILF==1B35 ;ILLEGAL FUNCTION
;RH10 BITS, FUNCTIONS
DO1CRC==40B5 ;RH10 CONTROL REG
DO1CDB==50 ;RH10 DATA BUFFER
DO1CRA==54B5 ;RH10 RAE REGISTER
;CONI/CONO BITS
;LH BITS
CI1ILF==400 ;ILLEGAL FUNCTION
CI1SDR==200 ;SELECTED DRIVE REGISTER ACCESS ERROR
CI1CDP==4 ;CHAN DATA PARITY ERROR
CI1CWP==2 ;CHAN COMMAND WORD PARITY ERROR
CI1NXM==1 ;CHAN-DETECTED NXM
;RH BITS
CI1DBP==400000 ;DATA BUS PARITY ERROR
CI1EXC==200000 ;EXCEPTION
CI1CER==100000 ;CHAN ERROR (CWPE,CDPE, NXM)
CI1WRT==40000 ;COMMAND WORD WRITTEN
CI1OVR==20000 ;OVERRUN
CI1DRE==10000 ;DRIVE RESPONSE ERROR
CI1ILC==4000 ;ILLEGAL COMMAND
CI1PSF==2000 ;POWER SUPPLY FAILURE
CI1CBO==200 ;CONTROL BUS OVERRUN
CI1RAE==100 ;REGISTER ACCESS ERROR
CI1ATN==40 ;ATTENTION
CI1BSY==20 ;BUSY
CI1DON==10 ;DONE
CO1ATN==40 ;ENABLE FOR ATTENTIONS INTRPTS
CO1STP==20 ;CLEAR BUSY, SET DONE
CI1ERR==536220
CO1CLR==734210 ;CLEAR ALL ERRORS
;DATAI/DATAO BITS
DIERRS==3600 ;DIB ERRORS
CBTO==2000 ;CONTROL BUS TIMEOUT
LR==4000 ;(LH)LOAD REGISTER
;RH20
;REGISTERS
DO.CT2==710000 ;SECONDARY TRANSFER CONTROL
DO.PBA==72B5 ;PRIMARY BLOCK ADDRESS
DO.CT1==73B5 ;PRIMARY TRANSFER CONTROL
DO.IVI==74B5 ;INTERRUPT VECTOR INDEX
;CONI/CONO
CI.RAE==4000 ;REGISTER ACCESS ERROR
CO.RAE==4000 ;CLEAR RAE
CI.ERR==515000
CO.CLR==5010
CO.MBE==400 ;MASSBUS ENABLE
CI.ATN==200 ;ATTENTION (COMES UP EVEN IF NOT ENABLED)
;DATAO
DO.DRE==400 ;DISABLE REGISTER ACCESS ERROR STOP
;DATAO STCR (LH)
D2.RCP==2000 ;RESET CHANNEL PC
D2.SCS==200 ;STORE CHANNEL STATUS
;DATAI
DI.TRA==200 ;TRANSFER (SHOULD BE ON)
DI.CPE==1000 ;CONTROL BUS PARITY ERROR
;CHANNEL LOGOUT AREA
CS1MPE==1B1 ;MEM PARITY ERROR
CS1NSE==1B2 ;NEGATION OF SBUS ERR
CS1NXM==1B4 ;NXM
CS1RHE==1B10 ;RH20 ERROR
CS1LWC==1B11 ;LONG WORD COUNT
CS1SWC==1B12 ;SHORT WORD COUNT
CS1OVR==1B13 ;OVERRUN
CS1ERR==32020,,0 ;ALL CHAN LOGOUT ERRS
;HERE TO START IO
TM2SIO: PUSHJ P,CHKIRB## ;GET IORB FOR THIS OP
JRST TAPDIS## ;NONE, GO AWAY
IFE FTKL10,<
PUSHJ P,SAVE1## ;SAVE P1
>
IFN FTKL10,<
PUSHJ P,SAVST2 ;SAVE ACS, SET P2=0 IF RH10, =1 IF RH20
>
LDB T4,PRBFCN## ;FUNCTION
SKIPN P1,FNCTBL(T4) ;LEGAL?
JRST ILLFNC ;NO
SKIPGE T2,TRBRCT(T1) ;IF POSITIVE IN ERROR RECOVERY
MOVEM T2,TT2UVA##(W) ;REAL IOWD - SAVE IT
LDB T2,[POINT 3,TUBAKA##(U),17] ;YES, GET DRIVE NUMBER
LDB T4,PRBDEN## ;GET DENSITY
CAILE T4,MAXDEN ;LEGAL?
MOVEI T4,MAXDEN ;TOO HIGH - MAKE IT THE HIGHEST
DPB T4,PRBDEN## ;SAVE
SKIPGE T4,DENTBL(T4) ;LEGAL DENSITY?
JRST ILLFNC ;NO
TRO T2,(T4) ;YES, PUT DENSITY INTO COMMAND
MOVSI T4,RB.PAR ;EVEN PARITY?
TDNE T4,TRBLNK(T1)
TRO T2,TC.PAR ;YES, TELL THE HARDWARE
LDB T4,PRBMOD## ;GET MODE
SKIPGE T4,MODTBL(T4) ;LEGAL?
JRST ILLFNC ;NO
TRO T2,(T4) ;YES, TELL THE HARDWARE
MOVEI T3,CO.MBE ;DONT ALLOW INTERRUPTS (BIT IGNORED IF RH10)
XCT TT2CO3##(W) ;(REWINDING DRIVE)
HRLI T2,(DO.TC) ;SET TO TALK TO TAPE CNTRL REG
PUSHJ P,WTREG ;TELL MODE, DENSITY, SLAVE #, PARITY
HRLI T3,-1 ;1ST TIME THROUGH
TM2SI2: MOVSI T2,(DO.DS) ;READ THE STATUS REGISTER OF THE SLAVE
PUSHJ P,RDREGX
TRNE T2,DS.BOT ;BOT?
JUMPL P1,[MOVE P1,FNCNOP ;YES, DONT DO IT
MOVSI T3,RB.SNM!RB.SBT ;IF THE DRIVE IS AT BOT
IORM T3,TRBSTS(T1) ;INDICATE NO MOTION, BOT
JRST .+1] ;AND CONTINUE
TLNN P1,(TB.WRT) ;ARE WE READING?
TRZ T2,DS.WRL ;YES, WRITE-LOCKED TAPE IS OK
SKIPL T3
TRZ T2,DS.ATA ;IF DID A DRIVE CLEAR IGNORE ATTN
TRZ T2,DS.OK ;CLEAR THE BITS WHICH DON'T MATTER
CAIE T2,DS.GUD ;IS THE DRIVE OK?
JRST NOSTRT ;NO, INVESTIGATE FURTHER
;YES, CONTINUE
TLNN P1,(TB.DAT) ;DATA OPERATION?
JRST TM2SI3 ;NO
HLRE T2,TT2UVA##(W) ;YES, GET WORD COUNT
HLRZS T4 ;NO OF FRAMES PER WORD
IMULI T2,(T4) ;COMPUTE FRAME COUNT
MOVNM T2,TKBCHR(W) ;SAVE IN KDB
TLNE P1,(TB.NFC!TB.OFC) ;0 OR -1 TO F.C.?
TM2SI3: SETZ T2, ;YES
TLNE P1,(TB.NFC!TB.DAT) ;IF T2 IS ALREADY SET,
JRST NOFC ;GO
TLNE P1,(TB.OFC) ;IF -1 TO F.C.
SOJA T2,NOFC ;GO
MOVN T2,TRBXCW(T1) ;GET -NO OF RECS TO SPACE
NOFC: ANDI T2,177777 ;ONLY 16 BIT'S WORTH
HRLI T2,(DO.FC) ;TALK TO FRAME COUNT REG
PUSHJ P,WTREGX ;TELL IT HOW MUCH TO DO
TM2SI4: HRRZ T2,TKBICP##(W) ;ICWA
HRRZ T3,TRBXCW(T1) ;CHAN LIST
IFN FTKL10,<
SKIPE P2 ;IF AN RH20,
TLO T3,RH2JMP## ; MAKE A JUMP-WORD
>
MOVEM T3,(T2) ;POINT ICWA AT IO LIST
IFN FTKL10,<
SKIPE P2 ;IF AN RH20,
TDZA T2,T2 ; ICWA ISNT IN COMMAND
>
LSH T2,6 ;POSITION ICWA FOR DATAO
TRO T2,(P1) ;INSERT FUNCTION
TLNE P1,(TB.DAT) ;TALK TO CS1 IF SPACE OP,
IFE FTKL10,<
TDO T2,[DO1CRC!DXES] ;TALK TO RH10 IF DATA OP
>
IFN FTKL10,<
TDO T2,[DO1CRC!DXES;TALK TO RH10 CNTRL REG
DO.CT2!D2.RCP!D2.SCS,,377700](P2) ;OR RH20 CNTRL REG
>
MOVEM T2,TT2REG##+3(U) ;SAVE LAST COMMAND IN UDB
MOVEM P1,TKBFLG(W) ;REMEMBER WHAT WE ARE DOING
PUSHJ P,WTREG ;GO START UP THE WORLD
MOVEI T3,TAPCHN##+CO.MBE ;PIA
TLNN P1,(TB.DAT) ;DATA OPERATION?
TRO T3,CO1ATN ;NO, ENABLE FOR ATTENTIONS
;CONTINUE
IFN FTKL10,<
JUMPE P2,TM2SI6 ;NO SWEAT IF RH10
MOVEI T2,CI.ATN ;IF A DATA OPERATION
TLNE P1,(TB.DAT) ; WE DONT ENABLE FOR ATTENTIONS
ANDCAM T2,TKBCSO##(W) ; BUT THE ATTEN BIT LIGHTS IN CONI ANYWAY
XCT TT2CI2##(W) ;DID WE WIN IN THE SETUP?
TRNE T2,CI.RAE
TRO T3,20 ;NO, CAUSE AN IMMEDIATE INTERRUPT
MOVE T2,TT2IVO## ;SET UP INTERRUPT VECTOR ADDRESS
XCT TT2DO2##(W)
>
TM2SI6: XCT TT2CO3##(W) ;TURN ON RH10 PI
POPJ P, ;GO AWAY AND WAIT FOR INTERRUPT
;HERE IF THE DRIVE STATUS REGISTER ISN'T RIGHT
NOSTRT: CAIE T2,DS.GUD!DS.WRL ;ONLY WRITE-LOCK?
JRST BADSTS ;NO, IT REALLY IS BAD
SKIPA T2,[RB.SLK!RB.SER,,] ;WRITE-LOCKED
ILLFNC: MOVSI T2,RB.SER!RB.SIL ;ILLEGAL FUNCTION
ILLORM: IORM T2,TRBSTS(T1) ;TELL TAPUUO WHAT THE PROBLEM IS
MOVE P1,FNCNOP ;DO AN OP TO GET TO PI LEVEL
LDB T2,[POINT 3,TUBAKA##(U),17]
HRLI T2,(DO.TC) ;TELL THE TM02 WHAT DRIVE
PUSHJ P,WTREG
JRST TM2SI4 ;GO CAUSE AN INTERRUPT
BADSTS: JUMPL T3,BADST2 ;IF NOT FIRST TIME,
MOVSI T2,TKSOFL ;SET DRIVE OFF-LINE
IORM T2,TUBSTS##(U)
MOVSI T2,RB.SOL!RB.SER ;SAY THE DRIVE IS DOWN
JRST ILLORM
BADST2: MOVSI T2,(DO.TC) ;FIRST TIME-CLEAR DRIVE
PUSHJ P,RDREGX
PUSH P,T2 ;SAVE TAPE CNTRL REG
PUSHJ P,CLRDRV ;DRVPOL CHANGES TC REG
POP P,T2
HRLI T2,(DO.TC)
PUSHJ P,WTREGX ;RESTORE TC REG
JRST TM2SI2 ;AND TRY AGAIN
;INTERRUPT CODE
TM2INT: MOVE U,TKBCUN##(W) ;UNIT WE'RE TALKING TO (MAYBE)
MOVE U,(U)
PUSHJ P,SAVE3## ;SAVE SOME ACS
IFN FTKL10,<
PUSHJ P,SETP2 ;SET P2=0 IF RH10, =1 IF RH20
XCT TT2CI2##(W) ;CONI
TRNE T2,CI.RAE ;REGISTER ACCESS ERROR?
JRST TM2IN3 ;YES, GO CLEAR IT AND RETRY
>
MOVSI T2,(DO.DS) ;READ STATUS REGISTER NOW, TALKING
PUSHJ P,RDREG ; TO TC REG LATER MAY CHANGE IT
PUSH P,T2 ;SAVE STATUS REG
SETZ T3, ;TALK TO THE TM02, UNIT 0 WILL DO
MOVSI T2,(DO.AS) ;READ THE ATTN SUMMARY REGISTER
PUSHJ P,RDREGX
ANDI T2,377 ;JUST THE ATTENTION BITS
JUMPE T2,TM2IN2 ;GO IF NO ATTN IS UP
HRLI T2,(DO.AS) ;CLEAR THE BITS WE JUST READ
PUSHJ P,WTREGX
HRRZ T1,T2
TM2IN1: LSHC T1,-1 ;NEXT UNIT
JUMPGE T2,NXTM02 ;GO IF ATTN NOT UP FOR IT
MOVE T4,T3 ;SAVE UNIT NUMBER
LSH T4,3 ;POSITION TO RIGHT PLACE
PUSHJ P,DRVPL1 ;POLL THE DRIVES FOR REW DONE
NXTM02: JUMPE T1,TM2IN2 ;GO IF ALL DONE
AOJA T3,TM2IN1 ;THERE IS ANOTHER - TEST NEXT UNIT
;HERE AFTER ALL ATTN'S HANDLED, IF THERE WERE ANY
TM2IN2: LDB T2,[POINT 3,TUBAKA##(U),17] ;SLAVE NUMBER
HRLI T2,(DO.TC) ;SET TO RECONNECT TO DRIVE, DRVPOL MIGHT HAVE
PUSHJ P,WTREG ; SET TO TALK TO ANOTHER SLAVE
POP P,T4 ;STATUS REGISTER
TM2IN3: SKIPL T1,TKBSCH(W) ;SCHEDULE CYCLE?
SKIPN T1,TKBFLG(W) ;OR OPERATION IN PROGRESS?
JRST [SETZM TKBSCH(W)
PJRST CLRCTL] ;RETURN 0 OR -1 TO TAPSER
SETZM TKBFLG(W) ;NOW NO OP IS GOING
MOVE P1,T1 ;FLAGS IN P1
LDB P3,[POINT 4,P1,17] ;INDEX FOR FUNCTION IN P3
PUSHJ P,CHKIRB## ;GET THE IORB
JRST TAPDIS## ;NOTHING THERE - GO AWAY
XCT TT2DI2##(W) ;DATAI
HLL T3,T2 ;SAVE (DBTO,CBTO)
XCT TT2CI2##(W) ;CONI
TLNN T3,CBTO ;IF NOT CNTRL BUS TIMEOUT
TRZ T2,CI1DRE ; IGNORE DRIVE RESPONSE ERR
IFE FTKL10,<
TRNE T2,CI1ERR ;ERROR?
>
IFN FTKL10,<
JUMPE P2,TM2IN4 ;EASY WIN IF RH10
MOVE T3,TKBICP(W) ;RH20, GET LOGOUT AREA
HLL T2,1(T3) ;GET ERROR BITS FROM ICWA+1
TLNN P1,(TB.DAT) ;IF NOT A DATA OPERATION
TLZA T2,-1 ; IGNORE ERROR BITS, THEY'RE USELESS
TLC T2,(CS1NSE) ;MAKE BIT=1 IF AN ERROR
TM2IN4: TDNE T2,[CI1ERR ;ERROR?
CS1ERR!CI.ERR](P2)
>
JRST CHNERR ;TOO BAD!
CAIN P3,RB.FYB ;YELLOW BALL/ILLEGAL FNCTN?
JRST INTNOP ;YES, GO HANDLE IT
TRNN T4,DS.ERR ;ERROR?
JRST TSTERR ;NO
MOVSI T2,(DO.ER) ;YES, READ ERROR REG
PUSHJ P,RDREG ;(ONLY CALL RDREG ON "REAL" ERROR)
HRL T4,T2 ;T4=ERROR,,STATUS
JRST TSTBOT
TSTERR: SKIPE TUBERR##(U) ;IN ERROR RETRY?
PUSHJ P,RDREGS ;YES, GET FINAL (GOOD) REGISTERS
TSTBOT: MOVSI T2,TUSBOT## ;CLEAR BOT
ANDCAM T2,TUBSTS##(U)
TRNE T4,DS.BOT ;AND SET IT IF WE REALLY ARE
IORM T2,TUBSTS##(U) ; AT BOT
MOVSI T2,TUSWTL## ;CLEAR WRITE-LOCK
ANDCAM T2,TUBSTS##(U)
TRNE T4,DS.WRL ;AND SET IT AGAN IF WE REALLY ARE
IORM T2,TUBSTS##(U) ; WRITE LOCKED
TRNN T4,DS.BOT ;AT BOT?
JRST TSTMOV ;NO
TLO T1,RB.SBT ;YES, TELL TAPUUO
PUSHJ P,UNIBOT## ;CLEAR TUBREC,FIL; SET TUBSTS
JUMPGE P1,TSTMOV ;IF WE MOVED BACKWARDS INTO BOT,
TLZE T4,ER.OPI!ER.NEF ; THESE REALLY AREN'T ERRORS
JRST NOMOVE ;IF ON WE DIDN'T MOVE TAPE
TSTMOV: TLNN T4,ER.ILF!ER.RMR!ER.NEF!ER.UNS
JRST MOVED ;TAPE REALLY MOVED
TLOA T1,RB.SNM!RB.SED ;TAPE DIDN'T MOVE
NOMOVE: TLO T1,RB.SNM
JRST TM2GO ;CONTINUE
MOVED: TLNE P1,(TB.REV) ;REVERSE?
SOSA TUBREC##(U) ;DECR OR INCR RECORD COUNT
AOS TUBREC##(U)
TRNN T4,DS.TM ;PASS OVER (OR JUST WROTE) EOF?
JRST NOTM ;NO
TLNE P1,(TB.REV) ;YES, INCR OR DECR FILE COUNT
SOSA TUBFIL##(U)
AOS TUBFIL##(U)
SETZM TUBREC##(U) ;AT 0TH RECORD ********* -1 IF REV?
TLNN P1,(TB.WRT) ;IF NOT WRITING AN EOF,
TLO T1,RB.STM ; TELL TAPUUO WHAT WE SAW
NOTM: TLNE P1,(TB.WRT) ;IF WRITING,
TRNN T4,DS.EOT ;AND WE SAW EOT
CAIA
TLO T1,RB.SET ;TELL TAPUUO
TM2GO: JRST @INTABL(P3) ;GO TO SPECIFIC INTRPT HANDLER
INTABL: TAPIFI##
INTRD ;(1)READ FORWARD
INTWRT ;(2)WRITE
INTRD ;(3)READ BACKWARDS
INTSPC ;(4)SKIP RECORD
INTSPC ;(5)BACKSPACE RECORD
TAPIFI## ;(6)SKIP FILE
TAPIFI## ;(7)BACKSPACE FILE
INTERA ;(10)ERASE GAP
TAPIFI## ;(11)DATA SECURITY ERASE
INTREW ;(12)REWIND
INTUNL ;(13)UNLOAD
INTWTM ;(14)WRITE TAPE MARK
INTNOP ;(15)YELLOW BALL/ILLEGAL FUNCTIONS
INTRD ;(16)CORRECTION READ
INTRD ;(17)LOW-THRESHOLD READ
;HERE ON READ INTERRUPT
INTRD: MOVSI T2,(DO.FC) ;READ THE FRAME COUNTER
PUSHJ P,RDREG
MOVEM T2,TRBRCT(T1) ;SAVE CHAR-COUNT OF RECORD
MOVEM T2,TUBCCR##(U)
ADDM T2,TUBCRD##(U) ;UPDATE TOTAL STATS
CAMLE T2,TKBCHR(W) ;TOO LARGE A RECORD?
TLO T1,RB.STL!RB.SER ;YES, TELL TAPUUO
LDB T3,PRBMOD## ;MODE
IDIV T2,TMODTB##(T3);COMPUTE NUMBER OF WORDS XFERRED
HRLM T2,TUBCHR##(U) ;SAVE WORDS
DPB T3,PMTNCR## ;SAVE RESIDUE
CAIE P3,RB.FRB ;IF READ BACKWARDS
JRST DONE
SKIPE T3 ;IF NOT EVEN NO OF WORDS
ADDI T2,1 ;BUMP WRDCNT
JUMPE T2,DONE
HRRZ P1,TT2UVA##(W) ;GET USER VIRTUAL ADDRESS
IFN FTKA10,<
TLO P1,R
>
IFN FTKI10!FTKL10,<
MOVE F,TUBCUR##(U) ;MAKE JOB ADDRESSABLE
PUSHJ P,SVEUF##
>
PUSH P,T1
LDB T3,PRBMOD## ;SINCE THE TM02 READS BACKWARDS
MOVE T2,TKBCHR(W) ; IN REVERSE ORDER, HALVES SWAPPED
IDIV T2,TMODTB##(T3) ; WE HAVE TO REARRANGE THE DATA
AOS P3,P1 ;FIRST WORD
ADDI P3,-1(T2) ;LAST WORD
LSH T2,-1
INTRD1: EXCTUX <MOVE T3,@P1> ;GET 2 WORDS
EXCTUX <MOVE T1,@P3>
EXCTXU <MOVSM T3,@P3> ;SWAP HALVES AND INVERT ORDER
EXCTXU <MOVSM T1,@P1>
ADDI P1,1
SUBI P3,1
SOJG T2,INTRD1 ;DO FOR WHOLE BLOCK
POP P,T1
CAMN P1,P3 ;IF AN ODD NUMBER OF WORDS,
EXCTUU <MOVSS @P1> ; SWAP HALVES OF MIDDLE WORD OF BLOCK
;HERE AFTER AN OPERATION IS THROUGH
DONE: TLNE T4,-1 ;ERROR BIT UP?
PUSHJ P,TM2ERR ;YES, GO HANDLE IT
TRBSTO: HLLZ T2,T1 ;BITS WE WANT TO TELL TAPUUO ABOUT
IORM T2,TRBSTS(T1) ;STORE IN THE IORB
TRBEXC: MOVSI T2,RB.EXC
TLZE T1,-1 ;ANY FUNNY THINGS?
IORM T2,TRBLNK(T1) ;YES, AN EXCEPTION HAS OCCURRED
CLRCTL:
IFE FTKL10,<
MOVEI T3,CO1CLR ;CLEAR ALL ERRORS
>
IFN FTKL10,<
MOVE T3,[CO1CLR
CO.CLR+CO.MBE](P2)
>
XCT TT2CO3##(W)
CLRCTX:
IFN FTKL10,<
MOVEI T2,CI.ATN ;IF AN RH20 WE MIGHT HAVE CLEARED ATTEN
SKIPE P2 ; FROM THE CONSO MASK,
IORM T2,TKBCSO##(W) ; SO RESET IT
>
MOVEI T3,TAPCHN##+CO1ATN+CO.MBE ;ENABLE FOR INTERRUPTS
XCT TT2CO3##(W)
SETZM TKBFLG(W) ;NOTHING HAPPENING NOW
POPJ P, ;AND RETURN
;HERE ON WRITE INTERPT
INTWRT: MOVE T2,TKBCHR(W) ;NO OF FRAMES WE WROTE
ADDM T2,TUBCWR##(U) ;UPDATE STATS
JRST DONE ;AND FINISH UP
INTSPC: JRST DONE
INTWTM: JRST DONE
INTERA: SOS TUBREC##(U) ;IT ISN'T ANOTHER RECORD
JRST DONE
INTUNL: MOVSI T2,TKSOFL## ;CLEAR OFF-LINE SO TAPSER
ANDCAM T2,TUBSTS##(U) ; WON'T GRUMBLE AT USER
TLO T1,RB.SOL ;SAY DRIVE IS OFF-LINE
INTREW: MOVSI T2,TUSREW## ;SAY WE'RE REWINDING
IORM T2,TUBSTS##(U)
TRNN T4,DS.PIP ;ARE WE?
PUSHJ P,REWDON## ;NO, MUST HAVE FINISH
SETZM TUBREC##(U) ;CLEAR STATS
SETZM TUBFIL##(U)
JRST DONE ;AND FINISH UP
INTNOP: PUSHJ P,CLRDRV ;CLEAR THE DRIVE
HLL T1,TRBSTS(T1) ;GET ERROR BITS
JRST TRBEXC ;SET EXCEPTION IF AN ERROR
;HERE ON CONI ERROR BIT
CHNERR:
IFE FTKL10,<
TLNN T2,CI1SDR ;SELECTED DRIVE RAE?
>
IFN FTKL10,<
TDNN T2,[CI1SDR,,
CI.RAE](P2)
>
JRST NORAE ;NO
IFN FTKL10,<
JUMPE P2,CHNER1
TLO T1,RB.SNM!RB.SED ;YES, NO TAPE MOTION+ERROR
JRST TRBSTO
CHNER1:>
MOVEI T2,1 ;YES, POSITION A BIT
LDB T3,[POINT 3,TUBAKA##(U),14]
LSH T2,(T3)
HRLI T2,(DO1CRA) ;CLEAR REG ACCESS ERROR
PUSHJ P,WTREG
JRST CHNRTY ;AND RETRY THE OPERATION
NORAE:IFE FTKL10,<
TLNN T2,CI1CDP!CI1CWP!CI1NXM ;MEMORY ERR?
>
IFN FTKL10,<
TDNN T2,[CI1CDP!CI1CWP!CI1NXM,,
CS1MPE!CS1NXM](P2)
>
JRST CHNRTY ;NO, JUST RETRY
PUSHJ P,SAVE1## ;YES
MOVEI T3,CHNNXM## ;SET TO CALL RIGHT ROUTINE
IFE FTKL10,<
TLNN T2,CI1NXM ;NXM?
>
IFN FTKL10,<
TDNN T2,[CI1NXM,,
CS1NXM](P2)
>
MOVEI T3,CHNMPE##
PUSH P,T1 ;SAE T1
HRRZ T1,TKBICP##(W) ;T1=ICWA
HRRZ P1,TKBCDB##(W) ;P1=CDB
PUSHJ P,(T3) ;GO CALL ERRCON
POP P,T1
CHNRTY: TLO T1,RB.SED ;INDICATE AN ERROR
PJRST TRBSTO ;FINISH UP
;HERE ON ERROR BIT IN TM02
TM2ERR: TLNN T4,ER.UNS!ER.FMT!ER.ILR!ER.ILF!ER.OPI!ER.NEF
JRST TM2ER1 ;NOT AN IMMEDIATE PROBLEM
TLNE T4,ER.UNS ;REALLY BAD PROBLEM
TLO T1,RB.SOL ;OFFLINE IF UNSAFE IS UP
TLO T1,RB.SED!RB.SER ;NON-RECOVERABLE ERROR
PJRST CLRDRV ;DRIVE-CLEAR AND RETURN
TM2ER1: TLNE P1,(TB.WRT) ;IF READING,
JRST TM2ER2
TLZ T4,ER.NSG!ER.FCE ;THESE AREN'T ERRORS
TRNE T4,DS.PES ;IF IN PE MODE
TLZ T4,ER.COR!ER.CS!ER.LRC ;THESE AREN'T ERRORS
TM2ER2: TLNN T4,ER.COR!ER.CS!ER.FCE!ER.NSG!ER.LRC!ER.DPA!ER.INC!ER.DTE!ER.CPA
PJRST CLRDRV ;NOT A "REAL" ERROR, CLEAR DRIVE AND RETURN
TLNN T4,ER.COR!ER.CS!ER.INC!ER.LRC ;REAL ERROR
TLOA T1,RB.SED ;PLAIN ERROR
TLO T1,RB.SDE!RB.SED ;DATA ERROR
PUSHJ P,RDREGS ;READ DRIVE REGS INTO UDB
;FALL INTO CLRDRV AND RETURN
;DUE TO THE PROBLEM OF DRIVE CLEAR MAKING DS.SSC GO AWAY
; IF SOME OTHER SLAVE BROUGHT IT UP, WE HAVE TO POLL THE DRIVES
; AFTER A DRIVE CLEAR TO FIND ANY THAT MAY HAVE FINISHED REWINDING
CLRDRV: MOVEI T2,DF.CLR ;CLEAR THE DRIVE
PUSHJ P,WTREG
DRVPOL: PUSH P,T4 ;SAVE T4
PUSHJ P,.+2
PJRST T4POPJ## ;RESTORE T4 AND RETURN
HLRZ T4,TUBAKA##(U) ;TM02 # + SLAVE NUMBER
ANDI T4,70 ;TM02 NUMBER
DRVPL1: MOVE T2,T4
ADD T4,TKBIUN##(W) ;POSITION TO RIGHT PART OF KDB
LSH T2,^D21 ;SHIFT TM02 #
ADD T2,T4 ;FORM LH OF AOBJN WORD
JUMPGE T2,CPOPJ## ;WE DON'T KNOW ABOUT THIS TM02 IF NOT NEG.
PUSHJ P,SAVE3## ;SAVE SOME ACS
PUSH P,U ;SAVE U
HRLI T4,P1 ;SET INDEX FOR RIGHT SLAVE NUMBER
MOVSI T2,(DO.DS) ;READ STATUS REG
PUSHJ P,RDREGX
TRNN T2,DS.SSC ;SLAVE STATUS CHANGE?
JRST DRVPL2 ;NO
MOVSI P1,-10 ;YES, HAVE TO FIND A DRIVE
MOVSI T3,TUSREW## ; WE CAN CLEAR - ANY SLAVE WHICH ISNT
FNDCLR: SKIPE T2,@T4 ; REWINDING WILL DO (EVEN NON-EXISTENT ONES)
TDNN T3,TUBSTS##(T2)
JRST FNDCL2 ;THIS ONE IS OK
FNDCL1: AOBJN P1,FNDCLR ;REWINDING - TRY NEXT DRIVE
MOVEI P1,7 ;NONE THERE, TRY DRIVE 7
FNDCL2: SKIPE T2,TKBFLG(W) ;IF WE'RE ACTIVELY TALKING TO A DRIVE
HRRZ T2,TKBCUN##(W) ;DONT CLEAR THAT DRIVE
CAIN T2,@T4
JUMPL P1,FNDCL1 ;SO TRY ANOTHER
MOVE T2,P1 ;WE CAN DO A DRIVE CLEAR ON THIS ONE
HRLI T2,(DO.TC) ;TALK TO THIS DRIVE
PUSHJ P,WTREGX
MOVEI T2,DF.CLR ;DO A DRIVE CLEAR
PUSHJ P,WTREGX
DRVPL2: MOVSI P1,-10 ;SET TO LOOK AT ALL DRIVES
DRVPL3: SKIPN U,@T4 ;POINT U AT UDB
JRST UPOPJ## ;NONE, WE'RE DONE
MOVSI T2,(DO.TC) ;SET TO TALK TO THIS DRIVE
HRR T2,P1
PUSHJ P,WTREGX ;CONNECT TO IT
MOVSI T2,(DO.DS)
PUSHJ P,RDREGX ;READ STAUS REGISTER
MOVSI P3,TKSOFL##
IFN FTMDA,<
TDNE P3,TUBSTS##(U) ;IF DRIVE WAS OFF-LINE
TRNN T2,DS.MOL ; AND IS NOW ON-LINE
CAIA
PUSHJ P,NOWON ;LET THE WORLD KNOW
>
TRNE T2,DS.MOL ;OFF LINE?
ANDCAB P3,TUBSTS##(U) ;NO
TRNN T2,DS.MOL
IORB P3,TUBSTS##(U) ;YES
TLNE P3,TUSREW## ;WAS IT LAST REWINDING?
TRNE T2,DS.PIP ;YES, IS IT NOW
JRST DRVPL4 ;YES, CONTINUE WITH NEXT DRIVE
PUSHJ P,REWDON## ;THROUGH REWINDING, TELL TAPUUO
DRVPL4: AOBJN P1,DRVPL3 ;GO TEST NEXT DRIVE
JRST UPOPJ## ;DONE, RETURN
IFN FTMDA,<
;SUBROUTINE TO TELL TAPUUO WHEN A SLAVE COMES ON-LINE
;PRESERVES ALL ACS
NOWON: PUSHJ P,SAVT## ;SAVE T1-T4
PJRST TPMONL## ;AND TELL TAPUUO
>
;HERE TO INITIALIZE THE TM02
TM2INI: MOVEI T1,TUCIRD## ;TELL TAPUUO WE GET AN INTERRUPT
MOVE T2,TKBCUN##(W) ; WHEN A REWIND FINISHES
TM2INL: SKIPE T3,(T2) ;NEXT DRIVE
IORM T1,TUBSTS##(T3);SET BIT IN IT
AOBJN T2,TM2INL
IFN FTKL10,<
PUSHJ P,SAVST2 ;SAVE ACS, SET UP P2
>
PUSH P,F ;SAVE F FOR SYSINI
MOVE T1,DEVNAM(F) ;GET NAME AS SET UP BY COMDEV
MOVE T4,TKBIUN##(W) ;SET TO LOOP OVER ALL UNITS
TM2INN: SKIPN U,(T4) ;GET A UNIT
JRST TM2INX ;NOT THERE
HRRZ T2,TUBADR##(U) ;HET UDB
DPB T2,PUNIT## ;STORE RIGHT UNIT
LSHC T2,-3 ;SET RIGHT NAME IN DDB
LSH T2,^D15
LSHC T2,3 ;HAVE TO FIDDLE CAUSE MORE THAN 1 TM02 DOES
ADD T2,T1 ; VERY FUNNY THINGS TO THE NAMES
MOVEM T2,DEVNAM(F) ;EG MTA21
LDB T2,[POINT 3,TUBAKA##(U),17]
HRLI T2,(DO.TC) ;SELECT RIGHT SLAVE
PUSHJ P,WTREG
MOVSI T2,(DO.SN) ;READ SERIAL NUMBER
PUSHJ P,RDREG ;AND STORE IN UDB
MOVEM T2,TT2REG##+14(U) ;FOR DIAGNOSTICS
MOVSI T2,(DO.DS) ;READ STATUS REG
PUSHJ P,RDREG
MOVSI T3,TKSOFL##
TRNN T2,DS.MOL ;IF NOT MEDIUM-ON-LINE
IORM T3,TUBSTS##(U) ; THE DRIVE IS OFF-LINE
HLRZ F,DEVSER(F)
TM2INX: AOBJN T4,TM2INN
POP P,F
IFE FTKL10,<
MOVEI T1,CI1DON+CI1ATN ;WHAT WE WANT TO INTERRUPT ON
>
IFN FTKL10,<
MOVE T1,[CI1DON+CI1ATN
CI.RAE+CI.ATN+CI1DON](P2)
>
HRRM T1,TKBCSO##(W) ;SET IN CONSO
IFN FTKL10,<
JUMPE P2,CLRCTL ;EASY IF RH10
MOVEI T3,CO.MBE!CO.RAE ;RH20, CLEAR POSSIBLE REG ACCESS ERROR
XCT TT2CO3##(W) ; (ON IF NON-EX DRIVE)
MOVE T2,TT2IVO## ;SET UP INTERRUPT VECTOR ADDR
XCT TT2DO2##(W)
>
JRST CLRCTL ;CLEAR RH10 AND RETURN
;HERE TO CAUSE A SCHEDULE CYCLE
TM2SCH:
IFN FTKL10,<
PUSHJ P,SAVST2 ;SAVE ACS, SET UP P2
>
SETOM TKBSCH(W) ;SET FLAG
JRST TM2RS1 ;CAUSE AN INTERRUPT
;HERE TO RESET AN ACTIVE DRIVE
TM2RES:
IFN FTKL10,<
PUSHJ P,SAVST2 ;SAVE ACS, SET UP P2
>
PUSHJ P,CLRDRV
TM2RS1: MOVEI T3,CO1STP ;CLEAR BUSY, SET DONE
XCT TT2CO3##(W) ;DO IT
JRST CLRCTX ;CLEA RH10 AND RETURN
;READ A REGISTER - ENTER, EXIT WITH FNCN IN T2
;RESPECTS T1,T4
RDREG: LDB T3,[POINT 3,TUBAKA##(U),14] ;TM02 NUMBER
RDREGX: TLO T2,(T3)
IFN FTKL10,<
SKIPE P2 ;IF AN RH20,
TLO T2,DO.DRE ; DISABLE REGISTER ACCESS ERR INTERRUPT
>
XCT TT2DO2##(W) ;SAY WHAT WE WANT TO READ
STALL
XCT TT2DI2##(W) ;READ IT
ANDI T2,177777 ;ONLY 16 BITS
POPJ P, ;AND RETURN
;ROUTINE TO WRITE A REGISTER
;ENTER T2=WHAT TO DO THE DATAO WITH
;RESPECTS T1, T4
WTREG: LDB T3,[POINT 3,TUBAKA##(U),14] ;TM02 NUMBER
WTREGX: TLO T2,LR(T3) ;LIGHT LR
IFN FTKL10,<
SKIPE P2 ;IF AN RH20,
TLO T2,DO.DRE ;NO INTERRUPT ON RAE
>
XCT TT2DO2##(W) ;DATAO
POPJ P, ;AND RETURN
IFN FTKL10,<
;PRESERVES T1
SAVST2: POP P,T4 ;SAVE RETURN ADDRESS
PUSHJ P,SAVE2## ;SAVE P1,P2
PUSH P,T4 ;RESTORE RETURN ADDR
;SUBROUTINE TO SET UP P2 =0 FOR RH10, =1 FOR RH20
;PRESERVES T1,T4
SETP2: LDB P2,[POINT 3,TT2DO2##(W),5] ;GET CONTROLLER CODE
CAIE P2,5 ;RH20?
TDZA P2,P2 ;NO, P2=0
MOVEI P2,1 ;YES, P2=1
JUMPE P2,CPOPJ## ;GO IF AN RH10
MOVEI T3,CO.MBE ;RH20, ENSURE THAT MASSBUS IS ENABLED
XCT TT2CO3##(W)
POPJ P, ;AND REURN
>
;ROUTINE TO READ REGISTERS ON ERROR
RDREGS: XCT TT2CI2##(W)
MOVEM T2,TT2REG##(U) ;SAVE CONI
IFE FTKL10,<
MOVSI T2,(DO1CRC)
>
IFN FTKL10,<
MOVE T2,[DO1CRC
DO.CT1](P2)
>
PUSHJ P,RDREG
MOVEM T2,TT2REG##+1(U) ;DATAI RH10 CNTRL REG
IFE FTKL10,<
MOVSI T2,(DO1CDB)
>
IFN FTKL10,<
MOVE T2,[DO1CDB
DO.PBA](P2)
>
PUSHJ P,RDREGX
MOVEM T2,TT2REG##+2(U) ;DATAI RH10 DATA BUFFER
PUSH P,T1
MOVEI T1,TT2REG##+4(U) ;(REG+3 = LAST COMMAND)
HRLI T1,-12 ;READ 12 REGISTERS
SETZ T2, ; STARTING AT 0
RDREG1: PUSHJ P,RDREGX
MOVEM T2,(T1) ;STORE DATA IN UDB
HLRZ T2,T1 ;SET FOR NEXT REGISTER
ADDI T2,13
LSH T2,^D18+14
AOBJN T1,RDREG1
JRST TPOPJ##
;TABLES TO CONTROL IO
TB.REV==1B0
TB.WRT==1B1
TB.DAT==1B2
TB.SPC==1B3
TB.RD==1B4
TB.ERA==1B5
TB.WTM==1B6
TB.NFC==1B7
TB.OFC==1B8 ;SET -1 IN FRAME COUNTER
TB.REW==1B9
FNCTBL: 0 ;0 - ILLEGAL
TB.DAT!TB.RD!TB.NFC!DF.RDF!1B17 ;1 - READ FORWARD
TB.WRT!TB.DAT!DF.WTF!2B17 ;2 - WRITE
TB.DAT!TB.RD!TB.NFC!TB.REV!DF.RDR!3B17 ;3 - READ REVERSE
TB.SPC!DF.SPF!4B17 ;4 - SKIP RECORD
TB.SPC!TB.REV!DF.SPR!5B17 ;5 - BACKSPACE RECORD
0 ;6 - SKIP FILE (ILLEGAL)
0 ;7 - BACKSPACE FILE (ILLEGAL)
TB.WRT!TB.ERA!TB.OFC!DF.ERA!10B17 ;10 - ERASE
0 ;11 - DATA SECURITY ERASE (ILLEGAL)
TB.NFC!TB.REW!TB.REV!DF.REW!12B17 ;12 - REWIND
TB.NFC!DF.UNL!13B17 ;13 - REW, UNLOAD
TB.WRT!TB.WTM!TB.OFC!DF.WTM!14B17 ;14 - WRITE TAPE MARK
FNCNOP: TB.SPC!DF.INT!15B17 ;15 - YELLOW BALL
TB.DAT!TB.RD!TB.NFC!DF.RDF!16B17 ;16 - CORRECTION READ
TB.DAT!TB.RD!TB.NFC!DF.RDF!17B17 ;17 - LOW THRESHOLD READ
;FRAMES/WORD,,MODE
MODTBL: -1 ;0 - ILLEGAL
5,,0B31 ;1 - CORE DUMP
4,,3B31 ;2 - BYTE (4 B-BIT BYTES/WRD)
-1 ;3 -SIXBIT...ILLEGAL
5,,2B31 ;4 - 7 BIT (ASCII)
6,,1B31 ;5 - 7 TRACK CORE DUMP
DENTBL: -1
0B27 ;200
1B27 ;556
2B27 ;800
4B27 ;1600
MAXDEN==.-DENTBL-1
TM2END: END