.MCALL .MODULE .MODULE TJ,VERSION=22,COMMENT= ; Copyright (c) 1998 by Mentec, Inc., Nashua, NH. ; All rights reserved ; ; This software is furnished under a license for use only on a ; single computer system and may be copied only with the ; inclusion of the above copyright notice. This software, or ; any other copies thereof, may not be provided or otherwise ; made available to any other person except for use on such ; system and to one who agrees to these license terms. Title ; to and ownership of the software shall at all times remain ; in Mentec, Inc. ; ; The information in this document is subject to change without ; notice and should not be construed as a commitment by Digital ; Equipment Corporation, or Mentec, Inc. ; ; Digital and Mentec assume no responsibility for the use or ; reliability of its software on equipment which is not supplied ; by Digital or Mentec, and listed in the Software Product ; Description. .SBTTL RT-11 MM (TJU16) MAGTAPE HANDLER ;EDITS: ; ; FIXED PARITY ERROR PROBLEMS ;BD0 ; ; FIXED XM ERROR REPORT PROBLEM ;BD1 ; ; FIXED CONTROL C ABORT AND SYSTEM JOB SUPPORT ;SD2 ; ; Edit History: ; ; 001 31-Dec-79 15:56 Davis, Scott (75474) [240,92] ; ALLOW ABORT ENTRY EVEN IF NO SERVICE ENTRY ; IT IS POSSIBLE TO ENTER AT ABORT ENTRY EVEN IF WE NEVER ENTERED ; AT THE I/O ENTRY IF THE USER OPENS THE MT NFS, THEN ABORTS ; (001) ; 002 31-Dec-79 16:04 Davis, Scott (75474) [240,92] ; FIX CRASH AFTER INTERRUPT WITH NO CURRENT QUEUE ELEMENT ; (002) ; 003 29-Jan-80 14:01 Davis, Scott (75474) [240,92] ; CHANGE AN INCORRECT CALL TO .DRFIN TO AN RTS. ; (003) ; 004 23-Apr-80 10:49 Davis, Scott H. [240,92] ; FIX XM BUFFER CLEARING/WRITELOK ERROR ; FIX THE XM BUFFER CLEARING BUG ; FIX THE WRITELOCK ERROR REPORTING ; (004) ; ; Edits following V5.2: ; ; 007 12-Sep-85 MBG More complete audit trail (hardware handler and ; file-structured module info), updated to using ; .DRSET macros, added CSR, VECTOR and RETRY SET ; commands, general code clean-up ; ; Edits following V5.4 ; ; 008 23-Jan-87 RHH Fix CSR addressing in error handling code ; ; 009 12-Mar-87 RHH Make error handling and NOODDPAR work on TE16 ; 01-May-87 Clean up comments and labels ; ; 010 19-May-87 RHH Fine tune NOODDPAR error handling after space ops. ; ; 011 15-JUN-87 RHH Fix MMG$T and NO FSM combination ; ; 012 28-JUN-88 RHH Add PURGE support ; ; 013 12-AUG-88 RHH Adapt for UMR support ; ; 015 18-May-89 RHH Fix unit check, employ SYSTEM.MLB, change error ; handling for FCE on WRITE ; ; 016 26-Jun-89 RHH Remove XBUMP, put it into FSM .SBTTL NOTES ON TJU16 HANDLER ; RT-11 HANDLER FOR THE TJU16 MAGNETIC TAPE DRIVE ; ; TJU16 Magnetic Tape Driver (handler) ; ; 1. This handler is designed to allow the RT-11 monitor to access DIGITAL ; TJU16 type magtape controllers. These include the TJU16 and TJE16. ; ; 2. Handler Input Formats ; ; The hardware handler accepts commands through a queue element which is ; passed to it by the system or the file structured module. The following ; table describes the queue element format and how the magtape handler ; interprets it. ; ; Word Mnemonic Purpose MM handler uses this for: ; ; 0 --- Link to next Not used. ; queue element ; ; 2 Q.CSW Pointer to MM handler reports status to monitor ; channel status by setting bit 13(EOF$) if an ; word end of file condition is detected or ; bit 0(HDERR$) if a hard error ; condition is detected. ; ; 4 Q.BLKN Starting block 1. .ENTER and .LOOKUP requests interpret ; number this argument as SEQNUM. ; 2. Negative codes use this as an address ; (ERRBLK) to report qualifying information. ; When zero no information is reported. ; 3. NFS .READx/.WRITx requests zero this ; word. ; ; 6(byte) Q.FUNC Special MM handler accepts the following codes: ; Function code ; 6 .PURGE ; 3 .LOOKUP (NFS) ; 1 .CLOSE ; 0 .READx/.WRITx (NFS) ; -1 Write EOF (tapemark) ; -2 Forward space ; -3 Backspace ; -4 Write with extended gap ; -5 Rewind ; -6 Offline and rewind ; -7 Write a block ; -8 Read a block ; -9 Stream (ignored) ; ; Any other codes detected will cause a hard ; error. ; ; 7(byte) Q.JNUM Job number The job number is used by lookup and abort ; <13:11> to determine whether a unit is being used by ; F/G. ; Unit number The unit number is used to select a tape unit ; <10:8> and also by lookup to determine whether a unit ; is busy. ; ; 10 Q.BUFF Buffer address Used by .LOOKUP as the address of the filename ; to be found. First word of filename must be ; zero. Used as buffer address by ; .READx/.WRITx, read, write and write extend. ; ; 12 Q.WCNT Word count Zeroed by .LOOKUP to indicate a non RT-11 file ; structured device. Used as a word count by ; .READx/.WRITx, read, write, and write extend. ; Used as a count for the number of blocks to ; space by forward space and backspace. ; ; 14 --- Completion Not used. ; Function ; ; 16 --- PAR1 register Not used. ; ; 20 --- --- Not used. ; ; 22 --- --- Not used. ; ; The following is a description of the action taken by the handler for a ; given code. ; ; Code Action ; 1 .PURGE The unit is marked unused. ; ; 3 .LOOKUP The filename at Q.BUFF is checked for zero (meaning a non ; file structured .LOOKUP.) Next the INUSE byte is examined to see ; whether another channel is using this unit. Finally, the SEQNUM ; argument (passed through Q.BLKN) is examined for a zero value ; which indicates that a rewind should be performed. ; ; 1 .CLOSE The unit is marked unused. ; ; 0 .READx/.WRITx These requests read or write blocks of data on the ; tape currently mounted. .WRITx will report end of file when it ; sees the EOT marker. .READx will report end of file only when it ; reads a tape mark (TM). It will ignore the EOT marker. ; ; -1 Write a tapemark. ; ; -2 Forward space n blocks (n specified in Q.WCNT) until n is ; satisfied, EOT marker is sensed, or a TM is read. ; ; -3 Backspace n blocks (n specified in Q.WCNT) until n is satisfied, ; BOT is sensed, or a TM is read. ; ; -4 Erase 3 inches of tape and write a block to tape (write with ; extended gap.) ; ; -5 Rewind the tape to BOT. ; ; -6 Turn tape unit offline and rewind. ; ; -7 Write a block to tape. ; ; -8 Read a block from tape. ; ; -9 Stream at 100 ips (TS05 only) This code will be ignored by the ; MT and MM handlers, as well as MS when it is running a TS11 ; ; Other input to the magtape handler comes when the handler is entered at the ; abort entry point. R4 must contain the job number of the job being ; aborted. ; ; 3. Handler conditionals. ; ; When the MM$FSM conditional is defined it creates an object module which ; must be linked with the file structure module (FSM.OBJ or FSMX.OBJ). This ; enables code which allows the handler to be called (at $MT) with a queue ; element (possibly created by FSM) and the handler will execute the ; command in the queue element and will return to either FSMDON or FSMERR ; depending on whether an exception condition (end of file or hard error) ; was detected during the operation. In addition, the handler provides the ; $DONE entry point for ending queue element processing (it exits to the ; monitor.) The legal codes which the FSM may issue to the handler are ; defined in the previous section. ; ; 4. Handler structure ; ; The handler is divided into 3 main parts. ; ; 1. The command dispatcher transforms a queue element into a command, ; initiates the command and then exits to the monitor while the unit ; is performing the command. ; ; 2. When the command completes the interrupt handler is entered. The ; interrupt handler is subdivided into 3 sections. ; ; 1. The exception condition evaluation section looks at the ; status of the controller to determine the result of the last ; operation. It can reach one of 3 conclusions. ; ; 1. The operation succeeded. ; ; 2. The operation failed but may be recoverable. ; ; 3. The operation failed and is unrecoverable. A ; hard error is issued and the handler goes to the ; monitor. ; ; 2. The recovery section is entered if a recoverable error is ; being processed. ; ; 3. The status checking and reporting section determines ; whether there are conditions such as TM, EOT and record ; length error to report. ; ; 3. The Data area stores information about which tape units are busy ; and what the recovery status is if an operation is being recovered. .SBTTL DEFINITIONS ; Conditional Rules .IIF NDF MM$FSM MM$FSM = 0 ; Default to NO FSM .IIF NDF MM$UN, MM$UN == 1 ; Default to one unit ; RT handler macros .MCALL .DRDEF, .ADDR, .ASSUME, .BR .IIF NE MMG$T .MCALL .SYNCH ; SYSTEM.MLB references .LIBRARY "SRC:SYSTEM.MLB" .MCALL .CF2DF, .ERMDF, .ERRDF, .FIXDF .MCALL .SFMDF, .UBVDF, .USSDF .CF2DF ; Define $CNFG2 bits .ERMDF ; Define Magtape errors .ERRDF ; Define System Errors .FIXDF ; Define Fixed Offsets .SFMDF ; Define Magtape SPFUNs .UBVDF ; Define UB offsets .USSDF ; Define USR function codes ; Local Macros .MACRO ...... .ENDM ; PSECT ordering .PSECT MMDVR,I,LCL,CON ; This handler .PSECT MTDVR,I,LCL,CON ; FSM code .PSECT NONRES,I,LCL,CON ; Non-resident LOAD/UNLOAD code .SBTTL DRDEF - Handler Definition .IF EQ MMG$T .DRDEF MM,20,,0,172440,224,DMA=NO .IFF; EQ MMG$T NUMRS = MM$FSM .DRDEF MM,20,,0,172440,224,DMA=YES,PERMUMR=NUMRS,SERIAL=YES .ENDC; EQ MMG$T .SBTTL DRPTR - Load/Fetch/Release/Unload Code pointers .DRPTR LOAD=LOAD,FETCH=LOAD,UNLOAD=UNLOAD,RELEASE=UNLOAD .SBTTL DREST - Extended Device Information .IF EQ MM$FSM .DREST CLASS=DVC.MT,MOD=DVM.NS ; device is NFS MAGTAPE .IFF; EQ MM$FSM .DREST CLASS=DVC.MT ; device is a MAGTAPE .ENDC; EQ MM$FSM .SBTTL DRSPF - SPFUN Definitions .DRSPF SF.MTM ; Write TAPE MARK .DRSPF SF.MFS ; Forward Space .DRSPF SF.MBS ; Backspace .DRSPF SF.MWE ; Write with Extended Gap .DRSPF SF.MRE ; Rewind .DRSPF SF.MOR ; Rewind Offline .DRSPF SF.MWR ; Write .DRSPF SF.MRD ; Read .DRSPF SF.MST ; Enable/Disable Streaming Mode .IIF NE MM$FSM .DRSPF SF.USR ; Async file operations .IF NE MMG$T .DRSPF +SPFTAB ; Pointer to SPFUN table for UMRs .ENDC; NE MMG$T ; Now we set the audit trail info .IIF EQ MM$FSM .FSM = 100000 .AUDIT .TJ ;Hardware handler .AUDIT .FSM ;File-structured module .SBTTL Hardware Definitions ; Status and Control register 1 bit definitions SC = 100000 ;SPECIAL CONDITIONS(RO) TRE = 040000 ;TRANSFER ERROR(RW) MCPE = 020000 ;MASSBUS CONTROL PARITY ERROR(RO) DVA = 004000 ;DRIVE AVAILABLE(RO) PSEL = 002000 ;PORT SELECT(RW) A17 = 001000 ;EXTENDED ADDRESS BITS(RW) A16 = 000400 RDY = 000200 ;READY(RO) IE = 000100 ;INTERRUPT ENABLE ; Function codes FNOOP = 000000 ;NO-OPERATION FOFF = 000002 ;REWIND OFF LINE FREWIND = 000006 ;REWIND FDRCLR = 000010 ;DRIVE CLEAR FERASE = 000024 ;ERASE FWRTTM = 000026 ;WRITE TAPE MARK FSPFOR = 000030 ;FORWARD SPACE FSPBAK = 000032 ;BACKSPACE FWRTCF = 000050 ;WRITE CHECK FORWARD FWRTCR = 000056 ;WRITE CHECK BACKWARD FWRITE = 000060 ;WRITE FREADF = 000070 ;READ FORWARD FREADR = 000076 ;READ BACKWARD GO = 000001 ;GO BIT ; Control and Status register 2 bit definitions DLT = 100000 ;DATA LATE(RO) WCE = 040000 ;WRITE CHECK ERROR(RO) UPE = 020000 ;UNIBUS PARITY ERROR(RW) NED = 010000 ;NON-EXISTENT DRIVE(RO) NEM = 004000 ;NON-EXISTENT MEMORY(RO) PGE = 002000 ;PROGRAM ERROR(RO) MXF = 001000 ;MISSED TRANSFER(RW) MDPE = 000400 ;MASSBUS DATA BUS PARITY ERROR(RO) OR = 000200 ;OUTPUT READY(RO) IR = 000100 ;INPUT READY(RO) CLR = 000040 ;CONTROLLER CLEAR(WO) PAT = 000020 ;PARITY TEST(RW) BAI = 000010 ;BUS ADDRESS INCREMENT INHIBIT(RW) ; DRIVE SELECT BITS MMCS2<2:0> (RW) DRIVEBIT= 000001 ;THIS IS THE DRIVE BIT IN MMAS REGISTER DRIVE = 0 ;DRIVE 0 IS DEFAULT ; Drive Status register bit definitions ATA = 100000 ;ATTENTION ACTIVE(RO) ERR = 040000 ;ERROR SUMMARY(RO) PIP = 020000 ;POSITION ING PROGRESS(RO) MOL = 010000 ;MEDIUM ON-LINE(RO) WRL = 004000 ;WRITE LOCKED(RO) EOT = 002000 ;END OF TAPE SENSED(RO) ; UNUSED DPR = 000400 ;DRIVE PRESENT(RO) DRY = 000200 ;DRIVE READY(RO) SSC = 000100 ;SLAVE STATUS CHANGE(RO) PES = 000040 ;PHASE ENCODED STATUS(RO) SDWN = 000020 ;SLOWING DOWN(RO) IDB = 000010 ;IDENTIFICATION BURST(RO) TM = 000004 ;TAPE MARK DETECTED(RO) BOT = 000002 ;BEGINNING OF TAPE DETECTED(RO) SLA = 000001 ;SLAVE ATTENTION(RO) ; Error register bit definitions CORCRC = 100000 ;CORRECTABLE DATA ERROR/CRC ERRROR(RO) UNS = 040000 ;UNSAFE(RO) OPI = 020000 ;OPERATION INCOMPLETE(RO) DTE = 010000 ;DRIVE TIMING ERROR(RO) NEF = 004000 ;NON-EXECUTABLE FUNCTION(RO) CSITM = 002000 ;CORRECTABLE SKEW/ILLEGAL TAPE MARK(RO) FCE = 001000 ;FRAME COUNT ERROR(RO) NSG = 000400 ;NON STANDARD GAP(RO) PEFLRC = 000200 ;PE FORMAT ERROR/LRC(RO) INCVPE = 000100 ;INCORRECTABLE DATA/VERTICAL PARITY ERROR(RO) DPAR = 000040 ;DATA BUS PARITY ERROR(RO) FMT = 000020 ;FORMAT ERROR(RO) CPAR = 000010 ;CONTROL BUS PARITY ERROR(RO) RMR = 000004 ;REGISTER MODIFICATION REFUSED(RO) ILR = 000002 ;ILLEGAL REGISTER(RO) ILF = 000001 ;ILLEGAL FUNCTION(RO) ; Tape Control register bit definitions ACCL = 100000 ;ACCELERATION(RO) FCS = 040000 ;FRAME COUNT STATUS(RO) TCW = 020000 ;TAPE CONTROL WRITE(RO) EAODTE = 010000 ;ENABLE ABORT ON DATA TRANSFER ERRORS(RW) ; UNUSED ; DENSITY BITS MMTC<10:8> D7$200 = 0 ;7 CHANNEL 200 BPI D7$556 = 000400 ;7 CHANNEL 556 BPI D7$800 = 001000 ;7 CHANNEL 800 BPI D9$800 = 001400 ;9 CHANNEL 800 BPI D9$1600 = 002000 ;9 CHANNEL 1600 BPI ; FORMAT BITS MMTC<7:4> NORMAL = 000300 ;NORMAL FORMATTING COREDP = 000320 ;CORE DUMP FORMATTING EVPAR = 000010 ;EVEN PARITY SELECT ODDPAR = 0 ;ODD PARITY SELECT EPCOMBO = EVPAR+NORMAL+D9$800 ;Even parity mode bits ; SLAVE SELECT BITS MMTC<2:0> .SBTTL SOFTWARE DEFINITIONS ; SPECIAL FUNCTIONS WRTEOF = -1 ;WRITE TAPE MARK FWDSPC = -2 ;FORWARD SPACE BKSPC = -3 ;BACKSPACE ERASE = -4 ;ERASE EXTENDED INTERBLOCK GAP REWIND = -5 ;REWIND OFFLINE = -6 ;OFFLINE AND REWIND WRITE = -7 ;WRITE READF = -8. ;READ FORWARD STR100 = -9. ;STREAM AT 100 IPS (TS05 ONLY) ; NOTE:if you add a SPFUN code, also add it to .DRSPF FN = 8. ;NUMBER OF FUNCTIONS ERRGAPS = -100. ;NUMBER OF 3" GAPS ALLOWED BETWEEN BLOCKS REDREC = -1 ;ERROR EVALUATION OUTPUTS THIS CODE IF IT ; DETECTS A RECOVERABLE ERROR ON A READ ; OPERATION WRIREC = -2 ;ERROR EVALUATION OUTPUTS THIS CODE IF IT ; DETECTS A RECOVERABLE ERROR ON A WRITE ; OPERATION ; System communications area $SYPTR = 54 ;Pointer to base of RMON ; miscellaneous UNITMK = 7 ;Unit number mask (Q$UNIT) NRETRY = 8. ;Default retry count .SBTTL Install Code .DRINS MM .SBTTL SET COMMANDS ;+ ; THE MAGTAPE HANDLER ACCEPTS 3 SET COMMANDS. ; ; 1. SET MM DENSE=N SETS THE DENSITY AT WHICH THE TAPE DRIVES RUN AT. ; LEGAL DENSITIES ARE: ; ; 800 SYNONYM FOR 809 ; 809 800 BPI FOR 9 TRACK DRIVE. ; 1600 1600 BPI FOR 9 TRACK DRIVE. ; ; 2. SET MM [NO] ODDPAR SETS THE HANDLER IN OR OUT OF ODD PARITY RECORDING. ; THE NO OPTION WILL SET EVEN PARITY RECORDING. IT IS RECOMMENDED THAT ; TAPES BE WRITTEN WITH ODD PARITY. WHEN THE PARITY IS EVEN AND NULL ; CHARACTERS ARE SENT TO THE TAPE UNIT THE CONTROLLER WILL CONVERT ; THESE NULLS TO OCTAL 20 CHARACTERS AND THIS IS WHAT WILL BE READ. ; ; 3. SET MM DEFALT=9 ; ; THIS COMMAND IS A GENERAL RESET THE OTHER OPTIONS. ; ; 9 SETS UP 800 BPI ODD PARITY FOR A 9 TRACK DRIVE. ; ;- .DRSET DENSE, NOP, O.DENS, NUM .DRSET ODDPAR, EVPAR, O.PAR, NO .DRSET DEFALT, NOP, O.DFLT, NUM .DRSET CSR, 160000, O.CSR, OCT .DRSET VECTOR, 500, O.VEC, OCT .DRSET RETRY, 127., O.RTRY, NUM ; SET MM DENSE={800|809|1600) O.DENS: CMP #809.,R0 ;IS TAPE 800BPI FOR A NINE TRACK DRIVE? BEQ 1$ ;YES CMP #800.,R0 ;IS TAPE 800BPI FOR A NINE TRACK DRIVE? BEQ 1$ ;YES CMP #1600.,R0 ;IS TAPE 1600BPI FOR A NINE TRACK DRIVE? BEQ 2$ ;YES SEC RETURN 1$: MOV #D9$800,R3 ;800 BPI BR 3$ 2$: MOV #D9$1600,R3 ;1600 BPI BIC #EVPAR,DENSE ;PHASE ENCODING MODE AUTO RESETS TO ODD PARITY 3$: BIC #3400,DENSE ;CLEAR OUT THE DENSITY BITS BIS R3,DENSE ;SO WE CAN INSERT THE NEW DENSITY CLC RETURN ; SET MM [NO]ODDPAR O.PAR: BR 2$ ;R3=EVPAR BIT NOP ;MAKE SURE THAT SETTING EVEN PARITY DOESN'T HAPPEN WHILE 1600 BPI IS SET MOV DENSE,R1 ;GET DENSITY WORD BIC #^C<3400>,R1 ;CLEAR OUT EVERYTHING BUT THE DENSITY CMP #D9$1600,R1 ;SEE IF ITS 1600 BPI BNE 1$ ;IT ISN'T SEC ;IT IS-GIVE ERROR RETURN 1$: BIS R3,DENSE ;SET EVEN PARITY BR 3$ 2$: BIC R3,DENSE ;SET ODD PARITY 3$: CLC RETURN ; SET MM DEFALT=9 O.DFLT: CMP #9.,R0 ;NINE TRACK IS THE ONLY KIND OF TJU16 BNE 1$ ;NOT THAT-GIVE ERROR MOV #D9$800+NORMAL+ODDPAR,DENSE ;RESET TO 800 BPI,ODD PARITY,NRZI CLC RETURN 1$: SEC RETURN ; SET MM CSR=octal_address O.CSR: CMP R0,R3 ;Valid CSR address? BLO O.BAD ;Nope, reject it MOV R0,INSCSR ;Yes, set the install-time MOV R0,DISCSR ; and display-time CSR addresses .ADDR #MMCS1,R1 ;R1 -> Device CSR table MOV #NREGS,R2 ;R2 = Count of registers to set 10$: MOV R0,(R1)+ ;Set a CSR address ADD #2,R0 ;Bump the address DEC R2 ;More table to fill? BGT 10$ ;Yep... O.GOOD: TST (PC)+ ;Good return, c-bit = 0 O.BAD: SEC ;Error return, c-bit = 1 RETURN ; SET MM VECTOR=octal_address O.VEC: CMP R0,R3 ;Is VECTOR specified valid? BHIS O.BAD ;Nope... MOV R0,MMSTRT ;Set the vector BR O.GOOD ; SET MM RETRY=n O.RTRY: CMP R0,R3 ;Test retry limits BHI O.BAD ;Out of Bounds MOV R0,RTRYCT ;Set the retry count BEQ O.BAD ;Zero retries not allowed BR O.GOOD .ASSUME . LE 1000,<;Set area overflow> .SBTTL Global Definitions .IF NE MM$FSM ;DEFINE GLOBALS TO FSM ; EXTERNAL GLOBAL SYMBOLS .GLOBL FSMDIS, FSMABT, FSMDON .GLOBL FSMERR, CODE, DVTBL .GLOBL FSMSIZ, RESTOR .GLOBL LABLIO HDR1LB ; INTERNAL GLOBAL SYMBOLS ; ; MMCQE IS THE FIFTH WORD OF THE HANDLER. WHENEVER THE HANDLER IS ; CALLED IT CONTAINS THE ADDRESS OF A QUEUE ELEMENT. ; ; MMCQ CONTAINS THE ADDRESS OF A QUEUE ELEMENT WHEN THE HARDWARE HANDLER ; IS CALLED FROM THE FILE STRUCTURE MODULE. ; ; $DONE IS THE ENTRY POINT WHERE THE FSM JUMPS WHEN QUEUE ELEMENT PROCESSING ; IS DONE. IT RELEASES THE QUEUE ELEMENT BY CALLING OR JUMPING TO I/O ; COMPLETE IN THE MONITOR AND IF THE GLOBAL VARIABLE SINK IS NON ZERO IT WILL ; DO A .SYNCH AND REPORT ERRORS (MEMORY MANAGEMENT ONLY.) ; ; $MT IS THE ENTRY POINT PROVIDED FOR FSM TO CALL THE HARDWARE HANDLER TO ; PERFORM A FUNCTION IN A QUEUE ELEMENT WHOSE ADDRESS IS IN MMCQ AND R3. .GLOBL MMCQE .IF NE MMG$T ; External global symbols for memory management .GLOBL OLDBA EXTADR JOBNM SYNBLK TEMP SINK ERBSAV .ENDC ;NE MMG$T .ENDC ;EQ MM$FSM .SBTTL Handler Entry Point .IF EQ MMG$T .DRBEG MM .IFF; EQ MMG$T .DRBEG MM,SPFUN=SPFTAB .ENDC; EQ MMG$T MMBASE =: MMSTRT + 6 ; MMLQE address BR MM ;Bypass CSR access words MMCS1: .WORD MM$CSR ;Control and Status register 1 MMWC: .WORD MM$CSR+2 ;Word Count register MMBA: .WORD MM$CSR+4 ;Bus Address register MMFC: .WORD MM$CSR+6 ;Frame Count register MMCS2: .WORD MM$CSR+10 ;Control and Status register 2 MMDS: .WORD MM$CSR+12 ;Drive Status register MMER: .WORD MM$CSR+14 ;Error register MMAS: .WORD MM$CSR+16 ;Attention Summary register MMCC: .WORD MM$CSR+20 ;Character Check register MMDB: .WORD MM$CSR+22 ;Data Buffer register MMMR: .WORD MM$CSR+24 ;Maintenance register MMDT: .WORD MM$CSR+26 ;Drive Type register MMSN: .WORD MM$CSR+30 ;Serial Number register MMTC: .WORD MM$CSR+32 ;Tape Control register NREGS = <.-MMCS1>/2 .ASSUME . LE MMSTRT+1000,<;Set object not in block 1> RTRYCT: .WORD NRETRY ; Max error recovery retry count .ASSUME . LE MMSTRT+1000,<;Set object not in block 1> .IF NE MMG$T .SBTTL SPFTAB - SPFUN table for UMR/DMA operations SPFTAB: .DRSPF -,<370>,TYPE=R .DRSPF -,<371,374>,TYPE=W .WORD 0 .ENDC; NE MMG$T ; THIS CODE GETS AN 18 BIT PHYSICAL ADDRESS FROM THE MONITOR AND STORES IT ; IN THE OLDBA AND EXTADR VARIABLES. ; ; BITS 6-9 FROM $MPPHY ARE USED TO DELIVER BITS 19-22 FOR 22 BIT ; MACHINES. BECAUSE MM IS A UNIBUS DEVICE, THESE BITS MUST BE 0 .ENABL LSB MM: .IF NE MMG$T MOV MMCQE,R5 ;MAKE 18 BIT ADDRESS CMP (R5)+,(R5)+ ;POINT TO Q$BUFF CALL @$MPPTR ;GET 18 BIT ADDRESS MOV (SP)+,OLDBA ;SAVE LOW ORDER 16 BITS OF ADDRESS 10$: ASR @SP ; Move extended address to bits <0:1> ASR @SP ; ... ASR @SP ; ... ASR @SP ; ... MOV (SP)+,EXTADR ; Store in EXTADR .ENDC ;NE MMG$T ; THIS CODE LOADS THE ADDRESS OF THE QUEUE ELEMENT IN R3. .IF EQ MM$FSM MOV MMCQE,R3 ;GET ADDRESS OF BLOCK NUMBER IN R3 .IFF ; IF MM$FSM IS DEFINED THE CODE CALLS FSM AND THIS ($MT) IS THE ENTRY POINT ; FOR THE FSM TO PASS REQUESTS TO THE HARDWARE HANDLER. JMP FSMDIS ;CALL THE FILE STRUCTURED MODULE $MT:: MOV MTCQ,R3 ;R3 -> Queue element to process .ENDC ;EQ MM$FSM ; THIS CODE GETS THE UNIT # FROM THE QUEUE ELEMENT AND SELECTS THE DRIVE. ; THIS CODE IS DELIBERATELY EXECUTED EARLY SO THAT THE CONTROLLER HAS ; TIME TO ACTUALLY COMPLETE THE SELECT OPERATION. THE CODE FROM THE ; QUEUE ELEMENT IS ALSO EXTRACTED. MOV SP,SPSAV ; Make a copy of current SP TST (R3)+ ;R3 POINTS TO CODE,UNIT,AND JOB# MOV @R3,R0 ;GET THE CODE AND UNIT NUMBER MOVB R0,R4 ;R4=FUNCTION CODE SWAB R0 ;PUT THE UNIT # IN BOTTOM OF R0 BIC #^C,R0 ;R0=TAPE UNIT # .IF EQ MM$FSM ; (This check is done in FSM) CMP R0,#MM$UN ; Valid unit? BLT 30$ ; Branch if so CMPB R4,#LOOK.. ; was it .LOOKUP? BEQ 20$ ; if so, tell USR nicely. JMP HDEROR ; Set hard error bit and return 20$: MOV #ER.IUN,R0 ; Return error to USR BR USRERR .ENDC; EQ MM$FSM 30$: MOV R0,R1 ;SAVE THE UNIT # BIS (PC)+,R0 ;OR IN THE DENSITY DENSE: .WORD D9$800+NORMAL+ODDPAR ; : 800 BPI, 9 track, NRZI .ASSUME . LE MMSTRT+1000,<;Set object not in block 1> TST (PC)+ ;MM USED SINCE LOADED OR FETCHED? ;010 MMUSED: .WORD 0 ; UNUSED flag ;010 BNE 40$ ;BRANCH IF SO ;010 CALL CONCLR ;CLEAR THE CONTROLLER ;010 INC MMUSED ;AND DON'T DO IT AGAIN ;010 40$: CALL DRICLR ;DRIVE CLEAR ;010 MOV R0,@MMTC ;SELECT THE SLAVE MOV #0,@MMCS2 ;Select the drive ;THIS INITIALIZES A FLAG MARKING NO NON FILE STRUCTURED .READX DONE. CLR NFSREAD ;INITIALIZE NFS READ DONE FLAG ; SET UP REGISTERS ; ; R0 -> RECOVE ; R1 = Unit Number (already) ; R2 = Job Number ; R3 -> Q.BLKN (already) ; R4 = Function Code (already) ; R5 -> Unit Table Entry .ADDR #RECOVE,R0 ;R0=POINTER TO INUSE WORD .ADDR #$TBL,R5 ;Point to unit table ADD R1,R5 ;Point to unit table entry MOV @R3,R2 ;GET JOB # ;SD2 SWAB R2 ;IN LOW BYTE ;SD2 ASR R2 ;SHIFT ;SD2 ASR R2 ;SHIFT ;SD2 ASR R2 ;SHIFT ;SD2 BIC #177740,R2 ;R2 = JOB NUM ;SD2 .IF NE MMG$T MOVB R2,JOBNM ;STORE JOB NUMBER IN JOBNM .ENDC ;NE MMG$T .DSABL LSB .SBTTL LOOKUP PROCESSING ;+ ; THIS ROUTINE PROCESSES A LOOKUP. IT CHECKS FOR A ZERO FILENAME AND GIVES ; A HARD ERROR IF NOT. IT CHECKS THE INUSE BYTE TO SEE IF OTHER CHANNELS ARE ; USING THE UNIT AND IF NOT ALLOCATES IT. WHEN BUSY IT ISSUES A CODE 2 ; ERROR. THEN THE SEQNUM (BLOCK #) ARGUMENT IS EXAMINED. WHEN ZERO THE TAPE ; IS REWOUND. WHEN -1 THAT ROUTINE EXITS. OTHERWISE, AN ILLEGAL ARGUMENT ; ERROR IS ISSUED VIA $SPUSR. ;- .ENABL LSB CMPB R4,#LOOK.. ; IS THIS COMMAND A LOOKUP? BNE 40$ ; NO HWXM = 0 ;+011 .IF NE MMG$T .IF EQ MM$FSM HWXM = 1 MOV MMCQE,R4 ; POINT TO QUEUE ELEMENT CALL @$GTBYT ; GET HALF OF 1ST FILENAME WORD CALL @$GTBYT ; GET OTHER HALF BISB (SP)+,(SP)+ ; ZERO? BNE 30$ ; NO .ENDC ;EQ MM$FSM .ENDC ;NE MMG$T .IF EQ HWXM TST @2(R3) ;YES-IS THIS A NFS LOOKUP? BNE HDEROR ;NO .ENDC ;EQ HWXM ;-011 CMPB #-1,@R5 ;IS THIS UNIT TAKEN? ;SD2 BEQ 10$ ;NO MOV #ER.SHR,R0 ;UNIT ALREADY IN USE USRERR: MOV @#$SYPTR,R1 ;POINT TO RMON MOV R0,$SPUSR(R1) ;GIVE ERROR .IF NE MM$FSM CALL RESTOR JMP $DONE ;IMMEDIATE ABORT ...... .IFF; NE MM$FSM BR 90$ ...... .ENDC ;NE MM$FSM 10$: CLR 4(R3) ;NFS DEVICE (RETURN ZERO IN WORD COUNT) MOVB R2,@R5 ;MARK DRIVE BUSY ;SD2 .IF NE MM$FSM BR 90$ ;B/G ...... .IFF; NE MM$FSM 20$: MOV -2(R3),R1 ;GET SEQNUM ARGUMENT(Q$BLKN) BEQ 60$ ;DO A REWIND BGT 30$ ;POSITIVE NUMBER-GIVE ERROR INC R1 ;SEQNUM=-1? BEQ 90$ ;YES 30$: MOVB #-1,@R5 ;VACATE THE UNIT ;SD2 MOV #ER.ISN,R0 ;ILLEGAL ARGUMENT BR USRERR ...... .ENDC ;NE MM$FSM .SBTTL CLOSE AND PURGE PROCESSING 40$: CMPB R4,#PURG.. ;THIS COMMAND A PURGE? BEQ 50$ ;YES - TREAT LIKE CLOSE CMPB R4,#CLOS.. ;THIS COMMAND A CLOSE? BNE 70$ ;NO 50$: MOVB #-1,@R5 ;VACATE THE UNIT ;SD2 BR 90$ ...... .IF EQ MM$FSM 60$: MOV #REWIND,R4 ;SET UP FOR A REWIND .ENDC; EQ MM$FSM ; FUNCTION IS SOMETHING OTHER THAN LOOKUP, CLOSE OR PURGE. ; INITIALIZE THE RECOVERY AND TAPELEN VARIABLES AND LEAVE R0 ; POINTING AT LASTCOM. 70$: MOV (PC)+,(R0)+ ;NUMBER OF 3" GAPS TO ALLOW .BYTE -1,ERRGAPS ;INITIALIZE RECOVERY AND TAPELEN MOV @MMDS,@R0 ;SAVE THE OLD EOT BIT BIC #^C,(R0)+ ;ISOLATE IT ; CHECK THE QUEUE ELEMENT CODE. ; ; 1. WHEN IN THE RANGE -1 TO -8 THEN IT'S A LEGAL SPFUN. ; ; 2. WHEN ZERO THEN IT WILL BE CONVERTED TO A -7 (WRITE) OR -8 (READ) ; DEPENDING ON THE SIGN OF THE WORD COUNT (+ MEANS READ) ; ; 3. WHEN NONE OF THE ABOVE ARE TRUE THEN ISSUE A HARD ERROR. ; ; 4. THE ONLY EXCEPTION IS FOR CODE -9. ; -9 IS VALID ONLY FOR A TS05. IF THE DRIVE IS ANYTHING ; ELSE, -9 WILL PASS THROUGH THE HANDLER WITHOUT DOING ; ANYTHING. CMP #STR100,R4 ;TS05 SPFUN? BEQ 90$ ;IF YES, EXIT. CMP #READF,R4 ;IS THE FUNCTION CODE A LEGAL CODE? BLOS 120$ ;YES TST R4 ;.READ/.WRITE? BNE HDEROR ;NO - Hard error. ; CONVERT .READ/.WRITE REQUESTS TO .SPFUN I/O MOV R3,R1 ;GET ADDRESS OF Q$FUNC CLR -2(R1) ;CLEAR Q$BLKN (ERRBLK) ARGUMENT TO ; PREVENT ERROR REPORTING CMP (R1)+,(R1)+ ;POINT TO Q$WCNT MOV #READF,R4 ;ASSUME .READ TST @R1 ;.READ OR .WRITE? BPL 100$ ;.READ NEG @R1 ;.WRITE-MAKE WORD COUNT POSITIVE .ASSUME WRITE EQ READF+1 INC R4 ;CHANGE CODE TO WRITEPHY BR 110$ ...... ; ISSUE A HARD ERROR. WHEN FILE SUPPORT IS PRESENT, R0-R3 ; MUST BE RESTORED BECAUSE WE MAY BE RUNNING AT .INTEN LEVEL. HDEROR: MOV SPSAV,SP ;Restore original stack pointer TST -(R3) ;POINT TO BLOCK # BIS #HDERR$,@-(R3) ;SET HARD ERROR BIT IN THE CSW 90$: .IF NE MM$FSM CALL RESTOR ;RESTORE REGISTERS BEFORE GOING BACK TO FSM .ENDC ;NE MM$FSM MMDON1: JMP MMDONE ...... ; FUNCTION IS .READ 100$: COM NFSREAD ;MARK A NON-FILE-STRUCTURED READ BEING DONE 110$: .IF NE MM$FSM MOV R4,CODE ;REMEMBER CODE OF REQUEST .ENDC ;NE MM$FSM ; TRANSFORM A CODE INTO A COMMAND AND LOAD IT INTO THE DEVICE ; REGISTER. NOTE THAT THE OLDBA VARIABLE IS NOT LOADED HERE IF MMG$T IS ; NOT EQUAL TO ZERO. 120$: ADD #FUNTAB-TABLE,R4 ; MAKE THE CODE POSITIVE MOV R4,(R0)+ ; SAVE AS LASTCOM (R0 -> OLDBA) .IF NE MMG$T MOV 4(R3),R1 ;GET WORD COUNT MOV R1,4(R0) ;SAVE WORD COUNT IN OLDWC .IFF TST (R3)+ ;POINT TO THE BUFFER MOV (R3)+,(R0)+ ;SAVE BUFFER ADDRESS IN OLDBA MOV @R3,@R0 ;SAVE WORD COUNT ; (R3 -> WORDCOUNT) IN OLDWC MOV @R3,R1 ;LOAD WC INTO R1 .ENDC ;NE MMG$T NEG R1 ;NEEDS NEGATION CALL DISPAT ;GO DO COMMAND ...... .DSABL LSB TABLE: .BYTE /2 .BYTE /2 .BYTE /2 .BYTE /2 .BYTE /2 .BYTE /2 .BYTE /2 .BYTE /2 FUNTAB: .BYTE FREADF+IE+GO ;READ FORWARDS .BYTE FWRITE+IE+GO ;WRITE .BYTE FOFF+IE+GO ;OFFLINE AND REWIND .BYTE FREWIND+IE+GO ;REWIND .BYTE FERASE+IE+GO ;WRITE WITH EXTENDED INTERBLOCK GAP .BYTE FSPBAK+IE+GO ;BACKSPACE .BYTE FSPFOR+IE+GO ;FORWARD SPACE .BYTE FWRTTM+IE+GO ;WRITE TAPEMARK .ENABL LSB ; Initiate a command by setting values in the controller's registers REDEF: RIGHT: .IF NE MMG$T MOV (R0)+,@MMBA ; load OLDBA into MMBA BIT BADBIT,@R0 ; check EXTADR for illegal UNIBUS bits BNE HDEROR ; oops. Something's haywire. MOV @R0,-(SP) ; get EXTADR SWAB @SP ; move high bits to high byte BIS (SP)+,R5 ; Merge extended bits with command .IFF; NE MMG$T MOV -(R3),@MMBA ; Set the buffer address .ENDC ;NE MMG$T MOV R1,@MMWC ;PUT IN THE WORD COUNT ASL R1 ;TURN WORD COUNT INTO BYTE COUNT MOV R1,@MMFC ;put in frame/block count BR RIGHTM ...... FORSPA: BAKSPA: MOV R1,@MMFC ;put in FRAME (or BLOCK) count AWFLINE: REWHINED: MOV #5000.,R0 10$: DEC R0 BEQ MMDON1 BIT #SDWN,@MMDS ;is unit not ready? (slowing down?) BNE 10$ ;if so, wait. ERACE: RIGHTM: MOV R5,@MMCS1 ; GO! CLRB CMDINI ; Indicate no interrupts yet ;010 .IF NE MM$FSM CALL RESTOR .ENDC ;NE MM$FSM RETURN .DSABL LSB .SBTTL MMABRT - ABORT ENTRY POINT ; ABORT ENTRY POINT. THIS CODE HALTS ANY OPERATION IN PROGRESS AND ; CLEARS THE INUSE WORD. WHEN THE F/G JOB ABORTED (R4 IS EXPECTED ; TO CONTAIN THE JOB NUMBER) THEN THE FOREGROUND UNITS ARE RE-PROTECTED ; BY MOVING THE FGCHAN BYTE TO THE INUSE BYTE. .ENABL LSB MMABRT: MOVB #-1,$FLG ;SAY NO COMPLETE ;SD2 MOV R3,-(SP) ;SAVE R3 ;SD2 .ADDR #$TBL,R5 ;GET TABLE ;SD2 MOV MMCQE,R3 ;GET QUEUE ELEMENT ;SD2 BEQ 30$ ;IF EQ THERE ISN'T ONE ;SD2 MOVB Q$JNUM(R3),-(SP);GET JOB NUMBER ;SD2 MOVB (SP)+,R3 ;GET JOB NUMBER ;SD2 ASR R3 ;SHIFT ;SD2 ASR R3 ; SHIFT ;SD2 ASR R3 ; SHIFT ;SD2 BIC #177760,R3 ;R3 = JOB NUM ;SD2 CMP R3,R4 ;IS THE ABORTING JOB ACTIVE? ;SD2 BNE 30$ ;IF NE NO ;SD2 CLRB $FLG ;CALL COMPLETE ;SD2 CALL CONCLR ;DRIVE CLEAR ;RHH .IF NE MM$FSM MOV R0,-(SP) ;SAVE R0 MOV DVTBL,R0 ;POINT TO DEVICE TABLE BEQ 20$ ;IF EQ NOT INITIALIZED YET ;001 MOV #-1,(R0)+ ;MARK TAPE POSITION LOST MOV #-1,@R0 ;MARK CURRENT BLOCK NUMBER LOST 20$: MOV (SP)+,R0 ;RESTORE R0 ;001 .ENDC ;NE MM$FSM ; Look through unit table, and release any unit associated with the ; aborting job. 30$: CMPB R4,@R5 ;RELEASE THIS UNIT? (JOBNO IN ENTRY?) ;SD2 BNE 40$ ;BRANCH IF NO ;SD2 MOVB #-1,@R5 ;RELEASE,RELEASE ;SD2 40$: CMPB #-2,(R5)+ ;END OF TABLE? ;SD2 BNE 30$ ;IF NE NO ;SD2 MOV (SP)+,R3 ;RESTORE R3 ;SD2 JMP $DONE ;EXIT ;SD2 .DSABL LSB .SBTTL DRAST - INTERRUPT ENTRY POINT ; ALL MAGTAPE INTERRUPTS COME THROUGH HERE. THE .DRAST MACRO GENERATES A ; PIC .INTEN CALL FOR PRIORITY LEVEL 5 AND ALSO GENERATES A BRANCH TO THE ; ABORT ENTRY POINT. ; ; THE INTERRUPT ROUTINE ONLY USES R4 AND R5. WHEN THESE REGISTERS ARE TO BE ; USED IN FUTURE MODIFICATIONS TO THE MAGTAPE HANDLER THEY MUST BE SAVED AND ; RESTORED. THE STACK IS USED ONLY LOCALLY AND FUTURE MODIFICATIONS SHOULD ; KEEP TO THIS CONSTRAINT BECAUSE THE HANDLER AT INTERRUPT LEVEL USES THE ; SYSTEM STACK. .DRAST MM,5,MMABRT .SBTTL ERROR-ERROR ROUTINE DISPATCHER ;+ ; THE ERROR ROUTINE IS ALWAYS ENTERED AND DOES ONE OF 2 THINGS. ; ; 1. DETECTS AN ABORTABLE CONDITION. IN THIS CASE THE PROPER ERROR CODE ; IS PUT IN R4 AND THE ABORT AND REPORT ROUTINE IS TRANSFERRED TO AND ; THE CONDITION IS REPORTED. EXECUTION OF THE INTERRUPT HANDLER IS ; ABORTED. ; ; 2. REPORTS THAT NO ERROR OCCURRED OR THAT A RECOVERABLE ERROR OCCURRED. ; IN THIS CASE THE VARIABLE ERRSUM (ERROR SUMMARY) IS LOADED WITH ; EITHER 0(NO ERROR) OR -1(RECOVERABLE ERROR). EXECUTION OF THE ; INTERRUPT HANDLER CONTINUES. ; ; THE BASIC PHILOSOPHY BEHIND THIS ERROR ROUTINE IS TO ASSUME THE ; OPERATION WAS GUILTY UNLESS IT CAN BE SHOWN TO BE INNOCENT. ;- .ENABL LSB TST MMCQE ;QUEUE ELEMENT? ;002 BNE 10$ ;IF NE YES ;002 JMP $RTS ;ELSE EXIT WITH NO CHECKS! ;003 ...... 10$: MOV @MMCS1,R5 ;SC(SPECIAL CONDITIONS) BIT SET? BMI 20$ ;YES JMP NOERR ;NO ...... 20$: BIT #MCPE,R5 ;THIS ERROR IS SO HORRIBLE THAT WE DON'T BNE NQ1 ;BOTHER TO LOOK FOR OTHER ERRORS ; ABORT (LINK TO NQUAL). MOV LASTCOM,R4 ;GET LAST COMMAND BIT #MOL,@MMDS ;IS DRIVE ON-LINE BNE 30$ ;YES CMP #FN+OFFLINE,R4 ;WAS AN OFFLINE COMMAND GIVEN? BEQ 30$ ;YES-MOL SHOULD BE OFF MOV #EM.OFL,R4 ;NO-GIVE DRIVE NOT AVAILABLE ERROR JMP AB1 ;GO ABORT ...... 30$: CALL DISPAT ...... .DSABL LSB .SBTTL TABLEE - DISPATCH TABLE TABLEE: .BYTE /2 .BYTE /2 .BYTE /2 .BYTE /2 .BYTE /2 .BYTE /2 .BYTE /2 .BYTE /2 .SBTTL ERROR-READ COMMAND WAS ISSUED LAST AND SC BIT WAS SET .ENABL LSB ERREAD: MOV @MMDS,R5 ;R5=MMDS-ATA BIT SET? BPL ERWRI1 ;NO-GO CHECK TRE ; ATA (ATTENTION ACTIVE) BIT SET BIT #ERR,R5 ;ERR BIT ON? BEQ TMEOTC ;NO-GO CHECK FOR EOT AND/OR TM MOV @MMER,R4 ;SAVE MMER IN R4 CALL DRICLR ;DRIVE CLEAR ;010 BIT #CSITM,R4 ;SKEW OR TM ERROR? BEQ 20$ ;NO BIT #PES,R5 ;YES-PHASE ENCODING? BNE 10$ ;YES-NO ERROR OCCURRED MOV #EM.POS,R4 ;NO-ABORT WITH POSITION ERROR BR AB1 ;LINK TO ABORT 10$: CLR R4 ;HARD ERROR BR ERWRI1 ;GO CHECK TRE 20$: CMP #EPCOMBO,DENSE ;even parity mode in effect? ;009 BNE 30$ ; skip if not. BIT #,R4;Isolate 2 error bits BNE 40$ ; skip if either set. ; BR NOERR2 ;otherwise, let it go. JMP NEXTI ;otherwise, wait for real interrupt. 30$: BIT #,R4 ;ANY RECOVERABLE ERRORS? BEQ 50$ ;NOT YET 40$: MOV #REDREC,R4 ;SET READ RECOVERY CODE BR ERWRI1 ;GO CHECK TRE 50$: BIT #CORCRC,R4 ;CORRECTABLE PE/CRC ERROR? BEQ 60$ ;NO BIT #PES,R5 ;YES-PHASE ENCODING? BNE 10$ ;YES-NO ERROR BR 40$ ;NO-DO READ RECOVERY 60$: BIT #FCE,R4 ;FRAME COUNT ERROR? BNE 10$ ;YES-NO ERROR NQ1: JMP NQUAL .DSABL LSB .SBTTL ERROR-WRITE COMMAND WAS ISSUED LAST AND SC BIT WAS SET .ENABL LSB ERWRIT: TST @MMFC ;POSSIBLE POSITION ERROR? BEQ 10$ ;NO MOV #EM.POS,R4 ;YES-POSITION ERROR BIT #WRL,@MMDS ;MIGHT BE WRITELOCK ;004 BEQ 10$ ;IF EQ NO (was AB1 - try to recover) ;015 MOV #EM.WLK,R4 ;REPORT WRITE LOCK ;004 BR AB1 ;LINK TO ABORT 10$: MOV @MMDS,R5 ;ATA? BPL 50$ ;NO-GO CHECK TRE ; ATA (ATTENTION) BIT IS ON BIT #ERR,R5 ;ERR BIT SET? BEQ TMEOTC ;NO-GO CHECK FOR EOT MOV @MMER,R4 ;R4=MMER CALL DRICLR ;DRIVE CLEAR ;010 BIT #NEF,R4 ;FUNCTION ERROR? BEQ 20$ ;NO BR NQ1 ;MERGE ;004 ;004 20$: BIT #INCVPE+PEFLRC+CORCRC+NSG,R4 ;ANY RECOVERABLE ERRORS?;**-5 BEQ 40$ ;NO CMP #EPCOMBO,DENSE ;EVEN parity in effect? BNE 30$ BIC #INCVPE,R4 ;try clearing just this bit BNE 30$ ;if any others remain, go do recovery NOERR2: JMP NOERR ;Otherwise, let it go. 30$: MOV #WRIREC,R4 ;YES-SET UP WRITE RECOVERY CODE BR 50$ 40$: BIT #CSITM,R4 ;SKEW OR TM ERROR? BEQ NQ3 ;NO BIT #PES,R5 ;YES-PHASE ENCODING? BEQ NQ3 ;NO BR 30$ ;YES-DO WRITE RECOVERY ; TRE (TRANSFER ERROR) BIT ON CHECK ERWRI1: 50$: CALL TREFND ;GO PROCESS TRE JMP CONT ...... .DSABL LSB .SBTTL TAPEMARK AND EOT CHECKER TMEOTC: BIT #SSC,R5 ;SSC SET? BNE DRCLR ;YES-IGNORE IT BIT #TM+EOT,R5 ;IF EITHER OF THESE THEN DON'T ABORT BEQ NQ3 ;NO-ABORT BR DRCLR ;GO DO A DRIVE CLEAR THEN NOERR ...... .SBTTL ERROR - ERASE OR WRITE TAPEMARK ISSUED LAST AND SC BIT WAS SET .ENABL LSB ERERAS: ERWRTM: MOV @MMDS,R5 ;R5=MMDS-ATA BIT SET? BMI 10$ ;NO-ABORT NQ3: JMP NQUAL 10$: BIT #ERR,R5 ;ERRORS? BEQ 30$ ;NO ; ERRORS DETECTED BIT #WRL,R5 ;YES-WRITE LOCK? BNE AB0 ;Branch if so. MOV @MMER,R4 CMP #EPCOMBO,DENSE ;EVEN parity in effect? BNE 20$ CMP #INCVPE,R4 ;is it VPE only because of SET NOODDPAR? BEQ NOERR2 ; if so, let it go. 20$: BIT #NEF,R4 ;NON EXISTANT FUNCTION? BEQ NQUAL ;NO-ABORT AB0: MOV #EM.WLK,R4 ;ISSUE WRITE LOCK ABORT AB1: BR ABORT ; NO ERRORS DETECTED 30$: CALL ONLINE ;GO CHECK FOR OTHER DRIVE BUSINESS CALL DRICLR ;DO A DRIVE CLEAR CMP #FN+ERASE,LASTCOM ;IS WRITE EXTEND BEING DONE? BNE NOERR1 ;NO ; THIS DOES A WRITE COMMAND MOV #FN+WRITE,LASTCOM ;REMEMBER THE WRITE MOV OLDWC,R4 ;GET THE WORD COUNT NEG R4 ;MUST BE NEGATIVE MOV MMWC,R5 ;POINT TO DEVICE REGISTERS ;008 MOV R4,(R5)+ ;MOVE IN WORD COUNT MOV OLDBA,(R5)+ ;MOVE IN BUFFER ADDRESS ASL R4 ;FRAME COUNT = WORD COUNT * 2 MOV R4,(R5)+ ;MOVE IN FRAME COUNT .IF NE MMG$T MOV EXTADR,R4 ; form a word for MMCS1 SWAB R4 ; move extended bits to high byte BISB FUNTAB+1,R4 ; insert a write command MOV R4,@MMCS1 ; start the operation... .IFF MOVB FUNTAB+1,@MMCS1 ; start the write .ENDC ;NE MMG$T RETURN ; to monitor ...... .DSABL LSB .SBTTL ERROR-SPACING COMMAND WAS ISSUED LAST AND SC BIT WAS SET. .ENABL LSB ERBKSP: ERFWSP: MOV @MMDS,R5 ;R5=MMDS-ATA BIT SET? BIT #,R5 ;tape still in motion? ;009 BNE NEXTI ; wait till it stops ;009 TST R5 BPL NQUAL ;NO-ABORT TSTB CMDINI ;Ev-par error interrupt occurred yet? ;010 BNE 2$ ;If so, don't check #ERR bit ;010 BIT #ERR,R5 ;ERR BIT SET? BEQ 2$ ;NO ; ERRORS DETECTED MOV @MMER,R4 ;GET ERROR REGISTER BIT #NEF,R4 ;NON EXISTANT FUNCTION? BEQ 1$ ;NO-CHECK FOR TM BIT #BOT,R5 ;YES-BOT CAN CAUSE THIS? BNE NOERR ;IT DID-NO ERROR BR NQUAL ;IT DIDN'T-ABORT ...... 1$: BIT #FCE,R4 ;SEE IF TM FOUND BEQ NQUAL ;NO-ABORT NOERR1: BR NOERR ;YES-NO ERROR ...... ; NO ERRORS DETECTED 2$: CALL ONLINE ;GO CHECK FOR OTHER DRIVE BUSINESS BR DRCLR ;DRIVE CLEAR .DSABL LSB .SBTTL ERROR-REWIND OR REWIND/OFFLINE ISSUED LAST AND SC BIT WAS SET. .ENABL LSB ERREWD: EROFFL: MOV @MMDS,R5 ;R5=MMDS,ATA SET? ; BPL NQUAL ;NO BIT #ERR,R5 ;ERRORS? BEQ 1$ ;NO ; ERRORS DETECTED BIT #OPI,@MMER ;OPI TIMER TIMEOUT? BEQ NQUAL ;NO-ABORT BR 3$ ;YES-NO ERROR AND DO DRIVE CLEAR ; NO ERRORS DETECTED 1$: TSTB RECOVERY ;1ST OR 2ND INTERRUPT? BPL 4$ ;2ND ; 1ST INTERRUPT CMP #FN+OFFLINE,LASTCOM ;OFFLINE ONLY GENERATES 1 INTERRUPT BEQ NOERR ;AND ITS DONE MOVB LASTCOM,RECOVERY ;SHOW THAT WE'RE WAITING FOR NEXT INT NEXTI: MOV #DRIVEBIT,@MMAS ;CLEAR ATA BIT SO WE CAN SET IE INCB CMDINI ;indicate that interrupt has occurred 2$: MOV #IE,@MMCS1 ;PUT IN INTERRUPT ENABLE BIT #PIP,@MMDS ;LAST CHANCE FOR BOT? BEQ 3$ ;NOT YET RETURN ;TO MONITOR ; JMP ASTEXI ;KEEP WAITING ...... DRCLR: 3$: CALL DRICLR ;CLEAR IE AND DRIVE CLEAR BR NOERR ...... ; 2ND INTERRUPT 4$: BIT #SLA,R5 ;SLAVE ATTENTION BIT ON? BNE 3$ ;YES-REWIND IS DONE ; NOTE-THE ONLY CASES WHERE SLA IS ON IS WHERE REWIND IS DONE OR TAPE HAS BEEN ; TURNED OFFLINE. IF THE TAPE WAS TURNED OFFLINE THEN THE NEXT OPERATION WILL ; FAIL BUT THE REWIND CAN STILL BE REPORTED AS DONE. CALL CONCLR ;RH11(MASSBUSS CONTROLLER) CLEAR BR 2$ ;GO WAIT FOR ANOTHER INTERRUPT ...... .DSABL LSB .SBTTL ERROR-ABORT OPERATION IN PROGRESS NQUAL: CLR R4 ;HARD ERROR HAS OCCURRED ABORT: CALL CONCLR ;DO AN RH11 RESET(CLEAR THE MASSBUSS AND DRIVE) MOV #HDERR$,-(SP) ;HARD ERROR HAS OCCURRED ; EXCEPTION REPORTING ROUTINE ; R4 CONTAINS ERROR QUALIFICATION CODE ; CSW BIT TO SET IS ON THE STACK EXCEP: .IF NE MM$FSM MOV (SP)+,R5 ;PUT CSW BIT IN R5 JMP FSMERR ;TELL FSM THAT OPERATION HAD AN EXCEPTION .IFF; NE MM$FSM MOV MMCQE,R5 ;POINT TO QUEUE ELEMENT BIS (SP)+,@Q$CSW(R5) ;SET BIT IN CSW TST @R5 ;DON'T SET ERRBLK IF ADDRESS IS ZERO BEQ MMDONE .IF NE MMG$T COM SINK ;SET SYNCH WILL BE DONE FLAG MOV @R5,ERBSAV ;REMEMBER ERRBLK ADDRESS MOV R4,TEMP ;THIS VALUE COMES BACK IN R0 AFTER .SYNCH MOVB Q$JNUM(R5),R5 ;GET THE JOB NUMBER IN <5:3> ASR R5 ;PUT IT IN <2:0> ASR R5 ASR R5 MOV R5,JOBNM ;STORE IT IN SYNCH BLOCK .IFF; NE MMG$T MOV R4,@(R5)+ ;MOVE CODE TO ERRBLK .ENDC ;NE MMG$T .ENDC; NE MM$FSM .SBTTL MMDONE ;+ ; MMDONE IS THE ROUTINE WHERE THE HARDWARE HANDLER COMES WHEN IT IS DONE WITH ; AN OPERATION WHICH COMPLETED WITH NO EXCEPTION CONDITIONS. WHEN THE FSM IS ; PRESENT THE HARDWARE HANDLER JUMPS TO FSMDON WHICH INDICATES THAT THE ; OPERATION COMPLETED WITH NO EXCEPTION CONDITIONS. ; ; WHEN FSM IS NOT PRESENT THE HANDLER EXITS TO THE I/O COMPLETE ROUTINE IN THE ; MONITOR. ; ; WHEN EXTENDED MEMORY SUPPORT IS INCLUDED THE HANDLER WILL DECIDE WHETHER TO ; DO A SYNCH SO THAT ERRORS CAN BE REPORTED TO THE USER'S ERRBLK ADDRESS. ;- MMDONE: .IF NE MM$FSM JMP FSMDON ;TELL FSM THAT OPERATION IS DONE ...... ; FSM comes to $DONE when it is done with all its processing. .ENDC ;NE MM$FSM .ENABL LSB $DONE:: TSTB $FLG ; ABORT WITH NO COMPLETE? ;SD2 BNE $RTS ; IF NE YES ;SD2 .IF NE MMG$T TST SINK ; SHOULD A JSR OR JMP BE DONE? BNE 10$ ; JSR .ADDR #MMCQE,R4 ; Point to MMCQE MOV @#$SYPTR,R5 ; GET BASE OF RMON JMP @$QCOMP(R5) ; ALL DONE ...... 10$: CLR SINK ; Reset .SYNCH HAS BEEN DONE flag .ADDR #SYNBLK,R4 ; point to global SYNCH block .SYNCH BR BADSYN ; From here down to the RETURN, we are a completion routine running in ; kernel mode for the job. MOV ERBSAV,R1 ; point to job's ERRBLK BIS #30000,@#177776 ; USER mode to previous MOV R0,-(SP) ; put exception code on stack MTPD (R1)+ ; store for user MOV ERRBL2,-(SP) ; 2nd word (typically a count) MTPD (R1)+ ; store for user ; DRFIN the queue element. We are in kernel mode, running as a completion ; routine in job-context. Only R0 and R1 are free, so save the other ; registers. MOV R2,-(SP) ; Save registers MOV R3,-(SP) ; that COMPLT MOV R4,-(SP) ; might use MOV R5,-(SP) .ADDR #MMCQE,R4 ; point to queue element, MOV @#$SYPTR,R5 ; get base of RMON, CALL @$QCOMP(R5) ; CALL COMPLT in RMON MOV (SP)+,R5 MOV (SP)+,R4 MOV (SP)+,R3 MOV (SP)+,R2 BADSYN: .BR $RTS .IFF; NE MMG$T .DRFIN MM ...... .ENDC ;NE MMG$T $RTS: CLRB $FLG ;RESET ABORT FLAG ;SD2 RETURN ;EXIT ;SD2 ...... .DSABL LSB .SBTTL STATUS REPORTING - COME HERE IF NO ABORTS ISSUED .ENABL LSB NOERR: CLR R4 ;MARK NO ERRORS CONDITION CONT: MOV R4,ERRSUM ;SAVE TYPE OF ERROR ; CHECK FOR RECOVERY IN PROGRESS TSTB RECOVERY ;IF NEGATIVE NO RECOVERY HAPPENING BPL RECOVR ;GO PROCESS RECOVERY ; CHECK FOR A RECOVERABLE ERROR TST ERRSUM ;IF ZERO THEN NO RECOVERABLE ERROR HAPPENED BEQ NEXT1 ;NOT FOUND ; A RECOVERABLE ERROR HAS HAPPENED CMP #FN+READF,LASTCOM ;WAS LAST COMMAND A READ? BNE 10$ ;NO-MUST BE A WRITE MOVB #5,BACK1 ;INITIALIZE RETRY COUNTERS MOVB RTRYCT,BACK5 MOV #FN+READF,R4 ;SET UP RECOVERY BR 20$ ...... 10$: MOV #FN+ERASE,R4 ;WRITE AND WRITEX RECOVER WITH WRITE EXT GAP 20$: MOVB R4,RECOVERY ;MARK THE TYPE OF RECOVERY IN PROGRESS BR REEDF1 ;THIS WILL DO A BACKSPACE 1 BLOCK ...... .DSABL LSB ; LENGTH ERROR CHECK FOR READ ; THIS ROUTINE CHECKS FOR DATA LENGTH ERRORS. THERE ARE TWO WHICH CAN OCCUR. ; ; 1. RECORD (BLOCK) LENGTH ERROR (RLE) OCCURS WHEN THE BLOCK ON TAPE WAS ; LARGER THAN THE WORD COUNT SPECIFIED. THE TJU16 REPORTS HOW MUCH DATA ; WAS NOT READ IN ERRBLK+2. CODE 5 IS RETURNED. ; ; 2. BLOCK IS SMALLER THAN SPECIFIED WORD COUNT. THE RESIDUAL COUNT IN THE ; MMBRC IS CHANGED TO A WORD COUNT AND REPORTED IN ERRBLK+2. CODE 6 IS ; RETURNED. ; ; RECOVERED ERRORS COME HERE .ENABL LSB NEXT1: MOV @MMFC,R4 CMP #FN+READF,LASTCOM ;IS READ HAPPENING? BNE NEXT2 ;NO ; READ COMMAND-CHECK LENGTH ERROR BIT #TM,@MMDS ;IF TM ITS JUST EOF HERE BNE NEXT3 ;TM FOUND MOV OLDWC,R5 ASL R5 ;OLDWC*2 SUB R4,R5 ;OLDWC-MMFC BEQ NEXT3 ;NO LENGTH ERROR BGT 10$ ;NOT ENOUGH DATA ; EXTRA DATA FOUND MOV #EM.BIG,R4 ;RECORD LENGTH ERROR NEG R5 ;MAKE NUMBER OF BYTES NOT READ POSITIVE BR 20$ ; NOT ENOUGH DATA 10$: MOV #EM.SML,R4 ;SMALL RECORD ERROR 20$: ASR R5 ;DIVIDE BY 2 .IF NE MMG$T MOV R5,ERRBL2 ;SAVE EXTRA WORDS TO REPORT FOR LATER .IFF; NE MMG$T MOV R5,-(SP) ;MAKE ROOM FOR ERRBLK ADDRESS .IF NE MM$FSM MOV @MTCQ,R5 ;GET ERRBLK ADDRESS (POSSIBLE FROM FSM) .IFF; NE MM$FSM MOV @MMCQE,R5 ;GET ERRBLK ADDRESS .ENDC ;NE MM$FSM BEQ 30$ ;ZERO MEANS DON'T USE ERRBLK TO REPORT ERRORS MOV @SP,2(R5) ;INSERT DIFFERENCE OF WORDS ACTUALLY ;READ FROM THE WORD COUNT 30$: TST (SP)+ ;FIX STACK .ENDC ;NE MMG$T .IF NE MMG$T JMP ABORT .IFF; NE MMG$T BR ABORT .ENDC; NE MMG$T ...... .DSABL LSB ;THIS ROUTINE CHECKS TO SEE WHETHER A SPACING COMMAND COMPLETED CORRECTLY ;OR WHETHER IT TERMINATED WITHOUT HAVING SPACED THE NUMBER OF BLOCKS ASKED ;FOR. WHEN A SPACING COMMAND TERMINATED WITHOUT HAVING SPACED THE CORRECT ;NUMBER OF BLOCKS THEN THE NUMBER OF BLOCKS NOT SPACED IS MADE POSITIVE AND ;REPORTED TO ERRBLK+2. .ENABL LSB NEXT2: CMP #FN+FWDSPC,LASTCOM BEQ 1$ ;FORWARD SPACE CMP #FN+BKSPC,LASTCOM BNE NEXT3 ;NOT A SPACING COMMAND ;SPACING COMMAND 1$: NEG R4 ;MAKE NUMBER OF BLOCKS NOT SPACED POSITIVE BEQ NEXT3 ;COMMAND COMPLETED .IF NE MMG$T MOV R4,ERRBL2 ;SAVE BLOCKS NOT SPACED .IFF .IF NE MM$FSM MOV @MTCQ,R5 ;GET ERRBLK ADDRESS(POSSIBLE FROM FSM) .IFF MOV @MMCQE,R5 ;GET ERRBLK ADDRESS .ENDC ;NE MM$FSM BEQ NEXT3 ;IF 0 THEN DON'T WRITE TO ERRBLK MOV R4,2(R5) ;REPORT NUMBER OF BLOCKS NOT SPACED .ENDC ;NE MMG$T .DSABL LSB ; SET EOF CODES IF ANY .ENABL LSB NEXT3: MOV @MMDS,R5 ;THIS HAS BOT,EOF,EOT INDICATORS CLR R4 ;THIS IS WHERE THE CODES GO BIT #BOT,R5 ;BOT? BEQ 10$ ;NO CMP #FN+REWIND,LASTCOM MMD1: BEQ REWHYN ;REWIND DOESN'T REPORT BOT CMP #FN+OFFLINE,LASTCOM BEQ MMD1 ;OFFLINE/REWIND DOESN'T REPORT BOT MOV #EM.BOT,R4 ;MARK BOT FOUND BR 40$ ;GO SET EOF BIT ...... 10$: BIT #TM,R5 ;TAPEMARK SET? BEQ 20$ ;NO CMP #FN+WRTEOF,LASTCOM BEQ 20$ ;WRITE TM DOESN'T REPORT EOF INC R4 ;SET BIT 0 20$: BIT #EOT,R5 ;END OF TAPE? BEQ 30$ ;NO TST NFSREAD ;YES-WAS A NON FILESTRUCTURED READ DONE? BNE 30$ ;YES-IGNORE THE EOT CONDITION! CMPB (R4)+,(R4)+ ;NO-SET BIT 1 30$: TST R4 ;EOF DETECTED? BEQ MMD1 ;NO 40$: MOV #EOF$,-(SP) ;YES-MARK IT JMP EXCEP ...... .DSABL LSB .SBTTL RECOVERY IN PROGRESS DISPATCHER ;RECOVERY IN INITIATED FOR READ, WRITE, OR WRITE WITH EXTENDED GAP COMMANDS ;WHICH DETECT CRC ERROR, PARITY ERROR OR BUS GRANT LATE. THE ALGORITHMS USED ;ARE AS FOLLOWS. NOTE THAT IF AN ERROR IS DETECTED ON ANY OF THE SPACING ;COMMANDS IT TERMINATES THE RECOVERY ATTEMPT AND CAUSES A HARD ERROR. ; ;READ RECOVERY ; ;1. BACKSPACE 1 BLOCK AND RE-READ, IF ERROR PERSISTS, REPEAT 4 MORE TIMES. ; ;2. BACKSPACE 5 BLOCKS (OR TO BOT WHICHEVER COMES FIRST), SPACE FORWARD ; 4 BLOCKS, THEN RE-READ. ; ;3. THIS ENTIRE SEQUENCE (STEPS 1 AND 2) SHOULD BE REPEATED 8 TIMES. WHEN ; ERROR STILL PERSISTS THEN THE RECOVERY IS DEEMED UNSUCCESSFUL AND A ; HARD ERROR IS GIVEN. ; ;WRITE RECOVERY ; ;1. BACKSPACE OVER BLOCK. ; ;2. ERASE THREE INCHES OF TAPE AND REWRITE THE BLOCK. ; ;3. WHEN ERROR PERSISTS AND THE TOTAL LENGTH OF THE GAP WRITTEN IS LESS ; THAN 25 FEET (TAPELEN BYTE IS NOT ZERO YET) THEN PERFORM SEQUENCE ; AGAIN. RECOVR: MOV LASTCOM,R4 CALL DISPAT ...... TABLER: .BYTE /2 .BYTE /2 .BYTE 0 .BYTE /2 .BYTE 0 .BYTE /2 .BYTE /2 .BYTE 0 .SBTTL RECOVERY-READ WAS THE LAST COMMAND ISSUED .ENABL LSB REEDF: TST ERRSUM ;RECOVERY COMPLETE BPL NEXT1 ;YES DECB BACK1 ;DECREMENT THE 1ST COUNTER BEQ 10$ ;IF EQ,TIME TO BACKSPACE 5 ;BD0+ BGT REEDF1 ;IF GT,KEEP BACKSPACE AT 1 ;ELSE TIME TO DECREMENT 2ND COUNTER ;AND RESET THE 1ST COUNTER MOVB #5,BACK1 ;RESET BACK1 COUNTER ;BD0- DECB BACK5 ;BACK5 COUNTER DONE? BEQ NQ2 ;YES-ABORT RECOVERY REEDF1: MOV #-1,R5 ;BACKUP 1 BLOCK ;BD0+ BR 20$ ;GO DO A BACKUP ;BD0- ...... 10$: MOV #-5,R5 ;GO BACK 5 BLOCKS 20$: MOV R5,@MMFC ;SET NUMBER OF BLOCKS TO BACKSPACE BR BACH2 ...... .DSABL LSB .SBTTL RECOVERY-WRITE WAS LAST COMMAND RITE: TST ERRSUM ;RECOVERY COMPLETED? BEQ NEXT1 ;YES INCB TAPELEN ;ANOTHER 3" GAP WRITTEN BEQ NQ2 ;TOO MANY-ABORT WRITE RECOVERY BIT #EOT,@MMDS ;EOT DETECTED? BEQ REEDF1 ;NO-BACKUP 1 BLOCK NQ2: JMP NQUAL ;YES-ABORT WRITE RECOVERY ...... .SBTTL RECOVERY-FORWARD SPACE WAS THE LAST COMMAND FORE: MOV @MMFC,R5 ;FORWARD SPACING ALL DONE? BNE BACH1 ;NO-ISSUE ANOTHER FORWARD SPACE COMMAND FORE1: MOV MMBA,R5 ;R5 POINTS TO TJU16 DEVICE REGISTER ;008 MOV OLDBA,@R5 ;PUT IN BUFFER ADDRESS MOV OLDWC,-(R5) ;PUT IN WORD COUNT NEG (R5) ;NEGATE THE WORD COUNT ;BD0 MOV #FN+READF,LASTCOM ;SAVE LAST COMMAND .IF NE MMG$T MOV EXTADR,R4 ; make word for MMCS1 SWAB R4 ; move extended address bits up, BISB FUNTAB,R4 ; combine with READ COMMAND ;BD0 MOV R4,-(R5) ; give the command .IFF MOVB FUNTAB,@MMCS1 ;GO! ;BD0 .ENDC ;NE MMG$T RETURN .SBTTL RECOVERY-REWIND WAS THE LAST COMMAND REWHYN: JMP MMDONE .SBTTL RECOVERY-BACKSPACE WAS LAST COMMAND ;WHEN BACKSPACE WAS THE LAST COMMAND ONE OF FOLLOWING ACTIONS IS TAKEN. ;1. WHEN WRITE RECOVERY IS BEING PERFORMED A WRITE WITH EXTENDED GAP ; COMMAND IS ISSUED. ;2. WHEN READ RECOVERY IS BEING DONE AND THE BACKSPACE COMPLETED A CHECK ; IS MADE AS TO WHETHER OR NOT THE BACKSPACE WAS PART OF 1 BLOCK OR ; 5 BLOCK SPACE. WHEN A 1 BLOCK BACKSPACE HAS COMPLETED A REREAD IS ; ISSUED. WHEN A 5 BLOCK BACKSPACE HAS COMPLETED A FORWARD SPACE TO BAD ; BLOCK IS PERFORMED. ;3. WHEN READ RECOVERY IS BEING DONE AND THE BACKSPACE DID NOT COMPLETE THE ; ROUTINE CHECKS FOR BOT. WHEN BOT IS FOUND THEN THE HANDLER ISSUES A ; FORWARD SPACE COMMAND WHICH WILL POSITION IT IN FRONT OF THE BAD BLOCK. ; OTHERWISE A TM HAS BEEN ENCOUNTERED (OR EOT) AND THE BACKSPACE COMMAND ; IS REISSUED. .ENABL LSB BACH: CMPB #FN+READF,RECOVERY ;READ OR WRITE RECOVERY? BEQ 1$ ;BRANCH IF READ ;ERASE AND REWRITE MOV #FN+ERASE,R4 ;THIS IS THE LASTCOM MOVB FUNTAB+4,R5 ;THIS IS THE COMMAND BR 4$ ;GO EXECUTE THE COMMAND ;READ RECOVERY 1$: MOV @MMFC,R5 ;DONE WITH BACKING UP? BEQ 6$ ;YES BIT #BOT,@MMDS ;NO-BOT DETECTED? BEQ BACH2 ;NO 2$: ADD #4,R5 ;YES-CALC NUMBER OF BLOCKS TO FORWARD SPACE BEQ 8$ ;GO READ IF NO SPACING REQUIRED ;BD0 3$: NEG R5 ;MAKE IT NEGATIVE BACH1: CALL DRICLR ;Clear Drive ;009 MOV #FN+FWDSPC,R4 ;THIS IS THE LASTCOM MOV R5,@MMFC ; RE-SET THE FRAME COUNT ;009 MOVB FUNTAB+6,R5 ;THIS IS THE COMMAND BR 4$ BACH2: CALL DRICLR ;Clear Drive ;009 MOV #FN+BKSPC,R4 ;THIS IS THE LASTCOM MOV R5,@MMFC ; RE-SET THE FRAME COUNT ;009 MOVB FUNTAB+5,R5 ;THIS IS THE COMMAND ;SET LASTCOM AND EXECUTE 4$: MOV R4,LASTCOM ;REMEMBER LASTCOM MOV R5,@MMCS1 ;GO! RETURN ;BACKUP DONE 6$: TSTB BACK1 ;ARE WE IN MIDDLE OF BACKING UP 5 BLOCKS ;BD0 BEQ 2$ ;YES. GO ISSUE FORWARD SPACE 8$: CALL DRICLR ;Clear the drive ;009 BR FORE1 ;Go Read Block DRICLR: MOV #,@MMCS1 ; Clear the tape drive ;009 RETURN CONCLR: MOV #CLR,@MMCS2 ; Clear the massbus controller RETURN .DSABL LSB .SBTTL TRE (TRANSFER ERROR) BIT FOUND SUBROUTINE ;THIS ROUTINE WILL DETERMINE WHETHER THE CONDITION WHICH CAUSED TRE TO BECOME ;SET SHOULD ABORT THE OPERATION OR NOT AND WILL ISSUE THE APPROPRIATE CODE ;TO BE PASSED BACK. ; BIT CODE ISSUED ; --- ---- ------ ; NEM NON EXISTANT MEMORY ERROR ; NED NON EXISTANT DRIVE ERROR ; MXF HARD ERROR ; MDPE HARD ERROR ; PGE HARD ERROR ; UPE HARD ERROR ; WCE HARD ERROR ; ; IF DLT(DATA LATE) IS DETECTED, A MINUS ONE IS LOADED INTO R4. ; ; IF NONE OF THE ABOVE ERRORS HAVE OCCURRED, THE ROUTINE ASSUMES ; THAT ALL IT HAS TO DO IS TO CLEAR THE RRE CONDITION, WHICH IT DOES ; BY WRITING A 1 INTO TRE. ; ; R5 IS LOADED WITH MMCS2. R4 IS SAVED UNLESS DLT WAS DETECTED. ALL OTHER ; REGISTERS ARE PRESERVED. ; ; THE SUBROUTINE IS CALLED WITH A JSR PC,TREFND. IF THE ROUTINE ABORTS ; THE OPERATION, THE STACK IS FIXED. .ENABL LSB TREFND: MOV @MMCS2,R5 ;R5=MMCS2 MOV #TRE,@MMCS1 ;CLEAR THE TRE CONDITION BIT #NEM,R5 ;NON EXISTANT MEMORY CONDITION? BEQ 10$ ;NO MOV #EM.NXM,R4 ;YES-ABORT WITH MEMORY ERROR BR 30$ 10$: BIT #NED,R5 ;NON EXISTANT DRIVE? BEQ 20$ ;NO MOV #EM.OFL,R4 ;YES-ABORT WITH DRIVE NOT AVAILABLE BR 30$ 20$: BIT #MXF+MDPE+PGE+UPE+WCE,R5 ;HARD ERROR? BEQ 40$ ;NO CLR R4 ;ABORT WITH HARD ERROR 30$: TST (SP)+ ;FIX THE STACK JMP ABORT 40$: BIT #DLT,R5 ;DATA LATE? BEQ 50$ ;NO MOV #REDREC,R4 ;ASSUME READ RECOVERY TO BE DONE 50$: RETURN .DSABL LSB .SBTTL ONLINE SUBROUTINE ;THIS SUBROUTINE CHECKS FOR AND HANDLES THE CASE WHERE ANOTHER UNIT IS ;TURNED ON LINE WHILE A COMMAND IS BEING PERFORMED ON ANOTHER UNIT. THE ;ROUTINE WILL CLEAR THE ATA BIT THEN ISSUE A NO OPERATION COMMAND WITH THE ;INTERRUPT ENABLE BIT SET IN ORDER TO SET THE INTERRUPT ENABLE BIT. .ENABL LSB ONLINE: BIT #SSC,R5 ;STATUS CHANGE? BEQ 10$ ;NO MOV #DRIVEBIT,@MMAS ;CLEAR ATA CONDITION TSTB @MMDS ;CHECK DRY BIT (THIS HAS TO BE ;CHECKED TO AVOID THE CASE WHERE ;THE ATA BIT WAS BEING SET JUST ;AS IT WAS BEING CLEARED. BMI 10$ ;OPERATION IS DONE MOV #FNOOP+IE+GO,@MMCS1 ;SET INTERRUPT ENABLE TST (SP)+ ;RETURN TO MONITOR 10$: RETURN .DSABL LSB .SBTTL DISPATCH SUBROUTINE ;THIS IS A DISPATCHING ROUTINE. FOR INPUT IT GETS AN INDEX IN R4 ;WHICH CORRESPONDS TO A BYTE IN A BYTE TABLE WHICH FOLLOWS THE CALLING ;JSR PC,DISPAT INSTRUCTION. IT ALSO GETS THE ADDRESS OF THAT TABLE ON ;THE STACK FROM THE JSR INSTRUCTION. ; ;THE ROUTINE ADDS THE TABLE ADDRESS TO THE INDEX TO GET AN ADDRESS IN R4 ;WHICH POINTS TO THE CORRECT TABLE ENTRY. NEXT A MOVB INSTRUCTION USES ;THIS ADDRESS TO FETCH A BYTE FROM A SECOND TABLE WHICH MAY DIRECTLY ;FOLLOW THE FIRST TABLE(THE SECOND TABLE IS OPTIONAL IN WHICH CASE ;R5 SHOULD BE IGNORED. IN ANY CASE R5 IS CHANGED). THE ROUTINE ;THEN FETCHES THE OFFSET BYTE INTO R4. THE HIGH ORDER BYTE OF R4 IS ;CLEARED THEN MULTIPLIED BY 2(BY SHIFTING). NOW THE RETURN ADDRESS ON THE ;STACK IS ADDED TO THE VALUE IN R4 TO GET THE ADDRESS OF THE ROUTINE TO GO TO ;(INCIDENTALLY THE ADDITION POPS THE STACK). R4 NOW CONTAINS THE ADDRESS OF ;THE PROPER ROUTINE AND IT IS JUMPED TO. DISPAT: ADD @SP,R4 ;CALC ADDRESS OF OFFSET BYTE MOVB FUNTAB-TABLE(R4),R5 ;GET BYTE FROM SECOND TABLE MOVB @R4,R4 ;GET OFFSET BYTE BIC #177400,R4 ;BLASTED SIGN EXTEND! ASL R4 ;MULTIPLY BY 2 ADD (SP)+,R4 ;CALC ADDRESS OF ROUTINE AND FIX STACK JMP @R4 ;GO THERE .SBTTL MAGTAPE DATA AREA ; RECOVERY BYTE - THIS BYTE IS USED TO INDICATE WHETHER OR NOT A MAGTAPE ; RECOVERY IS IN PROGRESS. IF THIS BYTE IS NEGATIVE THEN THERE IS NO RECOVERY ; IN PROGRESS. IF POSITIVE THEN IT CONTAINS A VALUE WHICH CORRESPONDS TO THE ; COMMAND BEING RECOVERED FROM. ; TAPELEN BYTE - THIS BYTE IS USED TO KEEP TRACK OF THE # OF INCHES OF ; CONSECUTIVE GAP WHICH HAS BEEN WRITTEN BY THE WRITE ERROR RECOVERY ROUTINE. ; THE DEC STANDARD SPECIFIES THAT A GAP OF GREATER THAN 300 INCHES IS ILLEGAL ; AND THE ERROR RECOVERY CODE WILL ISSUE A HARD ERROR IF IT INCREMENTS ; TAPELEN PAST 0. EACH INCREMENT REPRESENTS ONE 3 INCH GAP WRITTEN. ; BACK5 AND BACK1 BYTES - THESE ARE COUNTERS USED BY THE READ ERROR RECOVERY ; CODE. THERE ARE TWO TYPES OF READ ERROR RECOVERY. ONE IS SIMPLY TO ; BACKSPACE AND REREAD. WHENEVER THE ERROR RECOVERY ALGORITHM DOES THIS ; IT DECREMENTS BACK1. ANOTHER READ RECOVERY IS TO BACKSPACE 5 BLOCKS THEN ; FORWARD SPACE 4 AND REREAD. WHENEVER THE ERROR RECOVERY ALGORITHM DOES THIS ; IT DECREMENTS BACK5. ; LASTCOM CONTAINS A VALUE WHICH CORRESPONS TO THE LAST TAPE MOVEMENT COMMAND ; ISSUED TO THE TAPE UNIT CONTROLLER. THIS VALUE IS CALCULATED BY ADDING 8 TO ; THE CORRESPONDING SPFUN CODE. VALUES ARE: ; OPERATION CODE (IN LISTING) ; ; 7 WRITE A TAPE MARK FN+WRTEOF ; 6 FORWARD SPACE N BLOCKS FN+FWDSPC ; 5 BACKSPACE N BLOCKS FN+BKSPC ; 4 ERASE 3" OF TAPE AND WRITE FN+WRTXTD ; 3 REWIND THE TAPE FN+REWIND ; 2 GO OFFLINE AND REWIND THE TAPE FN+OFFLINE ; 1 WRITE A BLOCK FN+WRITEPHY ; 0 READ A BLOCK IN FORWARD DIRECTION FN+READF ; ; OLDBA WORD - THIS WORD CONTAINS THE BUFFER ADDRESS FOR THE LAST READ OR ; WRITE COMMAND. IT IS SAVED SO THAT THE ERROR RECOVERY CODE CAN REISSUE ; THE COMMAND WHICH IS BEING RECOVERED. IF THE HANDLER IS CONDITIONALIZED ; FOR EXTENDED MEMORY THEN OLDBA CONTAINS THE LOW 16 BITS OF A PHYSICAL ; ADDRESS. THIS WORD IS A GLOBAL WHICH CAN BE ACCESSED BY FSM. ; ; EXTADR WORD - THIS WORD IS ONLY IN A HANDLER CONDITIONALIZED FOR EXTENDED ; MEMORY. IT CONTAINS THE 2 HIGH ORDER BITS OF A PHYSICAL ADDRESS. ; THIS WORD IS A GLOBAL WHICH IS ACCESSED BY FSM. ; ; OLDWC WORD - THIS WORD CONTAINS THE WORD COUNT FOR THE LAST COMMAND. ; THIS IS USED BY THE ERROR RECOVERY CODE. ; ; ERRSUM WORD - AFTER ANY INTERRUPT THE TAPE CONTROLLER REGISTERS ARE ; EXAMINED FOR STATUS AND ERROR CONDITIONS TO DETERMINE WHICH OF THE ; FOLLOWING STATES THE MAGTAPE OPERATION IS IN. THIS RESULT IS SUMMARIZED ; IN THIS WORD. THE STATES ARE: ; ; VALUE ; HARD ERROR NOT SPECIFIED, OPERATION IS ABORTED ; RECOVERABLE ERROR NON ZERO ; NO ERROR ZERO ; ; NFSREAD WORD - THIS WORD IS IN SPECIAL CASE THE PROBLEM OF HOW TO ; REMEMBER THAT THE READ OEPRATION BEING DONE STARTED LIFE AS A .READ ON ; A CHANNEL OPENED WITH A NON FILE STRUCTURED .LOOPUP. WHEN THE EOT ; MARKER IS DETECTED AND THIS WORD IS NON ZERO THEN THE CONDITION IS IGNORED. ; ; .SYNCH REQUEST BLOCK [ONLY IN HANDLER CONDITIONALIZED FOR EXTENDED MEMORY] ; SYNBLK IS THE ADDRESS OF THE BLOCK. JOBNUM IS THE CURRENT JOB NUMBER FOR ; REQUEST BEING SERVICED. TEMP IS VARIABLE WHICH WILL BE USED TO ; LOAD R0 ON RETURN FROM THE .SYNCH. ; ; SINK WORD - THIS WORD IS SET TO INDICATE THAT THERE ARE ERRORS TO REPORT TO ; THE CALLING PROGRAM. WHEN ALL PROCESSING FOR THE CURRENT QUEUE ELEMENT IS ; DONE THIS WORD IS CHECKED FOR A NON ZERO VALUE. IF NOT FOUND THE HANDLER ; JUMPS TO THE I/O COMPLETE SUBROUTINE. IF SINK IS NON ZERO THEN THE HANDLER ; DOES A JSR TO THE I/O COMPLETE SUBROUTINE IN ORDER TO FREE UP THE QUEUE ; ELEMENT AND GET OUT OF INTEN LEVEL (SET WHEN INTERRUPT HANDLER WAS ENTERED). ; THEN THE HANDLER DOES A .SYNCH TO GET THE CONTEXT OF THE JOB WHICH WANTED ; THE INFORMATION REPORTED AND THEN USES THE INFORMATION STORED IN ERBSAV TO ; POINT INTO THE USERS AREA. THEN R0 (LOADED FROM TEMP IN .SYNCH BLOCK) ; AND ERRBC2 ARE STORED IN ERRBLK AND ERRBLK+2 RESPECTIVELY. ; DO NOT CHANGE THE ORDER OF THE FOLLOWING VARIABLES $TBL: .REPT MM$UN ;SD2 .BYTE -1 ;SD2 .ENDR ;SD2 .BYTE -2 ;SD2 $FLG: .BYTE 0 ;SD2 .EVEN ; THE ORDER OF THE NEXT SEVERAL BYTES IS CRITICAL (SEE "MOV (PC)+,(R0)+") RECOVE: .BYTE -1 TAPELE: .BYTE ERRGAPS OLDEOT: BACK5: .BYTE 0 BACK1: .BYTE 0 .EVEN LASTCO: .WORD 0 OLDBA: .WORD 0 .IF NE MMG$T EXTADR: .WORD 0 ;HIGH ORDER BITS FOR 18 BIT ADDRESS .ENDC; NE MMG$T OLDWC: .WORD 0 ERRSUM: .WORD 0 ;SUMMARIZE ERRORS HERE NFSREA: .WORD 0 ;THIS WORD IS SET TO -1 IF A ;NON-FILE-STRUCTURED READ WAS JUST DONE ;ELSE IT IS ZERO. IF SET THE EOT ;CONDITION WILL BE IGNORED. .EVEN SPSAV: .WORD 0 ; SP stored here for hijack returns .IF NE MMG$T ; .SYNCH REQUEST BLOCK SYNBLK: .WORD 0 ;RESERVED FOR SYSTEM USE JOBNM: .WORD 0 ;JOB NUMBER GOES HERE .WORD 0,0 ;UNUSED TEMP: .WORD 0 ;THIS WORD IS LOADED IN R0 AFTER SUCCESSFUL ;COMPLETION OF THE .SYNCH REQUEST .WORD -1,0 ;LEAVE THESE ALONE SINK: .WORD 0 ;IF ZERO SYNCH WAS NOT DONE AND DON'T ;JSR TO COMPLETE ;IF NON ZERO A SYNCH WAS DONE AND ;REGISTERS NEED TO BE RESTORED ;ON RETURN FROM COMPLETE. ERBSAV: .WORD 0 ;SAVE THE ADDRESS OF ERRBLK HERE ERRBL2: .WORD 0 ;THIS CONTAINS THE VALUE TO GO TO ERRBLK + 2 BADBIT: .WORD 177774 ;Bad Address bits mask .ENDC ;NE MMG$T .IF NE MM$FSM MTCQ:: .WORD 0 ;FAKE AN MMCQE FOR FILE SUPPORT DRIVEN==MM$UN DVINFO::.REPT DRIVEN .WORD -1 ;D.CFSN - FILE SEQ NUMBER .WORD -1 ;D.CBLK - CURRENT BLOCK NUMBER .WORD -1 ;D.HBLK - HIGHEST BLOCK WRITTEN .BYTE 0 ;D.FTYPE - FILE TYPE, 0=LOOKUP,1=ENTER .BYTE 0 ;D.EOT - POSITIONED PAST EOT FLAG .WORD 0,0,0 ;D.FNAM - RAD50 FILENAME .ENDR .ENDC ;NE MM$FSM CMDINI: .BYTE 0 ;Indicates SPACE command has interrupted .EVEN .IF EQ MM$FSM .DREND MM .IFF .GLOBL $FKPTR,$INPTR .IIF NE MMG$T, .GLOBL $RLPTR,$MPPTR,$GTBYT,$PTBYT,$PTWRD .IIF NE ERL$G, .GLOBL $ELPTR .IIF NE TIM$IT, .GLOBL $TIMIT .ENDC ;EQ MM$FSM SIZE=. SIZED=SIZE-MMSTRT/2 ;+ ; THE FOLLOWING DEFINITIONS ARE FOR FSM'S BENEFIT ;SHD ;- MTDONE == MMDONE MTCQE == MMCQE MT == MM MTLQE == MMLQE MTSTRT == MMSTRT .SBTTL LOAD code ;+ ; LOAD/FETCH code ; ; Entry environment: ; ; R0 = Starting address of handler service routine ; R1 = Address of GETVEC routine (PRO only) ; R2 = $SLOT*2 value (length of $PNAME table in bytes) ; R3 = type of entry ; R4 = address of SY read routine (not used) ; R5 = $ENTRY entry address for this handler ;- .PSECT NONRES,I .ENABL LSB LOAD: .IF NE ; Allocate one UMR for MMX handler when built with FSM. MOV @#$SYPTR,R0 ; RMON base MOV $H2UB(R0),R3 ; R3 = UBVECT pointer MOV @R5,R1 ; Point to handler base MOV R1,-(SP) ; save it for later MOV #NUMRS,R0 ADD #,R1 ; point to FSM's HDR1 label area MOV R5,R4 ; $ENTRY entry address SUB R2,R4 ; $PNAME entry address CLR R2 ; high bits of FSM buffer CALL UB.ALL(R3) ; Allocate the UMR for FSM MOV (SP)+,R3 ; restore handler base in R3 BCS 10$ ; NO LOAD on failure from ALLUMR MOV R1,(R3) ; low 16 bits of UB adrs of HDR1LB MOV R2,(R3) ; high 2 bits of UB adrs of HDR1LB ADD #,R1 ; calculate effective UNIBUS address ADC R2 ; of LABLIO in FSM MOV R1,(R3) ; low 16 bits of UB adrs of LABLIO MOV R2,(R3) ; high 2 bits of UB adrs of LABLIO .ENDC; NE CLC ; Indicate successful LOAD 10$: RETURN .DSABL LSB .SBTTL UNLOAD code ;+ ; UNLOAD/RELEASE code ;- UNLOAD: .IF NE MOV R5,R1 ; Point to $ENTRY entry SUB R2,R1 ; Point to $PNAME entry MOV @#$SYPTR,R4 ; RMON base MOV $H2UB(R4),R5 ; Get H2UB vector entry CALL UB.RLS(R5) ; Release UMR .ENDC; NE CLR R0 ; Ensure clean UNLOAD RETURN .END