Trailing-Edge
-
PDP-10 Archives
-
bb-bt99q-bb
-
ts1kon.x23
There is 1 other file named ts1kon.x23 in the archive. Click here to see a list.
TITLE TS1KON - SA10/STC DEVICE DEPENDENT CODE FOR TAPSER V16
SUBTTL D. P. MASTROVITO/DPM (DEC) & JEFF GUNTER/JEG (ADP) 16-MAY-89
;OLD AUTHORS - CYPHERNETICS CORPORATION 18-MAR-76
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 1987,1988.
;ALL RIGHTS RESERVED.
.CPYRT<1987,1988>
XP VTS1KN,16
SALL
TS1KON::ENTRY TS1KON
;$$*** I DON'T SEE ANY REASON WHY TS1KON CAN'T BE A MULTI-BLOK DRIVER.
;$$*** I DON'T SEE ANY REASON NOT TO SUPPORT READ-BACKWARDS
;SA10 COMMANDS SPECIFIC TO MAGTAPES
MO.NOP==003 ;NOP
MO.SNS==004 ;SENSE COMMAND
MO.CTL==007 ;CONTROL (TAPE MOTION COMMANDS)
MC.BSB==040 ;BACKSPACE RECORD
;DEVICE COMMAND CODES (BITS 8-15 OF DEVICE COMMAND WORD)
O.WR==001 ;WRITE
O.RD==002 ;READ
O.RDB==014 ;READ BACKWARDS
O.SNS==004 ;SENSE
O.CTL==007 ;CONTROL (TAPE MOTION OPERATIONS)
O.TIE==033 ;REQUEST TRACK IN ERROR (9 TRACK NRZI ONLY)
O.7MS==003 ;7 TRACK MODE SET
O.9MS==303 ;9 TRACK MODE SET
O.NOP==003 ;NO OPERATION
;TAPE MOTION OPERATIONS (OR'ED WITH O.CTL)
C.REW==000 !O.CTL ;REWIND
C.RUN==010 !O.CTL ;REWIND AND UNLOAD
C.ERG==020 !O.CTL ;ERASE GAP
C.WTM==030 !O.CTL ;WRITE TAPE MARK
C.BSB==040 !O.CTL ;BACK SPACE BLOCK
C.BSF==050 !O.CTL ;BACK SPACE FILE
C.FSB==060 !O.CTL ;FORWARD SPACE BLOCK
C.FSF==070 !O.CTL ;FORWARD SPACE FILE
C.DSE==220 !O.CTL ;DATA SECURITY ERASE
;9 TRACK MODE SETTINGS (OR'ED WITH O.9MS)
N.PE==000 ;1600 BPI PHASE ENCODED
N.NRZI==010 ;800 BPI NON RETURN TO ZERO INVERTED
N.GCR==020 ;6250 BPI GROUP CODED RECORDING
N.STD==N.PE ;INSTALLATION STANDARD FOR 9 TRACK
;7 TRACK DENSITY SETTINGS (OR'ED WITH O.7MS)
D.200==000 ;200 BPI
D.556==100 ;556 BPI
D.800==200 ;800 BPI
;7 TRACK MODE MODIFIERS (OR'ED WITH O.7MS)
M.DIAG==010 ;FOR DIAGNOSTIC USE ONLY
M.DCON==020 ;DATA CONVERTER ON
M.EPAR==040 ;EVEN PARITY
M.TRON==010 ;TRANSLATOR ON
;MODE DEFINITIONS
F.9TK==F.TAPC ;9 TRACK DEC COMPATIBLE (TAPE COMPATIBILITY MODE)
F.IND==F.BYTE ;9 TRACK IBM COMPATIBLE (BYTE MODE)
F.7TK==F.NAT ;7 TRACK ODD PARITY (NATURAL MODE)
F.7TE==F.BYTE ;7 TRACK EVEN PARITY (BYTE MODE)
NOPCMD==F.NMT!F.XEC!<O.NOP>B15 ;A GENERIC NOP COMMAND
;BYTE POINTERS
CSYDVA: POINT CSSKON+CSSUNI,T1,CSNUNI ;DEVICE ADDR IN CSW
DVYDVA: POINT DVSDVA,T2,DVNDVA ;DEVICE ADDR IN DVW
;PROTOTYPE SENSE CHANNEL PROGRAM
SNSPGM: PHASE 0
SNSNOP:! F.NMT!F.XEC!F.CC!<MO.NOP>B15 ;PUT A CHAINED NOP BEFORE SENSE
SNSDVW:! F.XEC!F.BYTE!<MO.SNS>B15!<000>B23 ;SENSE-I/O COMMAND
SNSDCW:! BYTE (1)1(DCSSIZ)-^D24(DCSADR)0 ;DCW FOR SENSE
SNSHLT:! EXP 0 ;TERMINATE CHANNEL PROG (HALT)
SNSDAT:! BLOCK SNSWDS ;SENSE BYTE STORAGE
SNSLEN:! DEPHASE ;LENGTH OF CHANNEL PROGRAM
TS1DMX==20 ;MAXIMUM DRIVES PER KONTROLLER
TS1HDN==TS1DMX-1 ;HIGHEST DRIVE NUMBER ON KONTROLLER
TS1ELN==6 ;SIZE OF FEP TABLE
DCWMAX==^D40 ;LENGTH OF CHANNEL PROGRAM AREA
;DRIVER CHARARCTERISTICS
; TS1 = TS1CNF
; MTA = MAGTAPE
; 0 = MAXIMUM DEVICES IN SYSTEM (NO LIMIT)
; K.TS1 = KONTROLLER TYPE
; TS1DMX = MAXIMUM DRIVES PER KONTROLLER
; TS1HDN = HIGHEST DRIVE NUMBER ON KONTROLLER
; MDSEC0 = SECTION FOR KDB/UDB
; MDSEC0 = SECTION FOR DDB
DRVCHR (TS1,MTA,0,K.TS1,TS1DMX,TS1HDN,MDSEC0,MDSEC0,<DR.XAD!DR.MCD!DR.DPU!DR.UCK!DR.GCC!DR.DDN>)
.ORG TKBUDB ;START OF SA10 SPECIFIC DATA
TS1UTB:! BLOCK TS1DMX ;TABLE OF POINTERS TO UDBS
TS1SNS:! BLOCK SNSLEN ;SENSE CHANNEL PROGRAM
TS1SUN:! BLOCK 1 ;NON-EXISTANT DRIVE BEING SENSED
TS1IUM:! BLOCK TS1DMW ;IGNORE UNIT MASK
TS1NUM:! BLOCK TS1DMW ;NEW UNIT MASK
TS1UNI:! BLOCK 1 ;SAVED UNIT NUMBER
TS1LCI:! BLOCK 1 ;CONI OF SA10 AT LAST INTERRUPT
TS1ICC:! BLOCK 1 ;SAVE INITIAL CSW AROUND SENSE CMD
TS1LST:! BLOCK 1 ;CSW AT LAST INTERRUPT
TS1SCN:! BLOCK 1 ;LH = SUBCHANNEL IN CONO POS, RH = SUBCHANNEL
TS1GSN:! BLOCK 1 ;GLOBAL SUBCHANNEL NUMBER
TS1DVP:! BLOCK 1 ;ADDRESS OF OUR DEVL SLOT
TS1PPC:! BLOCK 1 ;PROGRAM PC DESIRED
TS1OFL:! BLOCK 1 ;-1 IF WE THINK KON IS OFFLINE, 0 IF NOT
TTSCSW:! BLOCK 1 ;ADDR OF CHANNEL STATUS WORD
TTSOFS:! BLOCK 1 ;DEVICE ADDR FOR UNIT ZERO (@TTSOFS(W))
TTSTCA:! BLOCK 1 ;TERMINAL COUNT,ADDR LAST IO INT (NOT SENSE)
TTSBUS:! BLOCK 1 ;(U) THAT GOT BUS-OUT ON USER OPERATION
TTSBSM:! BLOCK 1 ;BUS-OUT MAP FOR POLLER
TS1STI:! BLOCK 1 ;(U) FOR UNIT THAT GOT DEFERED AT STIDON
TS1DUM:! BLOCK 1 ;(U) FOR UNIT THAT GOT DEFERED AT TTSDMD
TTSOPU:! BLOCK 1 ;(U) FOR UNIT THAT GOT BUSYED
TTSBCT:! BLOCK 1 ;TIMER SET WHEN BUSY RECEIVED
TTSBRC:! BLOCK 1 ;COUNT OF BUSYS,,COUNT OF TIMER EXPIRED
TTSDMD:! BLOCK 1 ;ADDR OF UNIT WAITING FOR DUMMY STATUS
TTSMIO:! BLOCK 1 ;VIRTUAL ADDRESS OF 1ST DCW IN TTSPRG
TTSPRG:! BLOCK DCWMAX ;THE ACTUAL CHANNEL PROGRAM LIVES HERE
BLOCK 3 ;THIS IS OVERWRITTEN WITH SENSE + HALT
TS1MDW:! BLOCK 1 ;STORAGE FOR MDT DATA WORD
TS1KLN:! ;LENGTH OF KDB
.ORG
.ORG TUBLEN
TS1SND:! ;START OF SENSE DATA
TS1IST:! BLOCK TS1ELN ;LAST ERROR INITIAL STATUS
TS1FST:! BLOCK TS1ELN ;LAST ERROR FINAL STATUS
TS1SIP:! BLOCK 1 ;SENSE IN PROGRESS - CONI WORD
BLOCK 1 ;SENSE IN PROGRESS - CSW WORD
TS1TIE:! BLOCK 1 ;SENSE BYTES 0,1,2,3 WHERE BYTE2=TIE BYTE
TS1ULN:! ;LENGTH OF UDB
.ORG
TS1KDB: KDBBEG (TS1,TS1KLN)
SETWRD (KDBNAM,<SIXBIT/MT/>) ;KONTROLLER NAME
SETWRD (KDBIUN,<TKBUDB>) ;INITIAL POINTER TO UDBS
SETWRD (KDBCUN,<TKBUDB>) ;CURRENT POINTER TO UDBS
SETWRD (KDBIUM,<TS1IUM>) ;OFFSET TO IGNORE UNIT MASK
SETWRD (KDBNUM,<TS1NUM>) ;OFFSET TO NEW UNIT MASK
SETWRD (KDBSTS,<INSVL.(1,KD.MPT)>) ;INITIALLY ONE PATH
KDBEND
TS1UDB: UDBBEG (TS1,TS1ULN)
SETWRD (UDBNAM,<SIXBIT/MT/>) ;DRIVE NAME
SETWRD (UDBPCC,< TS1ELN,,TS1FST>) ;PHYSICALLY CONTIGUOUS CORE
SETWRD (TUBIEP,<-TS1ELN,,TS1IST>) ;INITIAL ERROR POINTER
SETWRD (TUBFEP,<-TS1ELN,,TS1FST>) ;FINAL ERROR POINTER
UDBEND
EQUATE (LOCAL,0,<TS1ICD,TS1ICL,TS1ULP,TS1ULB>)
EQUATE (LOCAL,CPOPJ##,<TS1CMD,TS1EDL,TS1IDL,TS1LOD>)
EQUATE (LOCAL,CPOPJ1##,<TS1CFG>)
TS1INT==TAPINT## ;INTERRUPT SERVICE
TS1ELG==TPELGX## ;MAKE AN ERROR LOG ENTRY
TS1DSP: DRVDSP (TS1,TAPCHN##,TDVDDB##,TDVLEN##,TPMDIA##)
TPK (TS1,NO,377777) ;SERVICE DEPENDENT DISPATCH
TS1CKT: EXP K.TX1,K.DX2,K.TS1,0 ;COMPATIBLE KONTROLLER TABLE
TS1NBF: TPNBF (RW,RU) ;NON-BLOCKING FUNCTION MASK
SAXDSP (TS1) ;GENERATE SA10 DRIVER DISPATCH
;DEFAULT MONGEN'ED DEVICE TABLE
DEFMDT: MDKL10 (7,274,0,0,<MD.KON>) ;DEVICE CODE 274
MDKL10 (7,270,0,0,<MD.KON>) ;DEVICE CODE 270
MDTERM ;TERMINATE TABLE
SUBTTL TAPE INTERUPT SERVICE
;CALLED FROM TAPSER WITH W := KDB
TS1ISR: PUSHJ P,SAVE4## ;SAVE SOME ACS
PUSHJ P,TRK111 ;$ GO TRACK "INT"
XCT KDBCNI(W) ;CONI SA10,T1
DMOVE T2,@TTSCSW(W) ;GET CSW & RESIDUAL COUNT
EXCH T1,T2 ;SWAP AROUND
MOVEM T1,TS1LST(W) ;SAVE INTERRUPTING STATUS
MOVEM T2,TS1LCI(W) ;SAVE CONI
TLNE T1,(S.BUSY) ;SKIP IF NOT BUSY
PJRST WTCUE ;GO WAIT FOR CUE IF WE'RE BUSYED
TLNE T1,(S.CUE) ;CHECK FOR NOT-BUSY-ANYMORE
PUSHJ P,GOTCUE ;CALL IF NOT BUSY ANYMORE
TRNE T2,SI.PAR!SI.NXM ;SKIP UNLESS MEMORY ERROR
JRST STECHN ;GO HANDLE CHANNEL ERROR
LDB T4,[POINT 2,TS1LST(W),1] ;GET STATUS TYPE BYTE
SETZM TS1OFL(W) ;IF WE GET INT CAN'T BE COMPLETELY OFFLINE
SKIPE T1 ;SKIP IF CSW WORD IS 0 (??)
TLNE T1,(S.SE) ;SKIP IF SELECT-ERROR IS CLEAR
JRST TS1IS3 ;BRANCH IF CSW=0 OR IF SELECT-ERROR IS ON
SKIPE T2,TTSDMD(W) ;SKIP IF NO DUMMY DEVICE
CAIE T4,S.DUM ;SKIP IF DUMMY STATUS
LDB T2,CSYDVA ;GET DEVICE FROM STATUS
SUBI T2,@TTSOFS(W) ;GET UNIT NUMBER
SETZB U,P1 ;DEFAULT TO NO UDB, NO IORB
PUSHJ P,SETUDB## ;SET UP UDB
PJRST NEWUNI ;POSSIBLY A NEW DRIVE JUST POWERED UP
PUSHJ P,CHKIRB## ;CHECK FOR IORB AND LOAD UP T1 WITH IT
JRST ONLUNI ;MAYBE THIS IS AN ONLINE INTERRUPT
PUSHJ P,SETACS ;LOAD UP VARIOUS PRESERVED STATUS
SKIPE TS1SIP(U) ;SKIP IF NOT SENSING
JRST [PUSHJ P,SNSANA ;GO ANALYZE SENSE DATA
PJRST TS1IS2] ;...THEN BRANCH TO COMPLETION ROUTINES
MOVEM T3,TTSTCA(W) ;SAVE FOR WORD COUNT CALCULATERS
MOVE T1,P1 ;GET IORB INTO T1 INCASE WE EXIT HERE AND NOW
CAIN T4,S.DUM ;SKIP UNLESS DUMMY STATUS
JRST TS1IS4 ;BRANCH IF WE GOT DUMMY INT FOR IDLE CTL
JUMPE P1,STSCLR
MOVSI T1,TUSBOT## ;GET BOT BIT
ANDCAM T1,TUBSTS(U) ;CLEAR SINCE IT WILL BE SET LATER IF NEEDED
TLNE P4,(S.UC) ;SKIP IF NO ERRORS DETECTED
JRST ERRSNS ;START SENSE, EXIT, RETURN LATER
MOVE T1,P1 ;GET IORB ADDRESS
LDB T1,PRBFCN## ;AND THE FUNCTION CODE
CAIE T1,RB.FRW ;REWIND?
CAIN T1,RB.FRU ;UNLOAD?
JRST TS1IS2 ;BRANCH IF INITIAL-STATUS FOR REW/RUN
TLNE P4,(S.DE) ;DEVICE END (COMMAND FINISHED)?
JRST TS1IS2 ;YES
PJRST NXTWAT ;ODD, MUST BE MORE STATUS COMING
;HERE WHEN WE (FINALLY) GET DEVICE-END FOR AN IORB PROGRAM
TS1IS2: MOVE T1,P1 ;WHERE TAPSER LIKES THE IORB
LDB T2,PRBFCN## ;GET DESIRED FCN
CAIG T2,STIMAX ;CHECK VALIDITY
JUMPG T2,@STIDSP(T2) ;DO IT
JRST TAPIFI## ;FUNCTION ERROR
;HERE IF SA10 OR TCU IS OFFLINE
TS1IS3: MOVSI T2,TKSOFL## ;GET THE OFFLINE BIT
IORM T2,TKBSTS##(W) ;SET IN KDB SINCE KON ITSELF IS OFFLINE
SETOM TS1OFL(W) ;REMEMBER TO OURSELVES IT IS OFFLINE
HRROS TS1SUN(W) ;UNLOCK THE POLLER IF WE DROP OFFLINE
HRROS KDBNUM(W) ;...
SETZM TTSOPU(W) ;NOTHING TO RESTART
SETZM TS1PPC(W) ;NOTHING TO START
LDB T2,CSYDVA ;TRY TO GET A VALID UNIT ADDRESS
SUB T2,TTSOFS(W) ;COMPUTE UNIT NUMBER
SETZB T1,P1 ;NO IORB YET
PUSHJ P,SETUDB## ;FIND UNIT
PJRST STSCLR ;EXIT INTERRUPT
MOVSI T1,TKSOFL## ;GET OFFLINE BIT AGAIN
IORM T1,TUBSTS##(U) ;MARK THE UNIT OFFLINE TOO
PUSHJ P,CHKIRB## ;GET IORB IF ANY
PJRST STSCLR ;EXIT INTERRUPT
MOVSI T2,RB.SOL!RB.SNM ;OFFLINE, NO MOTION
IORM T2,TRBSTS##(T1) ;SET OFFLINE
MOVE P1,T1 ;COPY IORB ADDRESS
JRST STIDON ;AND THEN SHORT CUT TO EXIT AND DISMISS INT
;HERE IF WE GET DUMMY INTERRUPT
TS1IS4: SKIPE TS1PPC(W) ;SKIP IF NO PROGRAMS IN PROGRESS
JRST TS1IS5 ;BRANCH IF PROGRAM RUNNING FOR THIS KON
SETZM TS1DUM(W) ;NO LONGER A DEFERED DUMMY INTERRUPT
SETZM TTSDMD(W) ;NO LONGER A PENDING DUMMY INTERRUPT
SKIPGE TTSBCT(W) ;SKIP IF BUSY TIMER NOT RUNNING
JRST DISMIS ;BRANCH IF BUSY TIMER RUNNING
PUSHJ P,CKSTRT ;CHECK SELECTION STATE
POPJ P, ;EXIT IF NEITHER STARTED NOR SELECTED. REQUEST SCHED
JRST STCSI1 ;BRANCH TO SETUP COMMANDS AND START UNIT
;HERE IF WE GET DUMMY INTERRUPT, BUT POLLER IS BUSY WITH A UNIT
TS1IS5: MOVEM U,TS1DUM(W) ;REMEMBER THE UNIT THAT UUO LEVEL WANTS
JRST NXTWAT ;AND DISMISS TO WAIT FOR POLLER DONE INTERRUPT
;ROUTINE TO ANALYZE SENSE DATA AND SETUP VARIOUS UDB AND IORB THINGS
SNSANA: PUSHJ P,SNSUNI ;GO SETUP UDB THINGS
PUSHJ P,SNSIOR ;GO SETUP IORB THINGS
POPJ P, ;RETURN TO CALLER
;ROUTINE TO DO SENSE ANALYSIS AND SETUP UDB THINGS
SNSUNI: PUSHJ P,TRK333 ;TRACK A SENSE DATA CALLBACK
JUMPE U,CPOPJ## ;EXIT IF NO UNIT (??????!!!!??!?!)
MOVEI T1,SNSWDS ;LOAD T1=# WORDS IN SENSE DATA
XMOVEI T2,TS1SND(U) ;POINT T2=SENSE DATA FROM SENSE CMD
XMOVEI T3,TS1IST(U) ;POINT T3="BEFORE" BUFFER FOR SENSE DATA
EXTEND T1,[XBLT] ;COPY DATA FROM UNIT BUFFER TO "BEFORE" BUFFER
MOVSI T1,TUSWTL## ;LOAD T1=UNIT BIT SAYING "WRITE-LOCKED-UNIT"
TLNN P2,(S01WLK) ;SKIP IF UNIT IS ACTUALLY LOCKED
ANDCAM T1,TUBSTS##(U) ;CLEAR BIT IF UNIT IF REALLY ENABLED
TLNE P2,(S01WLK) ;SKIP IF UNIT IS ACTUALLY ENABLED
IORM T1,TUBSTS##(U) ;SET BIT IF UNIT IS REALLY LOCKED
TLNN P2,(S00IRQ!S00BOC) ;SKIP IF UNIT HAS FALLEN OFFLINE
TLNE P2,(S01BOT) ;SKIP IF NOT BEGINNING-OF-TAPE
PUSHJ P,REWDON## ;LET TAPE-SERVICE KNOW WE HIT B-O-T
MOVSI T1,TKSOFL## ;LOAD T1=UNIT BIT SAYING "UNIT OFFLINE"
TLNE P2,(S00IRQ!S00BOC) ;SKIP IF ONLINE WITHOUT ERROR
IORM T1,TUBSTS(U) ;SET OFFLINE BIT IF OFFLINE OR BUS PARITY ERR
TLNE P2,(S00BOC) ;SKIP IF NOT BUS-OUT PARITY ERROR
MOVEM U,TTSBUS(W) ;REMEMBER LAST UNIT ON OUR KON HAVING ERROR
TLNE P2,(S00DCK) ;SKIP IF NOT DATA-CHECK
MOVEM P2,TS1TIE(U) ;SAVE T-I-E INFO IF DATA CHECK
; (N.B.: TIE ONLY VALID IF 800 NRZI 9 TRACK UNIT)
TLNE P3,(S067TK) ;SKIP IF 9-TRACK UNIT
SETOM TS1TIE(U) ;REJECT TIE INFO IF 7TRACK UNIT
TRNE P2,S03D16 ;SKIP IF NOT 1600 BPI
SETOM TS1TIE(U) ;REJECT TIE INFO IF PE UNIT
TRNE P3,S06D62 ;SKIP IF NOT 6250 BPI CAPABLE UNIT
SETOM TS1TIE(U) ;REJECT TIE INFO IF GCR UNIT
POPJ P, ;EXIT WHEN DONE WITH UDB STUFF
;HERE TO ANALYZE SENSE DATA AND SETUP IORB STUFF
SNSIOR: JUMPE P1,CPOPJ## ;EXIT IF NO IORB!
SETZ T1, ;START OFF WITH NO MODIFIER BITS
TLNE P2,(S00IRQ!S00BOC) ;SKIP IF OFFLINE AND NO BUS ERRORS
TLO T1,RB.SOL!RB.SNM ;SET OFFLINE AND NO-MOTION
MOVE T2,TS1SND+S04WRD(U) ;GET SENSE DATA
TLNE T2,(S04TPI) ;SKIP IF "INDICATE" LIGHT IS OFF
TLO T1,RB.SET ;SET "END-OF-TAPE" IF BEYOND EOT MARKER
TLNE P2,(S00DCK) ;SKIP IF DATA-CHECK
TLO T1,RB.SDE ;SET DATA-ERROR
IORM T1,TRBSTS(P1) ;SET BITS IN IORB
MOVE T1,P1 ;POINT T1 AT IORB FOR PRBDEN
TLNN P2,(S01BOT) ;CAN'T UPDATE DENSITY IF HAVEN'T READ TAPE
TLNE P2,(S017TK) ;SKIP IF 9TRACK UNIT
POPJ P, ;7TRK DOESNT NEED UPDATE (AND WE CAN"T READ IT)
MOVEI T2,RB.D62 ;IF 3600 SERIES, DEFAULT TO 6250
TRNN P3,S06D62 ;SKIP IF 3600 SERIES DRIVE
MOVEI T2,RB.D8 ;IF 3400 SERIES, DEFAULT
TRNE P2,S03D16 ;SKIP IF NOT 1600 BPI
MOVEI T2,RB.D16 ;IF KNOWN TO BE 1600 BPI, MUST BE 1600 BPI!
DPB T2,PRBDEN## ;UPDATE IORB WITH CURRENT DENSITY INFO
POPJ P, ;EXIT WITH IORB INFO UPDATED
;ROUTINE TO LOAD THE INTERESTING ACS.
; P1= IORB
; P2= 1ST 4 SENSE BYTES, OR ZERO IF NOT SENSING
; P3= 2ND 4 SENSE BYTES, OR ZERO IF NOT SENSING
; P4= CSW WORD APLLYING TO THE ERROR, IF ANY
SETACS: MOVE P1,T1 ;SAVE IORB IN A SAFER PLACE
SETZB P2,P3 ;DEFAULT TO NO ERRORS
SKIPE TS1SIP(U) ;SKIP IF NOT SENSING
DMOVE P2,TS1SND+S00WRD(U) ;LOAD UP THE FIRST 8 SENSE BYTES
SKIPE TS1SIP(U) ;SKIP IF NOT SENSING
SKIPA P4,TS1SIP+1(U) ;LOAD UP THE SAVED CSW INFO
MOVE P4,TS1LST(W) ;LOAD UP THE "REAL" CSW INFO
POPJ P,
;HERE ON UN-EXPECTED INTERRUPT FOR KNOWN DRIVE (IE: UDB BUT NO IORB)
ONLUNI: MOVE T1,TS1LST(W) ;GET CSW WORD
TLNE T1,(S.CUE) ;SKIP IF NOT BUSY-CALL-BACK
JRST NXTWAT ;IGNORE INTERRUPT IF BUSY-CALL-BACK
SKIPN TS1SIP(U) ;SKIP IF WE'VE GOT SENSE DATA ALREADY
PJRST ERRSNS ;PICK UP SENSE DATA
PUSHJ P,SETACS ;SETUP THE ACS
MOVE P1,TUBSTS(U) ;FORGET IORB AND REMEMBER TUSREW INSTEAD
PUSHJ P,SNSUNI ;SETUP UDB DATA
TLNN P1,TUSREW## ;SKIP IF WE JUST REWINDING
TLNE P2,(S00IRQ) ;SKIP IF NOT OFFLINE
SKIPA ;SKIP IF REWINDING OR OFFLINE
PUSHJ P,TPMONL## ;TELL MDC WHEN DRIVE COMES ONLINE
SETZB P1,T1 ;MAKE SURE THERE IS NO IORB HANGING AROUND
PJRST STIDON ;FINISH INTERRUPT
;HERE ON AN UNSOLICITED INTERRUPT FROM AN UNKNOWN DRIVE
;IF NOT THE POLLER'S DRIVE, JUST IGNORE IT, AS POLLER WILL EVENTUALLY
;DO A SENSE AND CLEAR THE CONNECTION.
NEWUNI: CAME T2,TS1SUN(W) ;SKIP IF THE UNIT WE WERE EXPECTING
JRST NXTWAT ;BR IF BAD UNIT. IGNORE-WILL BE SENSED LATER.
MOVE T1,BITTBL##(T2) ;GET ASSOCIATED BIT
TDNE T1,TS1IUM(W) ;WANT TO IGNORE THIS DRIVE?
JRST NEWUN1 ;BR IF WE WANT TO IGNORE IT (??!)
MOVE T3,TS1SNS+SNSDAT+S23WRD(W) ;GET LAST WORD
TRNE T3,17 ;SKIP IF SENSE PROCEEDED CORRECTLY
JRST NEWUN3 ;BR IF SENSE DIDN'T HAPPEN OR FAILED
MOVE T3,TS1SNS+SNSDAT+S01WRD(W) ;GET SENSE BYTE 1
TLNE T3,(S01TUA!S01TUB) ;DOES DRIVE EXIST?
JRST NEWUN2 ;BRANCH IF DRIVE SEEMS TO EXIST
;HERE DRIVE DOESN'T (OR SHOULDN'T) EXIST. UNFREEZE POLLER AND DISMISS INTRP
NEWUN1: HRROS TS1SUN(W) ;OK TO CHECK ANOTHER DRIVE NOW
HRROS KDBNUM(W) ;GIVE AUTCON A FLAG
JRST NEWUN4 ;CHECK FOR PENDING UNIT, DISMISS
;HERE IF WE FIND A NEWLY EXISTING DRIVE
NEWUN2: MOVE T3,TS1SNS+SNSDAT+S06WRD(W) ;GET SENSE BYTE 6 ET AL
TDNN T3,[S06MOD] ;IS MODEL FIELD FILLED IN?
JRST NEWUN1 ;HM - MUSTBE FALSE ALARM?
IORM T1,TS1NUM(W) ;TELL PER-SECOND LEVEL WHICH DRIVE TO FIND
JRST NEWUN4 ;CHECK FOR PENDING UNIT, DISMISS
;HERE TO START A SENSE BECAUSE EXISTING FAILED OR DIDN'T HAPPEN
NEWUN3: MOVEI T3,TS1SNS+SNSDVW(W) ;POINT AT VIRTUAL ADDRESS OF PROGRAM
MOVEM T3,TS1PPC(W) ;SAVE FOR STARTUP/RESTARTS
MAP T3,TS1SNS+SNSDVW(W) ;POINT AT SENSE AFTER NO-OP CMD
ADDI T2,@TTSOFS(W) ;COMPUTE FULL UNIT ADDRESS
DPB T2,[POINT SASDLD,T3,SANDLD] ;INSERT IT
MOVEI T2,DL.STA ;GET START OPCODE
DPB T2,[POINT SASDLO,T3,SANDLO] ;INSERT OPCODE
PMOVEM T3,TS1DVP(W) ;CREATE NEW DEVL ENTRY
SETZM TS1SNS+SNSDAT+SNSWDS-1(W) ;MAKE IT LOOK LIKE IT WON THIS TIME
JRST SETGOB ;START SENSE-ONLY PROGRAM
;HERE WHEN SENSE COMPLETED. DECLARE PENDING UUO LEVEL DONE.
NEWUN4: SETZM TS1PPC(W) ;NO MORE POLLING PROGRAM
SKIPN U,TS1STI(W) ;GET PENDING UNIT'S U
JRST NEWUN5 ;BRANCH IF NO "STIDON" PENDING UNIT
SETZM TS1STI(W) ;NOTHING PENDING NOW
PUSHJ P,CHKIRB## ;GET IORB FOR IT
SETZ T1, ;VERY STRANGE
MOVE P1,T1 ;GET P1=IORB FOR STIDON ET AL
PJRST STIDON ;END IT
;HERE WHEN SENSE COMPLETED BUT NO "STIDON" IS PENDING
NEWUN5: SKIPN TS1DUM(W) ;SKIP IF PENDING DUMMY INTERRUPT
JRST NXTWAT ;BRANCH IF NOTHING MORE TO DO
MOVE U,TS1DUM(W) ;GET THE UNIT WE'RE DEFERRING
SETZM TS1DUM(W) ;NO LONGER DEFERRING IT
JRST STCSI1 ;START IT UP
;$ TRACK SUPPORT
;$ TRACK 111111 - TRACK AN INTERRUPT
;$
TRK111: MOVSI T1,111000 ;$ TYPE 1
IOR T1,TIME## ;$ MERGE WITH TIME STAMP
PUSHJ P,SHOVE
DMOVE T1,@TTSCSW(W) ;$ T1=CSW, T2=WC
PUSHJ P,SHOVE ;$
MOVE T2,T1 ;$ T1=WC
PUSHJ P,SHOVE ;$
CONI 274,T1 ;$
PUSHJ P,SHOVE
POPJ P,
;$ TRACK 222222 - TRACK AN INTENT TO SET GO FLAG
;$
TRK222: PUSHJ P,SAVT## ;$ SAVE ALL ACS
PUSHJ P,TRKLOK ;$ DON'T PERMIT AN INTERRUPTION
PUSH P,SHVPTR ;$ SAVE THE SHOVE POINTER
MOVE T1,[222222,,3] ;$ INITIAL RECORD TYPE 2
PUSHJ P,SHOVE ;$ REMEMBER IT
MOVE T1,UDBNAM(U) ;$ PICK UP THE UNIT NAME
PUSHJ P,SHOVE ;$ SAVE IT
PMOVE T1,TS1DVP(W) ;$ GET DEVL POINTER
MOVE T2,T1 ;$ COPY DEVL POINTER
PUSHJ P,SHOVE ;$ SAVE DEVL POINTER
MOVSI T3,-50 ;$
LDB T1,[POINT 4,T2,11] ;$ GET STATE
CAIN T1,17 ;$ SKIP IF NOT STOPPED
JRST TRK22B ;$ BRANCH IF STOPPED
AND T2,[17,,-1] ;$ ISOLATE ADDRESS ONLY
TRK22A: PMOVE T1,T2 ;$ PICK UP A PROGRAM INSTRUCTION
PUSHJ P,SHOVE ;$
TLZ T1,400000 ;$ TURN OFF MUX BIT
SKIPE T1 ;$ SKIP IF WE HALTED
AOBJN T3,[AOJA T2,TRK22a] ;$ LOOP FOR ALL ISNTRUCTIONS
TRK22B: POP P,T1 ;$ GET SHOVE POINTER
MOVE T3,SHVPTR ;$ GET SHOVE POINTER
SUB T3,T1 ;$ GET TRUE COUNT
SKIPE T1 ;$ SKIP IF POINTER WAS BOGUS TO START WITH
HRRM T3,(T1) ;$ FIXUP HEADER
POPJ P, ;$ RETURN
TRK333: PUSHJ P,TRKLOK ;$ DON'T PERMIT INTERRUPTION
MOVE T1,[333333,,10] ;$
PUSHJ P,SHOVE
MOVE T1,UDBNAM(U) ;$
PUSHJ P,SHOVE
MOVE T1,TS1SND(U) ;$
PUSHJ P,SHOVE
MOVE T1,TS1SND+1(U) ;$
PUSHJ P,SHOVE
MOVE T1,TS1SND+2(U) ;$
PUSHJ P,SHOVE
MOVE T1,TS1SND+3(U) ;$
PUSHJ P,SHOVE
MOVE T1,TS1SND+4(U) ;$
PUSHJ P,SHOVE
MOVE T1,TS1SND+5(U) ;$
PUSHJ P,SHOVE
POPJ P,
;$ TRACK A CONO
TRK444: PUSHJ P,TRKLOK ;$ DON"T PERMIT INTERRUPTION
PUSH P,T1
MOVE T1,[444444,,3]
PUSHJ P,SHOVE
MOVE T1,UDBNAM(U)
PUSHJ P,SHOVE
POP P,T1
PUSHJ P,SHOVE
POPJ P,
TRK555: PUSHJ P,TRKLOK ;$ DON'T PERMIT INTERRUPTION
PUSH P,T1 ;$ SAVE IORB POINTER
MOVE T1,[555555,,6] ;$ 5=SETCMD TIME
PUSHJ P,SHOVE ;$
MOVE T1,UDBNAM(U) ;$
PUSHJ P,SHOVE
MOVE T1,0(P1) ;$IORB
PUSHJ P,SHOVE
MOVE T1,1(P1)
PUSHJ P,SHOVE
MOVE T1,2(P1)
PUSHJ P,SHOVE
MOVE T1,3(P1)
PUSHJ P,SHOVE
POP P,T1
POPJ P,
SHOVE: SKIPE SHVPTR
SKIPN SHVCTR
POPJ P,
MOVEM T1,@SHVPTR
AOS SHVPTR
SOSLE SHVCTR
POPJ P,
PUSH P,T1
MOVEI T1,6000
MOVEM T1,SHVCTR
MOVEI T1,SHVBFR
MOVEM T1,SHVPTR
POP P,T1
POPJ P,
$LOW
SHVPTR: EXP SHVBFR
SHVCTR: 6000
SHVBFR: BLOCK 6001
$HIGH
TRKLOK: CONSZ PI,PI.IPA-PI.IP7 ;SKIP IF UUO LEVEL
POPJ P, ;$ EXIT IF ALREADY AT INTRP LEVEL
TAPOFF ;$ DISABLE TAPE INTERRUPTS
PUSHJ P,@(P) ;$ CALL CALLER
SKIPA ;$ NO SKIP RETURN
AOS -1(P) ;$ PASS ALONG SKIP
POP P,(P) ;$ WASTE CALLER'S PC
TAPON ;$ RE-ENABLE TAPE INTERRUPTS
POPJ P, ;$ RETURN TO CALLER'S CALLER
STIDSP: IFIW TAPIFI## ;(00) ILLEGAL
IFIW STIRD ;(01) READ
IFIW STIWT ;(02) WRITE
IFIW TAPIFI## ;(03) READ BACKWARDS (ILLEGAL)
IFIW STISR ;(04) SKIP RECORD
IFIW STIBR ;(05) BACKSPACE RECORD
IFIW STISF ;(06) SKIP FILE
IFIW STIBF ;(07) BACKSPACE FILE
IFIW STIEG ;(10) ERASE GAP
IFIW STIDSE ;(11) DATA SECURITY ERASE
IFIW STIRW ;(12) REWIND
IFIW STIUN ;(13) REWIND / UNLOAD
IFIW STITM ;(14) WRITE TAPE MARK
IFIW STISTS ;(15) STATUS REQUEST
IFIW STIRD ;(16) CORRECTION READ
IFIW STIRD ;(17) READ LOW THRESHOLD
STIMAX==.-STIDSP-1
;HERE IF NO IORB - MAKE SURE DONT LOSE CUE OR DE
STCIN1: SKIPE TTSOPU(W) ;SKIP UNLESS WAITING FOR CUE/DE
PUSHJ P,SETGOP ;SET UP COMMAND WAITING FOR
JRST TAPDIS## ;DISMISS THIS INT
;HERE TO CHECK FOR DUMMY STATUS INTERUPT - SEE IF ALREADY SELECTED
; NON-SKIP IF NOT SELECTED
; SKIP RETURN IF ALREADY SELECTED
CKSTRT: MOVSI T2,TKSSEL##
TDNN T2,TKBSTS(W) ;SELECTED?
PJRST CLRCTL ;NOT STARTED OR SELECTED, CLEAR CONTROL
MOVSI T2,TKSSTD## ;SELECTED, SEE IF ALSO STARTED
TDNE T2,TKBSTS(W) ;SKIP IF NOT STARTED
PJRST CPOPJ1## ;SELECTED AND STARTED, CONTINUE
PJRST CLRCTL ;CLEAR CONTROL, ASK FOR SCHEDULING
;ROUTINE TO MAKE CONTROLLER IDLE
CLRCTL:
STCIDL: SETOM TS1UNI(W) ;NO UNIT SELECTED
PJRST STSCLR ;CLEAR STATUS FLAG AND RETURN
;HERE TO RESET ACTIVE I/O
TS1RES: MOVEI T2,SO.RCH ;RESET SUBCHANNEL
PUSHJ P,CNOCLR ;DO IT
PUSHJ P,CLRCTL ;CLEAR WORLD
SETZM TTSBCT(W) ;AND CLEAR BUSY TIMER
SETZM TTSOPU(W) ;AND NO BUSY UNIT
HRROS TS1SUN(W) ;FREE UP POLLER IF RUNNING
HRROS KDBNUM(W) ;FREE AUTO MASK
SETZM TS1PPC(W) ;FORGET PROGRAM IN PROGRESS
HLRZ T1,TS1SCN(W) ;SUBCHANNEL IN CONO POSITION
TRO T1,SO.CME+SO.RCH ;CLEAR SUBCHANNEL AND MEMORY ERRORS
XCT KDBCNO(W) ;CONO SA10,(T1)
MOVEI T2,SO.ENB ;ENABLE INTERRUPTS
PUSHJ P,CNOSET ;DO IT
XCT KDBCNI(W) ;CONI SA10,T1
HRRZ T3,TS1SCN(W) ;GET SA10 SUBCHANNEL
MOVNS T3 ;T3=MINUS SUBCHANNEL NUMBER
MOVEI T2,SI.ENB ;INTERRUPT ENABLE FLAG FOR CHAN 0
LSH T2,(T3) ;T2=INTERRUPT ENABLE FLAG FOR OUR CHAN
TDNE T1,T3 ;SKIP IF ENABLE DIDNT SET
POPJ P, ;OK
;ROUTINE TO CAUSE AN INTERUPT TO FORCE A SCHEDULE CYCLE
STCRSL: ;ALSO REQUEST SELECTION INTERRUPT
TS1SCH: PUSHJ P,SAVE4## ;SAVE ACS FOR CALLER
MOVE T1,UDBPDN(U) ;GET PHYSICAL DRIVE NUMBER
ADDI T1,@TTSOFS(W) ;MAKE DEVICE ADDR
MOVEM T1,TTSDMD(W) ;SAVE AS LAST DUMMY DEVICE
MOVSI T2,(SA.SIR) ;SOFT-INTERUPT-REQUEST BIT
IORM T2,KDBUNI(W) ;SET IT FOR SAXSER
MOVEI T2,SO.SRQ ;STATUS REQUEST
PUSHJ P,CNOSET ;REQUESTS AN INTERRUPT
POPJ P,
;ROUTINE TO CHECK IF KONTROLLER IS ON LINE
;CALLED ONCE A SECOND.
;TAKE THIS OPPORTUNITY TO CHECK BUSY TIMER
TS1ONL: SKIPE TTSBCT(W) ;SKIP IF TIMER NOT SET
SOSLE TTSBCT(W) ;SKIP IF TIMER EXPIRES
JRST TS1ON1 ;GO CHECK/POLL FOR NEW UNITS
SETOM TTSBCT(W) ;MAKE SURE NEGATIVE FOR ENSUING INTERRUPT
AOS TTSBRC(W) ;COUNT TIMES TIMER EXPIRED
MOVE U,KDBCUN(W) ;GET CURRENT UNIT
MOVE U,(U) ;ADDR OF UDB
PUSHJ P,TS1SCH ;REQUEST SCHEDULING INTERRUPT
TS1ON1: PUSHJ P,TS1BOC ;GO REPORT BUS OUT CHECK IF NEEDED
SKIPE TS1OFL(W) ;SKIP IF WE THINK WE'RE ONLINE
JRST TS1ON0 ;BRANCH IF WE'RE OFFLINE
;$ SKIPL @KDBCHN(W) ;CHANNEL BUSY?
;$ JRST CPOPJ1## ;LEAVE IT ALONE
SKIPE T1,TS1NUM(W) ;GET BIT MASK
JFFO T1,TS1ON4 ;FIND FIRST UNIT NUMBER
HRRZS KDBNUM(W) ;INDICATE NO DRIVES TO CONFIGURE
SKIPL T1,TS1SUN(W) ;GET NON-EXISTANT UNIT BEING SENSED
JRST CPOPJ1## ;DO NOTHING IF SENSE IN PROGRESS
PUSHJ P,SAVE4## ;SAVE SOME ACS
AOS T1 ;ADVANCE TO NEXT UNIT
HRRZS T1 ;CLEAR LH FLAG
CAILE T1,TS1HDN ;OVERFLOW?
MOVEI T1,0 ;START WITH DRIVE ZERO
ADD T1,KDBIUN(W) ;INDEX INTO TABLE
TS1ON2: SKIPN (T1) ;KNOWN UNIT?
JRST TS1ON3 ;NO
CAMGE T1,KDBFUN(W) ;END OF TABLE?
AOJA T1,TS1ON2 ;TRY ANOTHER
SETOM TS1SUN(W) ;RESET COUNTER
JRST CPOPJ1## ;AND INDICATE CONTROLLER ONLINE
TS1ON3: SUB T1,KDBIUN(W) ;REDUCE TO A DRIVE NUMBER
MOVEM T1,TS1SUN(W) ;SAVE FOR NEXT TIME
SKIPL @KDBCHN(W) ;SKIP IF CHANNEL IS FREE
JRST CPOPJ1## ;BRAND (AND RETURN LATER) IF CHANNEL BUSY
;HERE FROM INTERRUPT LEVEL WHEN WE COMPLETE AN IORB
TS1ONI: PUSH P,M ;SAVE M
MOVE M,TS1GSN(W) ;GET GLOBAL SUBCHANNEL NUMBER
LDB P1,[POINT WIDCUA,KDBUNI(W),17] ;GET TCU NUMBER
XMOVEI P4,TS1SNS(W) ;POINT TO SENSE PROGRAM
HRRO P3,T1 ;GET MASSBUS UNIT (NONE),,DRIVE NUMBER
PUSHJ P,TS1DCK ;QUEUE UP SENSE REQUEST
JFCL ;SHOULD NEVER SKIP
JRST MPOPJ1## ;RETURN
TS1ON4: PUSHJ P,AUTLOK## ;GET AUTCON INTERLOCK
JRST CPOPJ1## ;TRY AGAIN NEXT TIME
PUSHJ P,SAVE4## ;SAVE SOME ACS
PUSH P,M ;SAVE M TOO
LDB P1,[POINT WIDCUA,KDBUNI(W),17] ;GET TCH
HRRO P3,T2 ;GET MASSBUS UNIT (NONE),,DRIVE NUMBER
XMOVEI P4,TS1SNS(W) ;POINT TO SENSE PROGRAM
MOVE T1,KDBDVC(W) ;DEVICE CODE
XMOVEI T2,TS1DSP ;DISPATCH
MOVE T3,KDBCHN(W) ;CHANNEL DATA BLOCK
PUSHJ P,AUTSET## ;SET UP CPU VARIABLES
PUSHJ P,TS1DRS ;TRY TO CONFIGURE A DRIVE
JFCL ;IGNORE ERRORS
PUSHJ P,AUTULK## ;RELEASE AUTCON INTERLOCK
HRROS TS1SUN(W) ;RELEASE THE POLLER (IE: UNLOCK THE SENSE BFR)
HRROS KDBNUM(W) ;GIVE AUTCON A FLAG
JRST MPOPJ1## ;TELL TAPSER THE CONTROLLER IS ALIVE
;HERE IF WE THINK WE'RE OFFLINE
TS1ON0: MOVE T1,KDBIUN(W) ;POINT AT UNIT TABLE
SOS (P) ;(UGH!) UNDO SKIP RETURN
JRST TS1ON3 ;GO FORCE A POLL FOR UNIT #0
TS1BOC: SKIPN TTSBUS(W) ;SKIP IF ANY UNITS GOT BUS OUT
POPJ P, ;EXIT IF OK
MOVE U,OPRLDB## ;POINT U FOR OUTPUT
PUSHJ P,INLMES## ;
ASCIZ *
% BUS-OUT Parity Error for * ;
SETZ T2,
EXCH T2,TTSBUS(W) ;GET OFFENDING UNIT
SKIPE T2 ;SKIP IF UNIT SOMEHOW DISAPPEARS
SKIPN T2,UDBNAM(T2) ;GET UNIT NAME
MOVSI T2,'MTA' ;THIS CAN'T HAPPEN
PUSHJ P,PRNAME## ;TYPE UNIT NAME
MOVE T2,.CPLOG## ;GET CPU NAME
LSH T2,-6 ;GET A LEADING SPACE
PUSHJ P,PRNAME ;TYPE CPU NAME
PUSHJ P,INLMES## ;
ASCIZ * SA* ;
LDB T1,[POINT 9,KDBCNO(W),11] ;GET DEVICE CODE
TRZ T1,3 ;TURN OFF OPCODE
PUSHJ P,PRTDI8## ;TYPE DEVICE CODE
PUSHJ P,INLMES## ;
ASCIZ * SC* ;
HRRZ T1,TS1SCN(W) ;GET LOCAL SUBCHANNEL #
PUSHJ P,PRTDI8## ;TYPE IT
PUSHJ P,INLMES## ;
ASCIZ * TCU* ;
HRRZ T1,TTSOFS(W) ;GET CU BASE ADDRESS
PUSHJ P,PRTDI8## ;
PJRST CRLF## ;EXIT
SUBTTL AUTOCONFIGURE
;CONFIGURE A SINGLE TCU
;P1/ TCU NUMBER
;P2/ JUNK,,LOCAL SUBCHANNEL #
;P4/ ADDRESS OF CHANNEL PROGRAM
;M/ GLOBAL SUBCHANNEL NUMBER
TS1CFS: PUSHJ P,SAVE4## ;SAVE SOME ACS
PUSHJ P,SAVW## ;SAVE FOR SAXSER
PUSH P,M ;SAVE M TOO
SETZ W, ;DON'T HAVE A KDB YET
MOVSI P3,-TS1DMX ;SET UP POINTER
PUSHJ P,TS1DC1 ;DO A SENSE TO GET SOME USEFUL INFORMATION
JFCL ;IGNORE POSSIBLE TIMEOUT (RELY ON SENSE BYTES)
MOVE T1,S17WRD+SNSDAT(P4) ;WORD WITH SENSE BYTE 17
AND T1,[S17TCE] ;ISOLATE TCU EC LEVEL
JUMPE T1,MPOPJ1## ;TCU ALWAYS HAS A NON-ZERO VALUE
HRRZ T1,P1 ;GET "TCU" NUMBER
TRO T1,400000 ;DON'T LET TAPINT THINK THIS IS RH
PUSHJ P,AUTKDB## ;BUILD A KDB
JRST MPOPJ## ;GIVE UP IF NO CORE
SKIPE TS1SNS(W) ;ALREADY HAVE A SENSE PROGRAM?
JRST TS1CF1 ;YES--EXISTING KDB
XMOVEI T1,TS1MDT## ;POINT TO MONGEN'ED DEVICE (SUB-)TABLE
SETZ T2, ;IMPLICIT DEFAULT MDT
HRLOI T3,(P2) ;SUB-CHANNEL,,ALL DRIVES
MOVEI T4,MD.KON ;KONTROLLER INFORMATION DESIRED
PUSHJ P,AUTMDT## ;SEE IF WE HAVE ANY DATA
SETZ T1, ;NO DATA
TRNN T1,-1 ;IF NO PORTING INFORMATION,
HRRI T1,-1 ;SET UP TO TRUST THE TX
MOVEM T1,TS1MDW(W) ;SAVE THE MDT DATA WORD
MOVEI T1,SNSLEN ;WORDS TO XFER
XMOVEI T2,SNSPGM ;SENSE CHANNEL PROGRAM
XMOVEI T3,TS1SNS(W) ;DENSTINATION
EXTEND T1,[XBLT] ;COPY
MOVEI T1,1 ;NUMBER OF DEVICE LIST ENTRIES NEEDED
PUSHJ P,SAXDVL## ;FILL IN THE TABLE
JRST MPOPJ## ;FAILED
MOVEM T1,TS1DVP(W) ;SAVE FOR LATER REFERENCE
TS1CF1: MOVEI T1,(P2) ;GET SUBCHANNEL
IMULI T1,SO.CHN ;POSITION
HRLZS T1 ; FOR CONI
HRRI T1,(P2) ;PUT SUBCHANNEL IN RH TOO
MOVEM T1,TS1SCN(W) ;SAVE
MOVEM M,TS1GSN(W) ;SAVE GLOBAL SUBCHANNEL NUMBER TOO
SETOM TS1SUN(W) ;NOT SENSING NON-EXISTANT UNITS
MOVE T2,SNSDVW(P4) ;GET SENSE COMMAND (FOR DRIVE#0)
LDB T1,DVYDVA ;GET ADDRESS FOR DRIVE#0
MOVEM T1,TTSOFS(W) ;REMEMBER DRIVE0 ADDRESS FOR LATER
MOVE T1,SAXSBA##(M) ;GET GLOBAL SUBCHANNEL DATA BLOCK ADDRESS
ADDI T1,.CLCSW ;ADD OFFSET TO COMPUTE ENDING STATUS WORD
MOVEM T1,TTSCSW(W) ;SAVE ADDRESS OF ENDING STATUS WORD
MOVE T1,KDBCSO(W) ;GET CONSO SKIP ADDRESS
MOVEI P3,(P1) ;GET TCU ADDRESS
MOVSI P3,-TS1DMX ;START WITH DRIVE ZERO
TS1CF2: PUSHJ P,TS1DRS ;BUILD UDB
JFCL ;PROBABLY NO DRIVE SWITCHED IN
AOBJN P3,TS1CF2 ;LOOP BACK FOR EACH POSSIBLE DRIVE
;$$*** DO WE WANT TO CALL TS1RES?
;$$*** DOESN'T IT ENABLE INTS?
;$$*** WE WOULD NEED TO INSERT WAIT TIMING SINCE
;$$*** ANY OTHER CU'S OF ANY KIND ON THE SAME SUBCHANNEL
;$$*** WILL REFUSE TO ANSWER OR RETURN BUSY'S WHILE RESET IS GOING.
PUSHJ P,TS1RES ;RESET SUBCHANNEL
JRST MPOPJ## ;RESTORE M AND RETURN
;AUTOCONFIGURE A SINGLE DRIVE FROM "UUO" LEVEL
TS1DRV: PUSHJ P,SAVE4## ;SAVE SOME ACS
PUSH P,M ;SAVE SOME MORE
LDB P1,[POINT WIDCUA,KDBUNI(W),17] ;GET TCU# FROM KDB
HRRO P3,U ;LOAD P3=<NO-MASS-BUS>,,DRIVE#
XMOVEI P4,TS1SNS(W) ;POINT P4 AT SENSE PROGRAM AND BUFFER
MOVE M,TS1GSN(W) ;GET GLOBAL SUBCHANNEL NUMBER FROM KDB
PUSHJ P,TS1DRS ;CALL INTERNAL ROUTINE TO CONFIGURE DRIVE
PJRST MPOPJ## ;NORMAL RETURN
PJRST MPOPJ1## ;SKIP RETURN
;AUTOCONFIGURE A SINGLE DRIVE VIA AN INTERNAL CALL
TS1DRS: PUSHJ P,TS1DCK ;DOES DRIVE EXIST?
POPJ P, ;NO
LDB T1,[POINTR (SNSDAT+S13WRD(P4),S13TCH)] ;HIGH BYTE TX S/N
LDB T2,[POINTR (SNSDAT+S14WRD(P4),S14TCL)] ;LOW BYTE TX S/N
ROT T2,-10 ;LEFT JUSTIFY
LSHC T1,10 ;MERGE HIGH + LOW BYTES
SKIPN T1 ;HAVE A NON-ZERO S/N?
MOVE T1,P1 ;NO, USE TCU NUMBER INSTEAD
TRNN P3,TS1DMX/2 ;CU FOR LOW NUMBERED DRIVES?
MOVEM T1,KDBSER(W) ;YES
TRNE P3,TS1DMX/2 ;CU FOR HIGH NUMBERED DRIVES?
MOVEM T1,KDBSER+1(W) ;YES
MOVE T1,SNSDAT+S17WRD(P4) ;SENSE BYTES 16-19
TLNN T1,(S172CH) ;TWO CHANNEL SWITCH CAPABILITY?
TLZ T1,(S17SWF) ;NO, IGNORE PORTING
LDB T1,[POINTR (T1,S17SWF)] ;GET SWITCH FEATURES
ANDI T1,3 ;STRIP OFF HI/LO UNIT BIT
AOS T1 ;GET MAXIMUM NUMBER OF PORTS
LSH T1,1 ;ACCOUNT FOR A/B PATH PER TCU
HRRZ T2,TS1MDW(W) ;GET PORT COUNT FROM MDT DATA WORD
CAILE T1,(T2) ;IF THE MDT KNOWS BETTER THAN WE DO,
MOVE T1,T2 ;THEN TRUST IT
DPB T1,[POINTR (KDBSTS(W),KD.MPT)] ;SAVE
MOVSI T2,(KD.MPD) ;GET A BIT
CAIE T1,1 ;IF MORE THAN ONE PATH,
IORM T2,KDBSTS(W) ;THEN SAY MULTI-PORTED DEVICE
TS1DR1: MOVSI T1,(S05NSS) ;BIT TO TEST
TDNN T1,S05WRD+SNSDAT(P4) ;NEW SUBSYSTEM?
JRST TS1DR2 ;MUST DUMMY UP S/N IF A TX01
MOVE T1,S12WRD+SNSDAT(P4) ;SENSE BYTES 12-15
MOVE T2,S16WRD+SNSDAT(P4) ;SENSE BYTES 16-19
LSH T1,-4 ;POSITION HIGH ORDER S/N BITS
ANDI T1,377 ;ISOLATE HIGH ORDER S/N BITS
LSHC T1,-34 ;MERGE HIGH AND LOW BITS
JUMPN T2,TS1DR3 ;CONTINUE IF S/N IS NON-ZERO
TS1DR2: MOVE T1,P1 ;GET TCU #
;$$ I WOULD PREFER TO SEE CODE HERE WHICH GETS THE DRIVE SERIAL
;$ FROM THE TCU SERIAL * 100 + DRIVE SO THAT THE SERIAL CAN BE
;$ HUMAN READ FROM "SYSERR" WITHOUT DIFFICULTY.
LSH T1,WIDUNA ;POSITION IN DEVICE ADDRESS
HRRZ T2,P3 ;GET PHYSICAL DRIVE NUMBER
IOR T2,T1 ;MERGE TCU + DRIVE
SETZ T1, ;NO HIGH ORDER S/N WORD
TS1DR3: DMOVEM T1,.CPTSN## ;SAVE TEMPORARILY
HRRZ T3,P3 ;GET PHYSICAL DRIVE NUMBER
PUSHJ P,AUTDPU## ;LINK UP DUAL PORTED DRIVES
JFCL ;MUST PROCEED EVEN IF DUAL PORTED
MOVEI T1,TUCD80##+TUCD16## ;ASSUME TU70
MOVE T2,S13WRD+SNSDAT(P4) ;SENSE BYTE 13
TLNN T2,(S13FET) ;SKIP IF WE HAVE NRZI FEATURE
MOVEI T1,TUCD16## ;ASSUME 1600 BPI ONLY
MOVE T2,S06WRD+SNSDAT(P4) ;SENSE BYTE 6
TLNE T2,(S067TK) ;7 TRACK?
MOVEI T1,TUCD20##+TUCD55##+TUCD80##+TUC7TK##
TRNE T2,S06D62 ;6250 DRIVE?
MOVEI T1,TUCD16##+TUCD62##
TRO T1,TUCIRD##+K.TS1 ;INCLUDE REWIND INTERRUPT AND KONT TYPE
MOVE T2,T1 ;COPY DRIVE INFO
HRRZ T1,P3 ;GET PHYSICAL DRIVE NUMBER
HRLS T1 ;MAKE IT THE TABLE INDEX TOO
PUSH P,P1 ;SAVE P1
HRRZ P1,P3 ;GET PHYSICAL DRIVE NUMBER
LDB T3,[POINTR (SNSDAT+S06WRD(P4),S06MOD)] ;GET TU MODEL BITS
SETZ T4, ;INCASE WE CAN'T FIGURE IT OUT
CAIN T3,5 ;TU70/71?
MOVE T4,['TU70 '] ;YES
TRNE T2,TUC7TK## ;BUT IS IT 7-TK?
TRO T4,10000 ;MAKE IT A TU71
CAIN T3,14 ;TU72?
MOVE T4,['TU72 '] ;YES
CAIN T3,15 ;TU73?
MOVE T4,['TU73 '] ;YES
XMOVEI T3,HNGTBL ;POINT TO HUNG TIMER TABLE
PUSHJ P,TAPDRV## ;BUILD AND LINK UP UDB AND DDB
JFCL ;FAILED
POP P,P1 ;RESTORE
DMOVE T1,.CPTSN## ;RETRIEVE DRIVE SERIAL NUMBER
DMOVEM T1,UDBDSN(U) ;SAVE IN UDB
JRST CPOPJ1## ;RETURN SUCCESS
;CHECK FOR DRIVE EXISTANCE
TS1DCK: JUMPE W,TS1DC2 ;JUMP IF NO KDB
HRRZ T1,P3 ;GET DRIVE NUMBER
MOVE T1,BITTBL##(T1) ;AND IT'S BIT
TDNE T1,TS1IUM(W) ;WANT TO IGNORE THIS DRIVE?
POPJ P, ;SAY IT DOESN'T EXIST
TS1DC1: JUMPE W,TS1DC2 ;JUMP IF NO KDB
SKIPL T1,TS1SUN(W) ;FULL AUTOCONFIGURE?
JRST TS1DC2 ;NO
HRRZS T1 ;ISOLATE POSSIBLE DRIVE NUMBER
HRRZ T2,P3 ;AND THE ONE BEING CONFIGURED NOW
CAIN T1,(T2) ;MATCH?
JRST CPOPJ1## ;THEN INTERRUPT LEVEL TOLD US IT EXISTED
TS1DC2: MOVE T1,P1 ;GET TCU #
LSH T1,WIDUNA ;POSITION IN DEVICE ADDRESS
ADDI T1,(P3) ;INCLUDE DRIVE NUMBER
MOVE T2,SNSPGM+SNSDVW ;GET SENSE COMMAND
DPB T1,DVYDVA ;INSERT DEVICE ADDRESS
MOVEM T2,SNSDVW(P4) ;STORE DVW
MOVE T2,SNSPGM+SNSNOP ;GET NOP COMMAND
DPB T1,DVYDVA ;INSERT ADDRESS
MOVEM T2,SNSNOP(P4) ;STORE NOP
MOVE T2,SNSPGM+SNSDCW ;GET THE -VE BYTE COUNT FOR SENSE DATA
HRRI T2,SNSDAT(P4) ;FILL IN ADDRESS OF SENSE DATA
MOVEM T2,SNSDCW(P4) ;STORE DCW
SETZM SNSHLT(P4) ;INSERT A HALT
MOVSI T2,SNSHLT(P4) ;SET UP TO CLEAR SENSE DATA
HRRI T2,SNSDAT(P4) ; (CONVENIENT WE CLEARED WORD 2, HUH?)
BLT T2,SNSDAT+SNSWDS-2(P4) ;ZERO THE SENSE DATA AREA
SETOM SNSDAT+SNSWDS-1(P4) ;LEAVE LAST BYTES -1 FOR VALIDITY CHECK
JUMPE W,TS1DC3 ;IF FIRST TIME HERE, NO KDB
SKIPGE TS1SUN(W) ;FULL AUTOCONFIGURE?
JRST TS1DC3 ;GLET SAXSER RUN THE CHANNEL PROGRAM
MOVEI T2,TS1SNS+SNSNOP(W) ;GET VIRTUAL PC OF SENSE PROGRAM
MOVEM T2,TS1PPC(W) ;WHERE TO START/RESTART
MAP T2,TS1SNS+SNSNOP(W) ;GET THE PHYSICAL PC OF THE SENSE'S NOP
MOVE T1,TTSOFS(W) ;GET UNIT#0 ADDRESS
ADD T1,P3 ;COMPUTE OUR UNIT #
DPB T1,[POINT SASDLD,T2,SANDLD] ;INSERT THE DEVICE ADDRESS
MOVEI T1,DL.STA ;GET THE "START" OPCODE
DPB T1,[POINT SASDLO,T2,SANDLO] ;INSERT THE OPCODE
PMOVEM T2,TS1DVP(W) ;CREATE NEW DEVL ENTRY
PJRST SETGOB ;SET "GO" BIT AND RETURN
TS1DC3: MOVE T1,P4 ;COPY CHANNEL PROGRAM ADDRESS
ADDI T1,SNSDVW ;SKIP OVER THE NO-OP -- CALLER ALREADY DID IT
PUSHJ P,SAXRCP## ;RUN THE CHANNEL PROGRAM
POPJ P, ;ERROR
MOVE T1,S17WRD+SNSDAT(P4) ;GET THE TCU EC WORD
AND T1,[S17TCE] ;ISOLATE THE LEVEL
JUMPE T1,CPOPJ## ;BRANCH IF UNIT IS NOT A TAPE UNIT
MOVSI T1,(S01TUA!S01TUB) ;BITS TO TEST
TDNN T1,S01WRD+SNSDAT(P4) ;DRIVE EXIST?
POPJ P, ;NO
MOVE T1,S06WRD+SNSDAT(P4) ;GET SENSE BYTE 6 (MODEL ID)
TDNN T1,[S06MOD] ;SKIP IF MODEL TYPE KNOWN
POPJ P, ;RETURN IF NOT A GOOD DRIVE AFTER ALL
JUMPE W,CPOPJ1## ;GIVE GOOD RETURN IF NO KDB TO FIX UP
HRRZ T1,P3 ;GET DRIVE NUMBER
SETCA T1,BITTBL##(T1) ;TRANSLATE DRIVE NUMBER TO A BIT
SETZ T2, ;ASSUME NO OTHER NEW DRIVES
SYSPIF ;AVOID RACE WITH INTERRUPT LEVEL
ANDB T1,TS1NUM(W) ;CLEAR SINCE DRIVE IS NO LONGER "NEW"
SKIPE T1 ;WORK PENDING FOR OTHER DRIVES?
MOVNI T2,1 ;YES
HLLM T2,KDBNUM(W) ;UPDATE FLAG
SYSPIN ;RELEASE INTERLOCK
JRST CPOPJ1## ;SAY DRIVE EXISTS
SUBTTL START I/O
;ROUTINE TO START I/O
;USER JOB MUST BE NAILED DOWN - CAUSE SELECTION INTERUPT
;OR JUST START I/O IF UNIT ALREADY SELECTED
TS1SIO: PUSHJ P,SAVE1## ;SAVE P1
MOVE T1,UDBPDN(U) ;PHYSICAL DEVICE NUMBER
CAME T1,TS1UNI(W)
PJRST STCRSL ;REQUEST SELECTION INTERRUPT
STCSI1: PUSHJ P,CHKIRB## ;GET IORB
JRST STSCLR ;BRANCH IF NO IORB AND DISMISS INTERRUPT
TAPOFF ;PREVENT POLLER INTERRUPT
SKIPE TS1PPC(W) ;SKIP IF POLLER IS IDLE
JRST TS1SI2 ;BRANCH TO DEFER STARTUP TILL POLLER IS DONE
TAPON ;ALLOW INTERRUPT AGAIN
MOVE P1,T1 ;LOAD UP IORB IN A SAFER PLACE
PUSHJ P,SETCMD ;SET-UP THE COMMAND LIST
JRST STIDON ;JUST EXIT IF ILLEGAL REQUEST
SETGOP: SKIPN TS1PPC(W) ;SKIP IF A PROGRAM TO DO
JRST NXTWAT ;PUNT IF NO PROGRAM TO RUN
PUSHJ P,SETDVP ;SETUP DEVL FROM PPC
SETGOB: MOVEI T2,SO.GO ;GO FLAG
PUSHJ P,CNOSET ;SET IT
PUSHJ P,TRK222 ;$ DO A GO TRACK
NXTWAT: PUSHJ P,STSCLR ;CLEAR STATUS FLAG
MOVEI T1,0 ;MORE INTS COMING
POPJ P, ;RETURN
TS1SI2: MOVEM U,TS1DUM(W) ;REMEMBER TO START UNIT WHEN POLLER IS DONE
TAPON ;ALLOW POLLER TO COMPLETE
JRST NXTWAT ;TILL UUO LEVEL THAT IT IS IN PROGRESS
;HERE IF NO STATUS WORTH REMEMBERING
STCOFL: MOVSI T2,RB.SOL ;SET OFF-LINE STATUS
IORM T2,TRBSTS(P1)
PUSHJ P,CLRCTL ;RESET CTL
PJRST STIDON ;AND DISMISS INTERRUPT
SUBTTL COMMAND SETUP
;ROUTINE TO SET UP CHANNEL PROGRAM HEADER
;T1 := IORB FOR THIS REQUEST
SETCMD: MOVE T1,P1 ;WHERE TAPSER NEEDS IORB ADDRESSES
PUSHJ P,TRK555 ;$ TRACK IORB REQUEST
PUSHJ P,SAVR## ;SAVE R
MOVEI R,TTSPRG(W) ;POINT AT PROGRAM
LDB T4,PRBFCN## ;GET DESIRED FCN
CAIG T4,IOFMAX ;SKIP IF NEW FUNCTION
SKIPN T2,IOFTAB(T4) ;CHECK LEGAL
JRST SETILG ;NOPE - ERROR
TRNE T2,IOXLST ;SKIP IF NOT DATA TRANSFER
JRST SETXFR ;HANDLE DATA XFER
TRNE T2,IOXDSE ;SKIP IF NOT DATA-SECURITY-ERASE
JRST SETDSE ;BRANCH TO HANDLE DATA-SECURITY-ERASE
TRNE T2,IOXXCW ;SKIP IF NOT "XCW HAS A SPACING COUNT"
JRST SETXCW ;BRANCH TO HANDLE SPACING-OPERATIONS
JRST SETCTL ;BRANCH TO HANDLE RANDOM CONTROL COMMAND
SETEND: MOVE T2,[BMXEND] ;GET THE END OF PROGRAM
MOVEM T2,(R) ;SAVE IT
MOVEI T4,TTSPRG(W) ;GET INITIAL ADDRESS OF PROGRAM
MOVEM T4,TS1PPC(W) ;SAVE PROGRAM-PC
JRST CPOPJ1## ;GIVE GOOD RETURN
;HERE TO BUILD A COMMAND LIST FOR DATA-SECURITY-ERASE
SETDSE: PUSH P,T2 ;SAVE THE DSE OPCODE
HLLZ T2,IOFTAB+RB.FLG ;GET ERG COMMAND
PUSHJ P,SETDVW ;SET A DEVICE-WORD INTO THE PROGRAM
POP P,T2 ;GET BACK THE DSE CMD
PUSHJ P,SETDVW ;INSERT DSE INTO PROGRAM
JRST SETEND ;SET UP END-OF-PROGRAM
;HERE TO BUILD A COMMAND LIST FOR A MULTI-REC SPACING OPERATION
; N.B.: TAPSER DOES THIS TO IMPLEMENT FORWARD/BACKWARD FILE.
; TAPSER DOES NOT NECESSARILY EXPECT THE TRUE COUNT OF OPS
; TO ACTUALLY TAKE PLACE, SO LONG AS WE RETURN IF WE FAIL.
SETCTL: SKIPA T4,[1] ;FAKE UP A COUNT OF 1 IF RANDOM-CTL COMMAND
SETXCW: HRRZ T4,@IRBACC(P1) ;GET COUNT
TRZN T2,IOXWRT ;SKIP IF READ OPERATION
JRST SETXC1 ;BRANCH IF A READ OPERATION
PUSHJ P,SETMOD ;SETUP MODE-SET-1/2
JRST SETILG ;BRANCH IF ILLEGAL SET REQUESTED
SETXC1: CAIN T4,1 ;SKIP IF NOT LAST OPERATION
TLZ T2,(F.CC) ;TURN OFF CHAINING FOR LAST OPERATION
PUSHJ P,SETDVW ;INSERT THE REQUESTED OPERATION
SOJLE T4,SETEND ;EXIT WHEN LAST OP INSERTED, SKIP TRAILING NOP
PUSHJ P,SETNOP ;INSERT A CHAINED NOP
JRST SETXC1 ;LOOP BACK FOR MORE OPS
SETNOP: PUSH P,T2 ;SAVE AN AC
MOVE T2,[F.CC!NOPCMD] ;GET A CHAINED NO-OP
PUSHJ P,SETDVW ;INSERT THE NO-OP INTO THE PROGRAM
POP P,T2 ;RESTORE THE AC
POPJ P, ;RETURN TO CALLER
;HERE AT INTERRUPT LEVEL TO LOAD T1=COUNT OF XCW OPS THAT WON
FNDXCW: LDB T1,[POINT 22,TTSTCA(W),35] ;GET UNDONE PC
;*** N.B.: THIS WORKS BECAUSE THE PROGRAM IS MAPPED 1:1 S0 WITH PHYSICAL
SUBI T1,TTSPRG(W) ;COMPUTE OFFSET INTO PROGRAM
LSH T1,-1 ;DIVIDE BY TWO
POPJ P, ;EXIT WITH WIN-COUNT IN T1
;HERE TO BUILD A PROGRAM TO DO ACTUAL USER-REQUEST DATA I/O
SETXFR: TRNE T2,IOXTIE ;SKIP IF NOT TRYING TIE RECOVERY
SKIPGE TS1TIE(U) ;SKIP IF TRYING TIE, AND WE HAVE VALID TIE DATA
PUSHJ P,SETMOD ;INSERT THE MODE-SET AS NEEDED
JFCL SETILG ;BRANCH IF MODE-SET REQUESTED IS ILLEGAL
TRZE T2,IOXTIE ;SKIP IF TIE CMD NOT NEEDED
PUSHJ P,SETTIE ;SETUP THE TRACK-IN-ERROR IF NEEDED
PUSHJ P,SETDVW ;INSERT THE I/O COMMAND INTO THE PROGRAM
PUSHJ P,MAPIO ;FINALLY, CONVERT DF10 LIST INTO SA10 LIST
JRST SETEND ;SET-UP THE END OF PROGRAM
;ROUTINE TO POSSIBLY SETUP A TRACK-IN-ERROR-REQUEST COMMAND
; IF THIS COMMAND REQUIRES IT
SETTIE: SKIPGE TS1TIE(U) ;SKIP IF TIE DATA TO USE
POPJ P, ;RETURN IF NO TIE DATA
PUSHJ P,SAVT## ;DON'T DESTROY CONTEXT
MOVE T2,[F.NMT!F.CC!F.SLI!F.OFP!<O.TIE>B15] ;TIE COMMAND
PUSHJ P,SETDVW ;INSERT IT
MAP T2,TS1TIE(U) ;GET PHYSICAL ADDRESS OF TIE BYTE
TLO T2,777700 ;INSERT BYTE COUNT OF 1
PUSHJ P,SETDCW ;INSERT DCW
SETOM TS1TIE(U) ;NO MORE TIE DATA
POPJ P, ;RETURN
;ROUTINE TO INSERT A MODE-SET-1 OR MODE-SET-2 INTO PROGRAM
SETMOD: PUSHJ P,SETFLG ;SET PROPER MODE BITS IN COMMAND IN T2
PUSH P,T2 ;SAVE THE I/O COMMAND
MOVE T1,P1 ;WHERE TAPSER DEMANDS IORB ADDRESSES
LDB T3,PRBDEN## ;GET DENSITY BYTE
MOVSI T2,RB.PAR ;CHECK PARITY
TDNE T2,TRBFNC(P1) ;ON FOR EVEN PARITY
TRO T3,20 ;REMEMBER EVEN PARITY
MOVEI T2,TUC7TK## ;7-TRACK BIT
TDNE T2,TUBCNF##(U) ;SKIP IF 9-TRACK UNIT
TRO T3,10 ;REMEMBER 7-TRACK
ROT T3,-1 ;DIVIDE BY TWO, REMAINDER TO SIGN BIT
HLLZ T2,MODTAB(T3) ;ASSUME WANT LH
SKIPGE T3 ;SKIP IF WAS EVEN
HRLZ T2,MODTAB(T3) ;THATS ODD, WANT RH
JUMPE T2,T2POPJ## ;BRANCH IF ILLEGAL SET REQUEST
TLO T2,(F.NMT!F.CC) ;NO MEMORY XFER, CHAINED
PUSHJ P,SETDVW ;SET MODE-SET INTO PROGRAM
JRST T2POJ1## ;GIVE GOOD RETURN
;THE FOLLOWING TABLE IS INDEXED BY THE 5 BIT QUANTITY FORMED BY
;PARITY,CHAN7,DENSITY,DENSITY,DENSITY
;THEN DIVIDED BY 2 TO ACCOUNT FOR HALF WORDS.
;(INDUSTRY-COMPATIBLE MODE IS FILTERED OUT BEFORE GET THIS FAR).
MODTAB: XWD <O.9MS+N.STD>_2 ,<O.9MS+N.NRZI>_2 ;0,,1
XWD <O.9MS+N.PE>_2 ,<O.9MS+N.NRZI>_2 ;2,,3
XWD <O.9MS+N.PE>_2 ,<O.9MS+N.GCR>_2 ;4,,5
XWD 0 ,0 ;6,,7
XWD <O.7MS+D.556+M.DCON>_2 ,<O.7MS+D.200+M.DCON>_2 ;10,,11
XWD <O.7MS+D.556+M.DCON>_2 ,<O.7MS+D.800+M.DCON>_2 ;12,,13
XWD 0 ,0 ;14,,15
XWD 0 ,0 ;16,,17
XWD 0 ,0 ;20,,21
XWD 0 ,0 ;22,,23
XWD 0 ,0 ;24,,25
XWD 0 ,0 ;26,,27
XWD <O.7MS+M.EPAR+D.556>_2 ,<O.7MS+M.EPAR+D.200>_2 ;30,,31
XWD <O.7MS+M.EPAR+D.556>_2 ,<O.7MS+M.EPAR+D.800>_2 ;32,,33
XWD 0 ,0 ;34,,35
XWD 0 ,0 ;36,,37
;SET IMPROPER MODE AND RETURN
SETILG: MOVSI T2,RB.SIL!RB.SER ;ILLEGAL OP
IORM T2,TRBSTS(P1) ;SET IN IORB
POPJ P, ;ERROR RETURN
;SUBROUTINE TO STORE DEVICE ADDR IN T2
SETDVA: MOVE T3,UDBPDN(U) ;PHYSICAL DEVICE NUMBER
ADDI T3,@TTSOFS(W) ;MAKE PROPER DEVICE ADDRESS
DPB T3,[POINT DVSDVA,T2,DVNDVA] ;STORE IT
POPJ P, ;RETURN
;SUBROUTINE TO SET SA10 MODE FLAGS
SETFLG: MOVEI T3,TUC7TK## ;7-TRACK FLAG
TDNN T3,TUBCNF##(U) ;SKIP IF 7-TRACK DRIVE
JRST SETF.9 ;NO, 9-TRACK
MOVSI T3,RB.PAR
TDNE T3,TRBFNC(P1) ;SKIP IF ODD PARITY
TLOA T2,(F.7TE) ;7-TRACK, EVEN PARITY FLAGS
TLO T2,(F.7TK) ;7-TRACK, ODD PARITY FLAGS
POPJ P, ;RETURN
SETF.9: MOVE T1,P1 ;WHERE TAPSER REQUIRES IORB ADDRESSES
LDB T3,PRBMOD## ;GET MODE
CAIN T3,RB.MBY ;SKIP UNLESS INDUSTRY-COMPATIBILITY
TLOA T2,(F.IND) ;9-TRACK, INDUSTRY-COMPATIBLE FLAGS
TLO T2,(F.9TK) ;9-TRACK, DEC-MODE
POPJ P,
;SUBROUTINE TO INSERT A DEVICE COMMAND IN T2 INTO THE PROGRAM BUFFER.
;ALWAYS INSERT THE DEVICE-ADDRESS, ALWAYS TURN ON COMMAND-CHAINING.
SETDVW: PUSHJ P,SETDVA ;ADDRESS DEVICE ADDRESS FIELD
TLO T2,(F.XEC) ;EXECUTE, NOT HALT.
SETDCW: MOVEM T2,(R) ;INSERT INTO THE PROGRAM
AOJA R,CPOPJ## ;EXIT
;TABLE FOR I/O FUNCTIONS - ALREADY IN POSITION
DEFINE IOT(CMD,BITS) <
BITS+<CMD>
>
;ALLOWABLE SPECIAL FCN BITS
IOXTIE==1B31 ;OPERATION REQUIRES TRACK-IN-ERROR REQUEST FIRST
IOXLST==1B32 ;DATA XFER LIST REQUIRED
IOXXCW==1B33 ;SPACING OPERATION FOR WHICH COUNT IMPLEMENTED
IOXDSE==1B34 ;DATA SECURITY ERASE
IOXWRT==1B35 ;WRITE OPERATION
IOFTAB: 0 ;0 - ILLEGAL
IOT(<<O.RD>B15>,IOXLST) ;1 - READ
IOT(<F.SLI!<O.WR>B15>,IOXLST!IOXWRT) ;2 - WRITE
0 ;3 - ILLEGAL
IOT(<F.NMT!F.CC!<C.FSB>B15>,IOXXCW) ;4 - FORWARD SPACE BLOCK
IOT(<F.NMT!F.CC!<C.BSB>B15>,IOXXCW) ;5 - BACKWARD SPACE BLOCK
IOT(<F.NMT!<C.FSF>B15>) ;6 - FORWARD SPACE FILE
IOT(<F.NMT!<C.BSF>B15>) ;7 - BACKSPACE FILE
IOT(<F.NMT!F.CC!<C.ERG>B15>,IOXWRT!IOXXCW) ;10 - WRITE LONG GAP
IOT(<F.NMT!<C.DSE>B15>,IOXWRT!IOXDSE) ;11 - DATA SECURITY ERASE
IOT(<F.NMT!<C.REW>B15>) ;12 - REWIND
IOT(<F.NMT!<C.RUN>B15>) ;13 - REWIND / UNLOAD
IOT(<F.NMT!<C.WTM>B15>,IOXWRT) ;14 - WRITE TAPE MARK
IOT(<<O.NOP>B15>) ;15 - "YELLOW BALL" STATUS
IOT(<<O.RD>B15>,IOXTIE!IOXLST) ;16 - CORRECTION READ
IOT(<<O.RD>B15>,IOXLST) ;17 - READ LOW THRESHOLD
IOFMAX==.-IOFTAB ;REMEMBER MAX FCN NUMBER
;HUNG TIMER TABLE
EXP ^D320 ;MAXIMUM TIMEOUT VALUE
HNGTBL: BYTE(9) ^D000,^D031,^D031,^D031 ;IL,RD,WT,RB
BYTE(9) ^D031,^D031,^D320,^D320 ;SR,BR,SF,BF
BYTE(9) ^D031,^D320,^D090,^D090 ;LG,SE,RW,RU
BYTE(9) ^D031,^D031,^D031,^D031 ;TM,YB,CR,RL
;ROUTINE TO CONVERT A DF10 IOWD LIST INTO AN SA10 LIST FOR A TAPE XFER
;ENTER:
; T1/ IORB ADDRESS
; U/ UDB ADDRESS
; W/ KDB ADDRESS
;BUT THEN:
; P1/ POINTER TO DF10 LIST
; P2/ POINTER TO SA10 LIST
; P3/ COUNT AS RETURNED IN T1 FROM GETIOW
; P4/ PA AS RETURNED IN T2 FROM GETIOW
MAPIO: PUSHJ P,SAVE4## ;SAVE SOME ACS
HLRE M,TRBRCT(P1) ;GET -VE COUNT
MOVMS M ;MAKE IT +VE COUNT
HRRZ T3,TRBRCT(P1) ;GET UVA OR 0 IF M IS BYTES
MOVE T1,P1 ;GET IORB ADDRESS
MOVEI T4,1 ;MULTIPLIER IS 1
LDB T2,PRBMOD## ;GET BYTE CONTAINING MODE INFO
CAIE T2,RB.MBY ;SKIP IF "MTIND." INDUSTRIAL MODE
SKIPN T3 ;SKIP IF WORD COUNT IS IN WORDS
MOVEI T4,4 ;IF A BYTE MODE, WE ONLY SUPPORT 4 BYTES PER WORD
HRRZ P1,@IRBACC(P1) ;POINT AT DF10 IOWD LIST
MOVEI P2,(R) ;POINT AT SA10 COMMAND LIST
MOVEM P2,TTSMIO(W) ;SAVE POINTER TO 1ST IOWD WORD
;HERE TO FETCH SOME MORE DF10 IOWDS
MAPIO1: PUSH P,T4 ;PROTECT THE MODE INFO
PUSHJ P,GETIOW## ;GET AN EXPANDED IOWD FROM DF10 LIST
POP P,T4 ;RESTORE THE MODE INFO
JUMPE T1,MAPIO4 ;BRANCH WHEN WE GET A HALT
IMULI T1,(T4) ;POSSIBLY CONVERT WORD COUNT TO BYTE COUNT
DMOVE P3,T1 ;COPY "IOWD" INTO P3/P4
;HERE TO SPLIT A DF10 EXPANDED IOWD INTO AS MANY SA10 DCWs AS NEEDED
MAPIO2: CAIG P3,^D2048 ;SKIP IF WE CAN'T FIT INTO ONE DCW
JRST MAPIO3 ;BRANCH IF ONLY ONE DCW FOR THIS IOWD
MOVE T1,P4 ;COPY ADDRESS PORTION (CUZ COUNT FIELD IS 0S)
MOVEM T1,(P2) ;INSERT THE DCW WORD WITH COUNT OF 2048
SUBI P3,^D2048 ;ADJUST THE COUNT REGISTER
MOVEI T1,^D2048 ;GET POSSIBLE COUNT
IDIVI T1,(T4) ;COMPUTE THE NUMBER OF ADDRESS UNITS
ADD P4,T1 ;COMPUTE NEW ADDRESS
AOJA P2,MAPIO2 ;LOOP TO FURTHER SPLIT UP THIS DF10 IOWD
;HERE WHEN THE REST OF A DF10 EXPANDED IOWD CAN EXACTLY FIT IN ONE SA10 DCW
MAPIO3: IMUL P3,[-100,,0] ;MAKE COUNT -VE AND POSITION
TLZ P3,(1B0) ;TURN OFF "THIS IS LAST DCW" BIT
OR P3,P4 ;INSERT THE ADDRESS PORTION
MOVEM P3,(P2) ;INSERT THE LAST ONE FOR THIS DF10 IOWD
AOJA P2,MAPIO1 ;BRANCH BACK TO GET ANOTHER DF10, IF ANY
;HERE WHEN WE ENCOUNTER THE DF10 HALT
MAPIO4: MOVSI T1,(1B0) ;GET THE "THIS IS LAST DCW" BIT
IORM T1,-1(P2) ;TURN IT ON
MOVEI R,(P2) ;PUT NEW PC INTO R
POPJ P, ;RETURN
SUBTTL CHECK FOR KONTROLLER BUSY
;CHECK FOR KONTROLLER BUSY
;CALL: MOVE W, KDB ADDRESS
; MOVE U, UDB FOR DRIVE TRYING TO SCHEDULE
; PUSHJ P,TS1BSY
; <NON-SKIP> ;BUSY
; <SKIP> ;NOT-BUSY
;
;USES T1 AND T2
TS1BSY: PUSHJ P,SAVE2## ;SAVE P1 AND P2
PUSH P,U ;SAVE U
MOVE P1,KDBIUN(W) ;POINT TO START OF DRIVE TABLE
MOVSI P2,-<TS1DMX/2> ;ACTUAL RANGE OF DRIVES PER KONT
MOVE T1,UDBPDN(U) ;GET PHYSICAL DRIVE NUMBER
TRZ T1,<TS1DMX/2>-1 ;MASK OUT DRIVE LEAVING KONTROLLER OFFSET
ADDI P1,(T1) ;ADJUST STARTING TABLE INDEX
TS1BS1: SKIPE U,(P1) ;GET A TUB ADDRESS
PUSHJ P,CHKIRB## ;SEE IF IT HAS A VALID IORB
JRST TS1BS2 ;TRY ANOTHER DRIVE
LDB T2,PRBFCN## ;GET FUNCTION CODE
MOVE T2,BITTBL## ;NOT PICK UP THE ASSOCIATED BIT
TDNN T2,TS1NBF ;NON-BLOCKING FUNCTION?
POPJ P, ;NO--KONT IS BUSY
TS1BS2: AOBJN P2,TS1BS1 ;LOOP BACK IF MORE DRIVES TO CHECK
JRST UPOPJ1## ;RESTORE U AND RETURN KONT NOT BUSY
SUBTTL STATUS REQUEST ("YELLOW BALL")
STISTS: SKIPN TS1SIP(U) ;SKIP IF WE GOT SENSE DATA
JRST ERRSNS ;CAUSE SNSANA TO BE INVOKED
JRST STIDON ;EXIT BECAUSE SNSANL DID OUR WORK
;HERE ON DONE INTERRUPT FOR DSE
STIDSE: PUSHJ P,CHKWLK ;CHECK FOR WRITE-LOCK
PUSHJ P,STCKMV ;CHECK FOR MOTION ERROR
JRST MOTERR ;PASS ALONG MOTION ERROR TO TAPSER
PUSHJ P,CHKEOT ;CHECK FOR AND SET EOT
PJRST STIDON ;ALL DONE
SUBTTL READ
;HERE ON DONE INTERUPT FOR READ
STIRD: SKIPN TS1SIP(U) ;SKIP IF WE HAVE SENSE DATA
PUSHJ P,STISNS ;GO FORCE A SENSE IF RECORD 0
PUSHJ P,STCKMV ;SEE IF TAPE MOVED
PJRST MOTERR ;BRANCH IF TAPE DID NOT MOVE
AOS TUBREC(U) ;ONE MORE RECORD
PUSHJ P,CHRCT ;GET CHARACTER COUNT
JRST [MOVSI T4,RB.STL
IORM T4,TRBSTS(P1)
JRST .+1]
MOVEM T2,TRBRCT(P1) ;SAVE COUNT IN IORB
MOVEM T2,TUBCCR##(U) ;AND IN UDB
TLNE P4,(S.UE) ;SKIP IF NO TAPE MARK
PUSHJ P,NXTFIL ;ADJUST TUBFIL AND TRBSTS FOR ONE MORE FILE
MOVE T2,TUBCCR##(U) ;GET CHAR COUNT FOR THIS RECORD
ADDM T2,TUBCRD##(U) ;AND UPDATE STATISTICS
ADDM T2,TKBCWR(W)
ADDM T2,.CPTFI##
; PJRST STIDON ;DISMISS INTERRUPT
;HERE TO FINISH INTERUPT AND EXIT TO TAPSER
STIDON: SETZM TS1SIP(U) ;NO LONGER SENSING
SETZM TS1PPC(W) ;NO MORE PROGRAM TO RUN
MOVE T1,P1 ;COPY IORB ADDRESS FOR TAPINT
JUMPE T1,STIDO3 ;BRANCH IF NO IORB TO UPDATE
MOVE T3,UDBPDN(U) ;PHYSICAL DEVICE NUMBER
MOVEM T3,TS1UNI(W) ;AND SAVE IT FOR LATER CHECK
HLRZ T3,TRBSTS(P1) ;LOOK AT FLAGS
JUMPE T3,STIDO2 ;RETURN IF NONE
MOVSI T2,RB.EXC ;ELSE SET EXCEPTION
IORM T2,TRBFNC(P1) ;IN IORB
STIDO2:
STIDO3: SKIPN TS1NUM(W) ;SKIP IF POLLER HAS INPUT ALREADY
SKIPGE TS1SUN(W) ;SKIP IF POLLER IS WAITING FOR A UNIT
JRST DISMIS ;DISMIS IF NO POLLING TO BE DONE
MOVE T1,TS1SUN(W) ;GET T1 NOW WE KNOW WE DON'T NEED IORB IN T1
PUSHJ P,TS1ONI ;STARTUP PENDING POLLING NOW
JFCL ;SO?
MOVEM U,TS1STI(W) ;REMEMBER UNIT NEEDING STIDON'ING
SETZ T1, ;TELL TAPSER THAT UUO ISN'T DONE YET
POPJ P, ;(IE: TELL IT LATER WHEN POLL IS COMPLETED)
DISMIS: SETZM TTSBCT(W) ;MAKE SURE STOP BUSY TIMER IF GET INT
SKIPE TTSOPU(W) ;SKIP IF NOTHING NEEDS RESTARTING
JRST SETGOP
MOVN T2,TS1SCN(W) ;GET NEGATIVE SUBCHANNEL NUMBER
MOVEI T3,SI.GO ;GO FLAG FOR SUBCHANNEL ZERO
LSH T3,(T2) ;GET OUR GO FLAG
MOVEI T2,SO.GO ;BIT TO START THE SUBCHANNEL
TDNN T3,TS1LCI(W) ;SKIP IF GO FLAG WAS ON
PJRST STSCLR ;CLEAR STATUS FLAG AND EXIT INTERRUPT
PUSHJ P,TRK222 ;$ TRACK GO
PJRST CNOSET ;$ SET THE GO BIT AND EXIT
SUBTTL WRITE
;HERE ON DONE INTERUPT FOR WRITE
STIWT: PUSHJ P,CHKWLK ;CHECK FOR AND SET WLK
PUSHJ P,STCKMV ;DID IT MOVE
PJRST MOTERR ;IF NO MOTION, BRANCH TO SET ERRORS AND EXIT
AOS TUBREC(U) ;ONE MORE RECORD FORWARD
TLNE P4,(S.UC) ;SKIP IF NO OTHER ERRORS PRESENT
PUSHJ P,STEANL ;BRANCH TO ANALYZE ERRORS AND SETUP TRBSTS
PUSHJ P,CHRCT ;GET CHARACTER COUNT
JFCL ;DON'T CARE
ADDM T2,TUBCWR##(U) ;ADD TO STATS
ADDM T2,TKBCWR(W)
ADDM T2,.CPTFO##
PUSHJ P,CHKEOT ;CHECK FOR AND SET EOT
PJRST STIDON ;AND EXIT
;HERE ON DONE INTERUPT FOR WRITE TAPE MARK
STITM: PUSHJ P,CHKWLK ;CHECK FOR AND SET WLK
PUSHJ P,STCKMV ;SKIP IF TAPE REALLY MOVED
PJRST MOTERR ;BRANCH IF NO MOTION
SETZM TUBREC(U) ;ZEROTH RECORD
AOS TUBFIL(U) ;AND 1 MORE FILE
TLNE P4,(S.UC) ;SKIP IF NO "SERIOUS" ERROR
PUSHJ P,STEANL ;UPDATE TRBSTS
PUSHJ P,CHKEOT
PJRST STIDON ;EXIT
SUBTTL REWIND/REWIND-UNLOAD
;HERE ON INTERUPT AFTER STARTING UNLOAD OR REWIND
;FINAL STATUS IS SEEN BY AND HANDLED BY "ONLUNI", NOT HERE
STIRW:
STIUN: TLNN P4,(S.UC) ;SKIP IF WE HAD PROBLEMS
PJRST STIDON ;EXIT IF NO PROBLEMS, LET TAPUUO DISCARD IORB
SKIPN TS1SIP(U) ;SKIP IF WE HAVE SENSE DATA ALREADY (?)
PJRST ERRSNS ;BRANCH TO GET SENSE DATA
PUSHJ P,REWDON## ;FAKE DONE TO AVOID HANG (SNSANL MIGHT NOT)
PJRST STIDON ;AND THEN EXIT INTERRUPT
;HERE ON DONE INTERUPT FROM BACKSPACE RECORD
STIBR: PUSHJ P,FNDXCW ;FIND THE XCW COUNT
MOVNS T1 ;MAKE THE XCW COUNT -VE (CUZ BACKWARDS MOTION)
ADDB T1,TUBREC(U) ;UPDATE TUBREC
SKIPGE T1 ;SKIP IF STILL POSSIBLE
SETZB T1,TUBREC(U) ;OOPS
TLNE P4,(S.UE) ;SKIP IF UNIT-EXCEPTION IS OFF
PUSHJ P,LSTFIL ;IF U-E ON, WE BSB'D BACK OVER TAPE MARK
STIBR2: TLNN P3,(S01BOT) ;SKIP IF SENSE BYTES SAY WE'RE AT BOT
PUSHJ P,STEANL ;UPDATE TRBSTS
JRST STIDON ;EXIT INTERRUPT
;HERE ON DONE INTERRUPT FROM BACKSPACE FILE
STIBF: SKIPN TS1SIP(U) ;SKIP IF WE HAVE SENSE DATA
PUSHJ P,STISNS ;GO GET SENSE BYTES
TLNN P4,(S.UC) ;UNIT CHECK?
JRST STIBF2 ;NO
SKIPN TUBFIL(U) ;SHOULD BE AT BOT
SKIPE TUBREC(U) ;ARE WE?
JRST STIBF3 ;NO
MOVSI T2,RB.SNM!RB.SBT ;NO MOTION + BOT BIT
JRST STIBF4 ;FINISH UP
STIBF2: SOS TUBFIL(U) ;PREVIOUS
SETZM TUBREC(U) ;..
STIBF3: TLNN P3,(S01BOT) ;LOAD POINT?
JRST STIDON ;NO
MOVSI T2,RB.SBT ;BOT BIT
STIBF4: IORM T2,TRBSTS(P1) ;UPDATE IORB
PUSHJ P,UNIBOT## ;TELL TAPSER WE'RE AT THE LOAD POINT
JRST STIDON ;GO DISMISS INTERRUPT
SUBTTL SKIP RECORD/FILE/ERASE GAP
;HERE ON DONE INTERUPT FROM SKIP FORWARD RECORD
STISR: PUSHJ P,FNDXCW ;FIND XCW COUNT (IE: # OF RECORDS THAT WON)
ADDM T1,TUBREC(U) ;UPDATE TUBREC
TLNE P4,(S.UE) ;SKIP IF NOT A TAPE MARK ABORT
PUSHJ P,NXTFIL ;COUNT A FILE IF WE GOT IT
JRST STIDON ;EXIT FROM INTERRUPT
;HERE ON DONE INTERRUPT FROM SKIP FORWARD FILE
STISF: SKIPN TS1SIP(U) ;SKIP IF WE HAVE SENSE DATA
PUSHJ P,STISNS ;GO GET SENSE BYTES
TLNE P4,(S.UC) ;UNIT CHECK?
PJRST MOTERR ;YES, MUST BE A MOTION ERROR
PUSHJ P,NXTFIL ;COUNT ONE MORE FILE
JRST STIDON ;AND EXIT
;HERE ON DONE INTERUPT FROM ERASE GAP
STIEG: PUSHJ P,CHKWLK ;CHECK FOR WRITE-LOCK
PUSHJ P,STCKMV ;SKIP IF MOTION TOOK PLACE
JRST MOTERR ;BRANCH IF NO MOTION
PUSHJ P,CHKEOT ;CHECK FOR END-OF-TAPE
PJRST STIDON ;EXIT INT
;HERE FOR CHANNEL ERROR
STECHN: PUSHJ P,SAVE1## ;SAVE P1
HRRZ P1,KDBCHN(W) ;PTR TO CHANNEL DATA BLOCK
MOVEI T3,CHENXM## ;ASSUME NXM
TRNE T2,SI.PAR ;SKIP UNLESS MEMORY PARITY ERROR
MOVEI T3,CHEMPE## ;NO - PARITY ERROR
MOVEI T1,@TTSCSW(W) ;ADDR OF CSW
MOVE T1,1(T1) ;GET TERMINAL COUNT,ADDR WORD
PUSHJ P,0(T3) ;EXERCISE ROUTINE
MOVEI T2,SO.CME ;CLEAR MEMORY ERROR
PUSHJ P,CNOCLR ;DO IT
MOVEI T2,SO.SRS ;SELECTIVE RESET REQUIRED TO GET OUT OF THIS
PUSHJ P,CNOCLR ;DO IT
MOVE U,KDBCUN(W) ;GET CURRENT UNIT
MOVE U,(U) ;ADDR OF UDB
PUSHJ P,CHKIRB## ;GET IORB PTR
JRST TAPDIS## ;NO USE CONTINUING IF NO IORB
MOVE P1,T1 ;PUT IORB IN A SAFER PLACE
MOVSI T2,RB.SER!RB.SED
IORM T2,TRBSTS(P1) ;TELL HIM WORLD ENDED
PJRST STIDON ;RETURN - NO RETRIES
;ROUTINE TO DETERMINE IF TAPE MOVED (DIVINATION)
STCKMV: SKIPN TS1SIP(U) ;SKIP IF WE HAD AN ERROR
JRST CPOPJ1## ;MUST HAVE MOVED IF NO ERROR
TLNE P2,(S00REJ!S00IRQ) ;SKIP IF MOTION HAPPENED
POPJ P, ;RETURN ERROR IF NO MOTION
JRST CPOPJ1##
;HERE FOR MOTION ERROR
MOTERR: MOVSI T2,RB.SER!RB.SNM ;NOTE NO MOTION
IORM T2,TRBSTS(P1) ;STASH INTO IORB
PJRST STIDON ;TELL TAPSER
;ROUTINE TO ANALYSE THE GENERIC SENSE BYTE ERRORS
STEANL: MOVEI T2,0 ;SET INITIAL ZERO
TLNE P2,(S00IRQ) ;SKIP IF NOT INTERVENTION REQUIRED
PUSHJ P,STCOFL ;SET UNIT OFF-LINE
TLNE P2,(S00REJ!S00IRQ);SKIP IF NO MOTION
TLO T2,RB.SNM!RB.SED;SET NO MOTION
TLNE P2,(S00OVR)
TLO T2,RB.SED ;SOME ERROR DETECTED (IE: CHANNEL OVERRUN)
TLNE P2,(S00DCK)
TLO T2,RB.SDE!RB.SED ;DATA ERROR
IORM T2,TRBSTS(P1) ;SET SELECTED BITS
POPJ P, ;RETURN
LSTFIL: SOSA TUBFIL(U) ;ONE LESS FILE
NXTFIL: AOS TUBFIL(U) ;ONE MORE FILE
SETZM TUBREC(U) ;ASSUME AT ZEROTH RECORD
MOVSI T2,RB.STM ;"SAW TAPE MARK"
IORM T2,TRBSTS(P1) ;FLAG IN IORB
POPJ P,
CHKEOT: MOVSI T1,RB.SET ;"SAW END(OF)TAPE"
ANDCAM T1,TRBSTS(P1) ;START OFF WITH IT OFF FOR SURE
TLNE P4,(S.UE) ;GOT UNIT EXCEPTION ON A WRITE COMMAND
IORM T1,TRBSTS(P1) ;SO REMEMBER WE SAW THE TAPE MARK GO BY
POPJ P,
CHKWLK: MOVSI T1,RB.SLK ;BITS FOR ABORTED FOR WRITE-LOCK
TLNE P2,(S01WLK) ;SKIP IF RING-PRESENT
TLNN P2,(S00REJ) ;SKIP IF NOT REJECTED
SKIPA
IORM T1,TRBSTS(P1) ;REJECTED, AND RING-NOT-PRESENT
POPJ P,
SUBTTL COMPUTE CHARACTER COUNTS
;ROUTINE COMPUTES CHARACTER COUNT
;RETURNS COUNT IN T2 , T1 SAVED
CHRCT: PUSHJ P,WRDCTS ;GET WORD COUNT
SKIPA ;LENGTH ERROR RETURN
AOS (P) ;SET FOR SKIP RETURN
MOVE T2,T1 ;WORD COUNT INTO T2
SETZ T4,
CHRCT1: DPB T4,PMTNCR## ;NOTE NO RESIDUE FOR MTCHR.
HRLM T2,TUBCHR##(U) ;STORE LAST WORD COUNT FOR MTCHR.
MOVE T1,P1 ;GET IORB FOR PRBMOD
LDB T1,PRBMOD## ;GET MODE
IMUL T2,TMODTB##(T1) ;WORDS TIMES CHARS PER WORD
DPB T4,PMTCRC## ;STORE ZERO FOR CRC FOR MTCHR.
POPJ P, ;RETURN
;ROUTINE TO COMPUTE NUMBER OF WORDS TRANSFERRED ON READ OPERATIONS
;RETURNS WORD COUNT IN T1
;CALLED WITH P1 := IORB
WRDCTS: SETZ T1, ;ACCUMULATE COUNT IN T1
MOVE T3,TTSMIO(W) ;GET 1ST DCW ADDRESS FROM MAPIO
LDB T4,[POINT DCSADR,TTSTCA(W),DCNADR] ;GET TERMINATION ADDRESS
; (THIS IS EITHER THE ADDRESS OF LAST
; DCW EXECUTED +1, OR, +2 IF FINISHED
; LIST AND LAST WORD)
WRD.1: LDB T2,[POINT DCSSIZ,(T3),DCNSIZ] ;LOAD NEGATIVE COUNT IN THIS DCW
ORCMI T2,<1_DCSSIZ>-1 ;CONVERT TO A TRUE NEGATIVE
SUB T1,T2 ;ACCUMULATE BY SUBTRACTION TO FORM
;A POSITIVE COUNT
SKIPL (T3) ;TEST FOR END OF LIST BY LOOKING, FIRST,
CAIL T3,-1(T4) ;AT HIGH-ORDER BIT OF DCW; THEN, BY
;COMPARING WITH TERMINATION ADDRESS
JRST WRD.2 ;END, T3 POINTS TO LAST DCW EXECUTED
AOJA T3,WRD.1 ;NOT END, LOOP FOR NEXT DCW
WRD.2: LDB T2,[POINT DCSSIZ,TTSTCA(W),DCNSIZ] ;ADJUST COUNT BY TERMINATION
JUMPE T2,WRD.3 ;COUNT (RESIDUAL COUNT) IF IT IS NONZERO
ORCMI T2,<1_DCSSIZ>-1 ;MAKE INTO A TRUE NEGATIVE
ADD T1,T2 ;BEFORE SUBTRACTING
WRD.3: PUSH P,T1 ;SAVE COUNT ON STACK
PUSHJ P,CHKMOD ;IF NOT WORD MODE,
TDZA T4,T4 ;CONVERT BYTE COUNT TO WORD COUNT
SETO T4, ;WORD MODE
POP P,T1 ;RESTORE WORD COUNT
JUMPN T4,WRD.4 ;JUMP IF WORD MODE
ADDI T1,3 ;BYTE MODE,
LSH T1,-2 ;CONVERT
WRD.4: SKIPGE (T3) ;TEST FOR LENGTH ERROR IF
SKIPE T2 ;FINISHED DATA CHAIN LIST INCLUDING LAST WORD
JRST CPOPJ1## ;DIDN'T FINISH LIST, RETURN
TLNN P4,(S.LE) ;TEST FOR LENGTH ERROR
AOS (P) ;NO LENGTH ERROR, SKIP RETURN
POPJ P, ;RETURN
WTCUEP: POP P,(P) ;WASTE RETURN
WTCUE: SETZM TTSOPU(W) ;UNIT NOT BUSY ANYMORE (YET)
TLNE T1,(S.CUE+S.DE) ;SKIP UNLESS NOT REALLY BUSY ANY MORE
JRST SETGOP ;START PROGRAM AND DISMISS INTERRUPT
LDB T2,CSYDVA ;GET UNIT ADDRESS FROM STATUS
SUBI T2,@TTSOFS(W) ;COMPUTE UNIT NUMBER
PUSHJ P,SETUDB## ;PICK UP U
SETZ U, ;HM - COUNT BE NXM UNIT FROM POLLER
SKIPN TS1PPC(W) ;SKIP IF WE HAVE A PROGRAM TO RESTART
JRST NXTWAT ;ULP - JUST TRY TO IGNORE IT
HRROM U,TTSOPU(W) ;REMEMBER UNIT THAT GOT BUSY
MOVEI T2,^D25 ;WAIT FOR 25 SECONDS (LESS THAN HUNG TIMER)
MOVEM T2,TTSBCT(W) ;WHEN TIMER EXPIRES, RETRY EVEN IF NO CUE
MOVSI T2,1 ;COUNT BUSYS IN LH
ADDM T2,TTSBRC(W) ;COUNT BUSYS
PJRST NXTWAT ;EXIT INT QUICKLY FOR NOW
GOTCUE: TLNE T1,(S.UC+S.DE+S.UE) ;SKIP UNLESS SOMETHING MORE IMPORTANT
POPJ P, ;JUST RETURN IF SOMETHING MORE IMPORTANT
SKIPE TTSOPU(W) ;SKIP IF NO UNIT KNOWN TO BE BUSY
SKIPN TS1PPC(W) ;SKIP IF KNOWN UNIT WITH KNOWN PROGRAM
JRST WTCUEP ;ODD, BUT PRETEND IT IS A BUSY
PUSHJ P,SAVT## ;SAVE THE ACS
HRRZ U,TTSOPU(W) ;GET THE U WHICH IS PENDED
SETZM TTSOPU(W) ;NO MORE U
SETZM TTSBCT(W) ;NO MORE TIMER
PUSHJ P,SETDVP ;SETUP DEVL ENTRY, ETC
MOVEI T2,SO.GO ;GET GO BIT
PUSHJ P,CNOSET ;SET GO BIT
PUSHJ P,TRK222 ;$ TRACK GO BIT
POPJ P, ;RETURN TO HANDLE REAL INTERRUPT
SETDVP: MAP T2,@TS1PPC(W) ;GET PC
MOVE T1,TS1SUN(W) ;ASSUME POLLER'S UNIT
SKIPE U ;SKIP IF AN UNKNOWN UNIT (IE: POLLER'S UNIT)
MOVE T1,UDBPDN(U) ;GET DRIVE NUMBER FROM UDB IF KNOWN UNIT
ADD T1,TTSOFS(W) ;COMPUTE ADDRESS OF UNIT
DPB T1,[POINT SASDLD,T2,SANDLD] ;INSERT UNIT ADDRESS INTO DEVL ENTRY
MOVEI T1,DL.STA ;GET "START" CODE
DPB T1,[POINT SASDLO,T2,SANDLO] ;INSERT OPCODE INTO DEVL ENTRY
PMOVEM T2,TS1DVP(W) ;INSERT DEVL ENTRY INTO PROPER SLOT
POPJ P, ;RETURN
;ROUTINE TO POSSIBLY CALL ERRSNS IF WE'RE AT INTERRUPT LEVEL
; ON A FORWARD MOTION AT RECORD 0
STISNS: SKIPN TUBFIL(U) ;SKIP IF NOT FILE 0
SKIPE TUBREC(U) ;SKIP IF BOTH FILE 0 AND RECORD 0
POPJ P, ;RETURN
POP P,(P) ;WASTE THE RETURN AS SNSANL WILL DO IT
; JRST ERRSNS ;ARRANGE A SENSE-DATA-CALLBACK FOR OUR CALLER
;ROUTINE TO DO SENSE COMMAND AT INTERRUPT LEVEL
ERRSNS: MOVE T1,TS1LCI(W) ;GET THE CONI
MOVE T2,TS1LST(W) ;GET THE CSW WORD
DMOVEM T1,TS1SIP(U) ;REMEMBER A SENSE IN PROGRESS
PUSHJ P,SETSNS ;SETUP FOR SENSE OPERATION
PJRST SETGOP ;START THE SENSE COMMAND
;ROUTINE TO SET UP FOR SENSE OPERATION
SETSNS: MOVE T2,UDBPDN(U) ;GET PHYSICAL DRIVE NUMBER
ADDI T2,@TTSOFS(W) ;COMPUTE ACTUAL DEVICE ADDRESS
DPB T2,[POINT DVSDVA,TS1SNS+SNSDVW(W),DVNDVA] ;UPDATE SENSE
MAP T1,TS1SND(U) ;GET PHYSICAL ADDRESS OF SENSE BYTES
DPB T1,[POINT DCSADR,TS1SNS+SNSDCW(W),DCNADR] ;UPDATE IOWD
MOVEI T2,TS1SNS+SNSDVW(W) ;GET VIRTUAL ADDRESS OF SENSE PROGRAM
MOVEM T2,TS1PPC(W) ;SAVE PC WE WANT TO RUN
SETZM TS1SND(U) ;INVALIDATE OLD SENSE
POPJ P,
;SUBROUTINE TO DECIDE IF CURRENT MODE IS BYTE MODE OR WORD MODE
;ARGS P1 := IORB
CHKMOD: MOVE T1,P1 ;GET IORB ADDRESS
LDB T1,PRBMOD## ;GET CURRENT MODE
CAIN T1,RB.MBY ;SKIP UNLESS INDUSTRY COMPATIBLE 9-TRACK
POPJ P, ;BYTE MODE
MOVEI T1,TUC7TK## ;7-TRACK BIT
TDNN T1,TUBCNF##(U) ;SKIP IF 7-TRACK DRIVE
JRST CPOPJ1## ;9-TRACK WORD MODE
MOVE T1,TRBFNC(P1) ;GET PARITY BIT
TLNN T1,RB.PAR ;SKIP IF EVEN PARITY
AOS (P) ;7-TRACK ODD PARITY IS WORD MODE
POPJ P, ;7-TRACK EVEN PARITY IS BYTE MODE
SUBTTL SA10 FUNCTIONS
;SUBROUTINE TO CLEAR STATUS FLAG
STSCLR: CONSO PI,PI.IPA-PI.IP7;SKIP IF ANY REAL INTERRUPT IN PROGRESS
POPJ P, ;RETURN IF AT UUO LEVEL
MOVEI T2,SO.STS ;STATUS FLAG
PJRST CNOCLR ;CLEAR IT
;SUBROUTINES TO SET OR CLEAR SA10 FLAGS
; T2=SA10 FUNCTION
CNOSET: TRO T2,SO.SET ;SET THE FLAG
CNOCLR: PUSH P,T1 ;SAVE T1
HLRZ T1,TS1SCN(W) ;GET SUBCHANNEL IN CONO POSITION
IOR T1,T2 ;COMBINE THEM
IORI T1,TAPCHN## ;INCLUDE PI
PUSHJ P,TRK444 ;$ DO A CONO RECORD
XCT KDBCNO(W) ;CONO SA10,(T1)
JRST TPOPJ## ;RESTORE T1 AND RETURN
SUBTTL END
$LIT
TS1END::!END