.MCALL .MODULE .MODULE MU,VERSION=26,COMMENT=,AUDIT=NO ; COPYRIGHT (c) 1984, 1985, 1986 BY ; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. ; ALL RIGHTS RESERVED. ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED ; ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND 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. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY ; TRANSFERRED. ; ; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE ; AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT ; CORPORATION. ; ; DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS ; SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL. UM$MU = 1 ;We're building MU UM$BOO = 0 ;No multi-port booting .IIF NDF MMG$T MMG$T = 0 ;No XM, if not defined .IIF NE MMG$T MU$32K= 1 ;If XM, need 32KW bound check .SBTTL TMSCP Magtape Handler Functional Description ;+ ; Handler Functional overview ; ; This handler provides support for TMSCP tape class devices interfaced ; via a UDA-50 or compatible port controler. It features: ; ; o Full functional use of TMSCP as required by RT-11 (not ; a subset). ; o Support for TK50 TMSCP tape class device ; o Transparent special function support to facilitate ; unlimited access to all TMSCP features. ; o Multiple unit (port) support as a sysgen option. ; o RT-11 unit translation for port number, CSR, vector, and ; TMSCP unit. (Unit:port:TMSCP unit is fixed, not SET'able ; like DU driver) ; o Plus standard RT-11 reads and writes (of course). ; o By-pass recovery. ; o Error Logging full support. ; ; SET options ; ; SET CSR = nnnnnn ; SET VECTOR = nnn ; SET SUCCES = Y/N ; SET RETRY = nn ; ; Special functions (see below) ; ; Code 377 write EOF ; Code 376 forward one block ; Code 375 backspace one block ; Code 374 write w/ext gap (= WRITE: for compatability w/MT:/MS:) ; Code 373 rewind to load point ; Code 372 rewind then go off-line ; Code 371 write ; Code 370 read ; Code 367 Stream at 100 IPS (IGNORED: for compatability w/MS:) ; Code 360 TMSCP Bypass mode ;- .SBTTL Special Function Codes ;+ ; Special Function Codes MU handler accepts the following codes: ; ---------------------- --------------------------------------- ; 3 .LOOKUP (NFS) ; 2 .DELETE - Illegal !! ; 1 .CLOSE ; 0 .READx/.WRITx (NFS) ; -1 Write EOF (tapemark) ; (Any other code will -2 Forward space ; cause a hard error.) -3 Backspace ; -4 Write with extended gap (== Write) ; -5 Rewind ; -6 Rewind and Offline ; -7 Write a block ; -10 Read a block ; -11 Stream at 100 IPS - Ignored !! ; -20 TMSCP Bypass ; ; The following describes the action taken by the handler for a given code. ; ; Code Action ; 3 .LOOKUP First, initialize command and message buffers. Next, check ; filename at Q.BUF for zero (means a non file structured .LOOKUP.) Then ; examine table entry in case another channel is using this unit. Last, ; see if the SEQNUM argument (= Q.BLK) is zero, meaning do a rewind. ; ; 1 .CLOSE Issue message buffer release command and mark the unit unused. ; ; 0 .READx/.WRITx Read/Write blocks of data on currently-mounted tape. ; .WRITx reports end of file when it sees EOT marker. .READx reports end ; of file only when it reads a tape mark (TM). It ignores EOT marker. ; ; -1 Write a tapemark. ; ; -2 Space FORWARD n (Q.WCNT) blocks til n expires, EOT sensed, or TM read. ; ; -3 Space BACK n (Q.WCNT) blocks til n expires, BOT sensed, or TM read. ; ; -4 Write a block to tape (same as -7, for compatability with MT,MS). ; ; -5 Rewind the tape to BOT. ; ; -6 Rewind to BOT and turn tape unit offline. ; ; -7 Write a block to tape. ; ; -10 Read a block from tape. ; ; -11 Stream at 100 IPS. (IGNORED for compatability with TS05.) ; ; -20 TMSCP Bypass (see below) ; ; 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. ;- .SBTTL Special Function Code 360 (-20) TMSCP Bypass ;+ ; Special Function Code 360 (-20) TMSCP Bypass ; ; Q$BLK = 0 -> DO NOT recover ; = 1 -> recover ; Special function code 360 enables direct access to the TMSCP port. The ; buffer address in the .SPFUN request must point to a 52-word area in ; in the user's job. The first 26 words are used to hold the response ; packet length (in bytes), the virtual circuit identifier and the end ; packet when the command is complete. The second 26 words must be set ; up by the caller to contain a length word, a virtual circuit ; identifier and a valid TMSCP command. ; ; ** Warning: under XM, the 52 word control block must be in low memory. ; ; ----------------------------------------- ; 0 | Response Packet Length | ; ----------------------------------------- ; 1 | Virtual Circuit ID (from UDA) | ; ----------------------------------------- ; 2 | TMSCP Response Buffer (24 Words) | ; ----------------------------------------- ; / / ; / / ; ----------------------------------------- ; 26 | Command Packet Length (48.) | ; ----------------------------------------- ; 27 | Virtual Circuit ID (from Host) | ; ----------------------------------------- ; 28 | TMSCP Command (24 Words) | ; ----------------------------------------- ; / / ; / / ; ----------------------------------------- ; 51 | Last Word of TMSCP Command Packet | ; ----------------------------------------- ; ;- .SBTTL Explanation of Handler Conditionals ;+ ; Handler conditionals. ; ; When the MU$FSM conditional is not = 0, 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. ; ; When the MMG$T (extended memory monitor present) conditional is specified ; the handler will support 18/22 bit I/O. ;- .IF NE MU$FSM ;If file structured ;+ ; DVINFO Table Offsets ;- D.CFSN = 0 ;Current File Sequence Number D.CBLK = 2 ;Current Block Number D.HBLK = 4 ;Highest Block Written D.FTYPE = 6 ;File Type, 1=NFS, 0=LOOKUP,-1=ENTER D.EOT = 7 ;Position is Past EOT Marker Flag D.FNAM = 10 ;RAD50 File Name .ENDC ;NE MU$FSM .SBTTL Error Codes Returned by Magtape Operations ;+ ; LOOKUP, ENTER, Codes found in BYTE 52 after an error. Placed there by ; READx, WRITx. FSM, if present, otherwise MU.SYS has to do it. ; -------------- ; READ, WRITE 0 = Attempt to read/write past EOT (TM) or ; block size too large on a READ ; EOF bit in CSW set ; READ, WRITE 1 = hard error ; hard error bit in CSW set ; ENTER, LOOKUP 2 = Device in Use by another Job ; DEVINUSE bit set and returned in SPUSER ; ENTER, LOOKUP 5 = Illegal Argument ; ILLARG bit set and returned in SPUSER ; SPFUNS ; ------ ; If EOF set in Byte 52: R5 : 1= hard error, 20000 = eof ; R4 : additional information about error. ; ; On return from error, whatever is in R4 is placed in Q$BLK, additional info ; may be placed in @Q$BLK+2, mainly the number of words not read or blocks not ; spaced. ; R5 R4 @Q$BLKN+2 ; SPFUN Byte 52 Word 1 Word 2 ; 0=eof,20000 in csw ERBSAV ; 1=hderr, 1 in csw ERRBL2 ;----------------------------------------------------------------------------- ; 370, 371, 375, 376 0 1 = EOF (TM) 375, 376 ; 370, 371, 375, 376 0 2 = EOT (no TM) 375, 376 ; 370, 371, 375, 376 0 3 = EOT & EOF 375, 376 ; 375 0 4 = BOT (no TM) 375 ; ; ALL 1 0 = Drive Dependent Error ; ALL 1 1 = Unit not Available ; 370, 371, 377 1 2 = Position Lost ; 370, 371, 377 1 3 = Non existant Memory ; 370, 371, 377 1 4 = Unit Write Locked ; 370 1 5 = Last record read had ; more information 370 ; 370 1 6 = Short block read 370 ;- DRVDEP = 0 ;Drive dependent error UNAVIL = 1 ;Unit unavailable or offline POSLST = 2 ;Position lost NOMEM = 3 ;Non - existent memory WRTLOC = 4 ;Write locked RECERR = 5 ;More infor in record SMLREC = 6 ;Short record read EOFFND = 1 ;EOF found via Tape Mark EOTFND = 2 ;EOT found no tape mark EOFEOT = 3 ;EOT and EOF found BOTFND = 4 ;Bottom of tape found, no tape mark MAXBLK = 77777 ;Max block count for fwd/bkwd space .SBTTL TMSCP TK50 Commands ;+ ; TMSCP TK50 Commands Used by RT-11 ; ------------------- ------------- ; Abort Yes ; Access No ; Available Yes ; Compare Host Data No ; Erase No ; Get Command Status No ; Get Unit Status No ; Online Yes ; Read Yes ; Reposition Yes ; Set Controller Characteristics Yes ; Set Unit Characteristics No ; Write Yes ; Write Tape Mark Yes ; ; ; TMSCP Commands That Will NOT Be Implemented: ; -------------------------------------------- ; ; Compare Controller Data This is not required in the TK50 ; Issuance of this command is a NOP ; and will return SUCCESS ; ; Determine Access Paths The TK50 can only communicate with ; one host at a time due to physical ; design constraints. Issuance of this ; command is a NOP and will return ; SUCCESS ; ; Erase Gap NO Not Implemented in Controller ; Returns SUCCESSFUL completion ; ; Flush The TK50 does not support caching. ; Issuance of this command is a NOP ; and will return SUCCESS ;- .SBTTL TMSCP Specific Protocol Definitions ;+ ; Only TMSCP specific mnemonics are defined here. Mnemonics common to MSCP and ; TMSCP are defined in module UM.MAC which is .INCLUDEd in DU.MAC and TU.MAC. ;- ;+ ; Control Packet Opcodes ;- OP.CCD =: 21 ;COMPARE CONTROLLER DATA Command OP.FLU =: 23 ;FLUSH Command OP.ERG =: 26 ;ERASE GAP Command OP.WTM =: 44 ;WRITE TAPE MARK Command OP.REP =: 45 ;REPOSITION Command ;+ ; NOTE: Command opcode bits 3 thru 5 indicate the command class which is ; encoded for TMSCP as follows: ; ; 000 Immediate command ; 001 sequential commands ; 010 sequential commands ; 100 sequential commands ; ; Write command opcodes bit 0 position is always a zero. ; ; Read command opcodes bit 0 position is always a one. ; ; NOTE: End packet opcodes are formed by ORing the end packet flag to the ; command opcode. For example, OP.RD!OP.END = OP.RD endcode. If the ; endcode is OP.END alone then the command was unknown. If the endcode is ; OP.SEX!OP.END then the command ended with a serious exception. ;- ;+ ; Generic Command Modifiers: ;- MD.CSE =: 20000 ;Clear serious exception MD.SWP =: 4 ;Enable Set Write Protect MD.NXU =: 1 ;Next Unit MD.RWD =: 2 ;Rewind ; (Will cause REWIND then SPACE FORWARD ; number of tapemarks and records found ; in P.RECC and P.TMGC. Make sure these ; fields ARE ZERO if plain old REWIND ; is desired.) MD.OBC =: 4 ;Object Count ; (If set causes count of records and ; tape marks - i.e. things written.) MD.REV =: 10 ;Reverse MD.UNL =: 20 ;Unload MD.EXC =: 40 ;Exclusive Access MD.IMM =: 100 ;Immediate Completion MD.DLE =: 200 ;Detect LEOT ;+ ; End Message Flags ;- EF.SEX =: 20 ;Serious Exception EF.EOT =: 10 ;End of Tape encountered EF.PLS =: 4 ;Position Lost (subject to firmware change) ;+ ; Unit Flags ;- UF.VSU =: 20 ;Variable Speed unit UF.VSS =: 40 ;Variable Speed Mode Suppression ;+ ; Error Log Message Format Codes ;- FM.TPE =: 5 ;Tape transfer errors FM.STI =: 6 ;STI communication or command failure FM.DEL =: 7 ;STI drive error log FM.FEL =: 10 ;STI formatter error log ;+ ; Tape Format Flag Values ;- TF.800 =: 1 ;NRZI 800 bpi TF.PE =: 2 ;Phase Encoded 1600 bpi TF.GCR =: 4 ;Group Code recording 6250 bpi TF.BLK =: 10 ;Cartridge Block Mode (subject to hdw change) ;+ ; Status and Event codes ;- ; 0 ;Status/event code bit offset ; 5 ;Status/event code field size ST.SUB =: 40 ;Sub-code multiplier ST.ABO =: 2 ;Command aborted ST.MFE =: 5 ;Media Format Error ST.CMP =: 7 ;Compare Error ST.HST =: 11 ;Host buffer access error ST.CNT =: 12 ;Controller error ST.FMT =: 14 ;Formatter error ST.BOT =: 15 ;BOT Encountered ST.TM =: 16 ;Tape mark encountered ; 17 ;UNASSIGNED ST.RDT =: 20 ;Record data truncated ST.POL =: 21 ;Position lost ST.SEX =: 22 ;Serious exception ST.LED =: 23 ;LEOT detected ; 24-16 ;UNASSIGNED ST.DIA =: 37 ;Message from an internal diagnostic ST.EOT =: 2000 ;SUCCESS and physical EOT found, see next page .SBTTL TMSCP Specific Status/Event Sub-Code Values ;+ ; NOTE: The combination of a status or event code with a sub-code should be ; expressed as: ; (sub-code * ST.SUB) + status/event code) ; ; Success status/event sub-codes: ; ; 0 normal ; 100 still connected ; 200 duplicate unit number ; 400 already online ; 1000 still online ; 1010 still online/unload ignored ; 2000 EOT encountered ; ; Invalid Command status/event sub-codes: ; ; 1 invalid message length ; other invalid command sub-code values should be referenced as ; follows: (note that this is combined with the status code) ; offset*256.+code ; where offset is the command message ofset symbol for the field ; in error, and code is the symbol for the invalid command ; status code. ; ; Unit-offline status/event sub-codes: ; ; 3 unit unknown or online to another controller ; 43 no media mounted or disabled via switch setting ; 103 unit is inoperative ; 203 duplicate unit number ; 403 unit disabled by field service or internal diagnostic ; ; Write protected status/event sub-codes: ; ; 20006 unit is hardware write protected ; 10006 unit is software write protected ; ; Data error status/event sub-codes: ; ; 10 log gap encountered ; 350 unrecoverable read error ; many controller and/or drive/formatter type dependent ; ; Controller error status/event sub-codes: ; ; 12 reserved for command timeout/retry limit exceeded ; many controller and/or drive/formatter type dependent ; ; Drive error / Formatter error / Message from internal diagnostic / ; Host buffer access error / status/event sub-codes: ; ; many controller and/or drive/formatter type dependent ;- .SBTTL TMSCP Command Packet Offsets and Field Lengths ;+ ; ONLINE and SET UNIT CHARACTERISTICS Command Packet Offsets and Field Lengths ;- P.FORM =: 40 ;2 Format P.SPED =: 42 ;2 Speed ;+ ; REPOSITION Command Packet Offsets and Field Lengths: ;- P.RECC =: 14 ;4 Replacement block number - # OF RECORDS P.TMGC =: 20 ;4 Tape Mark Count or N/A - # OF TAPE MARKS ;+ ; End and Attention Message Offsets and Field Lengths: ; ; ACCESS, COMPARE HOST DATA, READ, REPOSITION, WRITE, WRITE TAPE MARK end ;- P.POS =: 34 ;4 Position (Object count) # OF THINGS ; WRITTEN TO THE TAPE ;+ ; ACCESS, COMPARE HOST DATA, READ end ;- P.TRBC =: 40 ;4 Tape record byte count ;+ ; GET UNIT STATUS End Packet Offsets and Field Lengths: ;- P.MEDI =: 34 ;4 Media Identifier P.FORM =: 40 ;2 Tape format P.SPED =: 42 ;2 Speed P.FMEN =: 44 ;2 Format Menu ;+ ; ONLINE and SET UNIT CHARACTERISTICS End Packet Offsets and Field Lengths: ;- P.MEDI =: 34 ;4 Media type identifier P.FORM =: 40 ;2 Tape format P.SPED =: 42 ;2 Speed P.MXWR =: 44 ;4 MAXIMUM WRITE record size P.NREC =: 50 ;2 Noise Record ;+ ; REPOSITION end ;- P.RCSK =: 14 ;4 Records Skipped P.TMSK =: 20 ;4 Tape Marks Skipped ;+ ; Error Log Message Packet Offsets and Field Lengths ;- L.FMTD =: 42 ;2 Format dependent L.GPCT =: 44 ;4 Position (object count) L.FSVR =: 50 ;1 Formatter software version L.FHVR =: 51 ;1 Formatter hardware version ;+ ; STI Communication Errors Error Log message Offsets ;- ; 42 ;2 Reserved L.SDI =: 54 ;12 STI UNSUCCESSFUL Response ;+ ; STI Formatter Error Error log Message Offsets ;- ; 42 ;2 Reserved L.STI =: 54 ;24 STE GET EXTNDED FORMATTER STATUS Response ;+ ; STI Drive Error Error Log Message Offsets ;- L.STI =: 54 ;62 STI GET EXTENDED DRIVE STATUS Response ;+ ; Tape Identifier Values ; ; MU TA78 066550,010116 PE/GCR, 125 ips start/stop ; MU TK50 066550,130062 100 MB Cartridge Drive ; MU TA81 066550,010121 STI version of the TU81 ;- ;+ ; Miscellaneous declarations ;- TAPEID =: 1 ;Virtual circuit id for TMSCP .INCLUDE "SRC:UM.MAC" ;Include the code common with DU .TITLE MU - TMSCP Tape Class Handler .SBTTL ************************* .SBTTL * MU * .SBTTL ************************* ; Now set the AUDIT trail .AUDIT .UM ;Universal (T)MSCP Class Handler .AUDIT .MU ;TMSCP Port Handler .SBTTL RT-11 Software Definitions ;+ ; Define RT-11 handler codes, vectors and CSRs. ;- ENTER = 4 ;ENTER LOOKUP = 3 DELETE = 2 ;(Illegal) CLOSE = 1 REDWRT = 0 ;READ/WRITE ;+ ; Special Functions ;- WRTEOF = SP.WTM ;Write tape mark FWDSPC = SP.FWD ;Forward space BKSPC = SP.BKS ;Backspace REWIND = SP.REW ;Rewind OFFLINE = SP.ORW ;Rewind and go Offline WRITEPHY= SP.WRT ;Write physical READF = SP.RD ;Read physical STR100 = SP.STR ;Stream at 100 IPS (ignored for compatability) BPASS = SP.BYP ;TMSCP Bypass ;+ ; Errors And Other Useful Things ;- ILLARG = RC.INV ;Illegal argument(lookup) DEVINUSE= RC.DIE ;Device in use by other job(lookup) CSWEOF = 20000 ;End of file indicator bit in csw SPUSR = 272 ;Rmon offset of special dev err word UNIT = 3400 ;Unit # bits in queue element word QCOMP = 270 ;Address of i/o completion mgr.(fixed offset) .SBTTL USRFN - Dispatch for USR Functions ;+ ; USRFN ; ; Control comes here from the common code, when it has been determined that ; the function is positive, non-zero (i.e. a USR function). ; ; R5 -> Current queue element ; R4 = Function (Q$FUNC) ; ; .UTTAB -> Unit Translation Table entry for this unit ; X.UTTAB -> " (if XM) ;- .ENABL LSB USRFN: MOVB Q$JNUM(R5),R2 ;Get job # and unit # BIC #^C,R2 ;We only want the job # bits .IF NE MMG$T MOV X.UTTAB,R3 ;R3 -> job # of owner of this unit. .IFF ;NE MMG$T MOV .UTTAB,R3 ;R3 -> job # of owner of this unit. .ENDC ;NE MMG$T .ASSUME UT.JOBN EQ 1 INC R3 ; (it's high byte) CMPB #LOOKUP,R4 ;Is function .LOOKUP? BNE 40$ ;No, it's an illegal code, give error. ;+ ; It's a .LOOKUP, check if Non-File-Structured (NFS). (I don't think this next ; check is needed in file-structured handler: only NFS lookups are passed from ; FSM. Hardware only handler must check, since it gets all lookups from user.) ;- .IF NE MMG$T ;If XM .IF EQ MU$FSM ;If not file structured MOV H$CQE,R4 ;Get real queue element CALL @H$GTBYT ;Get half of file name TSTB (SP)+ ;NFS .Lookup? BNE 30$ ;If NE, Error, for HH, must be NFS CALL @H$GTBYT ;Get second half TSTB (SP)+ ;NFS .Lookup? BNE 30$ ;Not NFS and must be for HH .IFF ;EQ MU$FSM ;If file structured MOV Q$BUFF(R5),R4 ;Q$BUFF from hi mem copy of q element .HP1EX P1LOW ; (Map to low memory) MOV @R4,R4 ;Is there something in Q.BUFF? .HP1EN ; (Mark end of block) TST R4 ; BNE 40$ ;Yes: not NFS .Lookup & must be for HH .ENDC ;EQ MU$FSM .IFF ;NE MMG$T ;If not XM TST @Q$BUFF(R5) ;Is there something in Q.BUFF? BNE 40$ ;Yes: not NFS .Lookup & must be for HH .ENDC ;NE MMG$T CMPB @R3,#UT.AVAL ;Unit available? BEQ 10$ ;Yes, go mark it ours MOV #RC.DIE,R0 ;No, device in use. SPERR: MOV @#SYSPTR,R1 ;Point to RMON MOV R0,SPUSR(R1) ;Return error .IF NE MU$FSM ;If file structured magtape .IF NE MMG$T ;If not XM .HP1EX P1LOW ; (Map to low memory) CALLR @#LRET6 ;Return to low for RESTOR call $REL .-2 LRET6 UMR ; ... .HP1EN ; (Mark end of block) ;********************************************************************* UMPSECT ;********************************************************************* LRET6: MOV 2(SP),SP ;Fix stack ADD #6,SP ;Pop some arguments .IFTF ;NE MMG$T ;If XM CALL RESTOR ;Restore CPU state CALLR $DONE ;Immediate abort .IFT ;NE MMG$T ;********************************************************************* UMXPSECT ;********************************************************************* .ENDC ;NE MMG$T .IFF ;NE MU$FSM ;If hardware handler only BR 50$ ;JMP MTDONE .ENDC ;NE MU$FSM 10$: CLR Q$WCNT(R5) ;For HH, zero word count to say NFS MOVB R2,@R3 ;Store job # in unit translation table ; to mark unit taken. .IF NE MU$FSM ;If file structured BR 50$ ;Let FSM tell us what's next .IFF ;NE MU$FSM ;If not file structured 20$: MOV @R5,R1 ;Get seq # .ASSUME Q$BLKN EQ 0 BEQ 60$ ;0 gets a REWIND BGT 30$ ;PLUS is an Invalid Argument error INC R1 ;Is sequence number = -1? BEQ 50$ ;Yes, no rewind, all done 30$: MOVB #UT.AVAL,@R3 ;Mark unit available MOV #RC.INV,R0 ;Code for Invalid Argument BR SPERR ;Go issue error .ENDC ;NE MU$FSM KLOSE: MOVB #UT.AVAL,UT.JOBN(R3) ;CLOSE function: mark unit available BR 50$ ;And finish up ;+ ; Issue Hard Error. If file support is present, then R0-R3 must be ; restored because we may be running at .INTEN level. ;- 40$: BIS #HDERR$,@-(R5) ;Set hard error bit in CSW word FNDISP: ;Come here to ignore TS05 .SPFUN 50$: .IF NE MU$FSM ;If file structured .IF NE MMG$T ;If not XM .HP1EX P1LOW ; (Map to low memory) CALLR @#LRET7 ;Return to low for RESTOR call $REL .-2 LRET7 UMR ; ... .HP1EN ; (Mark end of block) ;********************************************************************* UMPSECT ;********************************************************************* LRET7: MOV 2(SP),SP ;Fix stack ADD #6,SP ;Pop some arguments .IFTF ;NE MMG$T ;If XM CALL RESTOR ;Restore CPU state CALLR LMUDONE ;Lets go home .IFT ;NE MMG$T ;********************************************************************* UMXPSECT ;********************************************************************* .ENDC ;NE MMG$T .IFF ;NE MU$FSM ;If hardware handler CALLR MUDONE ;Lets go home .ENDC ;NE MU$FSM RERWRT: .IF NE MMG$T ;If XM MOV H$CQE,R5 ;R5 -> hi memory copy of queue element .IFF ;NE MMG$T .IF NE MU$FSM ;If file structured MOV MUCQ,R5 ;R5 -> fake queue element .IFF ;NE MU$FSM ;If hardware handler MOV UMCQE,R5 ;R5 -> queue element .ENDC ;NE MU$FSM .ENDC ;NE MMG$T BR RWRT1 ;Redo the Q$FUNC .IF EQ MU$FSM 60$: MOVB #SP.REW,R4 ;Set up for a Rewind .BR RWRT ;Go to it .ENDC ;EQ MU$FSM .SBTTL RWRT - Handle READ/WRITE and Most .SPFUNs ;+ ; RWRT - Handle READ/WRITE and most .SPFUNs ; RWRT1 - Redo function for some error cases (entry from interrupt service) ; ; The following routine validates the queue element code. ; ; -1 >= R4 >= -8 Code is a legal .SPFUN ; R4 =0 It's .READ/.WRITE, and is converted to .SPFUN read or write ; based on the sign of the word count (+ = read). ; else Illegal function code: hard error is issued ;- RWRT: MOV R4,(PC)+ LASCOM: .WORD 0 ;Last command stored here RWRT1: MOV LASCOM,R4 ;Get the command CMPB #SP.RD,R4 ;Is the function legal? BLOS 90$ ;If LOS, yes TST R4 ;.READ or .WRITE? BNE 40$ ;If NE, no ;+ ; Convert to proper format for .READ and .WRITE ;- MOVB #SP.RD,R4 ;Assume .READ .ASSUME Q$BLKN EQ 0 CLR (R5) ;0->Q$BLKN (ERRBLK),NO error reporting TST Q$WCNT(R5) ;.READ? BPL 70$ ;Branch if yes NEG Q$WCNT(R5) ;Make count positive INC R4 ;Change code to write .ASSUME SP.WRT EQ SP.RD+1 BR 80$ ;Skip next 70$: COM NFSREAD ;Say non-file-structrd READ being done 80$: MOV R4,LASCOM ;Store function we do (for retry) .IF NE MU$FSM ;If file structured handler .IF EQ MMG$T MOV R4,CODE ;Save code of new request .IFF ;EQ MMG$T .HP1EX P1LOW ; (Map to low memory) MOV R4,@#CODE ;Save code of new request $REL .-2 CODE UMR ; ... .HP1EN ; (Mark end of block) .ENDC ;EQ MMG$T .ENDC ;NE MU$FSM 90$: ADD #FUNTAB-TABLE,R4 ;Make the code positive MOV Q$WCNT(R5),R1 ;Get word count CALL DISPCH ;Go jump to proper routine .BR TABLE ; (TABLE must be next: return addr on ; stack used as pointer into tables) .DSABL LSB ;+ ; The next two tables must be kept in order so that the following routines ; will be found properly. ;- TABLE: .BYTE REDEF-NULLFN ;Address of read routine .BYTE WRIT-NULLFN ;Address of write routine .BYTE OFFLN-NULLFN ;Address of rewind/offline .BYTE RWND-NULLFN ;Address of rewind .BYTE WRIT-NULLFN ;374 write-gap treated as write .BYTE BCKSPC-NULLFN ;Address of backspace routine .BYTE FRSPC-NULLFN ;Address of forward space .BYTE WRITM-NULLFN ;Address of tape mark routine FUNTAB: .BYTE OP.RD ;Read .BYTE OP.WR ;Write .BYTE OP.AVL ;Rewind & Offline, available & unload .BYTE OP.REP ;Rewind, reposition & rewind .BYTE OP.WR ;Write gap is treated as Write .BYTE OP.REP ;Backspace, reposition and reverse .BYTE OP.REP ;Forward space, reposition .BYTE OP.WTM ;Write tapemark .EVEN .SBTTL DISPCH - Dispatcher Routine ;+ ; DISPCH ; ; This routine uses the special function code, which has been translated to a ; positive number (0-7) as a byte offset into two tables. The first (TABLE) is ; the address of a routine to do function specific setup, like word count to ; byte count adjustment for read/write. The second table (FUNTAB) is the TMSCP ; command which the RT-11 special function translates into (SP.WRT->OP.WR). ; ; For example, if the special function is a rewind, on entry, the rewind code ; (373 or -5) has been converted to a positive offset (3) into the tables. The ; table entries for this value are 'RWND-NULLFN' (the rewind specific routine ; which sets the rewind bit in the TMSCP command buffer), and 'OP.REP' (the ; TMSCP command for Reposition, which, with the rewind bit set, will cause the ; tape to rewind to BOT). The equivalent inline code, would be: ; ; MSCP OP.REP ; DO RWND,THEN,MUDONE ; Input: ; R4 = positive byte offset for the desired function ; (SPFUNS 370-377 have been converted to offsets 0-10) ; (SP) = Address of TABLE ;- DISPCH: MOVB R4,MCODE ;Save for MUINIT later ADD (SP)+,R4 ;Add addr of TABLE to function offset MOVB @R4,NULLFN ;Store address of function specific ; routine for 'DO' macro MOVB FUNTAB-TABLE(R4),WHAT ;Store command for TMSCP buffer setup JSR R5,GETCBF ;Equivalent to: MSCP OP.xxx WHAT: .WORD 0 ; TMSCP funct from FUNTAB (eg: OP.WRT) MOV R4,R2 ;COORD uses R4, so save it in R2! CLR BCKTM ;Init internal Backup Tape Mark flag MUDO: DO NULLFN,THEN,MUDONE ;Becomes, e.g.: DO WRIT,then,MUDONE NULLFN =: .-2 ; or, DO BCKSPC,then,MUDONE .ASSUME NULLFN EQ MUDO+6 .SBTTL xxxx - Final Setup Routines for Specific I/O Operations ;+ ; All commands come here from DISPCH for final setup and execution. ;- .ENABL LSB WRIT: ;Write REDEF: ;Read .IF EQ MMG$T MOV OLDBA,P.BUFF(R2) ;Fill in low 16 bits of buffer address .IFF ;EQ MMG$T ;If XM .HP1EX P1LOW ; (Map to low memory) MOV @#OLDBA,R4 ;Get low 16 bits of buffer address $REL .-2 OLDBA UMR ; ... MOV @#EXTADR,R5 ;Get high bits $REL .-2 EXTADR UMR ; ... .HP1EN ; (Mark end of block) MOV R4,P.BUFF(R2) ;Fill in low 16 bits of buffer address MOV R5,P.BUFF+2(R2) ;Fill in high bits .ENDC ;EQ MMG$T ASL R1 ;Turn word count into byte count .IF NE P.BCNT-P.RECC ;Combine some code TST R1 BGE 10$ MOV #MAXBLK,R1 ;Highest positive number 10$: MOV R1,P.BCNT(R2) ;Fill in byte count BR FNSHUP ;Finish up then do command .IFF ;NE P.BCNT-P.RECC .ASSUME P.BCNT EQ P.RECC ;Since these are the same we can BR FRSPC ; use common code .ENDC ;NE P.BCNT-P.RECC ; *Backspace* BCKSPC: BIS #MD.REV,P.MOD(R2) ;Reverse mode INC R1 ;Is this the -1 from FSM? (=backup TM) BNE 20$ ;If NE, no INC R1 ;Make R1 = 1 (so 0 stored in P.RECC) MOV R1,P.TMGC(R2) ;Say 'backup 1 tape mark' COM (PC)+ ;Set backup tape mark flag BCKTM: .WORD 0 ; -1 => backup tape mark issued 20$: DEC R1 ;Get 'correct' value back .BR FRSPC ; *Forward space* FRSPC: MOV R1,P.RECC(R2) ;# records to space (or bytes to r/w) BGE FNSHUP ; MOV #MAXBLK,P.RECC(R2) ;Highest positive # records (or bytes) BR FNSHUP ;Finish up then do command ; *Offline* OFFLN: BIS #MD.UNL,P.MOD(R2) ;Available Command ; *Write tapemark* WRITM: BR FNSHUP ;Finish up then do command ; *Rewind* RWND: BIS #MD.RWD,P.MOD(R2) ;Set rewind mode FNSHUP: MOV R2,R4 ;POLL expects R4 -> cmd buffer MOV P.RECC(R2),(PC)+ ;Save count for space/read functs RBCNT: .WORD 0 ; # Records/Bytes (space/read functs) .ASSUME P.RECC EQ P.BCNT RETURN ;Return, POLL routine starts command. .DSABL LSB .SBTTL UM$AB1 - Abort Entry Point ;+ ; UM$AB1 - Abort entry point. ; This code halts any operation in progress and updates the inuse table. ; It sets flags to keep track of whether abort is in progress, and ; whether there is an outstanding command that must be aborted. These ; are needed so that when the response messages from the outstanding ; command and the abort command cause interrupts, we can keep track of ; when to release the queue element, and we don't return it twice. Like- ; wise, the code checks whether this is a second call to the abort ; entry point (either for this job or for another job) and insures that ; the interrupt counting doesn't get screwed up. ;- .ENABL LSB UM$AB1: .IF NE MMG$T ;If XM MOV 2(SP),SP ;Restore stack pointer CMP (SP)+,(SP)+ ;Pop some arguments off (R1 & KISAR1) MOV (SP)+,R0 ;Restore R0 (not restored: we JMP'd) .IFTF ;NE MMG$T CLR BCKTM ;0->backspace tape mark interrupt flag CLR -(SP) ;Clear stack flag => nothing to abort .IFT ;NE MMG$T .HP1EX P1LOW ; (Map to low memory) MOV @#UMCQE,R5 ;R5 -> current queue element, if any. $REL .-2 UMCQE UMR ; ... .HP1EN ; (End of block) TST R5 ;Is there a current queue element? BEQ 20$ ;If EQ no active q element MOV H$CQE,R5 ;Yes there is, R5 -> Hi copy of CQE. .IFF ;NE MMG$T ; MOV UMCQE,R5 ;R5 -> current queue element, if any. BEQ 20$ ;If EQ no active q element .ENDC ;NE MMG$T MOVB Q$JNUM(R5),R5 ;Now get job # BIC #^C,R5 ;Clear some bits ASR R5 ;Shift ASR R5 ; into ASR R5 ; place CMP R5,R4 ;Is aborting job active? BNE 20$ ;If NE, no .IF NE MU$FSM ;If file structured .IF EQ MMG$T ;If not XM MOV DVTBL,R5 ;Point to device table .IFF ;EQ MMG$T ;If XM .HP1EX P1LOW ; (Map to low memory) MOV @#DVTBL,R5 ;Point to device table $REL .-2 DVTBL UMR ; ... .IFTF ;EQ MMG$T BEQ 10$ ;If EQ, not initialized yet MOV #-1,@R5 ;Mark tape position lost MOV (R5)+,@R5 ;Mark current block number lost 10$: .IFF ;EQ MMG$T ;If XM .HP1EN ; (End of block) .ENDC ;EQ MMG$T .ENDC ;NE MU$FSM TST ABTFLG ;Abort flag already set? (2nd call?) BNE 50$ ;If NE, yes, nothing much to do... INC @SP ;No, set stack flag => got to abort MOV #-1,(PC)+ ;Set flag to abort current command ABTFLG: .WORD 0 ; -1 => abort current command .IF EQ MMG$T ;If not XM CLR UMFBLK+2 ;Cancel the .FORK, if it's pending .IFF ;EQ MMG$T ;If XM .HP1EX P1LOW ; (Map to low memory) CLR @#UMFBLK+2 ;Cancel the .FORK, if it's pending $REL .-2 UMFBLK+2 UMR ; ... .HP1EN ; (End of block) .ENDC ;EQ MMG$T 20$: .IF EQ MMG$T ;If not XM .ADDR #,R5 ;Get unit table (job owner byte) .IFF ;EQ MMG$T MOV #,R5 ;Get unit table (job owner byte) $REL .-2 XUTTAB+UT.JOBN UMX HIGH ; ... .IFTF ;EQ MMG$T MOV R5,-(SP) ;Put address of .IFT ;EQ MMG$T ADD #UTTBND-UTTAB-UT.JOBN,@SP ; table end on stack .IFF ;EQ MMG$T ADD #XUTTBND-XUTTAB-UT.JOBN,@SP ; table end on stack .ENDC ;EQ MMG$T 30$: CMPB R4,(R5) ;Does this unit belong to this job? BNE 40$ ;Branch if no MOVB #UT.AVAL,(R5) ;Mark unit unbusy 40$: ADD #UT.ESZ,R5 ;Get next entry CMP R5,@SP ;End of table? BLO 30$ ;Branch if no TST (SP)+ ;Pop stk junk 50$: TST (SP)+ ;Check stack flag, must we abort? BEQ 60$ ;If EQ, nope ADD ABTFLG,INTEXP ;Abort last cmd? (Must be 1 instr.!!) BCC ABRTND ;If CC, no need, or it's already done. DO ABRT,THEN,UMEXIT ;Go abort it, then return to RMON. ;(UMEXIT won't be executed at @NEXT: a ; .DRFIN will be done after .DRAST) ABRTND: CLR INTEXP ;Clear count of interrupts expected. .IF EQ MMG$T ;If not XM 60$: RETURN ;Just return .IFF ;EQ MMG$T 60$: CALLR HRET ;Just return (back to low before RTS) .ENDC ;EQ MMG$T .SBTTL ABRT - Abort An Outstanding Command ;+ ; ABRT - There's an outstanding command to be aborted. ; ; We must wait until the command descriptor slot is returned to us, and ; then issue the abort command. In general the descriptor should always ; be free, but protocol dictates we check. We return to a different part ; of the POLL routine (ABPOLL), since we've already adjusted INTEXP. ;- ABRT: .IF EQ MMG$T ;If not XM TST CRING+2 ;Can we use the command buffer? .IFF ;EQ MMG$T ;If XM TST XCRING+2 ;Can we use the command buffer? .ENDC ;EQ MMG$T BMI ABRT ;If MI, no, wait till it's available MOV (PC)+,-(SP) ;Get last command ref number for abort CUROPT: .WORD 0 ; Last command ref number stored here MSCP OP.ABO ;Get ABORT command CLR P.MOD(R4) ;MD.CSE illegal on ABORT, so clear it. MOV (SP)+,P.OTRF(R4) ;Outstanding command number ADD #ABPOLL-POLL,@SP ;Special entry to POLL for Abort cmd. RETURN ;Return, POLL will get it started. .DSABL LSB .SBTTL UMERR - Handle Interrupt Level Errors ;+ ; UMERR - Handle interrupt level errors. ; ; The interrupt entry point will transfer control here if there is an ; error of some kind that it cannot fix by doing an ONLINE. ; ; R1 = P.STS of command masked to only major status bits (37) ; ; NOTE: R1 may be ZERO, in which case we could be doing an internal back ; tape mark and it succeeded, or, it's a READ function, and the ; byte counts requested and transferred are not equal. We'll catch ; these at the individual command specific routines, below. ;- .ENABL LSB UMERR: CMPB #OP.END!OP.ONL,P.OPCD(R5) ;Was it an Online command? BEQ 30$ ;Yes, hard error CMPB #ST.OFL,R1 ;Is status = offline? BNE 40$ ;No, check command CMPB #OP.END!OP.AVL,P.OPCD(R5) ;Is this an offline rewind? BEQ GOTOFF ;Then go finish it. DEC RETRY ;Should we try again? BLE 20$ ;No ;;;10$: DO IONLIN,THEN,RERWRT ;Yes, go online then redo Q$FUNC 10$: DO IONLIN,THEN,HSTART ;Yes, go online then redo Q$FUNC ;(Does not return) ;+ ; Get 'Device in use' error on NFS Lookup if do rewind, it errors, & we retry. ; To fix, either change above to RERWRT, or fix UTTAB to allow NFS Lookup ; on a unit we already own. (I don't like either of those soln's.) ;- 20$: MOV #UNAVIL,R4 ;Say we're offline and unavailable BR ABORT ;Leave ;+ ; Error during Online cmd: hard error ;- 30$: BR UMHERR ;Hard error ;+ ; Dispatch, based on last command, to appropriate error routine ;- 40$: CALL GOT$IT ;Go see what routine we want .BR GOTTAB ;+ ; GOTTAB - Table for dispatching to correct routine ; ; Format of entry: ; .byte GOTRD - GOTTAB - (.-GOTTAB) ;.-GOTTAB= positive funct code (MCODE) ; which becomes ; .byte GOTRD - . ;- GOTTAB: .BYTE GOTRD - . ;Read op.rd .BYTE GOTWR - . ;Write op.wr .BYTE GOTOFF - . ;Rewind and offline op.avl .BYTE GOTREW - . ;Rewind op.rep .BYTE GOTWR - . ;Write ext gap = Write op.wr .BYTE GOTBAC - . ;Backspace op.rep .BYTE GOTFOR - . ;Forward space op.rep .BYTE GOTTM - . ;Tape mark op.wtm .DSABL LSB .ENABL LSB GOT$IT: CLR R4 ;Error bits for user (0=>no xtra info) CMPB #ST.POL,R1 ;Position Lost? (Status return) BEQ 20$ ;Yes CMPB #ST.SEX,R1 ;Serious Exception? BEQ 10$ ;Yes CMPB #ST.CMD,R1 ;Invalid Command? BEQ 10$ ;Yes .ASSUME ST.HST EQ ST.DAT+1 ;Check .ASSUME ST.CNT EQ ST.HST+1 ; these .ASSUME ST.DRV EQ ST.CNT+1 ; all .ASSUME ST.FMT EQ ST.DRV+1 ; together CMPB R1,#ST.DAT ;Data, Host Buffer Access, Control, ; Drive, or Formatter error? BLO 40$ ;If LO, no, go see what it is CMPB R1,#ST.FMT ;Well, is it one of these? BHI 40$ ;No, go see what it is 10$: BITB #EF.PLS,P.FLGS(R5) ;Position Lost? (End flag return) BEQ 30$ ;No 20$: MOV #POSLST,R4 ;Say we're lost 30$: TST (SP)+ ;Clear stack junk BR ABORT ;Leave now 40$: ADD (PC)+,@SP ;Modified function code + table addr. MCODE: .WORD 0 ; Modified code from RWRT (byte!) MOV @SP,-(SP) ;Make a copy of it MOVB @(SP)+,-(SP) ;Get offset to proper routine CLRB 1(SP) ;Its only a byte ADD (SP)+,@SP ;Offset + table addr + code = routine CALLR @(SP)+ ;Go do routine GOTOFF: CMPB #ST.OFL,R1 ;How bout an offline, rewind? BNE GOTERR ;No, must be a problem, RETRY .IF NE MMG$T ;If XM CLR XISTEP ;Yes, must reinit the port next time .IFF ;NE MMG$T ;If not XM CLR ISTEP ;Yes, must reinit the port next time .ENDC ;NE MMG$T ; we are used in case someone flipped ; the controller off. CALLR GO$ON ;Go JMP @NEXT GOTTM: ;Tape mark GOTWR: ;Write CMPB #ST.WPR,R1 ;Write Protected? BNE GOTBAC ;No MOV #WRTLOC,R4 ;Yes, say we're write locked BR ABORT ;Hard error exit GOTBAC: ;Backspace BIT #ST.MSK,R1 ;Is this backup tape mark? (success) BNE GOTFOR ;If NE, no MOVB #ST.TM,R1 ;Yes, say we hit a tape mark. GOTFOR: ;Forward space CMPB #ST.BOT,R1 ;BOT? BNE 60$ ;No, skip some read stuff BIS #BOTFND,R4 ;Yes, say BOT found BR GOTERR ;+ ; Did we read all that was in record, or, did we try to read too much? ; ; R1 = status bits (0 -> short record, which TMSCP calls 'success') ; R2 = command buffer ; R5 = message buffer ; R4 = exception conditions ;- GOTRD: CMPB #ST.RDT,R1 ;Record data truncated? BNE 50$ ;No, skip next MOV #RECERR,R4 ;Yes, say its a record error BR ABORT ;Report condition 50$: BIT #ST.MSK,R1 ;Did we try to read too much? BNE 60$ ;No, skip next MOV RBCNT,R2 ;Yes, get requested # bytes to read SUB P.BCNT(R5),R2 ;Minus actual # bytes read ASR R2 ;Make it a word count. MOV #SMLREC,R4 ;Say short block read MOV #HDERR$,-(SP) ;Hard error so FSM will compare labels BR EBLKST ;Go store # of words not transferred 60$: CMPB #ST.TM,R1 ;Tape mark found? BNE 70$ ;No, check EOT .ASSUME EOFFND EQ 1 INC R4 ;Yes, value 1 for TM 70$: BITB #EF.EOT,P.FLGS(R5) ;Real EOT found? BEQ GOTERR ;No, retry TST NFSREAD ;Yes, was .READ non-file structured? BNE GOTERR ;Yes, so ignore the EOT condition .ASSUME EOTFND EQ 2 CMPB (R4)+,(R4)+ ;No, value 2 for Physical EOT GOTREW: ;Plain ole rewind GOTERR: TST R4 ;How did we get here BNE OBJCNT ;Don't retry ;Non qualifying error, retry function. DEC RETRY ;Tried too much? BLE UMHERR ;Can do no more, error exit ;;; Problem if REWIND for NFS lookup fails: retry will find unit in use??? CALLR RERWRT ;No, lets try again OBJCNT: MOV #EOF$,-(SP) ;EOF error on the stack for EXCEP CMPB #OP.END!OP.REP,P.OPCD(R5) ;Is this a space function BNE 80$ ;No, skip next MOV RBCNT,R2 ;Get requested # records to space SUB P.RCSK(R5),R2 ;Minus actual # records spaced EBLKST: .IF NE MMG$T ;If XM .HP1EX P1LOW ; (Map to low memory) MOV R2,@#ERRBL2 ;Put it in error block $REL .-2 ERRBL2 UMR ; ... .HP1EN ; (End of block) .IFF ;NE MMG$T .IF NE MU$FSM ;If file structured MOV @MUCQ,R5 ;Get ERRBLK address .IFF ;NE MU$FSM ;If not file structured MOV @UMCQE,R5 ;Get ERRBLK address .ENDC ;NE MU$FSM BEQ 80$ ;If EQ, don't write to ERRBLK MOV R2,2(R5) ;Report # blks not spaced/wds not read .ENDC ;NE MMG$T 80$: BR EXCEP ;Error exit (@SP = HDERR$ or EOF$) .DSABL LSB .SBTTL UMHERR - Error Completion Routines ;+ ; There are several entry points ; ; UMHERR -- Is the entry point to issue a hard error ; ABORT -- Is the entry point to issue a hard error when more specific ; information to report ; EXCEP -- Is the entry point to report an exception conditon ; ; R4 = the error qualification code ; CSW bit to set is on the stack ;- .ENABL LSB UMHERR: CLR R4 ;Say no error qualification code ABORT: MOV #HDERR$,-(SP) ;Say hard error EXCEP: .IF NE MU$FSM ;If file structured MOV (SP)+,R5 ;R5= error type .IF NE MMG$T ;If XM MOV @H$CQE,-(SP) ;Copy Q$BLKN (ERRBLK) changes to low .HP1EX P1LOW ; (Map to low memory) CALLR @#LRET4 ;Return to low FSMERR exit $REL .-2 LRET4 UMR ; ... .HP1EN ; (End of block) .IFF ;NE MMG$T CALLR FSMERR ;Go to FSM .ENDC ;NE MMG$T .IFF ;NE MU$FSM ;If not file structured .IF EQ MMG$T MOV UMCQE,R5 ;R5 -> current queue element. .IFF ;EQ MMG$T MOV H$CQE,R5 ;R5 -> current queue element .ENDC ;EQ MMG$T BIS (SP)+,@Q$CSW(R5) ;Set bit in CSW TST @R5 ;Do we have more errors to report BEQ MUDONE ;Branch if no .IF NE MMG$T ;If XM .HP1EX P1LOW ; (Map to low memory) CALLR @#LRET10 ;Return to low FSMERR exit $REL .-2 LRET10 UMR ; ... .HP1EN ; (End of block) ;********************************************************************* UMPSECT ;********************************************************************* LRET10: MOV 2(SP),SP ;Fix stack CMP (SP)+,(SP)+ ;Pop some arguments MOV (SP)+,R0 ;Restore R0 COM SINK ;Set .SYNCH flag MOV UMCQE,R5 ;R5 -> current queue element (lo mem!) MOV @R5,ERBSAV MOV R4,TEMP ;This value returns in R0 after SYNCH MOVB Q$JNUM(R5),R5 ;Get job number BIC #^C,R5 ASR R5 ;Shift ASR R5 ; into ASR R5 ; place MOV R5,JOBNM ;Store in .SYNCH BLOCK BR $DONE .IFF ;NE MMG$T ;If not XM MOV R4,@(R5)+ ;Move code to ERRBLK .BR $DONE .ENDC ;NE MMG$T .ENDC ;NE MU$FSM .DSABL LSB .SBTTL MUDONE - Normal Completion Routines ;+ ; MUDONE is the routine that the hardware handler comes to when an operation ; completed with no exception conditions. When FSM is present, a jump to FSM ; is excecuted. If FSM is not present, the hardware handler will exit to the ; completion routine in the monitor. ;- .ENABL LSB .IF EQ MU$FSM ;********************************************************************* UMXPSECT ;********************************************************************* .ENDC ;EQ MU$FSM MUDONE: .IF NE MU$FSM ;If file structured .IF NE MMG$T ;If XM .HP1EX P1LOW ; (Map to low memory) CALLR @#LRET3 ;Return to low FSMDON exit $REL .-2 LRET3 UMR ; ... .HP1EN ; (End of block) ;********************************************************************* UMPSECT ;********************************************************************* LRET3: MOV 2(SP),SP ;Fix stack CMP (SP)+,(SP)+ ;Pop some arguments MOV (SP)+,R0 ;Restore R0 .IFTF ;NE MMG$T LMUDONE:CLR R4 ;No exception codes CALLR FSMDON ;Tell FSM that we are done ;FSM returns to $DONE when it's done .IFT ;NE MMG$T LRET4: MOV 2(SP),SP ;Fix stack CMP (SP)+,(SP)+ ;Pop some arguments MOV (SP)+,R0 ;Restore R0 MOV (SP)+,@MUCQ ;Copy Q$BLKN (ERRBLK) changes from hi CALLR FSMERR ;Go to FSM .ENDC ;NE MMG$T .ENDC ;NE MU$FSM .DSABL LSB ;+ ; Standard exit to RT-11 ;- .ENABL LSB .IF NE MU$FSM .IF NE MMG$T ;If XM ;********************************************************************* UMXPSECT ;********************************************************************* .ENDC ;NE MMG$T .ENDC ;NE MU$FSM UMEXIT: .IF NE MMG$T ;If XM .HP1EX P1LOW ; (Map to low memory) CALLR @#LRET2 ;Return to low .DRFIN exit $REL .-2 LRET2 UMR ; ... .HP1EN ; (End of block) ;********************************************************************* UMPSECT ;********************************************************************* LRET2: MOV 2(SP),SP ;Fix stack CMP (SP)+,(SP)+ ;Pop some arguments MOV (SP)+,R0 ;Restore R0 .ENDC ;NE MMG$T $DONE:: .IF NE MMG$T ;If XM .ADDR #UMCQE,R4 MOV @#SYSPTR,R5 ;Get base of RMON TST SINK ;CALL or CALLR BNE 10$ ;Branch if CALL CALLR @QCOMP(R5) ;Split 10$: CLR SINK ;Initialize .SYNCH has been done flag CALL @QCOMP(R5) ;JSR to complete .ADDR #SYNBLK,R4 ;Point to .SYNCH block .SYNCH ;Do the .SYNCH BR BADSYN ; Error on .SYNCH MOV ERBSAV,R1 ;Point to ERRBLK BIS #30000,@#177776 ;User mode to previous MOV R0,-(SP) ;Put exception code onto stack MTPI (R1)+ ;Store for the user MOV ERRBL2,-(SP) ;2ND word MTPI (R1)+ ;Store for user BADSYN: RETURN .IFF ;NE MMG$T ;If not XM .DRFIN UM ;Macro, macro what do you do? .ENDC ;NE MMG$T .DSABL LSB .IF NE MMG$T ;If XM .SBTTL XBUMP - Bump Buffer Address by 512 in XM ;+ ; XBUMP ; This routine is called by FSM it will add 512 to the buffer addresses ; in EXTADR and OLDBA for MMG$T. ;- XBUMP:: MOV UMCQE,-(SP) ;Point to queue element ADD #Q$PAR,@SP ;Point to par value ADD #10,@(SP)+ ;Bump it by a block ADD #512.,OLDBA ADC EXTADR ;Add carry if any RETURN .ENDC ;NE MMG$T .SBTTL Magtape Data Area ;+ ; 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 correctly ; positioned so that they can be OR'ed into the appropriate device register ; without any shifting. This word is a global which is accessed by FSM. ; ; NFSREAD word - This word is in special case the problem of how to remember ; that the read operation being done started life as a .READ on a channel ; opened with a non file structured .LOOKUP. When the EOT marker is detected ; and this word is non zero then the condition is ignored. ;- ; Do not change the order of the following variables OLDBA:: .WORD 0 ;Low order 16 bits of Buffer Address .IF NE MMG$T ;If XM EXTADR::.WORD 0 ;Hi order of 18/22 bit Buffer Address ;********************************************************************* UMXPSECT ;********************************************************************* .ENDC ;NE MMG$T NFSREAD::.WORD 0 ;This word is set to -1 if a ;Non filestructured READ was just ;done, else it is zero. If set, the ;EOT condition will be ignored. .IF NE MMG$T ;If XM ;********************************************************************* UMPSECT ;********************************************************************* SYNBLK::.WORD 0 ;.SYNCH Block JOBNM:: .WORD 0 ; Job number goes here .WORD 0 ; (Unused) .WORD 0 ; (Unused) TEMP:: .WORD 0 ; Loaded in R0 after successful .SYNCH .WORD -1 ; (Leave this alone!) .WORD 0 ; (Leave this alone!) SINK:: .WORD 0 ;= 0 -> .SYNCH not done, so JMP COMPLT ;<>0 -> .SYNCH done, so JSR PC,COMPLT ERBSAV::.WORD 0 ;Save the address of ERRBLK here ERRBL2: .WORD 0 ;Contains value to go to ERRBLK + 2 .ENDC ;NE MMG$T .IF EQ MU$FSM ;If not file structured .DREND UM ;This is the end .IFF ;EQ MU$FSM ;If file structured MUCQ: .WORD 0 ;Fake a UMCQE for file support DRIVEN == MU$UN ;Used by FSM DVINFO:: ;FSM's Unit table .REPT DRIVEN .WORD -1 ;Current file sequence number .WORD -1 ;Current block number, -1 = unknown .WORD -1 ;Highest block written .BYTE 0 ;File type (0= lookup, -1 = enter) .BYTE 0 ;Position is past EOT marker flag .WORD 0,0,0 ;RAD50 file name .ENDR ;+ ; The following definitions are for FSM compatibility ;- MTDONE == MUDONE MTCQE == UMCQE MT == UM MTLQE == UMLQE MTSTRT == UMSTRT MTCQ == MUCQ MUSTRT == UMSTRT .ENDC ;EQ MU$FSM .IF NE MMG$T ;+ ; UMX Calculations ;- ;********************************************************************* UMXPSECT ;********************************************************************* .ASSUME UMRLSZ EQ UMR.CNT ;Insure UMR.LST is proper size .IF NE MU$32K ;If 32KW bound check .ASSUME UMHLSZ EQ UMH.CNT ;Insure UMH.LST is proper size .ASSUME UMXLSZ EQ UMX.CNT ;Insure UMX.LST is proper size .ENDC ;NE MU$32K UMXEND:: UMXSIZ ==: UMXEND - UMXBAS ;Size in bytes Psect UMX .ASSUME . LE UMXBAS+<4000> ;< 1024 Words .ENDC ;NE MMG$T ;********************************************************************* UMPSECT ;********************************************************************* SIZE = . SIZED = /2 .END