1
0
mirror of https://github.com/PDP-10/its.git synced 2026-01-24 03:18:05 +00:00
PDP-10.its/src/system/nmtape.30
2016-10-31 08:41:05 +01:00

2433 lines
75 KiB
Plaintext
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;********************************
;**
;** TO BE DONE:
;**
;** RECORDS LONGER THAN 1K
;** AUTOMATIC DETERMINATION OF DENSITY AND RECORD LENGTH WHEN READING
;** ALLOW CLOSE WHEN TAPE HAS BEEN TAKEN OFF
;** BE MORE FORGIVING OF CONTROLLER LOSSAGE
;** PASS .MTAPE TO JOB DEVICE
;** HAVE AN IGNORE ERRORS SWITCH
;** THIS HORRIBLE BLETCHEROUS IOT CODE SHOULD BE REDESIGNED
;**
;********************************
;Do not be deceived by the TM10 conditionals. This file is only good
; for a TM03/RH11 on a KS10. See MTAPE for anything else. Barf.
IFE TM10A+TM10B+TM03S,.ERR NO MAGTAPE CONTROLLER TYPE SELECTED
IFN TM10A,INFORM IO BUSS MAG TAPE,1
IFN TM10B,INFORM DATA CHANNEL MAG TAPE,1
IFN TM03S,INFORM RH11/TM03 MAG TAPE,1
IFN TM10P,[
$INSRT TM10
]
IFN TM03S,[
$INSRT TM03S
]
$INSRT T20MAC
MSCBL==8 ;Command buffer length
MGQDLL==10. ;PI level PDL length
IF2 IFN MNUMB-140600, .ERR IMPLICIT DEPENDENCY ON MNUMB
MSEOFP==210100 ;High bit of MNUMB in MEMBLT is EOF flag
MSCHN==140500 ;Other 5 bits of MNUMB is drive number
MTXP==410300,, ;BP to set/get transport number from IOCHNM
MUNITF==170300 ;BP to set/get unit field in MTC CONI
IFN TM10P,[
;Tape controller commands
MNOPIN==10000 ;NOP and interrupt when idle
MWRITE==4000 ;Write data
MW3IN==14000 ;Write data and long EOR gap
MSPRR==7000 ;Space in reverse direction
MREAD==2000 ;Read data
MSPFR==6000 ;Space in forward direction
MSPFF==16000 ;Space forward to EOF
MSPRF==17000 ;Space reverse to EOF
MREWND==1000 ;Rewind
MRWNDD==11000 ;Rewind and unload
MWEOF==5000 ;Write EOF mark
]
MGNRTY==10. ;Number of retries on read
;Modes in OPEN call
;
%MMOUT==1,,0 ;Open for output, 0=>input
%MMBLK==2,,0 ;Block mode, 0=>unit mode
%MMIMG==4,,0 ;Image mode, 0=>Ascii
%MMCNK==10,,0 ;"Chunk" mode, 0=>stream mode
%MMNSE==20,,0 ;No skip to EOF on close, 0=>do skip
%MMEP==40,,0 ;Even parity, 0=>odd
%MMDEN==300,,0 ;Density select
; 00=> "Default" - 1600 for KS/TU77
; 01=> 800 BPI
; 10=> 1600 BPI
; 11=> 6250 BPI
%MM32B==400,,0 ;"IBM" mode, write 8-bit bytes from LH 32 bits
; 0=> core dump
%MMRSZ==7000,,0 ;Record Size
; Ranging binarily from 0=>1024. to 7=>8. bytes
EBLK
SUBTTL MAG TAPE STORAGE AREA
MGVTC: 0 ;Scratch word for virgin tape check
MGJDTI: 0 ;"Wait for job done" time out value
MGNWRD: 0 ;Number of words read in a PI level read
MGTBZY: -1 ;Flag to get interrupt started
MGSFTI: 0 ;Software interrupt in progress
MGUNIT: -1 ;Unit expecting interrupt
MGWCW: 0 ;"Wait for control word written" flag
LMIOWD: 0 ;Last MIOWD
MSRAC: BLOCK NMTCS ;Transport software status flags
%MA==1,,525252
%MAEOF==400000 ;4.9 EOF seen on read - must be 4.9
%MAETR==200000 ;4.8 EOT on internal read
%MAETW==100000 ;4.7 EOT on write
%MAERR==040000 ;4.6 PI level got an error
%MARCE==020000 ;4.5 Read compare error
%MACTH==014000 ;4.4 Core allocator says stop
;4.3 " (WHY 2 BITS?)
%MASTP==002000 ;4.2 Stop read ahead
%MANWT==001000 ;4.1 Nothing written on tape yet
%MAEFA==000400 ;3.9 EOF seen on read-ahead, user hasn't seen
%MAESO==000200 ;3.8 EOF read since open
%MAMSO==000100 ;3.7 Tape moved since first open
%MAREW==000040 ;3.6 "Tape is rewinding" flag
%MARAC==000020 ;3.5 Read active flag
%MAMOL==000010 ;3.4 Transport on line
%MAWSW==000004 ;3.3 Wants software (timing) interrupts
MGERRC: BLOCK NMTCS ;Error count
MTCEFW: BLOCK NMTCS ;Number of EOF's written at close
MGEOFR: BLOCK NMTCS ;Number of EOF's since last read
MTPSAV: BLOCK NMTCS ;Storage to restore P on EOF
MSCMDC: REPEAT NMTCS,0 ;Number of commands in command list
MGSPCD: BLOCK NMTCS ;Spacing operation command
MGSCNT: BLOCK NMTCS ;Spacing operation count
MGEOTT: BLOCK NMTCS ;Timeout for detecting virgin tape
MSBUFP: REPEAT NMTCS,0 ;Mag tape MP<->PI buffer queue in,,out
MSNBOL: BLOCK NMTCS ;Number of buffers on list
MSCRW: BLOCK NMTCS ;R/W flag, -1=>output 0=>input
MSMPRC: BLOCK NMTCS ;Words left in buffer
MSMPRP: BLOCK NMTCS ;Next word in buffer
MTMDN: REPEAT NMTCS,-1 ;Block active at MP
MGCABN: REPEAT NMTCS,-1 ;Buffer active at PI level
MTUSE: REPEAT NMTCS,-1 ;Number of channels open on this transport
MTUSR: REPEAT NMTCS,-1 ;User index of transport user
MTBLKS: BLOCK NMTCS ;If write, buffer size
;If read, size of last record read
MTMFNC: BLOCK NMTCS ;.MTAPE function storage
MTMCNT: BLOCK NMTCS ;.MTAPE count
MTMTAP: BLOCK NMTCS ;MTAPE call word
MGCMTS: BLOCK NMTCS ;PI level status info (CONI MTS or similar)
MGCMTC: BLOCK NMTCS ;PI level controller info (CONI MTC or similar)
IFN TM10P,[
MTCONO: REPEAT NMTCS,\.RPCNT_17+20 ;Prototype CONO word for each transport
]
IFN TM03S,[
MTSELW: BLOCK NMTCS ;Select word (TC reg val) for each transport
MTSELM==3777 ;density/format/parity/unit bits mask
MTWTFC: BLOCK NMTCS ;-10 word count to tape frame conversion factor
]
;Build table of QDL (PI level stack) pointers
MGQDLP: REPEAT NMTCS,-MGQDLL,,CONC MGQD,\.RPCNT,-1
;Built storage for command lists and PI level stacks
REPEAT NMTCS,[
CONC MSCB,\.RPCNT,:
BLOCK MSCBL ;Space for command list
MGRCV ;Fake "command", causes list to wrap around
MGNCMD ;Function on botton of Q PDL, gets new command
CONC MGQD,\.RPCNT,:
BLOCK MGQDLL ;Space for PI level stack
IFE .RPCNT,MSLCTB==.-MSCB0 ;Length of each table
]
;Build table of pointers for adding commands to command list
MTCMBP: REPEAT NMTCS,-MSCBL-1,,CONC MSCB,\.RPCNT,-1
;Build table of bytepointers for removing commands from command list
MGCMBP: REPEAT NMTCS,4400,,CONC MSCB,\.RPCNT,-1
;It is depressing to discover that the DUMP program sucks these directly
; out of the running ITS. If you change what's in here fix DUMP too.
MGEMTC: 0 ;CONI MTC, at last error
MGEMTS: 0 ;CONI MTS, at last error
IFE TM10B,[
MIOWD: BLOCK 2 ;Channel program
]
IFN TM10A,[
MGDBRK: 0
CONO MTS,1
JRST 12,@MGDBRK
];TM10A
BBLK
;Random Macros
;Enqueue and Dequeue buffers from the lists used to pass buffers between
; main program and PI level. Assumes W has a valid transport number...
DEFINE MTENQB REG,TEMP=TT
SKIPG MSNBOL(W) ;;Any buffers on list already?
IFSKP.
HLRZ TEMP,MSBUFP(W) ;;Yes, get old tail pointer
DPB REG,[MLO,,MEMBLT(TEMP)] ;;Add new one onto end of list
ELSE.
HRRM REG,MSBUFP(W) ;;No, make new buffer head of list
ENDIF.
HRLM REG,MSBUFP(W) ;;New buffer is tail in any event
SETZM TEMP
DPB TEMP,[MLO,,MEMBLT(REG)] ;;Indicate end of list
AOS MSNBOL(W) ;;Increment count of buffers on list
TERMIN
DEFINE MTDEQB REG,TEMP=TT
HRRZ REG,MSBUFP(W) ;;Get head of buffer list
HLRZ TEMP,MSBUFP(W) ;;Get tail
CAMN REG,TEMP ;;Tail == head?
IFSKP.
LDB TEMP,[MLO,,MEMBLT(REG)] ;;No, get next buffer on list
HRRM TEMP,MSBUFP(W) ;;Make it the new head of list
ELSE.
SETZM MSBUFP(W) ;;Only one buffer, list is now empty
ENDIF.
SOS MSNBOL(W) ;;Decrement count of buffers on list
TERMIN
IFN TM03S,[
;Macros for testing various status bits as set up by MGGXPT and friends
IRP OP,,[NN,NE,NA,O,OE,ON,OA,Z,ZE,ZN,ZA,C,CE,CN,CA]
DEFINE TT!OP REG,#MSK
...TSF==0
IFSE REG,CS1,[
TL!OP I,MSK
...TSF==-1
]
IFSE REG,CS2,[
TR!OP I,MSK
...TSF==-1
]
IFSE REG,FS,[
TL!OP J,MSK
...TSF==-1
]
IFSE REG,ERR,[
TR!OP J,MSK
...TSF==-1
]
IFE ...TSF,.ERR Invalid register name REG given in TTxxx macro
TERMIN
TERMIN
];IFN TM03S
SUBTTL MAG TAPE OPEN ROUTINE
; C/ MODE,,DEV
; D/ MODE (ROT 1) 4.9=1=>OUTPUT
; I/ DEVICE NUMBER
; R/ IOCHNM WORD POINTER
MAGTO: SKIPL W,I ;Get device
CAIL W,NMTCS ;Too big?
JRST OPNL1 ;No such device
MOVSI T,%MAREW
TDNE T,MSRAC(W) ;Rewinding?
PUSHJ P,UFLS ;Yes, wait for completion
CONO PI,CLKOFF ;Don't want transport status changed under me
SKIPL MTUSE(W) ;See if we are the first opener
IFSKP. ;First opener. Initialize database for device
SETZM MSBUFP(W) ;Indicate no buffers on chain
SETZM MSNBOL(W) ;Another way of saying above
SETZM MSMPRC(W) ;Buffer words remaining
SETZM MSMPRP(W) ;Pointer to buffers
SETOM MTMDN(W) ;No buffer at MP level
SETOM MGCABN(W) ;No buffer owned by PI code
SETZM MSRAC(W) ;Initialize transport software status word
MOVEI A,2
MOVEM A,MTCEFW(W) ;Number of EOF's written
MOVSI A,%MANWT
IORM A,MSRAC(W) ;Indicate nothing written on tape
ELSE. ;Not first opener. Check legality of this open
CAME U,MTUSR(W) ;Same user as previous open?
JRST OPNL10 ;Different user, report error
MOVE B,D ;Check direction of open
EQV B,MSCRW(W) ;Same as previous direction?
SKIPL B ;Yes, OK
JRST OPNL2 ;No, wrong direction
ENDIF.
MOVEM U,MTUSR(W) ;Store user
SETZM MSCRW(W) ;Indicate read until found to be otherwise
TLNE C,1 ;Read or write?
SETOM MSCRW(W) ;Indicate write
AOS MTUSE(W) ;Indicate 1 more user
PUSHJ P,SOSSET
MTUSE(W) ;SOS if PCLSR'd
CONO PI,CLKON ;Let um (em?) get me (who's em?)
PUSHJ P,MTSTAT ;Get transport status in standard form
MOVE A,MSRAC(W)
TLNE A,%MAERR ;PI error means device not there
JRST MTODNP ;Go report error
IFN TM03S,[
TTNN FS,%TMSFP ;Formatter present?
JRST MTODNP ;No, can't win
TTNN FS,%TMSOL ;Slave on line?
JRST MTODOL ;No, lose
]
IFN TM10P,[
TXNN J,%T1STH ;Transport hung, by chance?
JRST MTOW1 ;No, proceed
TXNN J,%T1SRW ;OK if rewinding
JRST OPNL7 ;Device not working
]
MTOW1: SKIPN MSCRW(W) ;Writing?
JRST MTOW2 ;No...
IFN TM10P,TXNE J,%T1SWL ;Yes. Write locked?
IFN TM03S,TTNE FS,%TMSWL
JRST OPNL26 ;Yes, device writelocked error
IFN TM10P, TXNN J,%T1SET ;At EOT?
IFN TM03S, TTNN FS,%TMSET
JRST MTOW2 ;No
MOVSI A,%MAETW+%MAERR ;If write and EOT, make .IOT give IOC error,
; but let open win
IORM A,MSRAC(W)
MTOW2: TXNE C,%MMDEN ;Density specified explicitly?
JRST MTOW3 ;Yes, go check for validity
IFN TM10P,MOVEI A,1 ;No, pick one. Use 800 for TM10
IFN TM03S,MOVEI A,2 ;Use 1600 for TM03
DPB A,[.BP %MMDEN,C] ;Set value
JRST MTOW4 ;Done and assumed correct
MTOW3: LDB A,[.BP %MMDEN,C] ;Get density from open
IFN TM10P,[
CAIE A,1 ;800 is the only currently OK speed for TM10
JRST OPNL12
IFN 0,[
;You need something like this if you arrange to allow non-800 TM10 speeds
TXNN C,%MM32B ;32-bit compatible mode requested?
JRST MTOW4 ;No, core dump
CAIN A,1 ;Density specified as 800?
JRST MTOW4 ;Yes, we can do that
JRST OPNL12 ;32-bit and not 800BPI, controller can't do it
]
];IFN TM10P
IFN TM03S,[
CAIN A,3 ;Specified 6250?
JRST OPNL12 ;Yep, loser. Else OK
]
;Here on successful open.
; Set up CONO or select word, IOCHNM word, blocksize
;
MTOW4: PUSHJ P,LSWDEL ;Release MTUSE switch
IFN TM10P,[
MOVEI A,MTCCHN_3 ;Start building CONO word. Set control PI level
IFN TM10A,TRO A,1 ;Add in data PI level for non-DF10 controller
LDB B,[.BP %MMDEN,C] ;Get density from open
CAIE B,1 ;800 BPI
BUG INFO,[ILLEGAL TM10 TAPE SPEED SETTING, USING 800BPI]
MOVEI B,%T1D80 ; Yep.
DPB B,[.BP %T1CDS,A] ;Set density field of CONO word
TXNN C,%MM32B ;32-bit mode specified?
TXO A,%T1CCD ;No, set core dump mode in CONO
TXNN C,%MMEP ;User wants even parity?
TXO A,%T1COP ;No, set odd parity
DPB W,[.BP %T1CNU,A] ;Set unit number field of CONO
MOVEM A,MTCONO(W) ;Save assembled CONO word
];IFN TM10P
IFN TM03S,[
MOVE A,W ;Get unit number being initialized
TXNN C,%MM32B ;User asked for industry compatible?
IFSKP. ;Yes...
MOVEI B,4 ;Set word-to-frame conversion factor
MOVEM B,MTWTFC(W)
MOVEI B,%TMFIC ;Set mode in budding select word
ELSE. ;Core dump...
MOVEI B,5 ; takes 5 tape frames per word
MOVEM B,MTWTFC
MOVEI B,%TMFCD ;Set CD format in select word
ENDIF.
DPB B,[.BP %TMTFS,A] ;Set format in select word
TXNE C,%MMEP ;User wants even parity?
TXO A,%TMTEP ;Yes, set even parity flag
LDB B,[.BP %MMDEN,C] ;Get density from open
CAIE B,1 ;800 BPI specified?
SKIPA B,[%TMD16] ;Anything else, use 16
MOVEI B,%TMD08 ;800, use that
DPB B,[.BP %TMTDS,A] ;Set density in select word
MOVEM A,MTSELW(W) ;Set select word for this unit
];IFN TM03S
LDB B,[.BP %MMRSZ,C] ;Get record size from open call
TRC B,7 ;Convert to power of two
MOVEI A,10 ;Minimum record size is 10 (8.) words
LSH A,(B) ;Blocksize = minimum * 2^power
MOVEM A,MTBLKS(W) ;Save blocksize in words
LDB A,[.BP <%MMBLK\%MMIMG>,C]
;Use unit/block and ascii/image bits as index
HLR C,MTOPTB(A) ;Get input dispatch routine from table
TLNE D,400000 ;Remember D? Skip if user opened in input mode
HRR C,MTOPTB(A) ;OK, get output dispatch routine instead
MOVEM C,(R) ;Save routine in IOCHNM word
DPB W,[MTXP(R)] ;Set transport number in IOCHNM word
JRST POPJ1 ;Skip return means success
;Here if device is not present
MTODNP: SETZM MSRAC(W) ;Too bad. Clear status word and report error
JRST OPNL1
;Here if device off line
MTODOL: SETZM MSRAC(W)
JRST OPNL7
;Table of I/O routines
;
MTOPTB: MTUAIX,,MTUAOX ;Unit Ascii
MTBIX,,MTBOX ;Block Ascii
MTUIIX,,MTUIOX ;Unit Image
MTBIX,,MTBOX ;Block Image
SUBTTL MAG TAPE CLOSE ROUTINES
;MTOCL - CLOSE TAPE OPEN FOR OUTPUT
MTOCL: LDB W,[MTXP(R)] ;Set up transport number
SOSL MTUSE(W) ;Decrement transport use counter
POPJ P, ;Not only channel open, all done
AOS MTUSE(W) ;Consistant state in case PCLSR'd
MOVSI A,%MAERR
TDNE A,MSRAC(W) ;See if error has occurred
PUSHJ P,MTOCL3 ;Yes, clean up a few things
SKIPL MTMDN(W) ;Is there a partially processed buffer?
PUSHJ P,MTWBFD ;Yes, write it to tape
MOVEI B,MGMEOT ;Queue a "Write EOT" command to PI level
PUSHJ P,MTCMD
SKIPLE MSCMDC(W)
PUSHJ P,UFLS ;Wait till done.
MOVEI A,1
MOVEM A,MGEOFR(W)
SKIPGE MTMDN(W) ;Active buffer at MP level?
IFSKP.
MOVE A,MTMDN(W)
BUG PAUSE,[MT: MP BUF REMAINS AT CLOSE],OCT,A
PUSHJ P,MEMR
ENDIF.
SKIPGE MGCABN(W) ;Active buffer at PI level?
IFSKP.
MOVE A,MGCABN(W)
BUG PAUSE,[MT: PI BUF REMAINS AT CLOSE],OCT,A
PUSHJ P,MEMR
ENDIF.
SKIPN MSNBOL(W) ;Any buffers on buffer queue?
IFSKP.
BUG PAUSE,[MT:],DEC,MSNBOL(W),[BFRS QUEUED AT CLOSE]
PUSHJ P,MTCBFF
ENDIF.
SETOM MTUSE(W) ;Nobody is using this transport
SETOM MTUSR(W) ;No user associated with this transport
SETZM MSRAC(W) ;reset transport software status word
POPJ P,
MTOCL3: SKIPL A,MTMDN(W) ;Have a buffer active at MP level?
PUSHJ P,MEMR ;Flush it if so
SETOM MTMDN(W)
SETZM MSMPRC(W) ;Say no words left in current buffer
POPJ P,
;Close routine for MT open for input
MTICL: LDB W,[MTXP(R)] ;Set up channel data pointer
SOSL MTUSE(W) ;Last user?
POPJ P, ;No, nothing to do
AOS MTUSE(W) ;Yes, save state for possible PCLSR
MOVEI T,1 ;This crock is because we want to allow
CAMGE T,MSCMDC(W) ; one outstanding command if rewinding
PUSHJ P,UFLS ;Wait till one or less outstanding command
MOVE T,MSRAC(W) ;Get transport software status
TLNE T,%MAREW ;Is it rewinding?
IFSKP.
SKIPLE MSCMDC(W) ;No, wait till no outstanding commands
PUSHJ P,UFLS
ENDIF.
SKIPGE MGCABN(W) ;Any PI-level buffers left?
IFSKP.
MOVE A,MGCABN(W)
BUG PAUSE,[MT: PI INPUT BUF LEFT AT CLOSE],OCT,A
PUSHJ P, MEMR
ENDIF.
PUSHJ P,MTRBD ;Release any MP-level buffers
SETOM MTUSR(W) ;Reset user identifier
PUSHJ P,MTCBFF ;Free some buffers ?whose+++
SOS MTUSE(W) ;Decrement use count
MOVE T,MSRAC(W) ;Get transport software status again
TLNE T,%MAREW ;Are we rewinding?
JRST MTICL2 ;Yes, don't have to skip to EOF
MOVSI A,(%MMNSE)
TDNE A,(R) ;Check if user wants skip to EOF
JRST MTICL2 ;No, forget it
MOVSI A,%MAMSO
TDNN A,MSRAC(W) ;Has tape moved at all since open?
JRST MTICL2 ;No...
SKIPE MGEOFR(W) ;
JRST MTICL2 ;Note that this disposes of a read-ahead EOF.
PUSHJ P,MTSTAT
IFN TM10P,[
MOVE B,MGCMTS(W)
TXNE B,%T1SBT ;BOT?
JRST MTICL2
]
IFN TM03S,[
TTNN FS,%TMSOL ;Still online?
JRST MTICL2 ;No, can't very well skip to EOF
TTNE FS,%TMSBT
JRST MTICL2
]
MOVEI B,MGSPFF ;Space forward to end of file
PUSHJ P,MTCMD
SKIPLE MSCMDC(W) ;Wait till command done
PUSHJ P,UFLS
MTICL2: MOVSI T,%MAREW
ANDM T,MSRAC(W) ;Clear all software status except rewinding
POPJ P, ;Done
;Free a chain of IO buffers pointed to by MSBUFP(W)
; Count of buffers is in MSNBOL(W)
;
MTCBFF: SKIPN MSNBOL(W) ;Any buffers on chain?
POPJ P, ;No, fine
DO.
HRRZ A,MSBUFP(W) ;Yes, get pointer
LDB T,[MLO,,MEMBLT(A)] ;Get pointer to next buffer
HRRM T,MSBUFP(W) ;Write that in chain header
PUSHJ P,MEMR ;Return buffer to IO pool
SOSLE MSNBOL(W) ;Any more to do?
JRST TOP. ;Yes, loop back for more
ENDDO.
SETZM MSBUFP(W) ;Zero buffer list pointer
POPJ P,
SUBTTL MAG TAPE INPUT .IOT ROUTINES
SKIPA B,[SIOKT]
MTUAI: MOVEI B,CHRKTI ;Unit ASCII input
MOVE E,[440700,,5]
JRST MTREAD
SKIPA B,[SIOKT]
MTUII: MOVEI B,CHRKTI ;Unit image input
MOVE E,[444400,,1]
JRST MTREAD
MTBI: MOVE E,[444400,,1] ;Block input
MOVEI B,BLKT
MTREAD: LDB W,[MTXP(R)] ;W <= Transport number
PUSHJ P,MTIECK ;Check for tape errors first
MOVEM P,MTPSAV(W) ;Save P for EOF return
JSP B,(B) ;IO Routine. BLKT,CHRKT,SIOKT
MSMPRP(W) ;Pointer to next word
MSMPRC(W) ;Count of words remaining
SETZ MTRBG ;Get new buffer (SETZ for CHRKT return on EOF)
MTRBD ;Discard buffer
JRST 4,. ;Unused
PUSHJ P,MTRBFW ;Code to wait for new buffer from PI level
;Get a new buffer for I/O code.
; This routine assumes that there is a buffer ready to get
; (i.e. MTRBFW was called)
;
MTRBG: SKIPG MSNBOL(W) ;Any buffers on list?
JRST MTRBG3 ;No, must be error or EOF
CONO PI,UTCOFF ;Stop I/O for a bit
MTDEQB TT,A ;Dequeue buffer into TT using A as temp
MOVEM TT,MTMDN(W) ;Remember buffer active at MP level
CONO PI,UTCON ;Turn I/O back on
LDB J,[MWC,,MEMBLT(TT)] ;Get word count from buffer
MOVEM J,MTBLKS(W) ;Save for .MTAPE 13
LSH TT,10. ;Convert buffer number into address
JRST SIOBGX ;TT/address, J/word count /E unchanged
;Here if no buffer ready, error or EOF assumed
;
MTRBG3: SKIPL MSRAC(W) .SEE %MAEOF ;EOF flag set in transport status?
IFSKP.
MOVSI T,%MAEFA ;The EOF is now no longer read-ahead
ANDCAM T,MSRAC(W) ;So remember that fact
JRST POPJ2 ;Double skip to tell I/O code about EOF
ENDIF.
PUSHJ P,MTIECK ;Not EOF. Check for error conditions
BUG HALT,[TAPE READ BUFFER VANISHED] ;No error, shoulda been a buffer
;MAG TAPE READ BUFFER DISCARD ROUTINE
MTRBD: SKIPGE A,MTMDN(W) ;Have an active MP buffer?
JRST MOVTWJ ;Set up T for buffer wait, return
CONO PI,UTCOFF ;Stop IO for a bit
SETOM MTMDN(W) ;No active MP buffer
SETZM MSMPRC(W) ;No data in nonexistant buffer
LDB TT,[MSEOFP,,MEMBLT(A)] ;Get EOF flag from PI level
PUSHJ P,MGMEMR ;Return buffer, enable UTC
JUMPN TT, [ MOVSI A,%MAEOF ;EOF seen?
IORM A,MSRAC(W) ;Record EOF in software status
JRST .+1 ]
MOVTWJ: MOVE T,W ;T gets transport number for bfr wait UFLS
POPJ P, ;Also MTRBG, MTRBFW rely on this setting T
;MAG TAPE READ WAIT FOR DATA ROUTINE
; Called under a UFLS by system IO code to wait for data to arrive.
; Note T, not W, has transport number. T must be set up by some
; previous routine
;
MTRBFW: MOVE TT,MSRAC(T) ;Get software status of transport
TLNN TT,%MAEOF\%MAERR ;PI code reports EOF or error?
SKIPLE MSNBOL(T) ;Or are any buffers available for reading?
JRST POPJ1 ;SOme interesting condition, unhang
TLNE TT,%MARAC ;Have we asked for a tape read yet?
POPJ P, ;Yes, nothing to do but wait, wait, wait
PUSH P,W ;This being done under a UFLS. only T good
PUSH P,B
MOVE W,T ;Set up transport number in usual place
MOVEI B,MGREAD ;What we want the PI level to do
MOVEI T,MSCBL ;Make sure that there is room in command list
CAMG T,MSCMDC(W) ;If there is room,
IFSKP. ; we will request a read operation
MOVSI TT,%MARAC
IORM TT,MSRAC(W) ;Read is active now, or will be shortly
PUSHJ P,MTCMD1 ;Queue up command request for PI level
ENDIF. ;If no room for command, all we can do is wait
MOVE T,W ;Fix up T for UFLS
POP P,B ;Clean up everything else
POP P,W
POPJ P,
SUBTTL MAG TAPE OUTPUT .IOT ROUTINES
SKIPA B,[SIOKT]
MTUAO: MOVEI B,CHRKT ;Unit ASCII output
MOVE E,[440700,,5]
JRST MTWRIT
SKIPA B,[SIOKT]
MTUIO: MOVEI B,CHRKT ;Unit image output
MOVE E,[444400,,1]
JRST MTWRIT
MTBO: MOVE E,[444400,,1] ;Block output
MOVEI B,BLKT
MTWRIT: LDB W,[MTXP(R)] ;Get transport number
PUSHJ P,MTIECK ;Check for tape errors first
HRLZI A,%MAETW
TDNE A,MSRAC(W) ;PI code think it hit EOT?
JRST IOCER9 ;Yep, go lose
JSP B,(B)
SETZ MSMPRP(W) ;Pointer to next word
MSMPRC(W) ;Count
SETZ MTWBFG ;Get new buffer
MTWBFD ;Write out buffer to tape
JRST 4,.
TRNA ;No wait for buffer routine needed
;MAG TAPE WRITE - BUFFER GET ROUTINE
MTWBFG: PUSHJ P,MTIECK ;Check for tape errors
PUSHJ P,TCALL ;Turn off UTC
JRST IOMQ ;Try to get buffer
POPJ P, ;Return noskip if no buffers available
MOVEM A,MTMDN(W) ;Store active buffer number
MOVEI T,MUMGB
DPB T,[MUR,,MEMBLT(A)] ;Tell world that it is a mag tape buffer
DPB W,[MSCHN,,MEMBLT(A)] ;Store channel number in buffer header
SETZM TT
DPB A,[121000,,TT] ;Convert block number in A to address in TT
MOVE J,MTBLKS(W) ;Get block size of write
JRST SIOBGX
;MAG TAPE WRITE - BUFFER FINISHED ROUTINE
; General IO code has filled a buffer or otherwise finished with it.
; Queue the buffer for writing if there is anything in it.
MTWBFD: PUSHJ P,MTIECK ;Check for tape errors
SKIPGE A,MTMDN(W) ;Have an active buffer?
POPJ P, ;No, nothing to do
MOVEI T,MSCBL ;See if there is any room in command list
CAMG T,MSCMDC(W)
PUSHJ P,UFLS ;Wait for room in command list
MOVE T,MTBLKS(W) ;Get blocksize we are writing
SUB T,MSMPRC(W) ;Subtract number of words remaining in buffer
CONO PI,UTCOFF ;Lock up while frobbing buffer lists
SETOM MTMDN(W) ;Clear active buffer
SETZM MSMPRC(W) ;Clear free word in buffer count
JUMPE T,MEMR ;Nothing in buffer, just return block
DPB T,[MWC,,MEMBLT(A)] ;Store word count
MTENQB A ;Queue buffer on to-PI list
CONO PI,UTCON ;Finished mucking with buffer list
PUSH P,B
MOVEI B,MGWRIT ;Issue a write request to PI level
PUSHJ P,MTCMD
MOVSI B,%MANWT
ANDCAM B,MSRAC(W) ;Note that we have written something to tape
SETZM MTCEFW(W) ;Note no EOF's written at end of tape
JRST POPBJ ;Restore B and return
SUBTTL MTCMD - GIVE COMMAND TO PI LEVEL
;PUSHJ P,MTCMD
;RH(W) has transport number
;RH(B) has address of PI level routine to execute
MTCMD: MOVEI T,MSCBL ;Pending command list length
CAMG T,MSCMDC(W) ;Count of commands currently in list
PUSHJ P,UFLS ;Wait for room in pending command list
CONO PI,UTCOFF ;Grab machine, keep count accurate
MTCMD1: MOVE T,MTCMBP(W) ;Get pointer to next slot in command list
AOBJN T,MTCMD2 ;Increment slot and check for wraparound
SUB T,[MSCBL,,MSCBL] ;Reached end of list, ring it
MTCMD2: MOVEM B,(T) ;Store new command
MOVEM T,MTCMBP(W) ;Store new pointer
AOS MSCMDC(W) ;Indicate one more command in list
JRST MSTRTR ;Go start up PI routine
SUBTTL MTIECK - CHECK FOR IOC ERROR
;PUSHJ P,MTIECK
;Returns +1 if no error
;Gives IOC error to user if error - never returns.
MTIECK: PUSH P,A
MOVE A,MSRAC(W) ;Get transport software status
TLNN A,%MAERR ;PI level report an error?
JRST POPAJ ;No, all is OK
SKIPLE MSCMDC(W) ;Wait for PI level to finish cleaning up
PUSHJ P,UFLS ; before throwing away buffers
SKIPL A,MTMDN(W) ;Have an active MP-level buffer?
PUSHJ P,MEMR ;Yes, throw it away
SETOM MTMDN(W) ;No active MP buffer
SETZM MSMPRP(W) ;No place to get/put next character
SETZM MSMPRC(W) ;No room to do it anyway
PUSHJ P,MTCBFF ;Free any buffers waiting for MP processing
POP P,A
MOVE T,MGCMTS(W) ;Get transport status data from PI level
IFN TM10P,[
TRNE T,%T1STH\%T1SIO ;Transport hung or illegal operation?
JRST IOCER1 ;Yes, report device error
TRNE T,%T1SPE\%T1SRC\%T1SRL\%T1SDL\%T1SBT ;Gruesome errors
JRST IOCER3 ;Report irrecoverable data error
TRNE T,%T1SET ;(Real) End of Tape?
JRST IOCER9 ;Device Full error
];IFN TM10P
IFN TM03S,[
MOVE I,MGCMTC(W) ;Get controller transport status from PI level
MOVE J,MGCMTS(W)
TTNE CS1,%TM1MP ;Control bus parity error?
JRST IOCER1
TTNN CS1,%TM1TE ;Transfer error? Could be TM03 or RH11
IFSKP.
TTNE CS2,%TM2DL\%TM2UP\%TM2NF\%TM2NM\%TM2PE\%TM2MT\%TM2MP
JRST IOCER1 ;Non-data errors
TTNN FS,%TMSES ;Formatter error?
IFSKP.
TTNE ERR,%TMEUS\%TMECT\%TMENX\%TMEMD\%TMEFS\%TMEMC\%TMERM\%TMEIR\%TMEIF
JRST IOCER1 ;Fatal formatter errors
TTNE ERR,%TMECE\%TMECS\%TMEFC\%TMENG\%TMEFL\%TMEIC
JRST IOCER3 ;Non-recoverable data errors
ENDIF.
ENDIF.
TTNE FS,%TMSET ;End of tape?
JRST IOCER9
];IFN TM03S
MOVE A,MGEOFR(W) ;Check for logical EOT
CAIL A,2 ;Read two EOF's since last record?
JRST IOCER9 ;Yes, report EOT
JRST IOCER3 ;No, give irrecoverable data error for now
SUBTTL MAG TAPE .STATUS ROUTINE
;Building a status word in D.
;Routine sets:
; 1.7-1.9 open modes
; 2.3 BOT
; 2.4 EOT
; 2.5 9 track (0 = 7 track)
; 2.6 IBM mode (0 = coredump)
; 2.7 Transport idle (no pending command)
; 2.8 EOF (last thing seen was a tape mark)
;
STAMTC:
;Open modes
LDB W,[MTXP(R)] ;Get transport number
DPB A,[60300,,D] ;Open mode
PUSHJ P,MTSTAT ;Get tape status from transport
;EOT?
LDB A,[.BP %MAETW_22,MSRAC(W)] ;EOT on write
LDB B,[.BP %MAETR_22,MSRAC(W)] ;EOT on read
IOR A,B
DPB B,[140100,,D] ;Tape at EOT?
IFN TM10P,[
;7 or 9 track drive?
LDB A,[20100,,J] ;Get 7/9 track bit
TRC A,1
DPB A,[150100,,D] ;7 or 9 track drive
.ERR Missing TM10 .STATUS code at STAMTC
]
IFN TM03S,[
;A bunch of new stuff. BOT?
SETZ A,
TTNE FS,%TMSBT ;Transport is at BOT?
SETO A,
DPB A,[130100,,D] ;BOT.
;7 or 9 track drive?
SETOM A ;TM03 is always 9-track
DPB A,[150100,,D] ;7 or 9 track drive
;Core dump or 32 bit mode?
MOVE A,MTWTFC(W) ;Get word to frame conversion. 4 or 5
TRC A,1 ;Flip last bit. Last bit now on iff 32bit mode
DPB A,[160100,,D] ;Sorry.
;Formatter busy?
SETO A,
SKIPLE MSCMDC(W) ;Idle if no pending commands
SETZ A,
DPB A,[170100,,D]
;EOF last thing seen?
SETZ A,
TTNE FS,%TMSTM ;Last thing seen was a tape mark?
SETO A,
DPB A,[200100,,D] ;EOF.
];IFN TM03S
POPJ P,
;RCHST ROUTINE FOR MAG TAPE
RCHMGT: HLRZ E,(R) ;Get open mode from IOCHNM word
LDB J,[MTXP(R)] ;Get the mag tape drive number
MOVSI J,'MT0(J) ;Return that drive's device name
TRZ E,(.BM MTXP) ;Clear drive # field in OPEN modes
JRST POPJ1 ;Skip so that J overrides built-in device name
SUBTTL MAG TAPE PI LEVEL
;Request magtape interrupt from MP-level software
; Must be called with I/O interrupts off (CONO PI,UTCOFF)
; This is called every 1/2 second by the ITS slow clock routine
;
MSTRTR: SETZM MGTBZY ;No busy tapes, flag software interrupt
CONO PI,MTCRQ ;Request interrupt on magtape channel
CONO PI,UTCON ;Reenable IO interrupt system
POPJ P, ;That is all
;Handle tape interrupt requested by software or other nonspecific cause
; Get here via non-vectored MTCCHN interrupt on the KS
;
MGSBRK: AOS MGTBZY ;Note interrupt level is busy
SETOM MGSFTI ;Note software interrupt in progress
MOVEI B,NMTCS-1 ;Loop over all transports
SKIPG MSCMDC(B) ;Any commands in command list?
MGSBK1: SOJGE B,.-1 ;No, try next transport
SKIPGE B ;Found command or finished scan. Which?
JRST MGSBK2 ;Finished scanning. Go check other things
MOVE W,B ;Have a command. Set up transport number
PUSH P,B ;Save B over call to command routine
MOVSI B,%MACTH
TDNN B,MSRAC(W) ;Core allocator saying go away?
PUSHJ P,MGXGO ;No, go start requested routine
POP P,B ;Restore transport count
JRST MGSBK1 ;Loop back for another transport
MGSBK2: SETZM MGSFTI ;Clear software interrupt flag
JRST MGEX ;That's all for now
;This probably should check for lost IE bits on TM03
;Handle interrupt caused by specific hardware conditions
; Get here via vectored interrupt on the KS
;
IFN TM10P,[
; A - result of CONI MTC,
; C - result of CONI MTS,
;
MGHBRK: SKIPGE W,MGUNIT ;Get unit we are expecting interrupt on
JRST MGUBRK ;None? Probably MP level bailed out. Punt.
LDB B,[MUNITF,,A] ;Get unit that controller is squacking about
CAME W,B ;Same unit?
BUG HALT,[MT PI CODE LOST TRANSPORT]
MOVE J,C
PUSH P,[MGEX] ;Cause POPJ P, in handler to dismiss interrupt
IFN TM10B,[
TXNE C,%T1SCP\%T1SNM\%T1SDP ;Check for DF10 errors
JRST MGERR ;Yes, go to error routine
];TM10B
TXNE C,%T1SIO ;Illegal operation error?
JRST MGERR ;Yes, go to error routine
JRST MGXGO ;No, go handle interrupt
;Here to unbreak on unexpected hardware interrupt
;
MGUBRK: LDB W,[MUNITF,,A] ;Who's the loser, anyway
MOVE B,MTCONO(W) ;Get prototype CONO word for that transport
CONO MTC,(B) ;Select offending unit
CONO MTS,31 ;Clear interrupt, DF10, stop any op in progress
JRST MGEX ;Go dismiss interrupt
];IFN TM10P
IFN TM03S,[
;Check for active unit. If none, go directly to inactive slave
;polling code. If active unit,check that controller is talking about
;this unit, then jump to its routine (MGXGO). When that finishes,
;see if controller is still showing attention, and check status
;of other transports if so.
;
;Well, almost.
EBLK
MGHBRK: 0
BBLK
JSR UTCSAV ;Save AC,s set up interrupt P PDL
AOS MGTBZY ;Note interrupt level is alive
SKIPGE W,MGUNIT ;Some transport waiting for an interrupt?
JRST MGNOUW ;Nope, either Slave Status Change or lossage
IORDI B,%TMTC ;Get transport the TM03 is thinking about
ANDI B,7
CAME B,W ;Same as the one we were waiting for?
BUG HALT,[MT PI CODE LOST TRANSPORT]
PUSHJ P,MGXGO ;Go jump into this unit's handler
MGNOUW:
IFN NMTCS-1,[
.ERR Missing multi-transport code at MGNOUW!
If more than one unit, have to see if this is an interrupt caused by a
SSC (slave status change), and if so poll all the inactive units and
update their software status (rewinding, on/off line, etc.) With only
one transport we currently avoid this by keeping the unit active
(MGUNIT set) as long as it is doing *anything*, and giving it all the
hardware interrupts. See rewind code, too.
];IFN NMTCS-1
JRST MGEX ;Go dismiss interrupt
];IFN TM03S
;Interrupt level control flow
;
; Each transport maintains the current state of its PI-level action
; routines on a seperate (per-transport) PDL with its SP in Q. This
; allows you to save the current state, dismiss the interrupt, and
; resume where you left off when the next interrupt for this transport
; arrives.
;
; Subroutine linkage between routines handling a per-drive PI-level
; action is with PUSHJ Q,xxx and POPJ Q,
;
; The MP level queues commands for the PI level to process on a per-
; transport queue at MGSBx (x=unit number)
;
; Ths general interrupt code transfers to the per-drive actions by
; jumping to MGXGO, which will load Q from the saved state of the
; current drive and start up whatever it finds there. This may be
; the MGNCMD routine, which will start a new command, or it may be
; the middle of an in-progress PI-level command handler.
;
; PI-level action routines can relinquish control in several ways:
;
; PUSHJ Q, CPOPJ will dismiss the current interrupt, arranging for
; control to return to the instruction following the PUSHJ when the
; next interrupt for this unit occurs.
;
; JRST MGOVER will dismiss the current interrupt, arranging for the
; currently executing subroutine to be restarted "from the top" when
; the next interrupt for this unit occurs.
;
; A simple POPJ P, will dismiss the current interrupt, arranging for
; the routine that called this one to be started at the point immediately
; after the call when the next interrupt comes in. This is generally not
; useful except from first-level action routines, where a POPJ P, will
; indicate that you have finished handling the current command and cause
; the next interrupt to fetch and start execution of a new command from the
; queued command list by transferring to MGNCMD. Got that?
;Transfer control to whatever the per-transport code wants to do.
;
MGXGO: MOVE Q,MGQDLP(W) ;Getsaved Q PDL pointer for current transport
PUSHJ P,QPOPJ ;"Return" to whatever is on top of Q PDL,
; arranging for POPJ P, to return to here
MOVEM Q,MGQDLP(W) ;Save current Q PDL for next time
POPJ P, ;Return, dismissing this interrupt
;Dismiss interrupt, arranging for next interrupt to restart routine
; we are currently executing (rather than either continuing here or
; starting a new command)
;
MGOVER:
IFN TM10P,[
CONSZ MTS,%T1STH\%T1SIO\%T1SCE ;Tape hung/ill op/DF10 error,
JRST MGERR ; go handle error condition
]
SOS (Q) ;Decrement address at top of Q PDL, now
; points to PUSHJ Q, <us> instruction so
; that we will get called again from MGXGO
; at next interrupt dispatch
POPJ P, ;Return to P PDL caller, dismissing interrupt
;This routine is always the last "command" in a transport command list
; Wraps the command list BP around the the beginning of the list,
; then gets and executes the next command.
;
MGRCV: MOVNI A,MSCBL+1 ;Get negative length of command list
ADDM A,MGCMBP(W) ;Wrap command extraction pointer back to start
MGNCM1: ILDB B,MGCMBP(W) ;Get new command from list
JRST (B) ;And jump to it
;This code is always the first (bottom) thing in a transport's Q PDL
; It is therefore executed whenever MGXGO transfers control to the
; Q PDL and there is no command in progress.
;
MGNCMD: AOBJN Q,MGNCM1 ;Got here w/ POPJ Q,. Fake PUSHJ to restore Q,
; then go get the next command
BUG ;Q PDL pointer clobbered
QPOPJ1: AOS (Q)
QPOPJ: POPJ Q,
;WAIT FOR JOB DONE BIT TO SET
; Called from PI-level command routines to wait for end of command.
; Called with PUSHJ Q,MGWTJD
;
; Returns +1 to caller if unusual termination
; +2 to caller if operation terminated normally
;
; I,J contain tape status:
; On TM10, I=CONI MTC,
; J=CONI MTS
; On TM03S, I=%TMCS1,,%TMCS2 (controller status),
; J=%TMFS,,%TMERR (formatter status)
IFN TM10P,[
MGWTJD: CONI MTS,J ;Get transport status
TXNE J,%T1STH\%T1SIO ;Transport hung or Illegal operation?
JRST MGERR ;Yes, job-done isn't ever going to get set
MGWJD1: CONI MTS,J ;Get status again
SKIPN MGJDTI ;Is there a time out set?
IFSKP.
MOVE T,TIME ;Yes, check it. Get current time
CAML T,MGJDTI ;Smaller than specified timeout time?
JRST MGERR ;No, lose
ENDIF.
TXNN J,%T1SJD ;JOB-DONE bit set?
JRST MGOVER ;No, we want to wait for it
CONI MTS,J ;Job Done. Get status
CONI MTC,I ;Get CONI MTC
MOVEM J,MGCMTS(W) ;Save for MP level
MOVEM I,MGCMTC(W)
IFN TM10B,[
SKIPE MGWCW ;Want to wait for control word?
PUSHJ Q,MGWCWC ;Check to see if it is written
SETZM MGWCW ;Clear wait-for-control-word request flag
]
CONO MTS,30 ;Clear channel conditions
MOVE B,MTCONO(W)
CONO MTC,(B) ;Release mtc, clear job done bit
IFN TM10B,[
TXNE J,%T1SCP\%T1SNM\%T1SDP ;Check for channel errors
POPJ Q, ;Channel error, return nonskip
]
TXNE J,%T1STH\%T1SIO\%T1SPE\%T1SRC%\T1SRL\%T1SDL\%T1SBT
POPJ Q, ;Random other things, not necessarily errors
JRST QPOPJ1 ;Success
];IFN TM10P
IFN TM03S,[
MGWTJD:
MGWJD1: IORDI T,%TMCS1 ;Get controller status
TXNN T,%TM1GO ;Go bit still set?
JRST MGWJD2 ;No, command is finished. Go check errors
SKIPE T,MGJDTI ;Is there a time out set? Get it if so.
CAML T,TIME ;Past timeout time
JRST MGOVER ;No timeout or not timed out yet, go wait
JRST MGERR ;Timed out. Go check transport
;Here if action has terminated. Set up status bits before returning
MGWJD2: HRLZ I,T ;%TMCS1,,?
IORDI T,%TMCS2
HRR I,T ;I = %TMCS1,,%TMCS2
IORDI J,%TMERR
IORDI T,%TMFS
HRL J,T ;J = %TMFS,,%TMERR - I,J now in standard form
MOVEM J,MGCMTS(W) ;Save for MP level
MOVEM I,MGCMTC(W)
TTNE CS1,%TM1MP ;Massbus control parity error
JRST MGERR ;Who knows what the transport is doing
TTNN CS1,%TM1TE ;Controller error?
TTNE FS,%TMSES ;Formatter error?
POPJ Q, ;Yes, return +1 for closer examination
JRST QPOPJ1 ;Success
];IFN TM03S
;Select the transport given by W
; Returns +1 with transport selected, status in I,J
; May dismiss and wait for a while first
;
MGGXPT:
IFN TM10P,[
CONSO MTS,%T1SNU ;Can controller select new unit right now?
JRST MGOVER ;No, wait for it
MOVE T,TIME
ADDI T,10.*30. ;Time out in 10. seconds
MOVEM T,MGJDTI ;Set up job-done timeout
MOVEM W,MGUNIT ;Note unit waiting for hardware interrupt
MOVE B,MTCONO(W) ;Get CONO word for new unit
CONO MTC,MNOPIN(B) ;NOP, but interrupt when new drive is ready
PUSHJ Q,MGWJD1 ;Wait for job done
JFCL ;Ignore any errors
SETZM MGJDTI ;No more timeout
SETOM MGUNIT ;Not waiting any more
POPJ Q, ;Return to caller
];IFN TM10P
IFN TM03S,[
IORDI T,%TMFS ;Get current formatter status
TXNN T,%TMSES\%TMSSC ;Showing error or slave status change?
IFSKP. ;Yes, clear errors before going ahead
IOWRI W,%TMTC ;Select slave
MOVEI A,10. ;Try 10 times to clear drive
MOVEI B,%TMCLR
DO.
IOWRI B,%TMCS1 ;Write drive clear command
IORDI T,%TMFS ;Get status
TXNN T,%TMSES ;Still have error
JRST ENDLP. ;No, done
SOJG A,TOP. ;Retry up to 10 times
JRST MGERR ;Else give up
ENDDO.
ENDIF.
MOVE T,MTSELW(W) ;Get desired settings
IOWRI T,%TMTC ;Tell TM03
MOVEI T,%TMNOP ;You may need this to set status values
IOWRI T,%TMCS1 ; but I'm not really sure
IORDI T,%TMCS1
PUSHJ Q,MGWJD2 ;Go set status registers appropriately
JFCL ;Maybe should check non-existant slave?
POPJ Q,
];IFN TM03S
;MGERR - HANDLE TAPE ERROR
;
;Called from PI level command routines which detect a tape or controller error
; Flags error in software status word, records error status in MGExxx.
; Flushes command in progress by resetting Q PDL to base.
; Flushes commands in PI-level command queue by resetting queue pointers.
; Flushes any buffers which might be queued for writing.
; Returns to P PDL, to wait for new commands.
MGERR:
IFN TM10P,[
CONI MTS,MGEMTS ;Get transport status for MP level analysis
CONI MTC,MGEMTC
]
IFN TM03S,[
IORDI T,%TMCS1 ;Get controller and transport status into
HRLM T,MGEMTC ; standard form
IORDI T,%TMCS2
HRRM T,MGEMTC
IORDI T,%TMFS
HRLM T,MGEMTS
IORDI T,%TMERR
HRRM T,MGEMTS
MOVE I,MGEMTC ;Get status to standard place for macros
MOVE J,MGEMTS
];IFN TM03S
MOVSI T,%MARAC ;Read not active, for sure
ANDCAM T,MSRAC(W)
SETZM MSCMDC(W) ;No commands active
SETOM MGUNIT ;Clear unit wait flag
SETZM MGJDTI ;No job-done timeout
IFN TM10B,[
TXNE J,%T1SCP\%T1SNM\%T1SDP ;Channel error?
BUG PAUSE,[MTAPE: CHANNEL ERROR, STATUS=],OCT,J,[MICWA+1=],OCT,MICWA+1,[MIOWD=],OCT,MIOWD
];TM10B
IFN TM03S,[
.ERR UBA errors? More gentle cleanup?
TTNE CS1,%TM1MP\%TM1TE ;Cbus parity or transfer error?
TTNE FS,%TMSES ;And no formatter error?
SKIPA ;Yes and yes (no) (what?). Controller error
BUG INFO,[MTAPE: RH11 ERROR, STATUS=],OCT,MGEMTC,[TM STATUS=],OCT,MGEMTS
TTNE FS,%TMSES ;Formatter error?
BUG INFO,[MTAPE: FORMATTER ERROR, STATUS=],OCT,MGEMTS
PUSHJ P,TMINIC ;Go reinit controller
];IFN TM03S
SKIPL A,MGCABN(W) ;Any buffers owned by PI routines?
PUSHJ P,IMEMR ;Yes, give them back to system
SETOM MGCABN(W) ;No PI buffer any more
HRLZI B,%MAERR ;Flag error detected by PI level
IORM B,MSRAC(W) ;Store in transport status word
MOVE Q,[-MGQDLL,,MGQD0-1];Reset Q PDL to base of this unit's stack,
MOVE T,MSLCTB ; thus flushing whatever command is in progress
IMUL T,W ;Find offset to base of Q PDL for this unit
ADD Q,T ;Add to prototype unit 0 QDP pointer,
PUSH P,Q ; and save it away
MOVE Q,[-MSCBL-1,,MSCB0-1] ;Get command list input pointer
ADD Q,T ;Offset it to this unit's command queue,
MOVEM Q,MTCMBP(W) ;And save it as new MP (input) queue pointer
MOVE Q,[4400,,MSCB0-1] ;Get new command list output pointer
ADD Q,T ;Offset correctly for this unit,
MOVEM Q,MGCMBP(W) ;And save as PI (output) command queue pointer
MOVSI B,%MAREW ;Does initting xport stop TM03 rewind?
ANDCAM B,MSRAC(W) ;Say not rewinding
SKIPN MSCRW(W) ;If reading,
JRST POPQJ ; we're done. Restore Q and exit
SKIPN MSNBOL(W) ;Writing. Any buffers on list?
JRST POPQJ ;No, restore Q and exit
DO. ;Here to free buffers on IO list
HRRZ A,MSBUFP(W) ;Get buffer pointer from head of chain
LDB T,[MLO,,MEMBLT(A)] ;Get back pointer (next buffer)
HRRM T,MSBUFP(W) ;Make next buffer head of chain
PUSHJ P,IMEMR ;Free current buffer
SOSLE MSNBOL(W) ;Decrement count, check for more
JRST TOP. ;More, loop back
ENDDO.
SETZM MSBUFP(W) ;Mark list as empty
JRST POPQJ ;Restore Q and return
IFN TM10B,[
;Wait for control word to get written
;
MGWCWC: SKIPE MICWA+1 ;Control word written?
POPJ Q, ;Yes, return to caller
CONO MTS,4 ;No, tell DF10 to write it
MGWCW1: SKIPE MICWA+1 ;Written yet?
JRST MGWCW2 ;Good, done
PUSHJ Q,CPOPJ ;Not written. Dismiss interrupt and wait
JRST MGWCW1 ;We're back. See if written yet.
MGWCW2: MOVE I,MGCMTC(W)
MOVE J,MGCMTS(W) ;Restore status
TLO J,10 ;Set control word written
POPJ Q, ;Return to caller
];IFN TM10B
IFN TM10A,[
MGDCSI: SKIPA A,[BLKI MTC,MIOWD]
MGDCSO: MOVE A,[BLKO MTC,MIOWD]
MOVEM A,MAGLOC
MOVE A,[JSR MGDBRK]
MOVEM A,MAGLOC+1
POPJ Q,
];IFN TM10A
IFN TM03S,[
;Note this one's called on P PDL
TMINIC: IORDI A,%TMTC ;Get TC reg value
ANDI A,MTSELM ;Keep interesting bits only
IORDI B,%TMCS2 ;Get CS2
ANDI B,7 ;Keep selected "drive" (TM03) number only
MOVEI T,%TM2CC
IOWRI T,%TMCS2 ;Clear controller logic
IOWRI B,%TMCS2 ;Reselect TM03
IOWRI A,%TMTC ;Reselect transport
MOVX T,%TMCLR ;Do a formatter clear command
IOWRI T,%TMCS1
POPJ P,
];IFN TM03S
SUBTTL MAG TAPE PI LEVEL WRITE
MGWRIT: PUSHJ Q,MGGXPT ;Select desired transport
IFN TM10P,[
TXNE J,%T1STH\%T1SRW\%T1SWL ;Write locked, hung or rewinding?
JRST MGERR ;Not a good thing
]
IFN TM03S,[
TTNE FS,%TMSFR ;Formatter ready?
TTNN FS,%TMSOL ;Transport on line?
JRST MGERR ;No or no, can't do operation
TTNE FS,%TMSWL ;Transport write locked?
JRST MGERR ;Shouldn't happen, we checked at open.
]
MOVSI A,%MACTH
TDNE A,MSRAC(W) ;Core alloc want quit temporarly?
JRST [ PUSHJ Q,CPOPJ ;OK, wait a while
JRST MGWRIT ] ;Then go back and try again
MOVEM W,MGUNIT ;Set unit
HRREI B,-MGNRTY ;Number of retries
MOVEM B,MGERRC(W) ;Store error count
MTDEQB A ;Get buffer to write off list
MOVEM A,MGCABN(W) ;Note this buffer active at PI
LDB B,[MWC,,MEMBLT(A)] ;Get word count from buffer
MOVNS B ;B -> -COUNT
HRLZS B ;B -> -COUNT,,0
IFN KL10P,LSH B,4 ;Shift if KL10 data channel
IFN KL10P,MOVE R,A ;Save core page number for cache sweep
IFE TM03S,[ ;TM03S IOWD is -COUNT,,ITS PAGE
LSH A,10. ;Convert buffer number to memory address
SUBI A,1 ;Address - 1
]
HRRM A,B ;B -> -COUNT,,ADDRESS-1; an IO word
IFN TM10B,DATAO MTS,[MICWA] ;Tell DF10 where IO channel program is
IFN TM10A,PUSHJ Q,MGDCSO ;
MOVEM B,MIOWD ;Put IO word where controller looks
MOVEM B,LMIOWD ;Remember what we're about to do
IFN TM10P,SETZM MIOWD+1 ;Stop after one operation
IFN KL10P,[
PUSHJ P,CSHSWP ;Unload buffer from cache into core
CAI
]
MGWRT2:
IFN TM10P,[
MOVE B,MTCONO(W) ;Get prototype CONO word
CONO MTC,MWRITE(B) ;Perform WRITE operation
]
IFN TM03S,[
HLRE A,MIOWD ;Get PDP10 word count
ASH A,1 ; * 2
IOWRI A,%TMWC ; = number of unibus words to transfer
HLRE A,MIOWD ;Get PDP10 word count again
IMUL A,MTWTFC(W) ;Convert to tape frame count
IOWRI A,%TMFC ;Set tape frames to write
HRRZ A,MIOWD ;Get ITS page to transfer to
LSH A,1 ;Convert ITS pg # to DEC pg #
TXO A,%UQVAL ;Valid mapping, I should hope
IOWRI A,UBAPAG+IUTPG_1 ;Set up first half of UBA mapping
TXO A,1 ;Next DEC page number
IOWRI A,UBAPAG+IUTPG_1+1 ;Set second half of UBA mapping
MOVEI A,IUTPG_14 ;Unibus address to DMA to
IOWRI A,%TMBA ;Tell controller
MOVX A,%TM1IE\%TMWRT ;Write, enable interrupts
IOWRI A,%TMCS1 ;Start controller
]
PUSHJ Q,MGWTJD ;Wait for job done
JRST MGWERR ;Error, go attempt to repair
;Here if tape written OK
MGWRT3: MOVE A,MGCABN(W) ;Get buffer number
HRLZI B,%MAETW+%MAERR ;End of tape check
IFN TM10P,TXNE J,%T1SET ;Controller says we're at EOT?
IFN TM03S,TTNE FS,%TMSET
IORM B,MSRAC(W) ;Tell MP
LDB T,[MUR,,MEMBLT(A)] ;Get buffer flavor from buffer
CAIE T,MUMGB ;Still a magtape buffer?
BUG HALT,[MT BUF CHANGED INTO SOME OTHER KIND??]
SETOM MGCABN(W) ;No buffer active at PI anymore
PUSHJ P,IMEMR ;Return buffer to system
MOVSI A,%MAMSO ;Note tape has moved since open
IORM A,MSRAC(W)
;JRST MGCMDR ;Falls through
;General exit routine for most PI-level command handlers
; Check command queue for more commands.
; If no further commands, dismiss interrupt.
; If further commands queued, wait for this one to finish, then fetch
; and begin processing of next command.
;
MGCMDR: SOS MSCMDC(W) ;Decrement command count
SETOM MGUNIT ;Reset active unit
SKIPG MSCMDC(W) ;Any more commands?
JRST MGCMR1 ;No. Go see about other units
IFN TM10P,[
MOVE B,MTCONO(W)
CONO MTC,MNOPIN(B) ;Tell controller to interupt when unit ready
MOVEM W,MGUNIT ;Set up unit number again for MGWTJD
PUSHJ Q,MGWTJD ;Go wait for unit to finish current command
JRST MGERR ;Oops
SETOM MGUNIT ;No unit waiting any more
];IFN TM10P
POPJ Q, ;Return on Q PDL. Most likely this will
; transfer control to MGNCMD routine at
; base of PDL, which will fetch and execute
; next command.
MGCMR1:
IFN NMTCS-1,[
;Ought to check other transports for commands to start.
; For now, will get started by 1/2 second timeout, if nothing else.
.ERR Unfinished multi-transport code at MGCMR1
];IFN NMTCS-1
POPJ P, ;No more, return on P to dismiss interrupt
;CONTROLLER DETECTED ERROR ON WRITE OPERATION
; Retry, or give up, or write some blank tape and then try again,
; depending on the type of error.
;
MGWERR:
IFN TM10P,[
IFN TM10B,SETZM MIOWD ;Seems to do one record anyway
IFN TM10A,[
MOVE A,[-1,,MGVTC-1]
MOVEM A,MIOWD ;Specify one record to space back cmd.
]
TXNE J,%T1STH\%T1SRW\%T1SIO\%T1SET\%T1SWL ;Bad types of errors
JRST MGERR ;OK, give up
AOSL MGERRC(W) ;Still retrying?
JRST MGERR ;No, give up
MOVE B,MTCONO(W)
CONO MTC,MSPRR(B) ;Space reverse one record
PUSHJ Q,MGWTJD ;Wait for job done
JRST MGERR ;Error
MOVE B,LMIOWD ;Get last operation's IOWD
MOVEM B,MIOWD ;We're going to try it again
MOVE B,MTCONO(W) ;Get prototype CONO
CONO MTC,14000(B) ;Write with extended EOR gap
PUSHJ Q,MGWTJD ;Wait for completion
JRST MGWBT ;Lost again, retry some more
JRST MGWRT3 ;Worked, return to normal write sequence
];IFN TM10P
IFN TM03S,[
TTNE ERR,%TMERM\%TMEUS\%TMEFS\%TMEIR\%TMEIF\%TMEMC\%TMECT\%TMENX\%TMEOI
JRST MGERR ;Fatal errors
TTNN FS,%TMSOL ;On line?
JRST MGERR ;This isn't so good either
TTNE ERR,%TMEFC\%TMENG\%TMEMD\%TMEIC\%TMECE\%TMECS\%TMEFL
JRST MGWER1 ;Error which retrying might fix
;Formatter seems happy. Check channel status before returning
; Currently this only catches the case where there was an RH11 error
; but no TM03 error, and thus should always end up jumping to MGERR.
; Formatter errors on which it might be OK to get here are %TMECE,
; %TMECS, %TMEFL, but someone needs to test this...
TTNE CS1,%TM1TE ;Transfer error?
TTNE FS,%TMSES ;And not formatter error?
CAIA
JRST MGERR ;Just lose for now
BUG INFO,[MT: ACCEPTING QUESTIONABLE WRITE OPERATION]
JRST MGWRT3
;Retry errors
MGWER1: AOSL MGERRC(W) ;Still retrying?
JRST MGERR ;No, give up
BUG INFO,[MT: RETRYING WRITE OPERATION]
PUSHJ P,TMINIC ;Hit controller with hammer
MOVEI B,1
MOVEM B,MGSPCD(W) ;1 record
PUSHJ Q,MGSPCR ;Reselect transport space back a record
TTNE FS,%TMSTM ;Stopped on EOF?
SOSGE MGEOFR(W) ;Yes, one less EOF in front of us
SETZM MGEOFR(W) ;But never less than zero
PUSHJ P,TMINIC ;Hit controller with hammer again
PUSHJ Q,MGGXPT ;Set up transport again
MOVEI B,%TMER3\%TM1IE
IOWRI B,%TMCS1 ;Erase a few inches of tape
PUSHJ Q,MGWTJD ;Wait for job done
JRST MGERR ;Can't get anything right...
MOVE B,LMIOWD ;Get last operation's IOWD
MOVEM B,MIOWD ;We're going to try it again
JRST MGWRT2 ;Go back to write code and retry operation
];IFN TM03S
SUBTTL MAG TAPE PI LEVEL READ
MGREAD: PUSHJ Q,MGGXPT ;Select desired transport
MGRD0:
IFN TM10P,[
TXNE J,%T1STH\%T1SRW\%T1SET ;Unit hung, rewinding, or EOT
JRST MGERR ;Seems so, report error
]
IFN TM03S,[
TTNE FS,%TMSFR ;Formatter ready?
TTNN FS,%TMSOL ;Transport on line
JRST MGERR ;No or no, can't do operation
]
MOVE B,MGEOFR(W) ;EOF's seen since last read
CAIL B,2 ;Apparent logical EOT?
JRST MGERR ;Yes, can't read anything
SKIPE MSCRW(W) ;Make sure open for reading
BUG HALT,[MT: CHN NOT OPEN FOR READING]
MOVSI B,%MACTH ;Core allocator wants to wait?
TDNN B,MSRAC(W) ;Check in status word
PUSHJ P,IOMQ ;No, get a buffer
JRST [PUSHJ Q,CPOPJ ;Wanted to wait some or failed,
JRST MGREAD ] ; wait a while, then start over
MOVEM A,MGCABN(W) ;Note active buffer at PI level
MOVEI B,MUMGB
DPB B,[MUR,,MEMBLT(A)] ;Note buffer belongs to mag tape code
MOVEM W,MGUNIT ;Set active unit number
HRREI B,-MGNRTY ;Number of retries
MOVEM B,MGERRC(W) ;Store error count
IFN KL10P, MOVE R,A ;Get page for cache flush routine
IFE TM03S,[ ;TM03S IOWD is -COUNT,,ITS PAGE
LSH A,10. ;Convert buffer number to memory address
SUBI A,1 ;address-1
]
IFE KL10P,HRLI B,-2000 ;Get count half of IOWD
IFN KL10P,HRLI B,-2000_4 ;The KL is, of course, different
HRR B,A ;-count,,address-1
MOVEM B,LMIOWD ;Remember IOWD for possible retry
IFN TM10B,[
DATAO MTS,[MICWA] ;Tell DF10 where the channel program is
SETZM MICWA+1 ;Stop after one operation
]
IFN TM10A,PUSHJ Q,MGDCSI
IFN TM10P,SETZM MIOWD+1
MGRD1: MOVEM B,MIOWD ;Save IOWD where channel expects it
MOVEI B,2000 ;Assume for now that the record has 2K words
MOVEM B,MGNWRD ;Set up word count
IFN KL10P,[
PUSHJ P,CSHSWP ;Ensure no residue of this page in cache
CAIA
]
IFN KS10P,CLRCSH ;KS needs cache invalidated on read
IFN TM10P,[
MOVE B,MTCONO(W) ;Get prototype CONO word
CONO MTC,MREAD(B) ;Issue READ command
]
IFN TM03S,[
HLRE A,MIOWD ;Get PDP10 word count
ASH A,1 ; * 2
IOWRI A,%TMWC ; = number of unibus words to transfer
SETZ A, ;Set FC to zero
IOWRI A,%TMFC ;Set tape frames to write
HRRZ A,MIOWD ;Get ITS page to transfer to
LSH A,1 ;Convert ITS pg # to DEC pg #
TXO A,%UQVAL
IOWRI A,UBAPAG+IUTPG_1 ;Set up first half of UBA mapping
TXO A,1 ;Next DEC page number
IOWRI A,UBAPAG+IUTPG_1+1 ;Set second half of UBA mapping
MOVEI A,IUTPG_14 ;Unibus address for DMA
IOWRI A,%TMBA ;Tell controller
MOVX A,%TM1IE\%TMRDF ;Read forward, enable interrupts
IOWRI A,%TMCS1 ;Start controller
];IFN TM03S
IFN TM10B,SETOM MGWCW ;Tell MGWTJD to wait for control word written
PUSHJ Q,MGWTJD ;Wait for command to complete
JRST MGRERR ;Error, go do something. May be retry, correct
; MGNWRD if frame count error, or give up
IFN TM03S,[
;Get true record size for TM03, which doesn't give a FC error on READ
MGRD1A: TTNE FS,%TMSTM ;Read a tape mark?
JRST [ SETZM MGNWRD ;Read a tape mark. No data, just EOF
JRST MGRD2 ]
IORDI A,%TMFC ;Get record size in tape frames
ADD A,MTWTFC(W) ;Round up to PDP10 words.
SUBI A,1 ;Add frames_per_word - 1
IDIV A,MTWTFC(W) ;Get record size in PDP10 words
MOVEM A,MGNWRD
];IFN TM03S
;Here if OK or error handler has fixed things up
MGRD2: MOVE A,MGCABN(W) ;Get buffer we just wrote
SETOM MGCABN(W) ;No buffer active at PI level
MTENQB A ;Queue buffer up for MP level
MOVE B,MGNWRD ;Get number of words we read
DPB B,[MWC,,MEMBLT(A)] ;Set number of words in buffer
IFN TM10P,TXNE J,%T1SEF ;Read an EOF?
IFN TM03S,TTNE FS,%TMSTM ; i.e. a tape mark?
IFSKP.
SETZM MGEOFR(W) ;No. Note no EOFs read since last record
ELSE.
MOVSI B,%MAESO+%MAEFA ;EOF seen since open, EOF read ahead
IORM B,MSRAC(W) ;Note this in transport status word
SETO B,
DPB B,[MSEOFP,,MEMBLT(A)] ;Set EOF flag in this buffer
AOS A,MGEOFR(W) ;Count EOFs
CAIL A,2 ;Enough for EOT?
JRST MGRD4 ;Logical EOT, space back over it
ENDIF.
MOVSI A,%MAMSO
IORB A,MSRAC(W) ;Note tape movement
IFN TM10P,TXNE J,%T1SET ;Real EOT reached?
IFN TM03S,TTNE FS,%TMSET
JRST MGRD3
MOVE C,MSNBOL(W) ;Get count of buffers on list
IFN TM10P,TXNN J,%T1SEF ;EOF?
IFN TM03S,TTNN FS,%TMSTM
; CAIL C,6 ; or read ahead six records?
JFCL ;Or just for the hell of it
JRST MGRD5 ;Yes, stop reading
TLNN A,%MASTP ;Somebody request we stop?
JRST MGRD0 ;No, go back and read another record
;Yes, fall through to terminate read
;Here to terminate read command
;
MGRD5: MOVSI A,%MASTP+%MARAC ;Clear read active, any read stop request
ANDCAM A,MSRAC(W)
JRST MGCMDR ;Go to standard command return routine
;Controller saw a real EOT
;
MGRD3: DPB B,[MSEOFP,,MEMBLT(A)] ;Fake EOF
DPB B,[420100,,MSRAC(W)] .SEE %MAETR ;Indicate EOT on read
JRST MGRD5 ;Terminate read
;Here if logical EOT (two EOF's in a row)
; Back up till between the two EOF's
;
MGRD4: MOVSI A,%MAESO+%MARAC+%MASTP ;SECOND EOF, LOGICAL EOT
ANDCAM A,MSRAC(W)
JRST MGSPRF ;Space reverse one file
;Error detected on read.
; Analyze error, retry read if it might help
;
MGRERR:
IFN TM10P,[
IFN TM10B,[
TXNE J,%T1SCP\%T1SNM\%T1SDP
JRST MGERR ;Channel error, forget it
]
TXNE J,%T1STH\%T1SRW\%T1SIO\%T1SRC ;Hard error?
JRST MGERR ;Yes, abandon read
TXNE J,%T1SPE\%T1SDL%T1SBT ;Parity, data-late, or bad tape?
JRST MGMRT ;Yes, a read retry might fix it
TXNN J,%T1SRL ;Record length error?
JRST MGERR ;No, who knows what is going on
;Here if record length error. Adjust MGNWRD to reflect data actually read
;
IFN TM10B,HRRZ A,MICWA+1
IFN TM10A,HRRZ A,MIOWD ;Get final control word
HRRZ B,LMIOWD ;Get original IOWD
SUB A,B ;Calculate words read
IFN TM10B,SOS A ;Channel funnyness
CAIE A,1 ;Length of 1 may just be EOF indication
IFSKP.
TXNE J,%T1SEF\%T1SET ;1 word, EOF? EOT?
SETZM A ;Yes, zero length record, just carries MSEOFP
ENDIF.
MOVEM A,MGNWRD ;Save new record length
JRST MGRD2 ;Go process as potentially correctly read data
];IFN TM10P
IFN TM03S,[
TTNE ERR,%TMERM\%TMEUS\%TMEFS\%TMEIR\%TMEIF\%TMEMC\%TMECT\%TMENX
JRST MGERR ;Fatal errors
TTNN FS,%TMSOL ;On line?
JRST MGERR ;This isn't so good either
TTZ ERR,%TMEFC\%TMENG ;Ignore NSG, Frame count error
TTNE FS,%TMSPE ;Phase encoded (1600BPI) mode?
TTZ ERR,%TMECE\%TMECS ;If so, ignore errors hardware already fixed
TTZN ERR,%TMECE\%TMECS\%TMEFC\%TMENG\%TMEFL\%TMEMD\%TMEIC ;Retryable?
JRST MGRER1 ;Nothing retrying will help
TTNE FS,%TMSTM ;Tape mark?
JRST MGRER2 ;Yes, no point in retrying
JRST MGMRT ;OK, go retry read
;Formatter seems happy. Check channel status before returning
MGRER1: TTNE ERR,177777 ;Sanity check. Shouldn't be any errors left
JRST MGERR
TTNE CS1,%TM1TE ;Transfer error?
TTNE FS,%TMSES ;And not formatter error?
CAIA
JRST MGERR ;Just lose for now
MGRER2: JRST MGRD1A
];IFN TM03S
;Retry a read operation
;
MGMRT: AOSL MGERRC(W) ;Still retrying?
JRST MGERR ;No, give up
IFN TM10P,[
IFN TM10B,SETZM MIOWD
IFN TM10A,[
MOVE A,[-1,,MGVTC-1]
]
MOVEM A,MIOWD ;One record
PUSHJ Q,MGDCSO
MOVE B,MTCONO(W)
CONO MTC,MSPRR(B) ;Back up one record
PUSHJ Q,MGWTJD ;Wait till done
JRST MGERR ;No errors allowed
IFN TM10A,PUSHJ Q,MGDCSI ;Put back PI 1 BLKI
];IFN TM10P
IFN TM03S,[
;This could be more refined
PUSHJ P,TMINIC ;Hit controller with hammer
PUSHJ Q,MGGXPT ;Set up transport again
SETO A,
IOWRI A,%TMFC ;1 record
MOVEI A,%TM1IE\%TMSPR ;Space backwards command
IOWRI A,%TMCS1 ;Do it
PUSHJ Q,MGWTJD ;Wait till finished
JRST MGERR ;Give up if error
];IFN TM03S
MOVE B,LMIOWD ;Get IOWD from last command
JRST MGRD1 ;Try operation again
SUBTTL MAG TAPE PI LEVEL SPACING COMMANDS
;Space forward and space reverse are completely under conditionals
IFN TM03S,[
;Space forward MGSPCD(W) records
MGSPCF: PUSHJ Q,MGGXPT ;Acquire transport
TTNE FS,%TMSFR ;Formatter ready?
TTNN FS,%TMSOL ;Transport on line
JRST MGERR ;No or no, can't do operation
MOVEM W,MGUNIT ;Note active transport
MOVN A,MGSPCD(W) ;Get -count
IOWRI A,%TMFC ;Tell controller
MOVEI A,%TMSPF ;Get command
TXO A,%TM1IE ;Turn on interrupts
IOWRI A,%TMCS1 ;Start controller
PUSHJ Q,MGWTJD ;Wait till command completes
IFNSK. ;Error?
TTNE CS1,%TM1MP ;Control parity err?
JRST MGERR ;Yes, nothing else valid
TTNE FS,%TMSES ;Formatter errors?
IFSKP.
PUSHJ P, TMINIC ;No formatter errors, ignore RH errors
ELSE.
TTNN ERR,%TMEFC ;Frame count error?
JRST MGERR ;Nope, must be important
PUSHJ P,TMINIC
ENDIF.
ENDIF.
POPJ Q,
;Space forward record
MGSPFR: MOVEI B,1 ;Do one record
MOVEM B,MGSPCD(W) ;Set count
MOVSI B,%MAMSO ;Note this command causes tape movement
IORM B,MSRAC(W) ;Set in transport software status
PUSHJ Q,MGSPCF ;Do spacing op
TTNN FS,%TMSTM
SETZB B,MGEOFR(W) ;Count EOFs since last record. None here
TTNE FS,%TMSTM
AOS B,MGEOFR(W) ;Saw one.
CAIL B,2 ;Saw two?
JRST MGSPRR ;Back up over last one...
JRST MGCMDR ;Clean up and leave
;Space forward file
MGSPFF: MOVSI B,%MAESO ;See if tape has already read ahead to EOF
TDZE B,MSRAC(W)
JRST MGCMDR ;EOF already read during the read, done
MOVEI B,1 ;Do one record
MOVEM B,MGSPCD(W) ;Set count
MOVSI B,%MAMSO ;Note this command causes tape movement
IORM B,MSRAC(W) ;Set in transport software status
PUSHJ Q,MGSPCF ;Space forward one record
TTNN FS,%TMSTM
IFSKP. ;Saw a TM
AOS B,MGEOFR(W) ;Saw one.
CAIL B,2 ;Saw two?
JRST MGSPRR ;Yes, back up over last one, and leave
JRST MGCMDR ;No, OK, but we're done
ENDIF.
SETZB B,MGEOFR(W) ;No tape mark, reset count of EOFs seen
MGSPF1: MOVEM B,MGSPCD(W) ;Set count to 0 (B zero from above)
PUSHJ Q,MGSPCF ;Do it
TTNE FS,%TMSTM ;Saw a EOF?
IFSKP. ;No..
TTNE FS,%TMSET ;Saw an EOT?
JRST MGERR ;Really shouldn't happen
JRST MGSPF1 ;Else go look for TM again
ENDIF.
AOS MGEOFR(W) ;Saw one.
JRST MGCMDR ;EOF read. done
;Space reverse MGSPCD(W) records
MGSPCR: PUSHJ Q,MGGXPT ;Set up transport and get status
TTNE FS,%TMSFR ;Formatter ready?
TTNN FS,%TMSOL ;Transport on line
JRST MGERR ;No or no, can't do operation
TTNE FS,%TMSBT ;At BOT?
POPJ Q,
MOVEM W,MGUNIT ;Save selected transport
MOVN A,MGSPCD(W) ;Get -count
IOWRI A,%TMFC ;Tell controller
MOVEI A,%TMSPR ;Space Reverse command
TXO A,%TM1IE ;Turn on interrupts
IOWRI A,%TMCS1 ;Start controller
PUSHJ Q,MGWTJD ;Wait till command completes
IFNSK. ;Error?
TTNE CS1,%TM1MP ;Control parity err?
JRST MGERR ;Yes, nothing else valid
TTNE FS,%TMSES
IFSKP.
PUSHJ P,TMINIC
ELSE.
TTNN ERR,%TMEFC ;Frame count error?
JRST MGERR ;Nope, must be important
PUSHJ P,TMINIC
ENDIF.
ENDIF.
POPJ Q,
;Space reverse one record
MGSPRR: MOVEI B,1
MOVEM B,MGSPCD(W) ;1 record
MOVSI B,%MAMSO ;Note this command causes tape movement
IORM B,MSRAC(W) ;Set in transport software status
PUSHJ Q,MGSPCR
TTNE FS,%TMSTM ;Stopped on EOF?
SOSGE MGEOFR(W) ;Yes, one less EOF in front of us
SETZM MGEOFR(W) ;But never less than zero
JRST MGCMDR ;Leave through general exit
;Space reverse fill
MGSPRF: MOVSI B,%MAESO ;See if tape has already read ahead to EOF
TDNN B,MSRAC(W)
JRST MGSPR2 ;No, we can just do command
MGSPR1: MOVEI B,1
MOVEM B,MGSPCD(W)
PUSHJ Q,MGSPCR ;Skip back 1 record, should backup over EOF
TTNN FS,%TMSTM ;Tape mark seen?
JRST MGSPR1 ;Well, apparently not
MOVSI B,%MAESO
ANDCAM B,MSRAC(W) ;Turn off EOF-read-ahead flag
MGSPR2: SETZ B,
MOVEM B,MGSPCD(W) ;Space backwards the maximum number of records
PUSHJ Q,MGSPCR ;Do it
TTNN FS,%TMSBT ;BOT?
TTNE FS,%TMSTM ;Tape mark seen?
JRST MGCMDR ;Yes or Yes, all done
JRST MGSPR2 ;No, go back and try to find one.
];End TM03S way back
;Rewind commands
;
MGRWND:
IFN TM10P,MOVEI B,MREWND ;Normal rewind
IFN TM03S,MOVEI B,%TMREW
CAIA
MGRWDM:
IFN TM10P, MOVEI B,MRWNDD ;Rewind and dismount
IFN TM03S, MOVEI B,%TMUNL
MOVEM B,MGSPCD(W) ;Set up command
PUSHJ Q,MGRWD1 ;Call action routine
JRST MGCMDR
;Action routine for rewind commands
MGRWD1: PUSHJ Q,MGGXPT
IFN TM03S,[
TTNE FS,%TMSFR ;Formatter ready?
TTNN FS,%TMSOL ;Transport on line
JRST MGERR ;No or no, can't do operation
]
MOVEM W,MGUNIT
MOVE B,MGSPCD(W) ;Get desired command
IFN TM10P,[
ADD B,MTCONO(W)
CONO MTC,(B)
]
IFN TM03S,[
TXO B,%TM1IE
IOWRI B,%TMCS1
]
PUSHJ Q,MGWTJD ;Start controller and wait till done
IFNSK.
TTNE FS,%TMSES
JRST MGERR ;Oops.
ENDIF.
SETZM MGEOFR(W) ;Seen no EOFs since last record
;Here after rewind command has started.
; Two possibilities: Tape is rewound already, or controller is finished
; but tape is still rewinding.
IFN TM10P,[
MGRWD2: TXNN J,%T1SRW ;Slave still rewinding tape?
JRST MGRWD3 ;No, at BOT
PUSHJ Q,CPOPJ ;Wait some.
CONI MTS,J ;Get status again
MOVEM J,MGCMTS(W) ;Update in memory
JRST MGRWD2 ;Go see if we're done yet.
;Here when tape has rewound
MGRWD3: MOVE T,TIME ;Wait 1 second more
ADDI T,30. ;This is an attempt to fix a hardware bug
MOVEM T,MGJDTI
MGRWD4: MOVE T,TIME
CAML T,MGJDTI ;Check time
JRST MGRWD5 ;Finished waiting, go clean up
PUSHJ Q,CPOPJ ;No, wait some more
JRST MGRWD4
MGRWD5: MOVSI A,%MAMSO+%MAREW
ANDCAM A,MSRAC(W) ;Say not rewinding, hasn't moved
SETZM MGJDTI ;Clear timeout
POPJ Q,
];IFN TM10P
IFN TM03S,[
;This could be a lot smarter; should dismiss the command completely
; after rewind is started, and just scan for rewinding transports
; when a SSC interrupt is received. This change is also necessary
; to make multiple slaves work right; currently the rewinding unit
; holds active unit (MGUNIT) until the rewind is completed.
MGRWD2: TTNN FS,%TMSPP ;Transport still rewinding?
JRST MGRWD3 ;No, go finish up
PUSHJ Q,CPOPJ ;Dismiss interrupt, wait a while
PUSHJ Q,MGGXPT ;Get right slave, set up status
JRST MGRWD2
MGRWD3: MOVSI A,%MAMSO+%MAREW
ANDCAM A,MSRAC(W) ;Say not rewinding, hasn't moved
POPJ Q,
];IFN TM03S
;SKIP TO LOGICAL EOT
;
MGSEOT: PUSHJ Q,MGGXPT ;Get transport
IFN TM10P,[
TXNE J,%T1STH\%T1SRW ;Hung or rewinding?
JRST MGERR
]
IFN TM03S,[
TTNE FS,%TMSFR ;Formatter ready?
TTNN FS,%TMSOL ;Transport on line
JRST MGERR ;No or no, can't do operation
]
MOVEM W,MGUNIT ;Set active unit
IFN TM10P,TXNE J,%T1SBT ;BOT?
IFN TM03S,TTNE FS,%TMSBT
JRST MGVTCK ;Yep, do virgin tape check
;Not at BOT
; Do we have enough CONDITIONALS yet?
MGNVT:
IFN TM10P,[
MOVE B,MTCONO(W) ;Get CONO word
IFN TM10A,[
PUSHJ Q,MGDCSO
MOVE A,[-1,,MGVTC-1]
MOVEM A,MIOWD ;Tell it to move one record
]
IFN TM10B,SETZM MIOWD
CONO MTC,MSPRR(B) ;Space reverse first
];IFN TM10P
IFN TM03S,[
SETO B, ;Space backwards one record
IOWRI B,%TMFC
MOVEI B,%TMSPR\%TM1IE
IOWRI B,%TMCS1
];IFN TM03S
PUSHJ Q,MGWTJD ;Wait till done
IFNSK.
TTNE FS,%TMSES
JRST MGERR
ENDIF.
SETZM MGEOFR(W)
AOS MGEOFR(W) ;Claim to have seen one EOF
MGEOT2:
IFN TM10P,[
MOVE B,MTCONO(W)
CONO MTC,MSPFF(B) ;Skip forward to EOF
PUSHJ Q,MGWTJD
JRST MGERR
]
IFN TM03S,[
AOS MSCMDC(W) ;Kludge so MGSPFF will return here.
PUSHJ Q,MGSPFF ;Space forward file
]
MOVSI B,%MAETR ;See if we hit real EOT
IFN TM10P, TXNE J,%T1SET
IFN TM03S, TTNE FS,%TMSET
IORM B,MSRAC(W) ;Yep, tell MP
IFN TM10P,[
MOVE B,MTCONO(W)
IFN TM10A,[
MOVE A,[-1,,MGVTC-1]
MOVEM A,MIOWD ;One record
]
IFN TM10B,SETZM MIOWD
CONO MTC,MSPFR(B) ;Space forward one record
]
IFN TM03S,[
SETO B,
IOWRI B,%TMFC
MOVEI B,%TMSPF\%TM1IE
IOWRI B,%TMCS1
]
PUSHJ Q,MGWTJD
IFNSK.
TTNE FS,%TMSES
JRST MGERR
ENDIF.
MOVSI B,%MAETR ;Check for real EOT again
IFN TM10P,TXNE J,%T1SET
IFN TM03S,TTNE FS,%TMSET
IORM B,MSRAC(W)
IFN TM10P,TXNN J,%T1SEF ;Is this another EOF?
IFN TM03S,TTNN FS,%TMSTM ;(i.e. a tape mark)
JRST MGEOT2 ;No, not at logical EOT. Go try again
IFN TM10P,[
MOVE B,MTCONO(W) ;Yes, at logical EOT, Back up over 1 EOF
CONO MTC,MSPRF(B) ;Space back one file
]
IFN TM03S,[
SETO B,
IOWRI B,%TMFC
MOVEI B,%TMSPR\%TM1IE
IOWRI B,%TMCS1
]
PUSHJ Q,MGWTJD
IFNSK.
TTNE FS,%TMSES
JRST MGERR
ENDIF.
MOVSI B,%MAEOF+%MAETR ;Tell MP at EOF, EOT
IORM B,MSRAC(W)
JRST MGCMDR
;Check for virgin tape
MGVTCK: MOVE T,TIME
ADDI T,60. ;Set a two second timeout
MOVEM T,MGEOTT(W) ; before we must see an EOT
IFN TM10P,[
IFN TM10B,[
SETZM MIOWD
DATAO MTS,[MICWA]
]
IFN TM10A,[
MOVE A,[-1,,MGVTC-1]
MOVEM A,MIOWD
PUSHJ Q,MGDCSO
]
MOVE B,MTCONO(W)
CONO MTC,MREAD(B) ;Read record. will time out if no EOF marks
MGVTC1: CONI MTS,J
MOVEM J,MGCMTS(W)
TXNE J,%T1SJD ;Job done?
JRST MGNVT ;Yep, not virgin tape
TXNE J,%T1STH\%T1SIO ;Transport hung or illegal operation?
JRST MGERR ;Yes, give up
MOVE T,MGEOTT(W) ;Get the timeout value
CAMG T,TIME ;Time up?
JRST MGVT ;Yes, it's a new tape
PUSHJ Q,CPOPJ ;Wait a while
JRST MGVTC1 ;Go back and check again
];IFN TM10P
IFN TM03S,[
SETO B,
IOWRI B,%TMFC ;Do one record
MOVEI B,%TMSPF\%TM1IE ;Space forward command
IOWRI B,%TMCS1
MGVTC1: IORDI T,%TMCS1 ;Get status
TXNN T,%TM1GO ;Still going?
IFSKP. ;Yep.
MOVE T,MGEOTT(W) ;Get the timeout value
CAMG T,TIME ;Time up?
JRST MGVT ;Yes, it's a new tape
PUSHJ Q,CPOPJ ;Wait a while
JRST MGVTC1 ;Go back and check again
ENDIF.
TXNE T,%TM1TE\%TM1MP ;Controller error?
JRST MGERR ;Yes, bad
IORDI T,%TMFS ;Get formatter status
TXNE T,%TMSES ;Formatter error?
JRST MGNVT ;No error, not a new tape
IORDI T,%TMERR ;Get formatter error register
TXNE T,%TMEFC ;Frame Count error?
JRST MGNVT ;Yes, that is probably an OK tape
JRST MGERR ;Not FC, must be a real problem
];IFN TM03S
;Virgin tape. Abort operation in progress, rewind tape
MGVT:
IFN TM10P,[
MOVE B,MTCONO(W)
CONO MTS,31 ;Clear controller
CONO MTC,MNOPIN(B) ;Start new command to clear things out
PUSHJ Q,MGWTJD
JFCL ;Ignore errors
]
IFN TM03S,[
PUSHJ P,TMINIC
]
IFN TM10P,MOVEI B,MREWND ;Do a rewind
IFN TM03S,MOVEI B,%TMREW
MOVEM B,MGSPCD(W)
PUSHJ Q,MGRWD1
SETZM MGEOFR(W) ;No EOFs seen
AOS MGEOFR(W) ;???
JRST MGCMDR ;Done
;Write EOT mark (two EOF's) on tape
;
MGMEOT: PUSHJ Q,MGGXPT
IFN TM10P,[
TXNE J,%T1STH\%T1SRW\%T1SWL ;Hung, rewinding, or write locked...
JRST MGERR
]
IFN TM03S,[
TTNE FS,%TMSFR ;Formatter ready?
TTNN FS,%TMSOL ;Transport on line
JRST MGERR ;No or no, can't do operation
TTNE FS,%TMSWL ;Transport write locked?
JRST MGERR ;Shouldn't happen, we checked at open.
];IFN TM03S
MOVEM W,MGUNIT ;Note active unit
SKIPE MTCEFW(W) ;Check # of EOF's already written
IFSKP. ;None. Need to write two
AOS MSCMDC(W) ;Kludge so MGWEOF will return here.
AOS MTCEFW(W) ;Increment EOF count
PUSHJ Q,MGWEOF ;Write an EOF
ENDIF.
MOVE A,MTCEFW(W) ;Get EOF count
SOSLE A ;Check for at least two EOF's written
IFSKP. ;No, need one more on tape
AOS MSCMDC(W) ;Again, force MGWEOF to return
AOS MTCEFW(W) ;Incr EOF count
PUSHJ Q,MGWEOF ;Write EOF
ENDIF.
MOVE A,MSRAC(W) ;Get transport software status
TLNE A,%MANWT ;Are we supposed to back up over last EOF?
IFSKP.
AOS MSCMDC(W) ;Yes. Force MGSPRF to return, then...
PUSHJ Q,MGSPRF ; ...do space reverse file command
ENDIF.
MOVSI A,%MANWT ;Note what we've done
IORM A,MSRAC(W)
JRST MGCMDR ;Leave through general exit routine
;Write one EOF mark on tape
;
MGWEOF: PUSHJ Q,MGGXPT ;Set up transport for IO
IFN TM10P,[
TXNE J,%T1STH\%T1SRW\%T1SWL ;Hung, rewinding, or write locked...
JRST MGERR ; ..lose
]
IFN TM03S,[
TTNE FS,%TMSFR ;Formatter ready?
TTNN FS,%TMSOL ;Transport on line
JRST MGERR ;No or no, can't do operation
TTNE FS,%TMSWL ;Transport write locked?
JRST MGERR ;Shouldn't happen, we checked at open.
]
MOVEM W,MGUNIT ;Remember active unit
IFN TM10P,[
MOVE B,MTCONO(W) ;Get CONO word for this unit
CONO MTC,MWEOF(B) ;Execute Write EOF function
]
IFN TM03S,[
MOVEI B,%TM1IE\%TMWTM ;Write tape mark, enable interrupts
IOWRI B,%TMCS1 ;Do it
]
PUSHJ Q,MGWTJD ;Wait around till command is complete
IFNSK.
TTNE FS,%TMSES
JRST MGERR
ENDIF.
MOVSI A,%MAMSO
IORM A,MSRAC(W) ;Note tape movement in software status
JRST MGCMDR ;Return through general exit routine
;Get transport and controller status
;
MGSTAT: PUSHJ Q,MGGXPT
JRST MGCMDR
;Write some blank space
;
MGW3IN: PUSHJ Q,MGGXPT
IFN TM10P,[
TXNE J,%T1STH\%T1SRW\%T1SWL ;Hung, rewinding, or write locked...
JRST MGERR
]
IFN TM03S,[
TTNE FS,%TMSFR ;Formatter ready?
TTNN FS,%TMSOL ;Transport on line
JRST MGERR ;No or no, can't do operation
TTNE FS,%TMSWL ;Transport write locked?
JRST MGERR ;Shouldn't happen, we checked at open.
];IFN TM03S
MOVEM W,MGUNIT ;Note active transport
IFN TM10P,[
;TM10 can't just write blank space, it has to write blank space followed
; by a data record
IFN TM10B,[
SETZM MIOWD ;Tell TM10 to write 1-word record
DATAO MTS,[MICWA]
]
IFN TM10A,[
MOVE A,[-1,,MGVTC-1] ;1-word record
MOVEM A,MIOWD
PUSHJ Q,MGDCSO
]
MOVE B,MTCONO(W)
CONO MTC,MW3IN(B) ;Write date record preceeded by 3-in gap
];IFN TM10P
IFN TM03S,[
MOVEI B,%TM1IE\%TMER3 ;Erase 3 inches command, enable interrupts
IOWRI B,%TMCS1 ;Do it
];IFN TM03S
PUSHJ Q,MGWTJD ;Wait...
JFCL ;Ignore errors (really should check kind)
IFN TM10P,JRST MGSPRR ;Now space record reverse over the bogus record
IFN TM03S,JRST MGCMDR ;TM03 does it right
SUBTTL .MTAPE UUO
;.MTAPE AC,
; AC/ CHNM,,COMMAND
; COMMAND/ COUNT,,FUNCTION
;Called with J/ AC field from UUO
AMTAPE: XCTR XR,[HLRZ R,(J)] ;Get IO channel from user
TRNE R,-NIOCHN ;Legal channel?
JRST ILUUO ;Lose
HRRZM R,UUAC(U) ;Cause errors to report on the correct channel
ADDI R,IOCHNM(U) ;Form IOCHNM pointer
HRRZ A,(R) ; A: CLSTB/IOTTB index
CAIL A,MTUAIX ; Min index for tape
CAILE A,MTBOX ; Max
POPJ P, ; Laconic error reportage.
LDB W,[MTXP(R)] ;Get transport number
CAME U,MTUSR(W) ;Same user?
POPJ P, ;No, give up
UMOVE A,(J) ;Get Channel,,Command from user
MOVEM A,MTMTAP(W) ;Save it
HRRZS A ;Get user address of Count,,Function word
PUSHJ P,MTIECK ;Check transport for error states
UMOVE A,(A) ;Get Count,,Function from user
HRRZM A,MTMFNC(W) ;Store function
HLREM A,MTMCNT(W) ; and count
SKIPN MTMCNT(W) ;Count of zero always means one, for
AOS MTMCNT(W) ; compatibility with the old code.
HRRZS A ;Just Function
CAIL A,NMTAPC ;Command in range?
POPJ P, ;No...
AOS (P) ;Command OK, skip return
JRST @MTAPDT(A) ;Go do command
MTAPDT: MTHANG ;0 Hang till tape motion done
MTRWND ;1 Rewind
MTRWDM ;2 Rewind and dismount
MTWEOR ;3 Write EOR if appropriate
MTW3IN ;4 Write 3 inches of blank tape
MTWEOF ;5 Write EOF
MTSPR ;6 Space records
MTSPF ;7 Space files
MTSPEOT ;10 Space to EOT
MTSTOP ;11 Abort all operations immediately
MTSBKS ;12 Set block size (to COUNT)
MTRBKS ;13 Read block size (to AC)
IFN 0,[
MTRTSW ;14 Read Transport Information (to AC)
MTRTEW ;15 Read Tape Error Word (to AC)
]
NMTAPC==.-MTAPDT
;Set block size for write
;
MTSBKS: MOVE A,MTMCNT(W) ;Desired blocksize
CAIL A,4 ;Check reasonableness
CAILE A,2000
SOSA (P) ;Fail if too big or too small
MOVEM A,MTBLKS(W) ;OK, change write-buffer size
POPJ P,
;Read current write blocksize
;
MTRBKS: MOVE A,MTBLKS(W) ;Get current write block size
JRST APTUAJ ;Return it
;Hang until all motion finished
;
MTHANG: SKIPLE MSCMDC(W) ;Check count of queued commands
PUSHJ P,UFLS ;Wait if there are any
JRST MTIECK ;Done, check for errors and return
;Rewind, Rewind and dismount
;
MTRWND: SKIPA B,[MGRWND] ;Get "REWIND" PI level command
MTRWDM: MOVEI B,MGRWDM ; or "REWIND and DISMOUNT" if appropriate
SKIPE MSCRW(W) ;Writing?
JRST MTSOSP ;Yes, error. Go undo skip rtn and exit
MOVSI A,%MAREW ;Note rewinding in software status
IORM A,MSRAC(W)
JRST MTCMD ;Go queue command for PI level
;"Write End of Record"
; This is really the FORCE system call, or should be.
;
MTWEOR: SKIPG MTMDN(W) ;MP level have an active buffer?
POPJ P, ;No, nothing to do
SKIPE MSCRW(W) ;Writing?
JRST MTWBFD ;Yes, go write buffer to tape
MTSOSP: SOS (P) ;Not writing, error. Undo skip return
POPJ P, ;Return
;Write EOF
;
MTWEOF: SKIPN MSCRW(W) ;Writing?
JRST MTSOSP ;No, can't write EOF. Take error exit
PUSHJ P,MTWEOR ;Flush current buffer, if any
MOVEI B,MGWEOF ;Get PI level EOF routine
AOS MTCEFW(W) ;Increment count of EOF's written
MOVSI TT,%MANWT ;Flag something written on tape
ANDCAM TT,MSRAC(W)
JRST MTCMD ;Queue MGWEOF command for PI level
;Write blank tape
;
MTW3IN: SKIPN MSCRW(W) ;Error if tape not open for write
JRST MTSOSP
MOVEI B,MGW3IN ;Get PI level command
SETZM MTCEFW(W) ;No EOF's since last record
MOVSI TT,%MANWT
ANDCAM TT,MSRAC(W) ;Note written something to tape
JRST MTCMD ;Go queue command for PI
;Space records, +=forward, -=back
;
MTSPR: SKIPE MSCRW(W) ;Not allowed if writing
JRST MTSOSP
PUSHJ P,MTFLRA ;Flush read-ahead, find out how far off we are
ADD B,C ;Get records tape is ahead of user (EOF=record)
MOVNS B ;Subtract this from user's request
ADDB B,MTMCNT(W) ;Adjust count
JUMPE B,CPOPJ ;If count is now zero, we are done
MTSPR1: PUSHJ P,MTCNTR ;Update user's copy in case PCLSR
JUMPG B,MTSPFR ;Space forward
MOVEI B,MGSPRR ;Get SPACE REVERSE command
PUSHJ P,MTCMD ;Queue it
AOSGE B,MTMCNT(W) ;Increment count, check if done
JRST MTSPR1 ;More
POPJ P, ;No more
MTSPFR: MOVEI B,MGSPFR ;Get SPACE FORWARD command
PUSHJ P,MTCMD ;Queue it
SOSLE B,MTMCNT(W) ;Decr count, check if done
JRST MTSPR1 ;More
POPJ P,
;This routine flushes readahead. Call before doing a spacing operation
; this doesn't actually undo the effect on the drive of the read-ahead.
; It does make sure that read-ahead's effect can't change, then returns
; in B the number of records ahead (non-negative) and in C the number of
; EOF's ahead (0 or 1). If called twice it will return zero the second
; time. Be sure to update your parameters.
;
MTFLRA: PUSHJ P,MTCNTR ;Make sure user space is writable first
MOVSI B,%MASTP
MOVSI T,%MARAC
IORM B,MSRAC(W) ;Tell PI-level read routine to stop reading
TDNE T,MSRAC(W) ;Wait until PI level actually stops
PUSHJ P,UFLS
ANDCAM B,MSRAC(W) ;Turn off %MASTP, things are now quiet
SKIPLE MSCMDC(W) ;Make sure PI level is completely inactive
PUSHJ P,UFLS ;Wait if necessary
MOVE B,MSNBOL(W) ;Get # bufs on read list (='s # records ahead)
LDB C,[.BP (%MAEFA),MSRAC(W)] ;1 if EOF read ahead
MOVSI T,%MAEFA ;Clear read-ahead EOF
ANDCAM T,MSRAC(W)
JRST MTCBFF ;Go flush read-ahead buffers
;Space files, + = forward, - = back
MTSPF: SKIPE MSCRW(W) ;Not allowed if writing
JRST MTSOSP
PUSHJ P,MTFLRA ;Flush read-ahead
MOVN B,C ;Number of files tape is ahead of user
ADDB B,MTMCNT(W) ;Adjust desired count
JUMPE B,CPOPJ ;If now zero we are done
MTSPF1: PUSHJ P,MTCNTR ;Update user's count in case of PCLSR
JUMPG B,MTSPFF ;Go do forward if needed
MOVEI B,MGSPRF ;Get space reverse file command
PUSHJ P,MTCMD ;Queue it
AOSGE B,MTMCNT(W) ;Done?
JRST MTSPF1 ;Nope
POPJ P,
MTSPFF: MOVEI B,MGSPFF ;Get space forward file command
PUSHJ P,MTCMD ;Do it
SOSLE B,MTMCNT(W) ;Count down
JRST MTSPF1 ; till done
POPJ P,
;Update user's FUNCTION,,COUNT word in case he's PCLSR'd
;
MTCNTR: HRRZ A,MTMTAP(W)
MOVE T,MTMFNC(W)
HRL T,MTMCNT(W)
XCTR XW,[MOVEM T,(A)]
POPJ P,
;Get Controller status words to I,J
;
MTSTAT: SKIPLE MSCMDC(W) ;Wait till commands queued to PI level are done
PUSHJ P,UFLS
MOVEI B,MGSTAT ;GET STATUS command
PUSHJ P,MTCMD ;Give to PI
SKIPLE MSCMDC(W) ;Wait till done
PUSHJ P,UFLS
MOVE I,MGCMTC(W)
MOVE J,MGCMTS(W)
POPJ P,
;Go to EOT
;
MTSPEOT:MOVEI B,MGSEOT ;Get SPACE-TO-LOGICAL-EOT command
JRST MTCMD ;Queue it. Note read-ahead doesn't matter here
;Stop whatever we are doing right now
; Very brute-force - throws away all pending commands, read-ahead buffers, etc.
;
MTSTOP: CONO PI,UTCOFF ;We are going to mess with buffer lists
SETZM MSCMDC(W) ;Poof, no more commands
MOVE Q,[-MGQDLL,,MGQD0-1] ;Reset Q PDL pointer to base of stack
MOVE T,MSLCTB
IMUL T,W
ADD Q,T
MOVEM Q,MGQDLP(W)
MOVE Q,[-MSCBL-1,,MSCB0-1] ;Reset command queue input pointer
ADD Q,T
MOVEM Q,MTCMBP(W)
MOVE Q,[4400,,MSCB0-1] ;Reset command queue output pointer
ADD Q,T
MOVEM Q,MGCMBP(W)
SKIPL A,MTMDN(W) ;Buffer active at MP level?
PUSHJ P,IMEMR ;Yes, release it
SETOM MTMDN(W) ;No buffer active at MP level
SETZM MSMPRP(W) ;Zero MP pointer into current buffer
SETZM MSMPRC(W) ;Zero count of available words in buffer
PUSHJ P,MTCBFF ;Flush any buffers queued for PI level
CAME W,MGUNIT ;Is interrupt level waiting for this unit?
JRST UTCONJ ;No, all set
SETOM MGUNIT ;Yes, say no unit waiting for interrupt.
;(Makes interrupt go away w/out doing anything)
IFN TM10P,[
CONI MTC,I ;See what drive controller thinks it's using
LDB B,[MUNITF,,I]
CAME W,B ;Same as the drive we're clearing?
JRST UTCONJ ;If not same unit, don't do anything
MOVE B,MTCONO(W) ;Yes, abort operation in progress
CONO MTS,31 ;Stop the tape
CONO MTC,(B) ;Clear interupts
];IFN TM10P
IFN TM03S,[
IORDI B,%TMTC
ANDI B,7 ;Get selected transport
CAME W,B ;Same?
JRST UTCONJ
PUSHJ P,TMINIC ;Yes, go reinit controller
];IFN TM03S
SKIPGE A,MGCABN(W) ;Any buffers active at PI level?
JRST UTCONJ ;No
PUSHJ P,IMEMR ;Yes, return buffer to system
SETOM MGCABN(W) ;Say no buffer active at PI level
JRST UTCONJ ;Leave